Merge branch 'main' into 109-nix-jazzy
This commit is contained in:
commit
ec2cebe5f1
46 changed files with 2696 additions and 1844 deletions
69
Dockerfile
69
Dockerfile
|
@ -1,46 +1,65 @@
|
||||||
FROM billf1nger/ros2-humble-cuda:v12.2.2-cudnn8-ubuntu22.04-gz-nvidia
|
FROM nvidia/cuda:12.6.2-cudnn-devel-ubuntu22.04
|
||||||
|
|
||||||
ARG WSDIR=rbs_ws
|
ARG WSDIR=rbs_ws
|
||||||
ARG config_type=sim
|
|
||||||
|
|
||||||
ENV RBS_ASSEMBLY_DIR=/assembly
|
ENV RBS_ASSEMBLY_DIR=/assembly
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
# COPY /home/bill-finger/assembly /assembly
|
# COPY /home/bill-finger/assembly /assembly
|
||||||
ENV IGN_GAZEBO_RESOURCE_PATH=/${WSDIR}/install/rbs_simulation/share/rbs_simulation/
|
ENV IGN_GAZEBO_RESOURCE_PATH=/${WSDIR}/install/rbs_simulation/share/rbs_simulation/
|
||||||
|
|
||||||
RUN apt update && apt install -y \
|
RUN apt-get update && apt-get upgrade -y && apt-get install -y \
|
||||||
git \
|
git \
|
||||||
|
software-properties-common \
|
||||||
python3-pip \
|
python3-pip \
|
||||||
lsb-release \
|
lsb-release \
|
||||||
wget \
|
curl \
|
||||||
gnupg
|
wget
|
||||||
|
|
||||||
RUN pip install vcstool
|
|
||||||
|
|
||||||
WORKDIR /libs
|
# WORKDIR /libs
|
||||||
RUN wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz &&\
|
# RUN wget https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.tar.gz &&\
|
||||||
tar -xf v3.11.3.tar.gz &&\
|
# tar -xf v3.11.3.tar.gz &&\
|
||||||
cd json-3.11.3 &&\
|
# cd json-3.11.3 &&\
|
||||||
mkdir build &&\
|
# mkdir build &&\
|
||||||
cd build &&\
|
# cd build &&\
|
||||||
cmake .. &&\
|
# cmake .. &&\
|
||||||
make &&\
|
# make &&\
|
||||||
make install
|
# make install
|
||||||
|
|
||||||
RUN git clone https://gitlab.com/robossembler/forks/megapose6d.git &&\
|
RUN add-apt-repository universe
|
||||||
cd megapose6d &&\
|
RUN curl -sSL https://raw.githubusercontent.com/ros/rosdistro/master/ros.key -o /usr/share/keyrings/ros-archive-keyring.gpg
|
||||||
pip install bokeh joblib pin torch transforms3d webdataset omegaconf tqdm &&\
|
RUN 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" | tee /etc/apt/sources.list.d/ros2.list > /dev/null
|
||||||
pip install -e .
|
|
||||||
RUN git clone https://github.com/thodan/bop_toolkit &&\
|
|
||||||
cd bop_toolkit &&\
|
RUN apt-get update && apt-get upgrade && apt-get install -y ros-humble-ros-base
|
||||||
pip install -e .
|
|
||||||
|
# RUN git clone https://gitlab.com/robossembler/forks/megapose6d.git &&\
|
||||||
|
# cd megapose6d &&\
|
||||||
|
# pip install bokeh joblib pin torch transforms3d webdataset omegaconf tqdm &&\
|
||||||
|
# pip install -e .
|
||||||
|
# RUN git clone https://github.com/thodan/bop_toolkit &&\
|
||||||
|
# cd bop_toolkit &&\
|
||||||
|
# pip install -e .
|
||||||
|
|
||||||
WORKDIR /${WSDIR}
|
WORKDIR /${WSDIR}
|
||||||
|
|
||||||
COPY . src/robossembler-ros2/
|
COPY . src/robossembler-ros2/
|
||||||
|
|
||||||
RUN vcs import src/. < src/robossembler-ros2/rbs.${config_type}.repos
|
RUN pip install vcstool uv
|
||||||
RUN apt update && rosdep update && \
|
|
||||||
|
# Install framework and dependencies
|
||||||
|
RUN vcs import src/. < src/robossembler-ros2/repos/all-deps.repos
|
||||||
|
RUN uv pip install --system -r src/robossembler-ros2/repos/requirements.txt
|
||||||
|
RUN apt-get update && rosdep update && \
|
||||||
rosdep install -y -r -q --from-paths src --ignore-src --rosdistro humble
|
rosdep install -y -r -q --from-paths src --ignore-src --rosdistro humble
|
||||||
RUN . /opt/ros/humble/setup.sh && \
|
RUN . /opt/ros/humble/setup.sh && \
|
||||||
colcon build --symlink-install --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
colcon build --symlink-install --cmake-args -DCMAKE_EXPORT_COMPILE_COMMANDS=1
|
||||||
|
|
||||||
|
|
||||||
|
WORKDIR /${RBS_ASSEMBLY_DIR}
|
||||||
|
RUN curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | bash
|
||||||
|
RUN apt-get install git-lfs
|
||||||
|
RUN git clone https://github.com/solid-sinusoid/rbs_assets_library.git
|
||||||
|
RUN cd rbs_assets_library && git lfs pull && pip install -e .
|
||||||
|
|
||||||
|
WORKDIR /${WSDIR}
|
||||||
|
|
110
doc/en/add_new_robot.md
Normal file
110
doc/en/add_new_robot.md
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
# Instructions for Adding a New Robot to the Robossembler ROS 2 Framework
|
||||||
|
|
||||||
|
First, you need to download the robot package containing `xacro` or `urdf` files, as well as geometry files in formats such as `.stl`, `.dae`, `.obj`, etc.
|
||||||
|
|
||||||
|
Before starting, it is important to understand the basics of the [xacro](https://github.com/ros/xacro/wiki) format. This format allows you to reuse existing fragments of a robot's URDF description, making it easier to create and modify descriptions.
|
||||||
|
|
||||||
|
### Steps for Adding a New Robot:
|
||||||
|
|
||||||
|
1. **Install the Robot Package**
|
||||||
|
After installing the robot package, create a file named `xacro_args.yaml` in the `{description_package}/config/` directory. This file should specify the arguments needed to convert the `xacro` file into a `urdf`.
|
||||||
|
|
||||||
|
2. **Configure the Launch File**
|
||||||
|
Edit the file [`rbs_bringup.launch.py`](../../rbs_bringup/launch/rbs_bringup.launch.py) to define the parameters required to launch the robot.
|
||||||
|
|
||||||
|
Example of a standard implementation:
|
||||||
|
```python
|
||||||
|
main_script = IncludeLaunchDescription(
|
||||||
|
PythonLaunchDescriptionSource(
|
||||||
|
[
|
||||||
|
PathJoinSubstitution(
|
||||||
|
[FindPackageShare("rbs_runtime"), "launch", "runtime.launch.py"]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
launch_arguments={
|
||||||
|
"with_gripper": "true",
|
||||||
|
"gripper_name": "rbs_gripper",
|
||||||
|
"robot_type": "rbs_arm",
|
||||||
|
"description_package": "rbs_arm",
|
||||||
|
"description_file": "rbs_arm_modular.xacro",
|
||||||
|
"robot_name": "rbs_arm",
|
||||||
|
"use_moveit": "false",
|
||||||
|
"moveit_config_package": "rbs_arm",
|
||||||
|
"moveit_config_file": "rbs_arm.srdf.xacro",
|
||||||
|
"use_sim_time": "true",
|
||||||
|
"hardware": "gazebo",
|
||||||
|
"use_controllers": "true",
|
||||||
|
"scene_config_file": "",
|
||||||
|
"base_link_name": "base_link",
|
||||||
|
"ee_link_name": "gripper_grasp_point",
|
||||||
|
}.items(),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
This configuration launches another file with specific arguments. Below is a description of each argument to help you decide whether it is needed.
|
||||||
|
|
||||||
|
### Parameter Descriptions:
|
||||||
|
|
||||||
|
- **`with_gripper`**
|
||||||
|
Indicates whether the robot has a gripper. If set to `true`, the `gripper_controller` will be configured and launched.
|
||||||
|
|
||||||
|
- **`gripper_name`**
|
||||||
|
Used as a keyword to identify links and joints related to the gripper. It is also applied in `xacro` arguments.
|
||||||
|
|
||||||
|
- **`robot_type`**
|
||||||
|
Specifies a group of robots of the same type, allowing you to semantically group robots with different names but similar designs.
|
||||||
|
|
||||||
|
- **`description_package`**
|
||||||
|
The package containing the robot's URDF description. This parameter is mandatory and is used to locate the URDF file and controller configuration files.
|
||||||
|
|
||||||
|
- **`description_file`**
|
||||||
|
The name of the description file, which should be located in `{description_package}/urdf/`.
|
||||||
|
|
||||||
|
- **`robot_name`**
|
||||||
|
A unique name for the robot to distinguish it from others in the scene.
|
||||||
|
|
||||||
|
- **`use_moveit`**
|
||||||
|
Indicates whether [MoveIt 2](https://moveit.picknik.ai/humble/index.html) should be used. While it is not required for basic movements, it is recommended when working with obstacles.
|
||||||
|
|
||||||
|
- **`moveit_config_package`**
|
||||||
|
The name of the MoveIt 2 configuration package generated based on the `{description_package}`. This parameter is required if you plan to use MoveIt 2.
|
||||||
|
|
||||||
|
- **`moveit_config_file`**
|
||||||
|
The MoveIt 2 launch file located in `{moveit_config_package}/launch/`.
|
||||||
|
|
||||||
|
- **`use_sim_time`**
|
||||||
|
A mandatory parameter for simulation. It ensures that time is synchronized with the simulator.
|
||||||
|
|
||||||
|
- **`hardware`**
|
||||||
|
Specifies the interface to be used for controlling the robot. For example, `gazebo`. This parameter is primarily used in `xacro` files.
|
||||||
|
|
||||||
|
- **`use_controllers`**
|
||||||
|
Indicates whether to use standard controllers. If set to `false`, the robot will not be able to move. This parameter controls the execution of the [control.launch.py](../../rbs_bringup/launch/control.launch.py) file. You can write a custom implementation instead of using this flag.
|
||||||
|
|
||||||
|
- **`scene_config_file`**
|
||||||
|
A YAML file that defines the scene configuration. A default example is available [here](../../env_manager/rbs_runtime/config/default-scene-config.yaml). Ensure that the degrees of freedom of your robot match the configuration file.
|
||||||
|
|
||||||
|
- **`base_link_name`**
|
||||||
|
The name of the robot's base link, which defines where the robot begins. This parameter is important for skill configuration. Review your robot's URDF to set this correctly.
|
||||||
|
|
||||||
|
- **`ee_link_name`**
|
||||||
|
The name of the end-effector link, which defines where the robot ends. This parameter is also important for skill configuration and should be set based on the URDF.
|
||||||
|
|
||||||
|
- **`control_space`**
|
||||||
|
Specifies the space in which the robot will be controlled.
|
||||||
|
Possible values:
|
||||||
|
- `task` — control in task space (e.g., using positions and orientations in the workspace).
|
||||||
|
- `joint` — control in joint space (e.g., using angular values for each robot joint).
|
||||||
|
Default value: `task`.
|
||||||
|
|
||||||
|
- **`control_strategy`**
|
||||||
|
Specifies the control strategy for the robot.
|
||||||
|
Possible values:
|
||||||
|
- `position` — position control, where desired positions are set for joints or the workspace target point.
|
||||||
|
- `velocity` — velocity control, where desired movement speeds are set.
|
||||||
|
- `effort` — effort control, where torques or forces applied to the joints are specified.
|
||||||
|
Default value: `position`.
|
||||||
|
|
||||||
|
- **`interactive`**
|
||||||
|
Specifies whether to run the `motion_control_handle` controller.
|
||||||
|
Default value: `true`.
|
18
doc/en/index.md
Normal file
18
doc/en/index.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
Robossembler ROS 2 Packages
|
||||||
|
|
||||||
|
- **`env_manager`** - virtual environment manager:
|
||||||
|
- **`env_manager`** - manages objects in Gazebo simulation scenes.
|
||||||
|
- **`env_manager_interfaces`** - ROS 2 interfaces for configuring, loading, activating, and unloading environments.
|
||||||
|
- **`rbs_gym`** - reinforcement learning module: training management, simulation environment creation, action and observation space handling, utilities.
|
||||||
|
- **`rbs_runtime`** - runs the main runtime using `env_manager`.
|
||||||
|
|
||||||
|
- **`rbs_bringup`** - launch scenarios: simulation, real robot, multi-robot configurations.
|
||||||
|
- **`rbs_bt_executor`** - executes behavior trees with Behavior Tree CPP v4.
|
||||||
|
- **`rbs_interface`** - interface linking behavior trees with skill servers (recommended to merge with `rbs_bt_executor`).
|
||||||
|
- **`rbs_perception`** - machine vision module with multiple implementations.
|
||||||
|
- **`rbs_simulation`** - simulation models (recommended to merge with `env_manager` or `rbs_gym`).
|
||||||
|
- **`rbs_skill_interfaces`** - common interfaces for interacting with skill servers and behavior trees.
|
||||||
|
- **`rbs_skill_servers`** - packages for skill servers (recommended to replace with individual packages for each server).
|
||||||
|
- **`rbs_task_planner`** - task planner based on PDDL.
|
||||||
|
- **`rbs_utils`** - utilities for working with configurations containing grasp positions.
|
||||||
|
- **`rbss_objectdetection`** - skill server for object detection using YOLOv8.
|
20
doc/index.md
20
doc/index.md
|
@ -1,20 +0,0 @@
|
||||||
Robossembler ROS 2 Packages
|
|
||||||
|
|
||||||
- `env_manager` - менеджер переключения виртуальных сред
|
|
||||||
- `env_interface` - базовый класс для создания конкретной среды на базе ROS 2 LifeCycle Node
|
|
||||||
- `env_manager` - основной пакет менеджера переключения виртуальных сред
|
|
||||||
- `env_manager_interfaces` - интерфейсы ROS 2 для env_manager, описывают сообщения о состоянии среды, сервисы по конфигурации/загрузке/включению/выгрузке среды
|
|
||||||
- `gz_environment` - конкретный экземпляр `env_interface` для симулятора Gazebo
|
|
||||||
- `planning_scene_manager` - управление сценой планирования для MoveIt (среда для MoveIt)
|
|
||||||
- `rbs_gym` - модуль обучения с подреплением: управление процесом обучения, формирование сред симуляции, управление пространствами действий(actions) и восприятия(observation), управление задачами, утилиты
|
|
||||||
|
|
||||||
- `rbs_bringup` - пакет для запуска разных launch сценариев: симуляция, реальный робот, разные конфигурации оборудования (multi-robot)
|
|
||||||
- `rbs_bt_executor` - модуль запуска деревьев поведения на Behavior Tree CPP v4
|
|
||||||
- `rbs_interface` - пакет для связывания деревьев со скилл-серверами (объединить с - `rbs_bt_executor`)
|
|
||||||
- `rbs_perception` - модуль машинного восприятия, где реализованы разные версии
|
|
||||||
- `rbs_simulation` - модели для симуляции (к удалить или объединить с env_manager/rbs_gym)
|
|
||||||
- `rbs_skill_interfaces` - общеиспользуемые (common) интерфейсы для взаимодействия с Серверами Навыков и Деревом поведения (специфичные интерфейсы размещаются в пакетах Серверов Навыков)
|
|
||||||
- `rbs_skill_servers` - пакеты Серверов Навыков (упразднить, для каждого Сервера Навыков свой пакет)
|
|
||||||
- `rbs_task_planner` - планировщик задач на базе PDDL
|
|
||||||
- `rbs_utils` - работа с конфигом, содержащим позиции захвата для деталей
|
|
||||||
- `rbss_objectdetection` - Сервер Навыка обнаружения объектов с помощью YOLOv8
|
|
112
doc/ru/add_new_robot.md
Normal file
112
doc/ru/add_new_robot.md
Normal file
|
@ -0,0 +1,112 @@
|
||||||
|
# Инструкция по добавлению нового робота в фреймворк Robossembler ROS 2
|
||||||
|
|
||||||
|
Прежде всего необходимо скачать пакет робота, содержащий файлы `xacro` или `urdf`, а также файлы геометрии робота в формате `.stl`, `.dae`, `.obj` и других.
|
||||||
|
|
||||||
|
Перед началом работы важно ознакомиться с основными аспектами формата [xacro](https://github.com/ros/xacro/wiki). Этот формат позволяет переиспользовать существующие фрагменты URDF-описания робота, что упрощает создание и модификацию описания.
|
||||||
|
|
||||||
|
### Шаги по добавлению нового робота:
|
||||||
|
|
||||||
|
1. **Установка пакета робота**
|
||||||
|
После установки пакета робота создайте файл `xacro_args.yaml` в директории `{description_package}/config/`. В этом файле необходимо указать аргументы для преобразования xacro-файла в URDF.
|
||||||
|
|
||||||
|
2. **Настройка запуска**
|
||||||
|
Отредактируйте файл [`rbs_bringup.launch.py`](../../rbs_bringup/launch/rbs_bringup.launch.py), указав параметры для запуска робота.
|
||||||
|
|
||||||
|
Пример стандартной реализации:
|
||||||
|
```python
|
||||||
|
main_script = IncludeLaunchDescription(
|
||||||
|
PythonLaunchDescriptionSource(
|
||||||
|
[
|
||||||
|
PathJoinSubstitution(
|
||||||
|
[FindPackageShare("rbs_runtime"), "launch", "runtime.launch.py"]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
launch_arguments={
|
||||||
|
"with_gripper": "true",
|
||||||
|
"gripper_name": "rbs_gripper",
|
||||||
|
"robot_type": "rbs_arm",
|
||||||
|
"description_package": "rbs_arm",
|
||||||
|
"description_file": "rbs_arm_modular.xacro",
|
||||||
|
"robot_name": "rbs_arm",
|
||||||
|
"use_moveit": "false",
|
||||||
|
"moveit_config_package": "rbs_arm",
|
||||||
|
"moveit_config_file": "rbs_arm.srdf.xacro",
|
||||||
|
"use_sim_time": "true",
|
||||||
|
"hardware": "gazebo",
|
||||||
|
"use_controllers": "true",
|
||||||
|
"scene_config_file": "",
|
||||||
|
"base_link_name": "base_link",
|
||||||
|
"ee_link_name": "gripper_grasp_point",
|
||||||
|
"control_space": "task",
|
||||||
|
"control_strategy": "position",
|
||||||
|
}.items(),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
Здесь выполняется запуск другого launch-файла с указанными аргументами. Ниже приводится описание каждого аргумента.
|
||||||
|
|
||||||
|
### Описание параметров:
|
||||||
|
|
||||||
|
- **`with_gripper`**
|
||||||
|
Указывает, есть ли на роботе захватное устройство (гриппер). Если значение `true`, будет настроен и запущен `gripper_controller`.
|
||||||
|
|
||||||
|
- **`gripper_name`**
|
||||||
|
Используется как ключевое слово для указания линков и джоинтов, относящихся к грипперу. Также применяется в xacro-аргументах.
|
||||||
|
|
||||||
|
- **`robot_type`**
|
||||||
|
Обозначает группу роботов одного типа. Например, все роботы с разными именами, но одинаковой конструкцией.
|
||||||
|
|
||||||
|
- **`description_package`**
|
||||||
|
Пакет, содержащий описание URDF робота. Обязательный параметр. Используется для определения пути к файлу описания и конфигурации контроллеров.
|
||||||
|
|
||||||
|
- **`description_file`**
|
||||||
|
Имя файла описания, который должен находиться в `{description_package}/urdf/`.
|
||||||
|
|
||||||
|
- **`robot_name`**
|
||||||
|
Уникальное имя робота, которое позволяет отличить его от других в сцене.
|
||||||
|
|
||||||
|
- **`use_moveit`**
|
||||||
|
Указывает, нужно ли использовать [MoveIt 2](https://moveit.picknik.ai/humble/index.html). Для базовых перемещений MoveIt 2 не обязателен, но для работы с препятствиями рекомендуется его включить.
|
||||||
|
|
||||||
|
- **`moveit_config_package`**
|
||||||
|
Имя пакета конфигурации MoveIt 2, который генерируется на основе `{description_package}`. Обязательный параметр, если используется MoveIt 2.
|
||||||
|
|
||||||
|
- **`moveit_config_file`**
|
||||||
|
Файл запуска MoveIt 2, находящийся в `{moveit_config_package}/launch/`.
|
||||||
|
|
||||||
|
- **`use_sim_time`**
|
||||||
|
Обязательный параметр при работе в симуляции. Обеспечивает синхронизацию времени с симулятором.
|
||||||
|
|
||||||
|
- **`hardware`**
|
||||||
|
Указывает интерфейс для управления роботом. Например, `gazebo`. Используется в основном в xacro-файлах.
|
||||||
|
|
||||||
|
- **`use_controllers`**
|
||||||
|
Указывает, нужно ли использовать стандартные контроллеры. Если значение `false`, робот не сможет двигаться. Влияет на запуск файла [control.launch.py](../../rbs_bringup/launch/control.launch.py).
|
||||||
|
|
||||||
|
- **`scene_config_file`**
|
||||||
|
Файл конфигурации сцены в формате YAML. Пример можно найти [здесь](../../env_manager/rbs_runtime/config/default-scene-config.yaml). Обратите внимание на соответствие количества степеней свободы робота.
|
||||||
|
|
||||||
|
- **`base_link_name`**
|
||||||
|
Имя базового линка, от которого начинается робот. Важно для настройки навыков. Рекомендуется свериться с URDF.
|
||||||
|
|
||||||
|
- **`ee_link_name`**
|
||||||
|
Имя конечного линка (энд-эффектора), где заканчивается робот. Этот параметр также настраивается на основе URDF.
|
||||||
|
|
||||||
|
- **`control_space`**
|
||||||
|
Указывает, в каком пространстве робот будет управляться.
|
||||||
|
Возможные значения:
|
||||||
|
- `task` — управление в пространстве задач (например, с использованием позиций и ориентации в рабочем пространстве).
|
||||||
|
- `joint` — управление в пространстве суставов (например, с использованием угловых значений для каждого сустава робота).
|
||||||
|
Значение по умолчанию: `task`.
|
||||||
|
|
||||||
|
- **`control_strategy`**
|
||||||
|
Указывает стратегию управления роботом.
|
||||||
|
Возможные значения:
|
||||||
|
- `position` — управление положением, когда задаются желаемые позиции для суставов или рабочей точки.
|
||||||
|
- `velocity` — управление скоростью, когда задаются желаемые скорости движения.
|
||||||
|
- `effort` — управление усилием, когда задаются моменты или силы, прикладываемые к суставам.
|
||||||
|
Значение по умолчанию: `position`.
|
||||||
|
|
||||||
|
- **`interactive`**
|
||||||
|
Указывает, нужно ли запускать контроллер `motion_control_handle`.
|
||||||
|
Значение по умолчанию: `true`.
|
18
doc/ru/index.md
Normal file
18
doc/ru/index.md
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
# Robossembler ROS 2 Packages
|
||||||
|
|
||||||
|
- **`env_manager`** - менеджер виртуальных сред:
|
||||||
|
- **`env_manager`** - управление объектами в сцене симуляции Gazebo.
|
||||||
|
- **`env_manager_interfaces`** - ROS 2 интерфейсы для конфигурации, загрузки, активации и выгрузки сред.
|
||||||
|
- **`rbs_gym`** - модуль обучения с подкреплением: управление обучением, создание симуляционных сред, управление пространствами действий и наблюдений, утилиты.
|
||||||
|
- **`rbs_runtime`** - запуск основного рантайма с использованием `env_manager`.
|
||||||
|
|
||||||
|
- **`rbs_bringup`** - запуск сценариев: симуляция, реальный робот, многороботные конфигурации.
|
||||||
|
- **`rbs_bt_executor`** - выполнение деревьев поведения с Behavior Tree CPP v4.
|
||||||
|
- **`rbs_interface`** - интерфейс для связи деревьев поведения со скилл-серверами (рекомендуется объединить с `rbs_bt_executor`).
|
||||||
|
- **`rbs_perception`** - модуль машинного зрения с различными версиями.
|
||||||
|
- **`rbs_simulation`** - модели для симуляции (рекомендуется объединить с `env_manager` или `rbs_gym`).
|
||||||
|
- **`rbs_skill_interfaces`** - общие интерфейсы для взаимодействия с скилл-серверами и деревьями поведения.
|
||||||
|
- **`rbs_skill_servers`** - пакеты для скилл-серверов (рекомендуется заменить на индивидуальные пакеты для каждого сервера).
|
||||||
|
- **`rbs_task_planner`** - планировщик задач на основе PDDL.
|
||||||
|
- **`rbs_utils`** - утилиты для работы с конфигурациями, содержащими позиции захвата.
|
||||||
|
- **`rbss_objectdetection`** - скилл-сервер для обнаружения объектов с YOLOv8.
|
32
doc/ru/installation.md
Normal file
32
doc/ru/installation.md
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
# Инструкция по установке фреймворка
|
||||||
|
|
||||||
|
Первым делом необходимо установить [ROS2 Humble](https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html). Рекомендуется минимальная установка.
|
||||||
|
|
||||||
|
Вторым делом надо собрать [`ros2_control`](https://github.com/ros-controls/ros2_control) из исходников из этого [форка](https://github.com/solid-sinusoid/ros2_control/tree/gz-ros2-cartesian-controllers) стоит отметить, что также существует альтернативная установка с использованием [`vsctool`](https://github.com/dirk-thomas/vcstool) который поставляется с базовыми пакетами ROS2.
|
||||||
|
|
||||||
|
Если устанавливать через `vcstool` тогда необходимые пакеты будут клонированы в тоже рабочее пространство, что и сам фреймворк. Сама команда будет выглядеть так
|
||||||
|
```sh
|
||||||
|
vcs import . < robossembler-ros2/repos/all-deps.repos
|
||||||
|
```
|
||||||
|
|
||||||
|
Заодно можно выполнить команду для установки всех требуемых библиотек Python
|
||||||
|
```shell
|
||||||
|
pip insatll -r robossembler-ros2/repos/requirements.txt
|
||||||
|
```
|
||||||
|
|
||||||
|
При этом команду надо выполнять в директории `{robossembler_ws}/src/`
|
||||||
|
|
||||||
|
Более четкая последовательность команд кому лень:
|
||||||
|
```sh
|
||||||
|
cd
|
||||||
|
mkdir -p robossembler-ros2/src && cd robossembler-ros2
|
||||||
|
git clone git clone https://seed.robossembler.org/z46gtVRpXaXrGQM7Fxiqu7pLy7kip.git robossembler-ros2
|
||||||
|
# Или если вы предпочитаете radicle
|
||||||
|
rad clone rad:z46gtVRpXaXrGQM7Fxiqu7pLy7kip
|
||||||
|
cd src
|
||||||
|
vcs import . < robossembler-ros2/repos/all-deps.repos
|
||||||
|
pip insatll -r robossembler-ros2/repos/requirements.txt
|
||||||
|
cd ..
|
||||||
|
rosdep install --from-paths src -y --ignore-src
|
||||||
|
colcon build --symlink-install
|
||||||
|
```
|
|
@ -27,4 +27,7 @@ class TerrainData:
|
||||||
spawn_position: tuple[float, float, float] = field(default=(0, 0, 0))
|
spawn_position: tuple[float, float, float] = field(default=(0, 0, 0))
|
||||||
spawn_quat_xyzw: tuple[float, float, float, float] = field(default=(0, 0, 0, 1))
|
spawn_quat_xyzw: tuple[float, float, float, float] = field(default=(0, 0, 0, 1))
|
||||||
size: tuple[float, float] = field(default=(1.5, 1.5))
|
size: tuple[float, float] = field(default=(1.5, 1.5))
|
||||||
|
ambient: tuple[float, float, float, float] = field(default=(0.8, 0.8, 0.8, 1.0))
|
||||||
|
specular: tuple[float, float, float, float] = field(default=(0.8, 0.8, 0.8, 1.0))
|
||||||
|
diffuse: tuple[float, float, float, float] = field(default=(0.8, 0.8, 0.8, 1.0))
|
||||||
model_rollouts_num: int = field(default=1)
|
model_rollouts_num: int = field(default=1)
|
||||||
|
|
|
@ -20,6 +20,9 @@ class Ground(model_wrapper.ModelWrapper):
|
||||||
size (tuple[float, float], optional): The size of the ground plane. Defaults to (1.5, 1.5).
|
size (tuple[float, float], optional): The size of the ground plane. Defaults to (1.5, 1.5).
|
||||||
collision_thickness (float, optional): The thickness of the collision surface. Defaults to 0.05.
|
collision_thickness (float, optional): The thickness of the collision surface. Defaults to 0.05.
|
||||||
friction (float, optional): The friction coefficient for the ground surface. Defaults to 5.0.
|
friction (float, optional): The friction coefficient for the ground surface. Defaults to 5.0.
|
||||||
|
ambient (tuple[float, float, float, float], optional): The ambient color of the material. Defaults to (0.8, 0.8, 0.8, 1.0).
|
||||||
|
specular (tuple[float, float, float, float], optional): The specular color of the material. Defaults to (0.8, 0.8, 0.8, 1.0).
|
||||||
|
diffuse (tuple[float, float, float, float], optional): The diffuse color of the material. Defaults to (0.8, 0.8, 0.8, 1.0).
|
||||||
**kwargs: Additional keyword arguments for future extensions.
|
**kwargs: Additional keyword arguments for future extensions.
|
||||||
|
|
||||||
Raises:
|
Raises:
|
||||||
|
@ -35,6 +38,9 @@ class Ground(model_wrapper.ModelWrapper):
|
||||||
size: tuple[float, float] = (1.5, 1.5),
|
size: tuple[float, float] = (1.5, 1.5),
|
||||||
collision_thickness=0.05,
|
collision_thickness=0.05,
|
||||||
friction: float = 5.0,
|
friction: float = 5.0,
|
||||||
|
ambient: tuple[float, float, float, float] = (0.8, 0.8, 0.8, 1.0),
|
||||||
|
specular: tuple[float, float, float, float] = (0.8, 0.8, 0.8, 1.0),
|
||||||
|
diffuse: tuple[float, float, float, float] = (0.8, 0.8, 0.8, 1.0),
|
||||||
**kwargs,
|
**kwargs,
|
||||||
):
|
):
|
||||||
# Get a unique model name
|
# Get a unique model name
|
||||||
|
@ -43,7 +49,7 @@ class Ground(model_wrapper.ModelWrapper):
|
||||||
# Initial pose
|
# Initial pose
|
||||||
initial_pose = scenario_core.Pose(position, orientation)
|
initial_pose = scenario_core.Pose(position, orientation)
|
||||||
|
|
||||||
# Create SDF string for the model
|
# Create SDF string for the model with the provided material properties
|
||||||
sdf = f"""<sdf version="1.9">
|
sdf = f"""<sdf version="1.9">
|
||||||
<model name="{model_name}">
|
<model name="{model_name}">
|
||||||
<static>true</static>
|
<static>true</static>
|
||||||
|
@ -75,9 +81,9 @@ class Ground(model_wrapper.ModelWrapper):
|
||||||
</plane>
|
</plane>
|
||||||
</geometry>
|
</geometry>
|
||||||
<material>
|
<material>
|
||||||
<ambient>0.8 0.8 0.8 1</ambient>
|
<ambient>{' '.join(map(str, ambient))}</ambient>
|
||||||
<diffuse>0.8 0.8 0.8 1</diffuse>
|
<diffuse>{' '.join(map(str, diffuse))}</diffuse>
|
||||||
<specular>0.8 0.8 0.8 1</specular>
|
<specular>{' '.join(map(str, specular))}</specular>
|
||||||
</material>
|
</material>
|
||||||
</visual>
|
</visual>
|
||||||
</link>
|
</link>
|
||||||
|
|
|
@ -573,6 +573,9 @@ class Scene:
|
||||||
position=self.terrain.spawn_position,
|
position=self.terrain.spawn_position,
|
||||||
orientation=quat_to_wxyz(self.terrain.spawn_quat_xyzw),
|
orientation=quat_to_wxyz(self.terrain.spawn_quat_xyzw),
|
||||||
size=self.terrain.size,
|
size=self.terrain.size,
|
||||||
|
ambient=self.terrain.ambient,
|
||||||
|
diffuse=self.terrain.diffuse,
|
||||||
|
specular=self.terrain.specular,
|
||||||
)
|
)
|
||||||
|
|
||||||
# Enable contact detection
|
# Enable contact detection
|
||||||
|
|
|
@ -65,7 +65,7 @@ def launch_setup(context, *args, **kwargs):
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
launch_simulation = LaunchConfiguration("launch_sim")
|
||||||
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
initial_joint_controllers_file_path = os.path.join(
|
||||||
get_package_share_directory('rbs_arm'), 'config', 'rbs_arm0_controllers.yaml'
|
get_package_share_directory('rbs_arm'), 'config', 'controllers.yaml'
|
||||||
)
|
)
|
||||||
|
|
||||||
single_robot_setup = IncludeLaunchDescription(
|
single_robot_setup = IncludeLaunchDescription(
|
||||||
|
@ -176,7 +176,7 @@ def generate_launch_description():
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"controllers_file",
|
"controllers_file",
|
||||||
default_value="rbs_arm_controllers_gazebosim.yaml",
|
default_value="controllers_gazebosim.yaml",
|
||||||
description="YAML file with the controllers configuration.",
|
description="YAML file with the controllers configuration.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -70,7 +70,7 @@ def launch_setup(context, *args, **kwargs):
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
launch_simulation = LaunchConfiguration("launch_sim")
|
||||||
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
initial_joint_controllers_file_path = os.path.join(
|
||||||
get_package_share_directory('rbs_arm'), 'config', 'rbs_arm0_controllers.yaml'
|
get_package_share_directory('rbs_arm'), 'config', 'controllers.yaml'
|
||||||
)
|
)
|
||||||
|
|
||||||
single_robot_setup = IncludeLaunchDescription(
|
single_robot_setup = IncludeLaunchDescription(
|
||||||
|
@ -195,7 +195,7 @@ def generate_launch_description():
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"controllers_file",
|
"controllers_file",
|
||||||
default_value="rbs_arm_controllers_gazebosim.yaml",
|
default_value="controllers_gazebosim.yaml",
|
||||||
description="YAML file with the controllers configuration.",
|
description="YAML file with the controllers configuration.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -52,7 +52,7 @@ def launch_setup(context, *args, **kwargs):
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
launch_simulation = LaunchConfiguration("launch_sim")
|
||||||
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
initial_joint_controllers_file_path = os.path.join(
|
||||||
get_package_share_directory("rbs_arm"), "config", "rbs_arm0_controllers.yaml"
|
get_package_share_directory("rbs_arm"), "config", "controllers.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
xacro_file = os.path.join(
|
xacro_file = os.path.join(
|
||||||
|
@ -158,7 +158,7 @@ def generate_launch_description():
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"controllers_file",
|
"controllers_file",
|
||||||
default_value="rbs_arm_controllers_gazebosim.yaml",
|
default_value="controllers_gazebosim.yaml",
|
||||||
description="YAML file with the controllers configuration.",
|
description="YAML file with the controllers configuration.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -69,7 +69,7 @@ def launch_setup(context, *args, **kwargs):
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
launch_simulation = LaunchConfiguration("launch_sim")
|
||||||
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
initial_joint_controllers_file_path = os.path.join(
|
||||||
get_package_share_directory('rbs_arm'), 'config', 'rbs_arm0_controllers.yaml'
|
get_package_share_directory('rbs_arm'), 'config', 'controllers.yaml'
|
||||||
)
|
)
|
||||||
|
|
||||||
single_robot_setup = IncludeLaunchDescription(
|
single_robot_setup = IncludeLaunchDescription(
|
||||||
|
@ -196,7 +196,7 @@ def generate_launch_description():
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"controllers_file",
|
"controllers_file",
|
||||||
default_value="rbs_arm_controllers_gazebosim.yaml",
|
default_value="controllers_gazebosim.yaml",
|
||||||
description="YAML file with the controllers configuration.",
|
description="YAML file with the controllers configuration.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -7,7 +7,7 @@ import torch
|
||||||
from rclpy.node import Node
|
from rclpy.node import Node
|
||||||
from sensor_msgs.msg import PointCloud2
|
from sensor_msgs.msg import PointCloud2
|
||||||
|
|
||||||
from rbs_gym.envs.utils import Tf2Listener, conversions
|
from env_manager.utils import Tf2Listener, conversions
|
||||||
|
|
||||||
|
|
||||||
class OctreeCreator:
|
class OctreeCreator:
|
||||||
|
|
|
@ -1,100 +1,129 @@
|
||||||
camera:
|
camera:
|
||||||
- clip_color: !tuple
|
- clip_color: !tuple
|
||||||
- 0.01
|
- 0.01
|
||||||
- 1000.0
|
- 1000.0
|
||||||
clip_depth: !tuple
|
clip_depth: !tuple
|
||||||
- 0.05
|
- 0.05
|
||||||
- 10.0
|
- 10.0
|
||||||
enable: true
|
enable: true
|
||||||
height: 128
|
height: 128
|
||||||
horizontal_fov: 1.0471975511965976
|
horizontal_fov: 1.0471975511965976
|
||||||
image_format: R8G8B8
|
image_format: R8G8B8
|
||||||
name: robot_camera
|
name: robot_camera
|
||||||
noise_mean: null
|
noise_mean: null
|
||||||
noise_stddev: null
|
noise_stddev: null
|
||||||
publish_color: true
|
publish_color: true
|
||||||
publish_depth: true
|
publish_depth: true
|
||||||
publish_points: true
|
publish_points: true
|
||||||
random_pose_focal_point_z_offset: 0.0
|
random_pose_focal_point_z_offset: 0.0
|
||||||
random_pose_mode: orbit
|
random_pose_mode: orbit
|
||||||
random_pose_orbit_distance: 1.0
|
random_pose_orbit_distance: 1.0
|
||||||
random_pose_orbit_height_range: !tuple
|
random_pose_orbit_height_range: !tuple
|
||||||
- 0.1
|
- 0.1
|
||||||
- 0.7
|
- 0.7
|
||||||
random_pose_orbit_ignore_arc_behind_robot: 0.39269908169872414
|
random_pose_orbit_ignore_arc_behind_robot: 0.39269908169872414
|
||||||
random_pose_rollout_counter: 0.0
|
random_pose_rollout_counter: 0.0
|
||||||
random_pose_rollouts_num: 1
|
random_pose_rollouts_num: 1
|
||||||
random_pose_select_position_options: []
|
random_pose_select_position_options: []
|
||||||
relative_to: base_link
|
relative_to: base_link
|
||||||
spawn_position: !tuple
|
spawn_position: !tuple
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 1.0
|
- 1.0
|
||||||
spawn_quat_xyzw: !tuple
|
spawn_quat_xyzw: !tuple
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.70710678118
|
- 0.70710678118
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.70710678118
|
- 0.70710678118
|
||||||
type: rgbd_camera
|
type: rgbd_camera
|
||||||
update_rate: 10
|
update_rate: 10
|
||||||
vertical_fov: 1.0471975511965976
|
vertical_fov: 1.0471975511965976
|
||||||
width: 128
|
width: 128
|
||||||
gravity: !tuple
|
gravity: !tuple
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- -9.80665
|
- -9.80665
|
||||||
gravity_std: !tuple
|
gravity_std: !tuple
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0232
|
- 0.0232
|
||||||
light:
|
light:
|
||||||
color: !tuple
|
color: !tuple
|
||||||
- 1.0
|
- 1.0
|
||||||
- 1.0
|
- 1.0
|
||||||
- 1.0
|
- 1.0
|
||||||
- 1.0
|
- 1.0
|
||||||
direction: !tuple
|
direction: !tuple
|
||||||
- 0.5
|
- 0.5
|
||||||
- -0.25
|
- -0.25
|
||||||
- -0.75
|
- -0.75
|
||||||
distance: 1000.0
|
distance: 1000.0
|
||||||
model_rollouts_num: 1
|
model_rollouts_num: 1
|
||||||
radius: 25.0
|
radius: 25.0
|
||||||
random_minmax_elevation: !tuple
|
random_minmax_elevation: !tuple
|
||||||
- -0.15
|
- -0.15
|
||||||
- -0.65
|
- -0.65
|
||||||
type: sun
|
type: sun
|
||||||
visual: true
|
visual: true
|
||||||
objects:
|
objects:
|
||||||
- color: null
|
- color: null
|
||||||
name: bishop
|
name: hole
|
||||||
orientation: !tuple
|
orientation: !tuple
|
||||||
- 1.0
|
- 1.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
position: !tuple
|
position: !tuple
|
||||||
- 0.0
|
- 0.1
|
||||||
- 1.0
|
- 0.3
|
||||||
- 0.3
|
- 0.1
|
||||||
randomize:
|
randomize:
|
||||||
count: 0
|
count: 0
|
||||||
models_rollouts_num: 0
|
models_rollouts_num: 0
|
||||||
random_color: false
|
random_color: false
|
||||||
random_model: false
|
random_model: false
|
||||||
random_orientation: false
|
random_orientation: false
|
||||||
random_pose: false
|
random_pose: false
|
||||||
random_position: false
|
random_position: false
|
||||||
random_spawn_position_segments: []
|
random_spawn_position_segments: []
|
||||||
random_spawn_position_update_workspace_centre: false
|
random_spawn_position_update_workspace_centre: false
|
||||||
random_spawn_volume: !tuple
|
random_spawn_volume: !tuple
|
||||||
- 0.5
|
- 0.5
|
||||||
- 0.5
|
- 0.5
|
||||||
- 0.5
|
- 0.5
|
||||||
relative_to: world
|
relative_to: world
|
||||||
static: false
|
static: false
|
||||||
texture: []
|
texture: []
|
||||||
type: 'model'
|
type: "model"
|
||||||
|
- color: null
|
||||||
|
name: peg
|
||||||
|
orientation: !tuple
|
||||||
|
- 1.0
|
||||||
|
- 0.0
|
||||||
|
- 0.0
|
||||||
|
- 0.0
|
||||||
|
position: !tuple
|
||||||
|
- 0.0
|
||||||
|
- 0.3
|
||||||
|
- 0.1
|
||||||
|
randomize:
|
||||||
|
count: 0
|
||||||
|
models_rollouts_num: 0
|
||||||
|
random_color: false
|
||||||
|
random_model: false
|
||||||
|
random_orientation: false
|
||||||
|
random_pose: false
|
||||||
|
random_position: false
|
||||||
|
random_spawn_position_segments: []
|
||||||
|
random_spawn_position_update_workspace_centre: false
|
||||||
|
random_spawn_volume: !tuple
|
||||||
|
- 0.5
|
||||||
|
- 0.5
|
||||||
|
- 0.5
|
||||||
|
relative_to: world
|
||||||
|
static: false
|
||||||
|
texture: []
|
||||||
|
type: "model"
|
||||||
physics_rollouts_num: 0
|
physics_rollouts_num: 0
|
||||||
plugins:
|
plugins:
|
||||||
fts_broadcaster: false
|
fts_broadcaster: false
|
||||||
|
@ -104,13 +133,13 @@ plugins:
|
||||||
robot:
|
robot:
|
||||||
gripper_joint_positions: 0.0
|
gripper_joint_positions: 0.0
|
||||||
joint_positions:
|
joint_positions:
|
||||||
- 0.0
|
- -1.57
|
||||||
- 0.0
|
- 0.5
|
||||||
- 0.0
|
- 3.14159
|
||||||
- 0.0
|
- 1.5
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 1.4
|
||||||
- 0.0
|
- 0.0
|
||||||
name: rbs_arm
|
name: rbs_arm
|
||||||
randomizer:
|
randomizer:
|
||||||
joint_positions: false
|
joint_positions: false
|
||||||
|
@ -120,33 +149,33 @@ robot:
|
||||||
joint_positions_std: 0.1
|
joint_positions_std: 0.1
|
||||||
pose: false
|
pose: false
|
||||||
spawn_volume: !tuple
|
spawn_volume: !tuple
|
||||||
- 1.0
|
- 1.0
|
||||||
- 1.0
|
- 1.0
|
||||||
- 0.0
|
- 0.0
|
||||||
spawn_position: !tuple
|
spawn_position: !tuple
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
spawn_quat_xyzw: !tuple
|
spawn_quat_xyzw: !tuple
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 0.0
|
- 0.0
|
||||||
- 1.0
|
- 1.0
|
||||||
urdf_string: ''
|
urdf_string: ""
|
||||||
with_gripper: true
|
with_gripper: true
|
||||||
terrain:
|
terrain:
|
||||||
model_rollouts_num: 1
|
model_rollouts_num: 1
|
||||||
name: ground
|
name: ground
|
||||||
size: !tuple
|
size: !tuple
|
||||||
- 1.5
|
- 1.5
|
||||||
- 1.5
|
- 1.5
|
||||||
spawn_position: !tuple
|
spawn_position: !tuple
|
||||||
- 0
|
- 0
|
||||||
- 0
|
- 0
|
||||||
- 0
|
- 0
|
||||||
spawn_quat_xyzw: !tuple
|
spawn_quat_xyzw: !tuple
|
||||||
- 0
|
- 0
|
||||||
- 0
|
- 0
|
||||||
- 0
|
- 0
|
||||||
- 1
|
- 1
|
||||||
type: flat
|
type: flat
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
|
from launch.launch_introspector import indent
|
||||||
import xacro
|
import xacro
|
||||||
from ament_index_python.packages import get_package_share_directory
|
from ament_index_python.packages import get_package_share_directory
|
||||||
from launch import LaunchDescription
|
from launch import LaunchDescription
|
||||||
|
@ -14,55 +15,115 @@ from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
||||||
from launch_ros.actions import Node
|
from launch_ros.actions import Node
|
||||||
from launch_ros.substitutions import FindPackageShare
|
from launch_ros.substitutions import FindPackageShare
|
||||||
|
|
||||||
|
from robot_builder.parser.urdf import URDF_parser
|
||||||
|
from robot_builder.external.ros2_control import ControllerManager
|
||||||
|
import yaml
|
||||||
|
|
||||||
|
|
||||||
def launch_setup(context, *args, **kwargs):
|
def launch_setup(context, *args, **kwargs):
|
||||||
# Initialize Arguments
|
# Initialize Arguments
|
||||||
robot_type = LaunchConfiguration("robot_type")
|
robot_type = LaunchConfiguration("robot_type")
|
||||||
# General arguments
|
# General arguments
|
||||||
with_gripper_condition = LaunchConfiguration("with_gripper")
|
with_gripper_condition = LaunchConfiguration("with_gripper")
|
||||||
cartesian_controllers = LaunchConfiguration("cartesian_controllers")
|
|
||||||
description_package = LaunchConfiguration("description_package")
|
description_package = LaunchConfiguration("description_package")
|
||||||
description_file = LaunchConfiguration("description_file")
|
description_file = LaunchConfiguration("description_file")
|
||||||
robot_name = LaunchConfiguration("robot_name")
|
use_moveit = LaunchConfiguration("use_moveit")
|
||||||
start_joint_controller = LaunchConfiguration("start_joint_controller")
|
|
||||||
initial_joint_controller = LaunchConfiguration("initial_joint_controller")
|
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
|
||||||
launch_moveit = LaunchConfiguration("launch_moveit")
|
|
||||||
launch_task_planner = LaunchConfiguration("launch_task_planner")
|
|
||||||
launch_perception = LaunchConfiguration("launch_perception")
|
|
||||||
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
||||||
moveit_config_file = LaunchConfiguration("moveit_config_file")
|
moveit_config_file = LaunchConfiguration("moveit_config_file")
|
||||||
use_sim_time = LaunchConfiguration("use_sim_time")
|
use_sim_time = LaunchConfiguration("use_sim_time")
|
||||||
sim_gazebo = LaunchConfiguration("sim_gazebo")
|
scene_config_file = LaunchConfiguration("scene_config_file").perform(context)
|
||||||
hardware = LaunchConfiguration("hardware")
|
|
||||||
env_manager = LaunchConfiguration("env_manager")
|
|
||||||
gazebo_gui = LaunchConfiguration("gazebo_gui")
|
|
||||||
gripper_name = LaunchConfiguration("gripper_name")
|
|
||||||
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
ee_link_name = LaunchConfiguration("ee_link_name").perform(context)
|
||||||
get_package_share_directory("rbs_arm"), "config", "rbs_arm0_controllers.yaml"
|
base_link_name = LaunchConfiguration("base_link_name").perform(context)
|
||||||
|
|
||||||
|
control_space = LaunchConfiguration("control_space").perform(context)
|
||||||
|
control_strategy = LaunchConfiguration("control_strategy").perform(context)
|
||||||
|
|
||||||
|
interactive = LaunchConfiguration("interactive").perform(context)
|
||||||
|
|
||||||
|
if not scene_config_file == "":
|
||||||
|
config_file = {"config_file": scene_config_file}
|
||||||
|
else:
|
||||||
|
config_file = {}
|
||||||
|
|
||||||
|
description_package_abs_path = get_package_share_directory(
|
||||||
|
description_package.perform(context)
|
||||||
|
)
|
||||||
|
|
||||||
|
simulation_controllers = os.path.join(
|
||||||
|
description_package_abs_path, "config", "controllers.yaml"
|
||||||
)
|
)
|
||||||
|
|
||||||
xacro_file = os.path.join(
|
xacro_file = os.path.join(
|
||||||
get_package_share_directory(description_package.perform(context)),
|
description_package_abs_path,
|
||||||
"urdf",
|
"urdf",
|
||||||
description_file.perform(context),
|
description_file.perform(context),
|
||||||
)
|
)
|
||||||
|
|
||||||
robot_description_doc = xacro.process_file(
|
xacro_config_file = f"{description_package_abs_path}/config/xacro_args.yaml"
|
||||||
xacro_file,
|
|
||||||
mappings={
|
|
||||||
"gripper_name": gripper_name.perform(context),
|
# TODO: hide this to another place
|
||||||
"hardware": hardware.perform(context),
|
# Load xacro_args
|
||||||
"simulation_controllers": initial_joint_controllers_file_path,
|
def param_constructor(loader, node, local_vars):
|
||||||
"namespace": "",
|
value = loader.construct_scalar(node)
|
||||||
},
|
return LaunchConfiguration(value).perform(
|
||||||
)
|
local_vars.get("context", "Launch context if not defined")
|
||||||
|
)
|
||||||
|
|
||||||
|
def variable_constructor(loader, node, local_vars):
|
||||||
|
value = loader.construct_scalar(node)
|
||||||
|
return local_vars.get(value, f"Variable '{value}' not found")
|
||||||
|
|
||||||
|
def load_xacro_args(yaml_file, local_vars):
|
||||||
|
# Get valut from ros2 argument
|
||||||
|
yaml.add_constructor(
|
||||||
|
"!param", lambda loader, node: param_constructor(loader, node, local_vars)
|
||||||
|
)
|
||||||
|
|
||||||
|
# Get value from local variable in this code
|
||||||
|
# The local variable should be initialized before the loader was called
|
||||||
|
yaml.add_constructor(
|
||||||
|
"!variable",
|
||||||
|
lambda loader, node: variable_constructor(loader, node, local_vars),
|
||||||
|
)
|
||||||
|
|
||||||
|
with open(yaml_file, "r") as file:
|
||||||
|
return yaml.load(file, Loader=yaml.FullLoader)
|
||||||
|
|
||||||
|
mappings_data = load_xacro_args(xacro_config_file, locals())
|
||||||
|
|
||||||
|
robot_description_doc = xacro.process_file(xacro_file, mappings=mappings_data)
|
||||||
|
|
||||||
|
robot_description_semantic_content = ""
|
||||||
|
|
||||||
|
if use_moveit.perform(context) == "true":
|
||||||
|
srdf_config_file = f"{description_package_abs_path}/config/srdf_xacro_args.yaml"
|
||||||
|
srdf_file = os.path.join(
|
||||||
|
get_package_share_directory(moveit_config_package.perform(context)),
|
||||||
|
"srdf",
|
||||||
|
moveit_config_file.perform(context),
|
||||||
|
)
|
||||||
|
srdf_mappings = load_xacro_args(srdf_config_file, locals())
|
||||||
|
robot_description_semantic_content = xacro.process_file(srdf_file, mappings=srdf_mappings)
|
||||||
|
robot_description_semantic_content = robot_description_semantic_content.toprettyxml(indent=" ")
|
||||||
|
control_space = "joint"
|
||||||
|
control_strategy = "position"
|
||||||
|
interactive = "false"
|
||||||
|
|
||||||
|
|
||||||
robot_description_content = robot_description_doc.toprettyxml(indent=" ")
|
robot_description_content = robot_description_doc.toprettyxml(indent=" ")
|
||||||
robot_description = {"robot_description": robot_description_content}
|
robot_description = {"robot_description": robot_description_content}
|
||||||
|
|
||||||
single_robot_setup = IncludeLaunchDescription(
|
# Parse robot and configure controller's file for ControllerManager
|
||||||
|
robot = URDF_parser.load_string(
|
||||||
|
robot_description_content, ee_link_name=ee_link_name
|
||||||
|
)
|
||||||
|
ControllerManager.save_to_yaml(
|
||||||
|
robot, description_package_abs_path, "controllers.yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
rbs_robot_setup = IncludeLaunchDescription(
|
||||||
PythonLaunchDescriptionSource(
|
PythonLaunchDescriptionSource(
|
||||||
[
|
[
|
||||||
PathJoinSubstitution(
|
PathJoinSubstitution(
|
||||||
|
@ -71,37 +132,31 @@ def launch_setup(context, *args, **kwargs):
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
launch_arguments={
|
launch_arguments={
|
||||||
"env_manager": env_manager,
|
|
||||||
"with_gripper": with_gripper_condition,
|
"with_gripper": with_gripper_condition,
|
||||||
"gripper_name": gripper_name,
|
"controllers_file": simulation_controllers,
|
||||||
"controllers_file": initial_joint_controllers_file_path,
|
|
||||||
"robot_type": robot_type,
|
"robot_type": robot_type,
|
||||||
# "controllers_file": controller_paramfile,
|
|
||||||
"cartesian_controllers": cartesian_controllers,
|
|
||||||
"description_package": description_package,
|
"description_package": description_package,
|
||||||
"description_file": description_file,
|
"description_file": description_file,
|
||||||
"robot_name": robot_type,
|
"robot_name": robot_type,
|
||||||
"start_joint_controller": start_joint_controller,
|
"use_moveit": use_moveit,
|
||||||
"initial_joint_controller": initial_joint_controller,
|
|
||||||
"launch_simulation": launch_simulation,
|
|
||||||
"launch_moveit": launch_moveit,
|
|
||||||
"launch_task_planner": launch_task_planner,
|
|
||||||
"launch_perception": launch_perception,
|
|
||||||
"moveit_config_package": moveit_config_package,
|
"moveit_config_package": moveit_config_package,
|
||||||
"moveit_config_file": moveit_config_file,
|
"moveit_config_file": moveit_config_file,
|
||||||
"use_sim_time": use_sim_time,
|
"use_sim_time": use_sim_time,
|
||||||
"sim_gazebo": sim_gazebo,
|
"use_controllers": "true",
|
||||||
"hardware": hardware,
|
|
||||||
"launch_controllers": "true",
|
|
||||||
"gazebo_gui": gazebo_gui,
|
|
||||||
"robot_description": robot_description_content,
|
"robot_description": robot_description_content,
|
||||||
|
"robot_description_semantic": robot_description_semantic_content,
|
||||||
|
"base_link_name": base_link_name,
|
||||||
|
"ee_link_name": ee_link_name,
|
||||||
|
"control_space": control_space,
|
||||||
|
"control_strategy": control_strategy,
|
||||||
|
"interactive_control": interactive,
|
||||||
}.items(),
|
}.items(),
|
||||||
)
|
)
|
||||||
|
|
||||||
rbs_runtime = Node(
|
rbs_runtime = Node(
|
||||||
package="rbs_runtime",
|
package="rbs_runtime",
|
||||||
executable="runtime",
|
executable="runtime",
|
||||||
parameters=[robot_description, {"use_sim_time": True}],
|
parameters=[robot_description, config_file, {"use_sim_time": True}],
|
||||||
)
|
)
|
||||||
|
|
||||||
clock_bridge = Node(
|
clock_bridge = Node(
|
||||||
|
@ -111,9 +166,13 @@ def launch_setup(context, *args, **kwargs):
|
||||||
output="screen",
|
output="screen",
|
||||||
)
|
)
|
||||||
|
|
||||||
delay_robot_control_stack = TimerAction(period=10.0, actions=[single_robot_setup])
|
delay_robot_control_stack = TimerAction(period=10.0, actions=[rbs_robot_setup])
|
||||||
|
|
||||||
nodes_to_start = [rbs_runtime, clock_bridge, delay_robot_control_stack]
|
nodes_to_start = [
|
||||||
|
rbs_runtime,
|
||||||
|
clock_bridge,
|
||||||
|
delay_robot_control_stack
|
||||||
|
]
|
||||||
return nodes_to_start
|
return nodes_to_start
|
||||||
|
|
||||||
|
|
||||||
|
@ -123,18 +182,20 @@ def generate_launch_description():
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"robot_type",
|
"robot_type",
|
||||||
description="Type of robot by name",
|
description="Type of robot by name",
|
||||||
choices=["rbs_arm", "ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e"],
|
choices=[
|
||||||
|
"rbs_arm",
|
||||||
|
"ar4",
|
||||||
|
"ur3",
|
||||||
|
"ur3e",
|
||||||
|
"ur5",
|
||||||
|
"ur5e",
|
||||||
|
"ur10",
|
||||||
|
"ur10e",
|
||||||
|
"ur16e",
|
||||||
|
],
|
||||||
default_value="rbs_arm",
|
default_value="rbs_arm",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# General arguments
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"controllers_file",
|
|
||||||
default_value="rbs_arm0_controllers.yaml",
|
|
||||||
description="YAML file with the controllers configuration.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"description_package",
|
"description_package",
|
||||||
|
@ -157,20 +218,6 @@ def generate_launch_description():
|
||||||
description="Name for robot, used to apply namespace for specific robot in multirobot setup",
|
description="Name for robot, used to apply namespace for specific robot in multirobot setup",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"start_joint_controller",
|
|
||||||
default_value="false",
|
|
||||||
description="Enable headless mode for robot control",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"initial_joint_controller",
|
|
||||||
default_value="joint_trajectory_controller",
|
|
||||||
description="Robot controller to start.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"moveit_config_package",
|
"moveit_config_package",
|
||||||
|
@ -194,14 +241,6 @@ def generate_launch_description():
|
||||||
This is needed for the trajectory planing in simulation.",
|
This is needed for the trajectory planing in simulation.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"gripper_name",
|
|
||||||
default_value="rbs_gripper",
|
|
||||||
choices=["rbs_gripper", ""],
|
|
||||||
description="choose gripper by name (leave empty if hasn't)",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"with_gripper", default_value="true", description="With gripper or not?"
|
"with_gripper", default_value="true", description="With gripper or not?"
|
||||||
|
@ -209,25 +248,7 @@ def generate_launch_description():
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"sim_gazebo", default_value="true", description="Gazebo Simulation"
|
"use_moveit", default_value="false", description="Launch moveit?"
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"env_manager", default_value="true", description="Launch env_manager?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_sim",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch simulator (Gazebo)?\
|
|
||||||
Most general arg",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_moveit", default_value="false", description="Launch moveit?"
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
|
@ -237,39 +258,55 @@ def generate_launch_description():
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"launch_task_planner",
|
"use_controllers",
|
||||||
default_value="false",
|
|
||||||
description="Launch task_planner?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"cartesian_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Load cartesian\
|
|
||||||
controllers?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"hardware",
|
|
||||||
choices=["gazebo", "mock"],
|
|
||||||
default_value="gazebo",
|
|
||||||
description="Choose your harware_interface",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_controllers",
|
|
||||||
default_value="true",
|
default_value="true",
|
||||||
description="Launch controllers?",
|
description="Launch controllers?",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"gazebo_gui", default_value="true", description="Launch gazebo with gui?"
|
"scene_config_file",
|
||||||
|
default_value="",
|
||||||
|
description="Path to a scene configuration file",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"ee_link_name",
|
||||||
|
default_value="",
|
||||||
|
description="End effector name of robot arm",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"base_link_name",
|
||||||
|
default_value="",
|
||||||
|
description="Base link name if robot arm",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"control_space",
|
||||||
|
default_value="task",
|
||||||
|
choices=["task", "joint"],
|
||||||
|
description="Specify the control space for the robot (e.g., task space).",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"control_strategy",
|
||||||
|
default_value="position",
|
||||||
|
choices=["position", "velocity", "effort"],
|
||||||
|
description="Specify the control strategy (e.g., position control).",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"interactive",
|
||||||
|
default_value="true",
|
||||||
|
description="Wheter to run the motion_control_handle controller",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
return LaunchDescription(
|
return LaunchDescription(
|
||||||
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
||||||
|
|
|
@ -4,6 +4,24 @@ import yaml
|
||||||
from dacite import from_dict
|
from dacite import from_dict
|
||||||
from env_manager.models.configs import SceneData
|
from env_manager.models.configs import SceneData
|
||||||
|
|
||||||
|
from typing import Dict, Any
|
||||||
|
from env_manager.models.configs import (
|
||||||
|
BoxObjectData, CylinderObjectData, MeshData, ModelData, ObjectData
|
||||||
|
)
|
||||||
|
|
||||||
|
def object_factory(obj_data: Dict[str, Any]) -> ObjectData:
|
||||||
|
obj_type = obj_data.get('type', '')
|
||||||
|
|
||||||
|
if obj_type == 'box':
|
||||||
|
return BoxObjectData(**obj_data)
|
||||||
|
elif obj_type == 'cylinder':
|
||||||
|
return CylinderObjectData(**obj_data)
|
||||||
|
elif obj_type == 'mesh':
|
||||||
|
return MeshData(**obj_data)
|
||||||
|
elif obj_type == 'model':
|
||||||
|
return ModelData(**obj_data)
|
||||||
|
else:
|
||||||
|
return ObjectData(**obj_data)
|
||||||
|
|
||||||
def scene_config_loader(file: str | Path) -> SceneData:
|
def scene_config_loader(file: str | Path) -> SceneData:
|
||||||
def tuple_constructor(loader, node):
|
def tuple_constructor(loader, node):
|
||||||
|
@ -15,4 +33,8 @@ def scene_config_loader(file: str | Path) -> SceneData:
|
||||||
|
|
||||||
scene_data = from_dict(data_class=SceneData, data=scene_cfg)
|
scene_data = from_dict(data_class=SceneData, data=scene_cfg)
|
||||||
|
|
||||||
|
scene_data.objects = [object_factory(obj) for obj in scene_cfg.get('objects', [])]
|
||||||
|
|
||||||
|
print(scene_data)
|
||||||
|
|
||||||
return scene_data
|
return scene_data
|
||||||
|
|
87
rbs_bringup/launch/control.launch.py
Normal file
87
rbs_bringup/launch/control.launch.py
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
from launch_ros.actions import Node
|
||||||
|
from launch import LaunchDescription
|
||||||
|
from launch.actions import DeclareLaunchArgument, OpaqueFunction
|
||||||
|
|
||||||
|
# from launch.conditions import IfCondition, UnlessCondition
|
||||||
|
from launch.substitutions import LaunchConfiguration
|
||||||
|
|
||||||
|
|
||||||
|
def create_spawner(controller_name, namespace, condition=None, inactive=False):
|
||||||
|
args = [controller_name, "-c", f"{namespace}/controller_manager"]
|
||||||
|
if inactive:
|
||||||
|
args.append("--inactive")
|
||||||
|
return Node(
|
||||||
|
package="controller_manager",
|
||||||
|
executable="spawner",
|
||||||
|
namespace=namespace,
|
||||||
|
arguments=args,
|
||||||
|
condition=condition,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def launch_setup(context, *args, **kwargs):
|
||||||
|
namespace = LaunchConfiguration("namespace").perform(context)
|
||||||
|
control_strategy = LaunchConfiguration("control_strategy").perform(context)
|
||||||
|
control_space = LaunchConfiguration("control_space").perform(context)
|
||||||
|
has_gripper = LaunchConfiguration("has_gripper").perform(context)
|
||||||
|
interactive_control = LaunchConfiguration("interactive_control").perform(context)
|
||||||
|
|
||||||
|
controllers_config = {
|
||||||
|
"joint_state_broadcaster": True,
|
||||||
|
"gripper_controller": has_gripper == "true",
|
||||||
|
"joint_trajectory_controller": control_strategy == "position"
|
||||||
|
and control_space == "joint",
|
||||||
|
"cartesian_motion_controller": control_strategy == "position"
|
||||||
|
and control_space == "task",
|
||||||
|
"cartesian_force_controller": control_strategy == "effort"
|
||||||
|
and control_space == "task",
|
||||||
|
"joint_effort_controller": control_strategy == "effort"
|
||||||
|
and control_space == "joint",
|
||||||
|
"force_torque_sensor_broadcaster": control_strategy == "effort"
|
||||||
|
and control_space == "task",
|
||||||
|
"motion_control_handle": interactive_control == "true"
|
||||||
|
and control_space == "task"
|
||||||
|
and control_strategy == "position",
|
||||||
|
}
|
||||||
|
|
||||||
|
nodes_to_start = []
|
||||||
|
for controller_name, should_start in controllers_config.items():
|
||||||
|
if should_start:
|
||||||
|
nodes_to_start.append(create_spawner(controller_name, namespace))
|
||||||
|
|
||||||
|
return nodes_to_start
|
||||||
|
|
||||||
|
|
||||||
|
def generate_launch_description():
|
||||||
|
declared_arguments = [
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"namespace", default_value="", description="A robot's namespace"
|
||||||
|
),
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"control_space",
|
||||||
|
default_value="task",
|
||||||
|
choices=["task", "joint"],
|
||||||
|
description="Control type: 'task' for Cartesian, 'joint' for joint space control.",
|
||||||
|
),
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"control_strategy",
|
||||||
|
default_value="position",
|
||||||
|
choices=["position", "velocity", "effort"],
|
||||||
|
description="Control strategy: 'position', 'velocity', or 'effort'.",
|
||||||
|
),
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"has_gripper",
|
||||||
|
default_value="true",
|
||||||
|
description="Whether to activate the gripper_controller.",
|
||||||
|
),
|
||||||
|
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"interactive_control",
|
||||||
|
default_value="true",
|
||||||
|
description="Wheter to run the motion_control_handle controller",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
return LaunchDescription(
|
||||||
|
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
||||||
|
)
|
|
@ -1,254 +0,0 @@
|
||||||
from launch import LaunchDescription
|
|
||||||
from launch.actions import (
|
|
||||||
DeclareLaunchArgument,
|
|
||||||
IncludeLaunchDescription,
|
|
||||||
OpaqueFunction
|
|
||||||
)
|
|
||||||
from launch.conditions import IfCondition
|
|
||||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
|
||||||
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
|
||||||
from launch_ros.substitutions import FindPackageShare
|
|
||||||
from launch_ros.actions import Node
|
|
||||||
import os
|
|
||||||
from ament_index_python.packages import get_package_share_directory
|
|
||||||
from nav2_common.launch import RewrittenYaml
|
|
||||||
|
|
||||||
def launch_setup(context, *args, **kwargs):
|
|
||||||
# Initialize Arguments
|
|
||||||
robot_type = LaunchConfiguration("robot_type")
|
|
||||||
# General arguments
|
|
||||||
with_gripper_condition = LaunchConfiguration("with_gripper")
|
|
||||||
controllers_file = LaunchConfiguration("controllers_file")
|
|
||||||
cartesian_controllers = LaunchConfiguration("cartesian_controllers")
|
|
||||||
description_package = LaunchConfiguration("description_package")
|
|
||||||
description_file = LaunchConfiguration("description_file")
|
|
||||||
robot_name = LaunchConfiguration("robot_name")
|
|
||||||
start_joint_controller = LaunchConfiguration("start_joint_controller")
|
|
||||||
initial_joint_controller = LaunchConfiguration("initial_joint_controller")
|
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
|
||||||
launch_moveit = LaunchConfiguration("launch_moveit")
|
|
||||||
launch_task_planner = LaunchConfiguration("launch_task_planner")
|
|
||||||
launch_perception = LaunchConfiguration("launch_perception")
|
|
||||||
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
|
||||||
moveit_config_file = LaunchConfiguration("moveit_config_file")
|
|
||||||
use_sim_time = LaunchConfiguration("use_sim_time")
|
|
||||||
sim_gazebo = LaunchConfiguration("sim_gazebo")
|
|
||||||
hardware = LaunchConfiguration("hardware")
|
|
||||||
env_manager = LaunchConfiguration("env_manager")
|
|
||||||
launch_controllers = LaunchConfiguration("launch_controllers")
|
|
||||||
gazebo_gui = LaunchConfiguration("gazebo_gui")
|
|
||||||
gripper_name = LaunchConfiguration("gripper_name")
|
|
||||||
|
|
||||||
|
|
||||||
sim_gazebo = LaunchConfiguration("sim_gazebo")
|
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
|
||||||
|
|
||||||
configured_params = RewrittenYaml(
|
|
||||||
source_file=os.path.join(
|
|
||||||
get_package_share_directory(
|
|
||||||
description_package.perform(context)),
|
|
||||||
"config",
|
|
||||||
controllers_file.perform(context)),
|
|
||||||
root_key=robot_name.perform(context),
|
|
||||||
param_rewrites={},
|
|
||||||
convert_types=True,
|
|
||||||
)
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
|
||||||
get_package_share_directory('rbs_arm'), 'config', 'rbs_arm0_controllers.yaml'
|
|
||||||
)
|
|
||||||
controller_paramfile = configured_params.perform(context)
|
|
||||||
namespace = "/" + robot_name.perform(context)
|
|
||||||
|
|
||||||
# spawner = Node(
|
|
||||||
# package="gz_enviroment_python",
|
|
||||||
# executable="spawner.py",
|
|
||||||
# namespace=namespace
|
|
||||||
# )
|
|
||||||
|
|
||||||
single_robot_setup = IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource([
|
|
||||||
PathJoinSubstitution([
|
|
||||||
FindPackageShare('rbs_bringup'),
|
|
||||||
"launch",
|
|
||||||
"rbs_robot.launch.py"
|
|
||||||
])
|
|
||||||
]),
|
|
||||||
launch_arguments={
|
|
||||||
"env_manager": env_manager,
|
|
||||||
"with_gripper": with_gripper_condition,
|
|
||||||
"gripper_name": gripper_name,
|
|
||||||
"controllers_file": controllers_file,
|
|
||||||
"robot_type": robot_type,
|
|
||||||
"controllers_file": initial_joint_controllers_file_path,
|
|
||||||
"cartesian_controllers": cartesian_controllers,
|
|
||||||
"description_package": description_package,
|
|
||||||
"description_file": description_file,
|
|
||||||
"robot_name": robot_name,
|
|
||||||
"start_joint_controller": start_joint_controller,
|
|
||||||
"initial_joint_controller": initial_joint_controller,
|
|
||||||
"launch_simulation": launch_simulation,
|
|
||||||
"launch_moveit": launch_moveit,
|
|
||||||
"launch_task_planner": launch_task_planner,
|
|
||||||
"launch_perception": launch_perception,
|
|
||||||
"moveit_config_package": moveit_config_package,
|
|
||||||
"moveit_config_file": moveit_config_file,
|
|
||||||
"use_sim_time": use_sim_time,
|
|
||||||
"sim_gazebo": sim_gazebo,
|
|
||||||
"hardware": hardware,
|
|
||||||
"launch_controllers": "true",
|
|
||||||
"gazebo_gui": gazebo_gui,
|
|
||||||
}.items()
|
|
||||||
)
|
|
||||||
|
|
||||||
nodes_to_start = [
|
|
||||||
# spawner,
|
|
||||||
single_robot_setup
|
|
||||||
]
|
|
||||||
return nodes_to_start
|
|
||||||
|
|
||||||
|
|
||||||
def generate_launch_description():
|
|
||||||
declared_arguments = []
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"robot_type",
|
|
||||||
description="Type of robot by name",
|
|
||||||
choices=["rbs_arm","ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e"],
|
|
||||||
default_value="rbs_arm",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# General arguments
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"controllers_file",
|
|
||||||
default_value="rbs_arm_controllers_gazebosim.yaml",
|
|
||||||
description="YAML file with the controllers configuration.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"description_package",
|
|
||||||
default_value="rbs_arm",
|
|
||||||
description="Description package with robot URDF/XACRO files. Usually the argument \
|
|
||||||
is not set, it enables use of a custom description.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"description_file",
|
|
||||||
default_value="rbs_arm_modular.xacro",
|
|
||||||
description="URDF/XACRO description file with the robot.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"robot_name",
|
|
||||||
default_value="arm0",
|
|
||||||
description="Name for robot, used to apply namespace for specific robot in multirobot setup",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"start_joint_controller",
|
|
||||||
default_value="false",
|
|
||||||
description="Enable headless mode for robot control",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"initial_joint_controller",
|
|
||||||
default_value="joint_trajectory_controller",
|
|
||||||
description="Robot controller to start.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"moveit_config_package",
|
|
||||||
default_value="rbs_arm",
|
|
||||||
description="MoveIt config package with robot SRDF/XACRO files. Usually the argument \
|
|
||||||
is not set, it enables use of a custom moveit config.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"moveit_config_file",
|
|
||||||
default_value="rbs_arm.srdf.xacro",
|
|
||||||
description="MoveIt SRDF/XACRO description file with the robot.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"use_sim_time",
|
|
||||||
default_value="true",
|
|
||||||
description="Make MoveIt to use simulation time.\
|
|
||||||
This is needed for the trajectory planing in simulation.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"gripper_name",
|
|
||||||
default_value="rbs_gripper",
|
|
||||||
choices=["rbs_gripper", ""],
|
|
||||||
description="choose gripper by name (leave empty if hasn't)",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("with_gripper",
|
|
||||||
default_value="true",
|
|
||||||
description="With gripper or not?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("sim_gazebo",
|
|
||||||
default_value="true",
|
|
||||||
description="Gazebo Simulation")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("env_manager",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch env_manager?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_sim",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch simulator (Gazebo)?\
|
|
||||||
Most general arg")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_moveit",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch moveit?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_perception",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch perception?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_task_planner",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch task_planner?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("cartesian_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Load cartesian\
|
|
||||||
controllers?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("hardware",
|
|
||||||
choices=["gazebo", "mock"],
|
|
||||||
default_value="gazebo",
|
|
||||||
description="Choose your harware_interface")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch controllers?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("gazebo_gui",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch gazebo with gui?")
|
|
||||||
)
|
|
||||||
|
|
||||||
return LaunchDescription(declared_arguments + [OpaqueFunction(function=launch_setup)])
|
|
|
@ -1,292 +0,0 @@
|
||||||
from launch import LaunchDescription
|
|
||||||
from launch.actions import (
|
|
||||||
DeclareLaunchArgument,
|
|
||||||
IncludeLaunchDescription,
|
|
||||||
OpaqueFunction,
|
|
||||||
)
|
|
||||||
from launch.conditions import IfCondition
|
|
||||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
|
||||||
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
|
||||||
from launch_ros.substitutions import FindPackageShare
|
|
||||||
from launch_ros.actions import Node
|
|
||||||
from nav2_common.launch import RewrittenYaml
|
|
||||||
import os
|
|
||||||
from ament_index_python import get_package_share_directory
|
|
||||||
from rbs_launch_utils.merged_yaml import MergedYaml
|
|
||||||
from rbs_launch_utils.launch_common import load_yaml
|
|
||||||
import yaml
|
|
||||||
|
|
||||||
def launch_setup(context, *args, **kwargs):
|
|
||||||
# Initialize Arguments
|
|
||||||
robot_type = LaunchConfiguration("robot_type")
|
|
||||||
# General arguments
|
|
||||||
with_gripper_condition = LaunchConfiguration("with_gripper")
|
|
||||||
controllers_file = LaunchConfiguration("controllers_file")
|
|
||||||
cartesian_controllers = LaunchConfiguration("cartesian_controllers")
|
|
||||||
description_package = LaunchConfiguration("description_package")
|
|
||||||
description_file = LaunchConfiguration("description_file")
|
|
||||||
robot_name = LaunchConfiguration("robot_name")
|
|
||||||
start_joint_controller = LaunchConfiguration("start_joint_controller")
|
|
||||||
initial_joint_controller = LaunchConfiguration("initial_joint_controller")
|
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
|
||||||
launch_moveit = LaunchConfiguration("launch_moveit")
|
|
||||||
launch_task_planner = LaunchConfiguration("launch_task_planner")
|
|
||||||
launch_perception = LaunchConfiguration("launch_perception")
|
|
||||||
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
|
||||||
moveit_config_file = LaunchConfiguration("moveit_config_file")
|
|
||||||
use_sim_time = LaunchConfiguration("use_sim_time")
|
|
||||||
sim_gazebo = LaunchConfiguration("sim_gazebo")
|
|
||||||
hardware = LaunchConfiguration("hardware")
|
|
||||||
env_manager = LaunchConfiguration("env_manager")
|
|
||||||
launch_controllers = LaunchConfiguration("launch_controllers")
|
|
||||||
gazebo_gui = LaunchConfiguration("gazebo_gui")
|
|
||||||
gripper_name = LaunchConfiguration("gripper_name")
|
|
||||||
robots_config_file = LaunchConfiguration("robots_config_file")
|
|
||||||
gazebo_world_filename = LaunchConfiguration("gazebo_world_filename")
|
|
||||||
|
|
||||||
ld = []
|
|
||||||
ld.append(IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource([
|
|
||||||
PathJoinSubstitution([
|
|
||||||
FindPackageShare('rbs_simulation'),
|
|
||||||
'launch',
|
|
||||||
'simulation_gazebo.launch.py'
|
|
||||||
])
|
|
||||||
]),
|
|
||||||
launch_arguments={
|
|
||||||
'sim_gazebo': sim_gazebo,
|
|
||||||
'debugger': "false",
|
|
||||||
'launch_env_manager': "false",
|
|
||||||
"gazebo_world_filename": gazebo_world_filename
|
|
||||||
}.items(),
|
|
||||||
condition=IfCondition(launch_simulation)
|
|
||||||
))
|
|
||||||
scene_file = robots_config_file.perform(context)
|
|
||||||
robots = load_yaml("rbs_bringup", "config/" + scene_file)
|
|
||||||
|
|
||||||
description_package = description_package.perform(context)
|
|
||||||
controllers_file = controllers_file.perform(context)
|
|
||||||
config = MergedYaml(context,
|
|
||||||
os.path.join(get_package_share_directory(description_package), "config", controllers_file),
|
|
||||||
root_keys=[i["name"] for i in robots["scene_config"]],
|
|
||||||
param_rewrites={},
|
|
||||||
convert_types=False,
|
|
||||||
).merge_yamls()
|
|
||||||
for robot in robots["scene_config"]:
|
|
||||||
namespace: str = "/" + robot["name"]
|
|
||||||
ld.append(IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource([
|
|
||||||
PathJoinSubstitution([
|
|
||||||
FindPackageShare('rbs_bringup'),
|
|
||||||
"launch",
|
|
||||||
"rbs_robot.launch.py"
|
|
||||||
])
|
|
||||||
]),
|
|
||||||
launch_arguments={
|
|
||||||
"env_manager": env_manager,
|
|
||||||
"with_gripper": with_gripper_condition,
|
|
||||||
"gripper_name": gripper_name,
|
|
||||||
"controllers_file": controllers_file,
|
|
||||||
"robot_type": robot["type"],
|
|
||||||
"controllers_file": config,
|
|
||||||
"cartesian_controllers": cartesian_controllers,
|
|
||||||
"description_package": description_package,
|
|
||||||
"description_file": description_file,
|
|
||||||
"robot_name": robot["name"],
|
|
||||||
"start_joint_controller": start_joint_controller,
|
|
||||||
"initial_joint_controller": initial_joint_controller,
|
|
||||||
"launch_simulation": launch_simulation,
|
|
||||||
"launch_moveit": launch_moveit,
|
|
||||||
"launch_task_planner": launch_task_planner,
|
|
||||||
"launch_perception": launch_perception,
|
|
||||||
"moveit_config_package": moveit_config_package,
|
|
||||||
"moveit_config_file": moveit_config_file,
|
|
||||||
"use_sim_time": use_sim_time,
|
|
||||||
"sim_gazebo": sim_gazebo,
|
|
||||||
"hardware": hardware,
|
|
||||||
"launch_controllers": launch_controllers,
|
|
||||||
"gazebo_gui": gazebo_gui,
|
|
||||||
"namespace": namespace,
|
|
||||||
"x": str(robot["pose"]["position"]["x"]),
|
|
||||||
"y": str(robot["pose"]["position"]["y"]),
|
|
||||||
"z": str(robot["pose"]["position"]["z"]),
|
|
||||||
"roll": str(robot["pose"]["orientation"]["x"]),
|
|
||||||
"pitch": str(robot["pose"]["orientation"]["y"]),
|
|
||||||
"yaw": str(robot["pose"]["orientation"]["z"]),
|
|
||||||
}.items()
|
|
||||||
))
|
|
||||||
|
|
||||||
gz_spawner = Node(
|
|
||||||
package='ros_gz_sim',
|
|
||||||
executable='create',
|
|
||||||
arguments=[
|
|
||||||
'-name', robot_name,
|
|
||||||
# '-x', str(robot["pose"]["position"]["x"]),
|
|
||||||
# '-y', str(robot["pose"]["position"]["y"]),
|
|
||||||
# '-z', str(robot["pose"]["position"]["z"]),
|
|
||||||
# '-R', str(robot["pose"]["orientation"]["x"]),
|
|
||||||
# '-P', str(robot["pose"]["orientation"]["y"]),
|
|
||||||
# '-Y', str(robot["pose"]["orientation"]["z"]),
|
|
||||||
'-topic', namespace + '/robot_description'],
|
|
||||||
output='screen',
|
|
||||||
condition=IfCondition(sim_gazebo))
|
|
||||||
ld.append(gz_spawner)
|
|
||||||
|
|
||||||
return ld
|
|
||||||
|
|
||||||
|
|
||||||
def generate_launch_description():
|
|
||||||
declared_arguments = []
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"robot_type",
|
|
||||||
description="Type of robot by name",
|
|
||||||
choices=["rbs_arm","ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e"],
|
|
||||||
default_value="rbs_arm",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# General arguments
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"controllers_file",
|
|
||||||
default_value="rbs_arm_controllers_gazebosim.yaml",
|
|
||||||
description="YAML file with the controllers configuration.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"description_package",
|
|
||||||
default_value="rbs_arm",
|
|
||||||
description="Description package with robot URDF/XACRO files. Usually the argument \
|
|
||||||
is not set, it enables use of a custom description.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"description_file",
|
|
||||||
default_value="rbs_arm_modular.xacro",
|
|
||||||
description="URDF/XACRO description file with the robot.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"robot_name",
|
|
||||||
default_value="arm0",
|
|
||||||
description="Name for robot, used to apply namespace for specific robot in multirobot setup",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"start_joint_controller",
|
|
||||||
default_value="false",
|
|
||||||
description="Enable headless mode for robot control",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"initial_joint_controller",
|
|
||||||
default_value="joint_trajectory_controller",
|
|
||||||
description="Robot controller to start.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"moveit_config_package",
|
|
||||||
default_value="rbs_arm",
|
|
||||||
description="MoveIt config package with robot SRDF/XACRO files. Usually the argument \
|
|
||||||
is not set, it enables use of a custom moveit config.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"moveit_config_file",
|
|
||||||
default_value="rbs_arm.srdf.xacro",
|
|
||||||
description="MoveIt SRDF/XACRO description file with the robot.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"use_sim_time",
|
|
||||||
default_value="true",
|
|
||||||
description="Make MoveIt to use simulation time.\
|
|
||||||
This is needed for the trajectory planing in simulation.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"gripper_name",
|
|
||||||
default_value="rbs_gripper",
|
|
||||||
choices=["rbs_gripper", ""],
|
|
||||||
description="choose gripper by name (leave empty if hasn't)",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("with_gripper",
|
|
||||||
default_value="true",
|
|
||||||
description="With gripper or not?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("sim_gazebo",
|
|
||||||
default_value="true",
|
|
||||||
description="Gazebo Simulation")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("env_manager",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch env_manager?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_sim",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch simulator (Gazebo)?\
|
|
||||||
Most general arg")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_moveit",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch moveit?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_perception",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch perception?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_task_planner",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch task_planner?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("cartesian_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Load cartesian\
|
|
||||||
controllers?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("hardware",
|
|
||||||
choices=["gazebo", "mock"],
|
|
||||||
default_value="gazebo",
|
|
||||||
description="Choose your harware_interface")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("launch_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch controllers?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("gazebo_gui",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch gazebo with gui?")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("gazebo_world_filename",
|
|
||||||
default_value="asm2.sdf",
|
|
||||||
description="Filename of Gazebo world file to launch")
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument("robots_config_file",
|
|
||||||
default_value="roboclone.yaml",
|
|
||||||
description="Filename for config file with robots in scene")
|
|
||||||
)
|
|
||||||
|
|
||||||
return LaunchDescription(declared_arguments + [OpaqueFunction(function=launch_setup)])
|
|
53
rbs_bringup/launch/rbs_bringup.launch.py
Normal file
53
rbs_bringup/launch/rbs_bringup.launch.py
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
from launch import LaunchDescription
|
||||||
|
from launch.actions import (
|
||||||
|
IncludeLaunchDescription,
|
||||||
|
OpaqueFunction,
|
||||||
|
)
|
||||||
|
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
||||||
|
from launch.substitutions import (
|
||||||
|
PathJoinSubstitution,
|
||||||
|
)
|
||||||
|
from launch_ros.substitutions import FindPackageShare
|
||||||
|
|
||||||
|
|
||||||
|
def launch_setup(context, *args, **kwargs):
|
||||||
|
main_script = IncludeLaunchDescription(
|
||||||
|
PythonLaunchDescriptionSource(
|
||||||
|
[
|
||||||
|
PathJoinSubstitution(
|
||||||
|
[FindPackageShare("rbs_runtime"), "launch", "runtime.launch.py"]
|
||||||
|
)
|
||||||
|
]
|
||||||
|
),
|
||||||
|
launch_arguments={
|
||||||
|
"with_gripper": "true",
|
||||||
|
"robot_type": "rbs_arm",
|
||||||
|
"description_package": "rbs_arm",
|
||||||
|
"description_file": "rbs_arm_modular.xacro",
|
||||||
|
"robot_name": "rbs_arm",
|
||||||
|
"use_moveit": "true",
|
||||||
|
"moveit_config_package": "rbs_arm",
|
||||||
|
"moveit_config_file": "rbs_arm.srdf.xacro",
|
||||||
|
"use_sim_time": "true",
|
||||||
|
"use_controllers": "true",
|
||||||
|
"scene_config_file": "",
|
||||||
|
"base_link_name": "base_link",
|
||||||
|
"ee_link_name": "gripper_grasp_point",
|
||||||
|
"control_space": "task",
|
||||||
|
"control_strategy": "position",
|
||||||
|
"interactive": "false"
|
||||||
|
}.items(),
|
||||||
|
)
|
||||||
|
|
||||||
|
nodes_to_start = [
|
||||||
|
main_script,
|
||||||
|
]
|
||||||
|
return nodes_to_start
|
||||||
|
|
||||||
|
|
||||||
|
def generate_launch_description():
|
||||||
|
declared_arguments = []
|
||||||
|
|
||||||
|
return LaunchDescription(
|
||||||
|
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
||||||
|
)
|
|
@ -21,33 +21,15 @@ from launch_ros.substitutions import FindPackageShare
|
||||||
|
|
||||||
|
|
||||||
def launch_setup(context, *args, **kwargs):
|
def launch_setup(context, *args, **kwargs):
|
||||||
# Initialize Arguments
|
|
||||||
robot_type = LaunchConfiguration("robot_type")
|
robot_type = LaunchConfiguration("robot_type")
|
||||||
# General arguments
|
|
||||||
launch_rviz = LaunchConfiguration("launch_rviz")
|
|
||||||
with_gripper_condition = LaunchConfiguration("with_gripper")
|
with_gripper_condition = LaunchConfiguration("with_gripper")
|
||||||
controllers_file = LaunchConfiguration("controllers_file")
|
|
||||||
cartesian_controllers = LaunchConfiguration("cartesian_controllers")
|
|
||||||
description_package = LaunchConfiguration("description_package")
|
description_package = LaunchConfiguration("description_package")
|
||||||
description_file = LaunchConfiguration("description_file")
|
description_file = LaunchConfiguration("description_file")
|
||||||
robot_name = LaunchConfiguration("robot_name")
|
robot_name = LaunchConfiguration("robot_name")
|
||||||
start_joint_controller = LaunchConfiguration("start_joint_controller")
|
use_moveit = LaunchConfiguration("use_moveit")
|
||||||
initial_joint_controller = LaunchConfiguration("initial_joint_controller")
|
|
||||||
launch_moveit = LaunchConfiguration("launch_moveit")
|
|
||||||
launch_task_planner = LaunchConfiguration("launch_task_planner")
|
|
||||||
launch_perception = LaunchConfiguration("launch_perception")
|
|
||||||
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
||||||
moveit_config_file = LaunchConfiguration("moveit_config_file")
|
|
||||||
use_sim_time = LaunchConfiguration("use_sim_time")
|
use_sim_time = LaunchConfiguration("use_sim_time")
|
||||||
hardware = LaunchConfiguration("hardware")
|
use_controllers = LaunchConfiguration("use_controllers")
|
||||||
launch_controllers = LaunchConfiguration("launch_controllers")
|
|
||||||
gripper_name = LaunchConfiguration("gripper_name")
|
|
||||||
x_pos = LaunchConfiguration("x")
|
|
||||||
y_pos = LaunchConfiguration("y")
|
|
||||||
z_pos = LaunchConfiguration("z")
|
|
||||||
roll = LaunchConfiguration("roll")
|
|
||||||
pitch = LaunchConfiguration("pitch")
|
|
||||||
yaw = LaunchConfiguration("yaw")
|
|
||||||
namespace = LaunchConfiguration("namespace")
|
namespace = LaunchConfiguration("namespace")
|
||||||
multi_robot = LaunchConfiguration("multi_robot")
|
multi_robot = LaunchConfiguration("multi_robot")
|
||||||
robot_name = robot_name.perform(context)
|
robot_name = robot_name.perform(context)
|
||||||
|
@ -55,83 +37,34 @@ def launch_setup(context, *args, **kwargs):
|
||||||
robot_type = robot_type.perform(context)
|
robot_type = robot_type.perform(context)
|
||||||
description_package = description_package.perform(context)
|
description_package = description_package.perform(context)
|
||||||
description_file = description_file.perform(context)
|
description_file = description_file.perform(context)
|
||||||
controllers_file = controllers_file.perform(context)
|
|
||||||
multi_robot = multi_robot.perform(context)
|
multi_robot = multi_robot.perform(context)
|
||||||
robot_description = LaunchConfiguration("robot_description")
|
robot_description_content = LaunchConfiguration("robot_description")
|
||||||
|
robot_description_semantic_content = LaunchConfiguration(
|
||||||
|
"robot_description_semantic"
|
||||||
|
)
|
||||||
|
control_space = LaunchConfiguration("control_space")
|
||||||
|
control_strategy = LaunchConfiguration("control_strategy")
|
||||||
|
ee_link_name = LaunchConfiguration("ee_link_name").perform(context)
|
||||||
|
base_link_name = LaunchConfiguration("base_link_name").perform(context)
|
||||||
|
|
||||||
remappings = []
|
remappings = []
|
||||||
if multi_robot == "true":
|
if multi_robot == "true":
|
||||||
remappings.append([("/tf", "tf"), ("/tf_static", "tf_static")])
|
remappings.append([("/tf", "tf"), ("/tf_static", "tf_static")])
|
||||||
|
|
||||||
controllers_file = os.path.join(
|
robot_description = {
|
||||||
get_package_share_directory(description_package), "config", controllers_file
|
"robot_description": robot_description_content.perform(context)
|
||||||
)
|
|
||||||
|
|
||||||
if not robot_description.perform(context):
|
|
||||||
xacro_file = os.path.join(
|
|
||||||
get_package_share_directory(description_package), "urdf", description_file
|
|
||||||
)
|
|
||||||
robot_description_doc = xacro.process_file(
|
|
||||||
xacro_file,
|
|
||||||
mappings={
|
|
||||||
"gripper_name": gripper_name.perform(context),
|
|
||||||
"hardware": hardware.perform(context),
|
|
||||||
"simulation_controllers": controllers_file,
|
|
||||||
"namespace": namespace,
|
|
||||||
"x": x_pos.perform(context),
|
|
||||||
"y": y_pos.perform(context),
|
|
||||||
"z": z_pos.perform(context),
|
|
||||||
"roll": roll.perform(context),
|
|
||||||
"pitch": pitch.perform(context),
|
|
||||||
"yaw": yaw.perform(context),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
robot_description_content = robot_description_doc.toprettyxml(indent=" ")
|
|
||||||
else:
|
|
||||||
robot_description_content = robot_description.perform(context)
|
|
||||||
|
|
||||||
robot_description = {"robot_description": robot_description_content}
|
|
||||||
|
|
||||||
robot_description_semantic_content = Command(
|
|
||||||
[
|
|
||||||
PathJoinSubstitution([FindExecutable(name="xacro")]),
|
|
||||||
" ",
|
|
||||||
PathJoinSubstitution(
|
|
||||||
[
|
|
||||||
FindPackageShare(moveit_config_package),
|
|
||||||
"config/moveit",
|
|
||||||
"rbs_arm.srdf.xacro",
|
|
||||||
]
|
|
||||||
),
|
|
||||||
" ",
|
|
||||||
"name:=",
|
|
||||||
robot_type,
|
|
||||||
" ",
|
|
||||||
"with_gripper:=",
|
|
||||||
with_gripper_condition,
|
|
||||||
" ",
|
|
||||||
"gripper_name:=",
|
|
||||||
gripper_name,
|
|
||||||
" ",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
|
|
||||||
robot_description_semantic = {
|
|
||||||
"robot_description_semantic": robot_description_semantic_content
|
|
||||||
}
|
}
|
||||||
robot_description_kinematics = PathJoinSubstitution(
|
|
||||||
[FindPackageShare(moveit_config_package), "config", "kinematics.yaml"]
|
robot_description_kinematics_filepath = os.path.join(
|
||||||
|
get_package_share_directory(moveit_config_package.perform(context)),
|
||||||
|
"config",
|
||||||
|
"kinematics.yaml",
|
||||||
)
|
)
|
||||||
|
|
||||||
# kinematics_yaml = load_yaml("rbs_arm", "config/kinematics.yaml")
|
# robot_description_kinematics = {
|
||||||
|
# "robot_description_kinematics": robot_description_kinematics
|
||||||
|
# }
|
||||||
|
|
||||||
robot_description_kinematics = {
|
|
||||||
"robot_description_kinematics": robot_description_kinematics
|
|
||||||
}
|
|
||||||
rviz_config_file = PathJoinSubstitution(
|
|
||||||
[FindPackageShare("rbs_bringup"), "config", "rbs.rviz"]
|
|
||||||
)
|
|
||||||
robot_state_publisher = Node(
|
robot_state_publisher = Node(
|
||||||
package="robot_state_publisher",
|
package="robot_state_publisher",
|
||||||
executable="robot_state_publisher",
|
executable="robot_state_publisher",
|
||||||
|
@ -141,32 +74,12 @@ def launch_setup(context, *args, **kwargs):
|
||||||
parameters=[{"use_sim_time": use_sim_time}, robot_description],
|
parameters=[{"use_sim_time": use_sim_time}, robot_description],
|
||||||
)
|
)
|
||||||
|
|
||||||
rviz_config_file = PathJoinSubstitution(
|
|
||||||
[FindPackageShare("rbs_bringup"), "config", "rbs.rviz"]
|
|
||||||
)
|
|
||||||
|
|
||||||
rviz = Node(
|
|
||||||
package="rviz2",
|
|
||||||
executable="rviz2",
|
|
||||||
name="rviz2",
|
|
||||||
output="log",
|
|
||||||
namespace=namespace,
|
|
||||||
arguments=["-d", rviz_config_file],
|
|
||||||
parameters=[
|
|
||||||
robot_description,
|
|
||||||
robot_description_semantic,
|
|
||||||
robot_description_kinematics,
|
|
||||||
{"use_sim_time": use_sim_time},
|
|
||||||
],
|
|
||||||
condition=IfCondition(launch_rviz),
|
|
||||||
)
|
|
||||||
|
|
||||||
control = IncludeLaunchDescription(
|
control = IncludeLaunchDescription(
|
||||||
PythonLaunchDescriptionSource(
|
PythonLaunchDescriptionSource(
|
||||||
[
|
[
|
||||||
PathJoinSubstitution(
|
PathJoinSubstitution(
|
||||||
[
|
[
|
||||||
FindPackageShare(description_package),
|
FindPackageShare("rbs_bringup"),
|
||||||
"launch",
|
"launch",
|
||||||
"control.launch.py",
|
"control.launch.py",
|
||||||
]
|
]
|
||||||
|
@ -174,12 +87,12 @@ def launch_setup(context, *args, **kwargs):
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
launch_arguments={
|
launch_arguments={
|
||||||
"control_space": "task",
|
"control_space": control_space,
|
||||||
"control_strategy": "position",
|
"control_strategy": control_strategy,
|
||||||
"has_gripper": "true",
|
"has_gripper": with_gripper_condition,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
}.items(),
|
}.items(),
|
||||||
condition=IfCondition(launch_controllers),
|
condition=IfCondition(use_controllers),
|
||||||
)
|
)
|
||||||
|
|
||||||
moveit = IncludeLaunchDescription(
|
moveit = IncludeLaunchDescription(
|
||||||
|
@ -195,16 +108,17 @@ def launch_setup(context, *args, **kwargs):
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
launch_arguments={
|
launch_arguments={
|
||||||
"robot_description": robot_description_content,
|
|
||||||
"moveit_config_package": moveit_config_package,
|
"moveit_config_package": moveit_config_package,
|
||||||
"moveit_config_file": moveit_config_file,
|
# "moveit_config_file": moveit_config_file,
|
||||||
"use_sim_time": use_sim_time,
|
"use_sim_time": use_sim_time,
|
||||||
"tf_prefix": robot_name,
|
"tf_prefix": robot_name,
|
||||||
"with_gripper": with_gripper_condition,
|
"with_gripper": with_gripper_condition,
|
||||||
|
"robot_description": robot_description_content,
|
||||||
"robot_description_semantic": robot_description_semantic_content,
|
"robot_description_semantic": robot_description_semantic_content,
|
||||||
|
"robot_description_kinematics": robot_description_kinematics_filepath,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
}.items(),
|
}.items(),
|
||||||
condition=IfCondition(launch_moveit),
|
condition=IfCondition(use_moveit),
|
||||||
)
|
)
|
||||||
|
|
||||||
skills = IncludeLaunchDescription(
|
skills = IncludeLaunchDescription(
|
||||||
|
@ -222,287 +136,222 @@ def launch_setup(context, *args, **kwargs):
|
||||||
launch_arguments={
|
launch_arguments={
|
||||||
"robot_description": robot_description_content,
|
"robot_description": robot_description_content,
|
||||||
"robot_description_semantic": robot_description_semantic_content,
|
"robot_description_semantic": robot_description_semantic_content,
|
||||||
"robot_description_kinematics": robot_description_kinematics,
|
"robot_description_kinematics": robot_description_kinematics_filepath,
|
||||||
"use_sim_time": use_sim_time,
|
"use_sim_time": use_sim_time,
|
||||||
"with_gripper_condition": with_gripper_condition,
|
"with_gripper_condition": with_gripper_condition,
|
||||||
"namespace": namespace,
|
"namespace": namespace,
|
||||||
|
"use_moveit": use_moveit,
|
||||||
|
"ee_link_name": ee_link_name,
|
||||||
|
"base_link_name": base_link_name,
|
||||||
}.items(),
|
}.items(),
|
||||||
)
|
)
|
||||||
|
|
||||||
task_planner = IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource(
|
|
||||||
[
|
|
||||||
PathJoinSubstitution(
|
|
||||||
[
|
|
||||||
FindPackageShare("rbs_task_planner"),
|
|
||||||
"launch",
|
|
||||||
"task_planner.launch.py",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
launch_arguments={
|
|
||||||
# TBD
|
|
||||||
}.items(),
|
|
||||||
condition=IfCondition(launch_task_planner),
|
|
||||||
)
|
|
||||||
|
|
||||||
perception = IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource(
|
|
||||||
[
|
|
||||||
PathJoinSubstitution(
|
|
||||||
[
|
|
||||||
FindPackageShare("rbs_perception"),
|
|
||||||
"launch",
|
|
||||||
"perception.launch.py",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
launch_arguments={
|
|
||||||
# TBD
|
|
||||||
}.items(),
|
|
||||||
condition=IfCondition(launch_perception),
|
|
||||||
)
|
|
||||||
|
|
||||||
asm_config = Node(
|
|
||||||
package="rbs_utils",
|
|
||||||
namespace=namespace,
|
|
||||||
executable="assembly_config_service.py",
|
|
||||||
)
|
|
||||||
|
|
||||||
nodes_to_start = [
|
nodes_to_start = [
|
||||||
robot_state_publisher,
|
robot_state_publisher,
|
||||||
control,
|
control,
|
||||||
moveit,
|
moveit,
|
||||||
skills,
|
skills,
|
||||||
asm_config,
|
|
||||||
# task_planner,
|
|
||||||
# perception,
|
|
||||||
rviz,
|
|
||||||
]
|
]
|
||||||
return nodes_to_start
|
return nodes_to_start
|
||||||
|
|
||||||
|
|
||||||
def generate_launch_description():
|
def generate_launch_description():
|
||||||
declared_arguments = []
|
declared_arguments = []
|
||||||
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"robot_type",
|
"robot_type",
|
||||||
description="Type of robot by name",
|
description="Type of robot to launch, specified by name.",
|
||||||
choices=["rbs_arm", "ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e"],
|
choices=[
|
||||||
|
"rbs_arm",
|
||||||
|
"ar4",
|
||||||
|
"ur3",
|
||||||
|
"ur3e",
|
||||||
|
"ur5",
|
||||||
|
"ur5e",
|
||||||
|
"ur10",
|
||||||
|
"ur10e",
|
||||||
|
"ur16e",
|
||||||
|
],
|
||||||
default_value="rbs_arm",
|
default_value="rbs_arm",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
# General arguments
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"controllers_file",
|
"controllers_file",
|
||||||
default_value="rbs_arm0_controllers.yaml",
|
default_value="controllers.yaml",
|
||||||
description="YAML file with the controllers configuration.",
|
description="YAML file containing configuration settings for the controllers.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"description_package",
|
"description_package",
|
||||||
default_value="rbs_arm",
|
default_value="rbs_arm",
|
||||||
description="Description package with robot URDF/XACRO files. Usually the argument \
|
description="Package containing the robot's URDF/XACRO description files. Can be set to use a custom description.",
|
||||||
is not set, it enables use of a custom description.",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"description_file",
|
"description_file",
|
||||||
default_value="rbs_arm_modular.xacro",
|
default_value="rbs_arm_modular.xacro",
|
||||||
description="URDF/XACRO description file with the robot.",
|
description="URDF/XACRO file describing the robot's model.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"robot_name",
|
"robot_name",
|
||||||
default_value="arm0",
|
default_value="arm0",
|
||||||
description="tf_prefix of the joint names, useful for \
|
description="Prefix for joint names to support multi-robot setups. If changed, ensure joint names in controllers configuration are updated accordingly.",
|
||||||
multi-robot setup. If changed than also joint names in the controllers' configuration \
|
|
||||||
have to be updated.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"start_joint_controller",
|
|
||||||
default_value="true",
|
|
||||||
description="Enable headless mode for robot control",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"initial_joint_controller",
|
|
||||||
default_value="joint_trajectory_controller",
|
|
||||||
description="Robot controller to start.",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"moveit_config_package",
|
"moveit_config_package",
|
||||||
default_value="rbs_arm",
|
default_value="rbs_arm",
|
||||||
description="MoveIt config package with robot SRDF/XACRO files. Usually the argument \
|
description="Package containing the MoveIt configuration files (SRDF/XACRO) for the robot. Can be customized.",
|
||||||
is not set, it enables use of a custom moveit config.",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"moveit_config_file",
|
"moveit_config_file",
|
||||||
default_value="rbs_arm.srdf.xacro",
|
default_value="rbs_arm.srdf.xacro",
|
||||||
description="MoveIt SRDF/XACRO description file with the robot.",
|
description="MoveIt SRDF/XACRO file for robot configuration.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"use_sim_time",
|
"use_sim_time",
|
||||||
default_value="true",
|
default_value="true",
|
||||||
description="Make MoveIt to use simulation time.\
|
description="Enables simulation time in MoveIt, needed for trajectory planning in simulation.",
|
||||||
This is needed for the trajectory planing in simulation.",
|
)
|
||||||
|
)
|
||||||
|
# declared_arguments.append(
|
||||||
|
# DeclareLaunchArgument(
|
||||||
|
# "gripper_name",
|
||||||
|
# default_value="",
|
||||||
|
# choices=["rbs_gripper", ""],
|
||||||
|
# description="Specify gripper name (leave empty if none).",
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"with_gripper",
|
||||||
|
default_value="true",
|
||||||
|
description="Specify if the robot includes a gripper.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"gripper_name",
|
"use_moveit",
|
||||||
|
default_value="true",
|
||||||
|
description="Specify if MoveIt should be launched.",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"use_controllers",
|
||||||
|
default_value="true",
|
||||||
|
description="Specify if controllers should be launched.",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"namespace",
|
||||||
default_value="",
|
default_value="",
|
||||||
choices=["rbs_gripper", ""],
|
description="ROS 2 namespace for the robot.",
|
||||||
description="choose gripper by name (leave empty if hasn't)",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"with_gripper", default_value="true", description="With gripper or not?"
|
"x",
|
||||||
|
default_value="0.0",
|
||||||
|
description="X-coordinate for the robot's position in the world.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"launch_rviz", default_value="false", description="Launch RViz?"
|
"y",
|
||||||
|
default_value="0.0",
|
||||||
|
description="Y-coordinate for the robot's position in the world.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"sim_gazebo", default_value="true", description="Gazebo Simulation"
|
"z",
|
||||||
|
default_value="0.0",
|
||||||
|
description="Z-coordinate for the robot's position in the world.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"launch_sim",
|
"roll",
|
||||||
default_value="true",
|
default_value="0.0",
|
||||||
description="Launch simulator (Gazebo)?\
|
description="Roll orientation of the robot in the world.",
|
||||||
Most general arg",
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"launch_moveit", default_value="true", description="Launch moveit?"
|
"pitch",
|
||||||
|
default_value="0.0",
|
||||||
|
description="Pitch orientation of the robot in the world.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"launch_perception", default_value="false", description="Launch perception?"
|
"yaw",
|
||||||
|
default_value="0.0",
|
||||||
|
description="Yaw orientation of the robot in the world.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_task_planner",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch task_planner?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"cartesian_controllers",
|
|
||||||
default_value="false",
|
|
||||||
description="Load cartesian\
|
|
||||||
controllers?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"hardware",
|
|
||||||
choices=["gazebo", "mock"],
|
|
||||||
default_value="gazebo",
|
|
||||||
description="Choose your harware_interface",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch controllers?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"gazebo_gui", default_value="false", description="Launch gazebo with gui?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"namespace", default_value="", description="The ROS2 namespace of a robot"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"x", default_value="0.0", description="Position of robot in world by X"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"y", default_value="0.0", description="Position of robot in world by Y"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"z", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"roll", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"pitch", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"yaw", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"roll", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"pitch", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"yaw", default_value="0.0", description="Position of robot in world by Z"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"multi_robot",
|
"multi_robot",
|
||||||
default_value="false",
|
default_value="false",
|
||||||
description="Flag if you use multi robot setup",
|
description="Specify if the setup is for multiple robots.",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument(
|
DeclareLaunchArgument(
|
||||||
"robot_description",
|
"robot_description",
|
||||||
default_value="",
|
default_value="",
|
||||||
description="Robot description that override internal robot desctioption",
|
description="Custom robot description that overrides the internal default.",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"control_space",
|
||||||
|
default_value="task",
|
||||||
|
choices=["task", "joint"],
|
||||||
|
description="Specify the control space for the robot (e.g., task space).",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"control_strategy",
|
||||||
|
default_value="position",
|
||||||
|
choices=["position", "velocity", "effort"],
|
||||||
|
description="Specify the control strategy (e.g., position control).",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"robot_description_semantic",
|
||||||
|
default_value="",
|
||||||
|
description="Custom semantic robot description (SRDF) to override the default.",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"ee_link_name",
|
||||||
|
default_value="",
|
||||||
|
description="End effector name of robot arm",
|
||||||
|
)
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument(
|
||||||
|
"base_link_name",
|
||||||
|
default_value="",
|
||||||
|
description="Base link name if robot arm",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,301 +0,0 @@
|
||||||
import os
|
|
||||||
|
|
||||||
from ament_index_python.packages import get_package_share_directory
|
|
||||||
from launch import LaunchDescription
|
|
||||||
from launch.actions import (
|
|
||||||
DeclareLaunchArgument,
|
|
||||||
IncludeLaunchDescription,
|
|
||||||
OpaqueFunction,
|
|
||||||
)
|
|
||||||
from launch.conditions import IfCondition
|
|
||||||
from launch.launch_description_sources import PythonLaunchDescriptionSource
|
|
||||||
from launch.substitutions import LaunchConfiguration, PathJoinSubstitution
|
|
||||||
from launch_ros.actions import Node
|
|
||||||
from launch_ros.substitutions import FindPackageShare
|
|
||||||
|
|
||||||
|
|
||||||
def launch_setup(context, *args, **kwargs):
|
|
||||||
# Initialize Arguments
|
|
||||||
robot_type = LaunchConfiguration("robot_type")
|
|
||||||
# General arguments
|
|
||||||
with_gripper_condition = LaunchConfiguration("with_gripper")
|
|
||||||
controllers_file = LaunchConfiguration("controllers_file")
|
|
||||||
cartesian_controllers = LaunchConfiguration("cartesian_controllers")
|
|
||||||
description_package = LaunchConfiguration("description_package")
|
|
||||||
description_file = LaunchConfiguration("description_file")
|
|
||||||
robot_name = LaunchConfiguration("robot_name")
|
|
||||||
start_joint_controller = LaunchConfiguration("start_joint_controller")
|
|
||||||
initial_joint_controller = LaunchConfiguration("initial_joint_controller")
|
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
|
||||||
launch_moveit = LaunchConfiguration("launch_moveit")
|
|
||||||
launch_task_planner = LaunchConfiguration("launch_task_planner")
|
|
||||||
launch_perception = LaunchConfiguration("launch_perception")
|
|
||||||
moveit_config_package = LaunchConfiguration("moveit_config_package")
|
|
||||||
moveit_config_file = LaunchConfiguration("moveit_config_file")
|
|
||||||
use_sim_time = LaunchConfiguration("use_sim_time")
|
|
||||||
sim_gazebo = LaunchConfiguration("sim_gazebo")
|
|
||||||
hardware = LaunchConfiguration("hardware")
|
|
||||||
env_manager = LaunchConfiguration("env_manager")
|
|
||||||
launch_controllers = LaunchConfiguration("launch_controllers")
|
|
||||||
gazebo_gui = LaunchConfiguration("gazebo_gui")
|
|
||||||
gripper_name = LaunchConfiguration("gripper_name")
|
|
||||||
|
|
||||||
sim_gazebo = LaunchConfiguration("sim_gazebo")
|
|
||||||
launch_simulation = LaunchConfiguration("launch_sim")
|
|
||||||
simulation = IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource(
|
|
||||||
[
|
|
||||||
PathJoinSubstitution(
|
|
||||||
[
|
|
||||||
FindPackageShare("rbs_simulation"),
|
|
||||||
"launch",
|
|
||||||
"simulation_gazebo.launch.py",
|
|
||||||
]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
launch_arguments={
|
|
||||||
"sim_gazebo": sim_gazebo,
|
|
||||||
"debugger": "false",
|
|
||||||
"launch_env_manager": env_manager,
|
|
||||||
"gazebo_world_filename": "asm2.sdf",
|
|
||||||
}.items(),
|
|
||||||
condition=IfCondition(launch_simulation),
|
|
||||||
)
|
|
||||||
|
|
||||||
# FIXME: namespaces
|
|
||||||
# configured_params = RewrittenYaml(
|
|
||||||
# source_file=os.path.join(
|
|
||||||
# get_package_share_directory(
|
|
||||||
# description_package.perform(context)),
|
|
||||||
# "config",
|
|
||||||
# controllers_file.perform(context)),
|
|
||||||
# root_key=robot_name.perform(context),
|
|
||||||
# param_rewrites={},
|
|
||||||
# convert_types=True,
|
|
||||||
# )
|
|
||||||
|
|
||||||
initial_joint_controllers_file_path = os.path.join(
|
|
||||||
get_package_share_directory("rbs_arm"), "config", "rbs_arm0_controllers.yaml"
|
|
||||||
)
|
|
||||||
|
|
||||||
# controller_paramfile = configured_params.perform(context)
|
|
||||||
# controller_paramfile = PathJoinSubstitution([
|
|
||||||
# FindPackageShare(robot_type), "config", "rbs_arm0_controllers.yaml"
|
|
||||||
# ])
|
|
||||||
# namespace = "/" + robot_name.perform(context)
|
|
||||||
namespace = ""
|
|
||||||
|
|
||||||
gz_spawner = Node(
|
|
||||||
package="ros_gz_sim",
|
|
||||||
executable="create",
|
|
||||||
# prefix=['gdbserver localhost:1234'],
|
|
||||||
arguments=[
|
|
||||||
"-name",
|
|
||||||
robot_name.perform(context),
|
|
||||||
"-topic",
|
|
||||||
namespace + "/robot_description",
|
|
||||||
],
|
|
||||||
output="screen",
|
|
||||||
condition=IfCondition(sim_gazebo),
|
|
||||||
)
|
|
||||||
|
|
||||||
single_robot_setup = IncludeLaunchDescription(
|
|
||||||
PythonLaunchDescriptionSource(
|
|
||||||
[
|
|
||||||
PathJoinSubstitution(
|
|
||||||
[FindPackageShare("rbs_bringup"), "launch", "rbs_robot.launch.py"]
|
|
||||||
)
|
|
||||||
]
|
|
||||||
),
|
|
||||||
launch_arguments={
|
|
||||||
"env_manager": env_manager,
|
|
||||||
"with_gripper": with_gripper_condition,
|
|
||||||
"gripper_name": gripper_name,
|
|
||||||
"controllers_file": initial_joint_controllers_file_path,
|
|
||||||
"robot_type": robot_type,
|
|
||||||
# "controllers_file": controller_paramfile,
|
|
||||||
"cartesian_controllers": cartesian_controllers,
|
|
||||||
"description_package": description_package,
|
|
||||||
"description_file": description_file,
|
|
||||||
"robot_name": robot_type,
|
|
||||||
"start_joint_controller": start_joint_controller,
|
|
||||||
"initial_joint_controller": initial_joint_controller,
|
|
||||||
"launch_simulation": launch_simulation,
|
|
||||||
"launch_moveit": launch_moveit,
|
|
||||||
"launch_task_planner": launch_task_planner,
|
|
||||||
"launch_perception": launch_perception,
|
|
||||||
"moveit_config_package": moveit_config_package,
|
|
||||||
"moveit_config_file": moveit_config_file,
|
|
||||||
"use_sim_time": use_sim_time,
|
|
||||||
"sim_gazebo": sim_gazebo,
|
|
||||||
"hardware": hardware,
|
|
||||||
"launch_controllers": "true",
|
|
||||||
"gazebo_gui": gazebo_gui,
|
|
||||||
# "x": "0.5",
|
|
||||||
# "y": "0.5",
|
|
||||||
# "z": "0.5"
|
|
||||||
}.items(),
|
|
||||||
)
|
|
||||||
|
|
||||||
nodes_to_start = [simulation, gz_spawner, single_robot_setup]
|
|
||||||
return nodes_to_start
|
|
||||||
|
|
||||||
|
|
||||||
def generate_launch_description():
|
|
||||||
declared_arguments = []
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"robot_type",
|
|
||||||
description="Type of robot by name",
|
|
||||||
choices=["rbs_arm", "ur3", "ur3e", "ur5", "ur5e", "ur10", "ur10e", "ur16e"],
|
|
||||||
default_value="rbs_arm",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
# General arguments
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"controllers_file",
|
|
||||||
default_value="rbs_arm0_controllers.yaml",
|
|
||||||
description="YAML file with the controllers configuration.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"description_package",
|
|
||||||
default_value="rbs_arm",
|
|
||||||
description="Description package with robot URDF/XACRO files. Usually the argument \
|
|
||||||
is not set, it enables use of a custom description.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"description_file",
|
|
||||||
default_value="rbs_arm_modular.xacro",
|
|
||||||
description="URDF/XACRO description file with the robot.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"robot_name",
|
|
||||||
default_value="arm0",
|
|
||||||
description="Name for robot, used to apply namespace for specific robot in multirobot setup",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"start_joint_controller",
|
|
||||||
default_value="false",
|
|
||||||
description="Enable headless mode for robot control",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"initial_joint_controller",
|
|
||||||
default_value="joint_trajectory_controller",
|
|
||||||
description="Robot controller to start.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"moveit_config_package",
|
|
||||||
default_value="rbs_arm",
|
|
||||||
description="MoveIt config package with robot SRDF/XACRO files. Usually the argument \
|
|
||||||
is not set, it enables use of a custom moveit config.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"moveit_config_file",
|
|
||||||
default_value="rbs_arm.srdf.xacro",
|
|
||||||
description="MoveIt SRDF/XACRO description file with the robot.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"use_sim_time",
|
|
||||||
default_value="true",
|
|
||||||
description="Make MoveIt to use simulation time.\
|
|
||||||
This is needed for the trajectory planing in simulation.",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"gripper_name",
|
|
||||||
default_value="rbs_gripper",
|
|
||||||
choices=["rbs_gripper", ""],
|
|
||||||
description="choose gripper by name (leave empty if hasn't)",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"with_gripper", default_value="true", description="With gripper or not?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"sim_gazebo", default_value="true", description="Gazebo Simulation"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"env_manager", default_value="true", description="Launch env_manager?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_sim",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch simulator (Gazebo)?\
|
|
||||||
Most general arg",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_moveit", default_value="false", description="Launch moveit?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_perception", default_value="false", description="Launch perception?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_task_planner",
|
|
||||||
default_value="false",
|
|
||||||
description="Launch task_planner?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"cartesian_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Load cartesian\
|
|
||||||
controllers?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"hardware",
|
|
||||||
choices=["gazebo", "mock"],
|
|
||||||
default_value="gazebo",
|
|
||||||
description="Choose your harware_interface",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"launch_controllers",
|
|
||||||
default_value="true",
|
|
||||||
description="Launch controllers?",
|
|
||||||
)
|
|
||||||
)
|
|
||||||
declared_arguments.append(
|
|
||||||
DeclareLaunchArgument(
|
|
||||||
"gazebo_gui", default_value="true", description="Launch gazebo with gui?"
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
return LaunchDescription(
|
|
||||||
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
|
||||||
)
|
|
|
@ -22,6 +22,7 @@ public:
|
||||||
bool setGoal(RosActionNode::Goal& goal) override {
|
bool setGoal(RosActionNode::Goal& goal) override {
|
||||||
getInput("robot_name", goal.robot_name);
|
getInput("robot_name", goal.robot_name);
|
||||||
getInput("pose", goal.target_pose);
|
getInput("pose", goal.target_pose);
|
||||||
|
goal.duration = 2.0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,6 +34,7 @@ public:
|
||||||
goal.target_pose = m_pose_vec->poses[0];
|
goal.target_pose = m_pose_vec->poses[0];
|
||||||
goal.end_effector_velocity = 0.3;
|
goal.end_effector_velocity = 0.3;
|
||||||
goal.end_effector_acceleration = 0.3;
|
goal.end_effector_acceleration = 0.3;
|
||||||
|
goal.duration = 2.0;
|
||||||
m_pose_vec->poses.erase(m_pose_vec->poses.begin());
|
m_pose_vec->poses.erase(m_pose_vec->poses.begin());
|
||||||
|
|
||||||
setOutput("pose_vec_out", m_pose_vec);
|
setOutput("pose_vec_out", m_pose_vec);
|
||||||
|
|
|
@ -6,7 +6,7 @@ rbs_skill_interfaces/PropertyValuePair[] joint_pairs # list of joint_pairs (join
|
||||||
float64[] joint_values
|
float64[] joint_values
|
||||||
float32 joints_velocity_scaling_factor
|
float32 joints_velocity_scaling_factor
|
||||||
float32 joints_acceleration_scaling_factor
|
float32 joints_acceleration_scaling_factor
|
||||||
float32 timeout_seconds #if this action cannot be completed within this time period it should be considered failed.
|
float32 duration #if this action cannot be completed within this time period it should be considered failed.
|
||||||
---
|
---
|
||||||
#result definition
|
#result definition
|
||||||
bool success
|
bool success
|
||||||
|
|
|
@ -11,7 +11,7 @@ geometry_msgs/Pose target_pose
|
||||||
string robot_name
|
string robot_name
|
||||||
float32 end_effector_velocity
|
float32 end_effector_velocity
|
||||||
float32 end_effector_acceleration
|
float32 end_effector_acceleration
|
||||||
float32 timeout_seconds #if this action cannot be completed within this time period it should be considered failed.
|
float32 duration #if this action cannot be completed within this time period it should be considered failed.
|
||||||
---
|
---
|
||||||
#result definition
|
#result definition
|
||||||
bool success
|
bool success
|
||||||
|
|
|
@ -1,12 +1,10 @@
|
||||||
cmake_minimum_required(VERSION 3.8)
|
cmake_minimum_required(VERSION 3.8)
|
||||||
project(rbs_skill_servers)
|
project(rbs_skill_servers)
|
||||||
|
|
||||||
# Default to C99
|
# Set default standards
|
||||||
if(NOT CMAKE_C_STANDARD)
|
if(NOT CMAKE_C_STANDARD)
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Default to C++17
|
|
||||||
if(NOT CMAKE_CXX_STANDARD)
|
if(NOT CMAKE_CXX_STANDARD)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
endif()
|
endif()
|
||||||
|
@ -15,7 +13,9 @@ if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
add_compile_options(-Wall -Wextra -Wpedantic)
|
add_compile_options(-Wall -Wextra -Wpedantic)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# find dependencies
|
set(CMAKE_SUPPRESS_DEVELOPER_WARNINGS TRUE)
|
||||||
|
|
||||||
|
# Find dependencies
|
||||||
find_package(ament_cmake REQUIRED)
|
find_package(ament_cmake REQUIRED)
|
||||||
find_package(rclcpp REQUIRED)
|
find_package(rclcpp REQUIRED)
|
||||||
find_package(rclcpp_components REQUIRED)
|
find_package(rclcpp_components REQUIRED)
|
||||||
|
@ -30,126 +30,89 @@ find_package(rbs_skill_interfaces REQUIRED)
|
||||||
find_package(rmw REQUIRED)
|
find_package(rmw REQUIRED)
|
||||||
find_package(tf2_eigen REQUIRED)
|
find_package(tf2_eigen REQUIRED)
|
||||||
find_package(tf2_msgs REQUIRED)
|
find_package(tf2_msgs REQUIRED)
|
||||||
find_package(tinyxml2_vendor REQUIRED)
|
|
||||||
find_package(TinyXML2 REQUIRED)
|
|
||||||
find_package(Eigen3 3.3 REQUIRED)
|
find_package(Eigen3 3.3 REQUIRED)
|
||||||
find_package(rbs_utils REQUIRED)
|
find_package(rbs_utils REQUIRED)
|
||||||
# find_package(moveit_servo REQUIRED)
|
find_package(controller_manager_msgs REQUIRED)
|
||||||
|
find_package(control_msgs REQUIRED)
|
||||||
|
|
||||||
# Default to Fortress
|
set(DEPS
|
||||||
set(SDF_VER 12)
|
|
||||||
|
|
||||||
# If the user didn't specify a GZ distribution, pick the one matching the ROS
|
|
||||||
# distribution according to REP 2000
|
|
||||||
if(NOT DEFINED ENV{GZ_VERSION} AND DEFINED ENV{ROS_DISTRO})
|
|
||||||
if("$ENV{ROS_DISTRO}" STREQUAL "humble")
|
|
||||||
set(ENV{GZ_VERSION} "fortress")
|
|
||||||
endif()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# Find libsdformat matching the picked GZ distribution
|
|
||||||
if("$ENV{GZ_VERSION}" STREQUAL "fortress")
|
|
||||||
find_package(sdformat12 REQUIRED)
|
|
||||||
set(SDF_VER ${sdformat12_VERSION_MAJOR})
|
|
||||||
message(STATUS "Compiling against Gazebo Fortress (libSDFormat 12)")
|
|
||||||
elseif("$ENV{GZ_VERSION}" STREQUAL "garden")
|
|
||||||
find_package(sdformat13 REQUIRED)
|
|
||||||
set(SDF_VER ${sdformat13_VERSION_MAJOR})
|
|
||||||
message(STATUS "Compiling against Gazebo Garden (libSDFormat 13)")
|
|
||||||
# No GZ distribution specified, find any version of libsdformat we can
|
|
||||||
else()
|
|
||||||
foreach(major RANGE 13 9)
|
|
||||||
find_package(sdformat${major} QUIET)
|
|
||||||
if(sdformat${major}_FOUND)
|
|
||||||
# Next `find_package` call will be a noop
|
|
||||||
set(SDF_VER ${major})
|
|
||||||
message(STATUS "Compiling against libSDFormat ${major}")
|
|
||||||
break()
|
|
||||||
endif()
|
|
||||||
endforeach()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
include_directories(SYSTEM ${TINYXML2_INCLUDE_DIR})
|
|
||||||
|
|
||||||
link_directories(${TINYXML2_LIBRARY_DIRS})
|
|
||||||
|
|
||||||
set(deps
|
|
||||||
rclcpp
|
rclcpp
|
||||||
rclcpp_action
|
rclcpp_action
|
||||||
moveit_core
|
moveit_core
|
||||||
moveit_ros_planning
|
moveit_ros_planning
|
||||||
moveit_ros_planning_interface
|
moveit_ros_planning_interface
|
||||||
|
control_msgs
|
||||||
|
controller_manager_msgs
|
||||||
moveit_msgs
|
moveit_msgs
|
||||||
# moveit_servo
|
|
||||||
geometry_msgs
|
geometry_msgs
|
||||||
tf2_ros
|
tf2_ros
|
||||||
rclcpp_components
|
rclcpp_components
|
||||||
rbs_skill_interfaces
|
rbs_skill_interfaces
|
||||||
tf2_eigen
|
tf2_eigen
|
||||||
tf2_msgs
|
tf2_msgs
|
||||||
tinyxml2_vendor
|
|
||||||
geometric_shapes
|
geometric_shapes
|
||||||
sdformat${SDF_VER})
|
)
|
||||||
|
|
||||||
if(BUILD_TESTING)
|
|
||||||
find_package(ament_lint_auto REQUIRED)
|
|
||||||
ament_lint_auto_find_test_dependencies()
|
|
||||||
endif()
|
|
||||||
|
|
||||||
# -- GripperActionServer --
|
|
||||||
add_library(gripper_action_server SHARED src/gripper_control_action_server.cpp)
|
|
||||||
target_include_directories(
|
|
||||||
gripper_action_server
|
|
||||||
PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
||||||
$<INSTALL_INTERFACE:include>)
|
|
||||||
target_compile_definitions(gripper_action_server
|
|
||||||
PRIVATE "GRIPPER_ACTION_SERVER_CPP_BUILDING_DLL")
|
|
||||||
ament_target_dependencies(gripper_action_server ${deps})
|
|
||||||
rclcpp_components_register_node(
|
|
||||||
gripper_action_server PLUGIN "rbs_skill_actions::GripperControlActionServer"
|
|
||||||
EXECUTABLE gripper_control_action_server)
|
|
||||||
|
|
||||||
# -- PickPlacePoseLoader --
|
|
||||||
# add_library(pick_place_pose_loader SHARED src/pick_place_pose_loader.cpp)
|
|
||||||
# target_include_directories(
|
|
||||||
# pick_place_pose_loader
|
|
||||||
# PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
|
||||||
# $<INSTALL_INTERFACE:include>)
|
|
||||||
# target_compile_definitions(pick_place_pose_loader
|
|
||||||
# PRIVATE "PICK_PLACE_POSE_LOADER_CPP_BUILDING_DLL")
|
|
||||||
# ament_target_dependencies(pick_place_pose_loader ${deps} Eigen3
|
|
||||||
# rbs_utils)
|
|
||||||
# rclcpp_components_register_node(
|
|
||||||
# pick_place_pose_loader PLUGIN "rbs_skill_actions::GetGraspPickPoseServer"
|
|
||||||
# EXECUTABLE pick_place_pose_loader_service_server)
|
|
||||||
|
|
||||||
# -- MoveitActionServers --
|
|
||||||
add_executable(move_to_joint_states_action_server
|
|
||||||
src/move_to_joint_states_action_server.cpp)
|
|
||||||
ament_target_dependencies(move_to_joint_states_action_server ${deps})
|
|
||||||
|
|
||||||
add_executable(move_topose_action_server src/move_topose_action_server.cpp)
|
|
||||||
ament_target_dependencies(move_topose_action_server ${deps})
|
|
||||||
|
|
||||||
add_executable(move_cartesian_path_action_server
|
|
||||||
src/move_cartesian_path_action_server.cpp)
|
|
||||||
ament_target_dependencies(move_cartesian_path_action_server ${deps})
|
|
||||||
|
|
||||||
|
|
||||||
# add_executable(servo_action_server
|
macro(add_ros2_component target_name source_file plugin_name executable_name)
|
||||||
# src/moveit_servo_skill_server.cpp)
|
add_library(${target_name} SHARED ${source_file})
|
||||||
# ament_target_dependencies(servo_action_server ${deps})
|
target_include_directories(${target_name}
|
||||||
#
|
PRIVATE $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||||
|
$<INSTALL_INTERFACE:include>)
|
||||||
|
target_compile_definitions(${target_name} PRIVATE "${target_name}_BUILDING_DLL")
|
||||||
|
ament_target_dependencies(${target_name} ${DEPS})
|
||||||
|
rclcpp_components_register_node(${target_name} PLUGIN ${plugin_name} EXECUTABLE ${executable_name})
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Add components
|
||||||
|
add_ros2_component(gripper_action_server
|
||||||
|
src/gripper_command.cpp
|
||||||
|
"rbs_skill_actions::GripperControlActionServer"
|
||||||
|
gripper_command)
|
||||||
|
|
||||||
|
add_ros2_component(cartesian_move_to_pose
|
||||||
|
src/mtp_cart.cpp
|
||||||
|
"rbs_skill_actions::CartesianMoveToPose"
|
||||||
|
mtp_cart)
|
||||||
|
|
||||||
|
add_ros2_component(move_to_joint_states
|
||||||
|
src/mtjs_jtc.cpp
|
||||||
|
"rbs_skill_actions::MoveToJointStateActionServer"
|
||||||
|
mtjs_jtc)
|
||||||
|
|
||||||
|
add_ros2_component(move_to_pose
|
||||||
|
src/mtp_jtc.cpp
|
||||||
|
"rbs_skill_actions::MoveToPose"
|
||||||
|
mtp_jtc)
|
||||||
|
|
||||||
|
add_ros2_component(move_to_pose_cartesian
|
||||||
|
src/mtp_jtc_cart.cpp
|
||||||
|
"rbs_skill_actions::MoveToPoseJtcCartesian"
|
||||||
|
mtp_jtc_cart)
|
||||||
|
|
||||||
|
add_ros2_component(move_to_pose_moveit
|
||||||
|
src/mtp_moveit.cpp
|
||||||
|
"rbs_skill_actions::MoveitMtp"
|
||||||
|
mtp_moveit)
|
||||||
|
|
||||||
|
add_ros2_component(move_to_pose_moveit_cartesian
|
||||||
|
src/mtp_moveit_cart.cpp
|
||||||
|
"rbs_skill_actions::MoveitMtpCart"
|
||||||
|
mtp_moveit_cart)
|
||||||
|
|
||||||
|
# Install directories and targets
|
||||||
install(DIRECTORY include/ DESTINATION include)
|
install(DIRECTORY include/ DESTINATION include)
|
||||||
|
|
||||||
install(DIRECTORY launch config DESTINATION share/${PROJECT_NAME})
|
install(DIRECTORY launch config DESTINATION share/${PROJECT_NAME})
|
||||||
|
|
||||||
install(
|
install(
|
||||||
TARGETS move_topose_action_server
|
TARGETS
|
||||||
gripper_action_server
|
gripper_action_server
|
||||||
move_to_joint_states_action_server
|
cartesian_move_to_pose
|
||||||
move_cartesian_path_action_server
|
move_to_joint_states
|
||||||
# servo_action_server
|
move_to_pose
|
||||||
|
move_to_pose_cartesian
|
||||||
|
move_to_pose_moveit_cartesian
|
||||||
|
move_to_pose_moveit
|
||||||
ARCHIVE DESTINATION lib
|
ARCHIVE DESTINATION lib
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION lib
|
||||||
RUNTIME DESTINATION lib/${PROJECT_NAME})
|
RUNTIME DESTINATION lib/${PROJECT_NAME})
|
||||||
|
|
|
@ -1,73 +0,0 @@
|
||||||
box1:
|
|
||||||
PreGraspPose: [0.25, 0.55, 0.6515, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
GraspPose: [0.25, 0.655, 0.6515, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose: [0.25, 0.655, 0.67, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose2: [0.25, 0.5, 0.67, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PrePlacePose: [-0.4500, -0.055, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PlacePose: [-0.4500, -0.055, 0.46, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PostPlacePose: [-0.4500, -0.055, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
box2:
|
|
||||||
PreGraspPose: [0.0, 0.55, 0.6515, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
GraspPose: [0.0, 0.655, 0.6515, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose: [0.0, 0.655, 0.67, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose2: [0.0, 0.5, 0.67, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PrePlacePose: [-0.4500, 0.0, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PlacePose: [-0.4500, 0.0, 0.46, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PostPlacePose: [-0.4500, 0.0, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
box3:
|
|
||||||
PreGraspPose: [-0.25, 0.55, 0.6515, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
GraspPose: [-0.25, 0.655, 0.6515, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose: [-0.25, 0.655, 0.67, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose2: [-0.25, 0.5, 0.67, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PrePlacePose: [-0.4500, 0.055, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PlacePose: [-0.4500, 0.055, 0.46, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PostPlacePose: [-0.4500, 0.055, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
box4:
|
|
||||||
PreGraspPose: [0.25, 0.55, 0.3015, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
GraspPose: [0.25, 0.655, 0.3015, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose: [0.25, 0.655, 0.32, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose2: [0.25, 0.5, 0.32, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PrePlacePose: [-0.4500, 0.0275, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PlacePose: [-0.4500, 0.0275, 0.49, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PostPlacePose: [-0.4500, 0.0275, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
box5:
|
|
||||||
PreGraspPose: [0.0, 0.55, 0.3015, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
GraspPose: [0.0, 0.655, 0.3015, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose: [0.0, 0.655, 0.32, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose2: [0.0, 0.5, 0.32, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PrePlacePose: [-0.4500, -0.0275, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PlacePose: [-0.4500, -0.0275, 0.49, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PostPlacePose: [-0.4500, -0.0275, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
box6:
|
|
||||||
PreGraspPose: [-0.25, 0.55, 0.3015, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
GraspPose: [-0.25, 0.655, 0.3015, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose: [-0.25, 0.655, 0.32, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PostGraspPose2: [-0.25, 0.5, 0.32, -0.707, 0.0, 0.0, 0.707]
|
|
||||||
PrePlacePose: [-0.4500, 0.0, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PlacePose: [-0.4500, 0.0, 0.56, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
PostPlacePose: [-0.4500, 0.0, 0.6, 1.0, 0.0, 0.0, 0.0]
|
|
||||||
|
|
||||||
|
|
||||||
pre_place_joint_states:
|
|
||||||
- 0.11030024152330242
|
|
||||||
- 0.8306162497371689
|
|
||||||
- -1.7680363334650195
|
|
||||||
- -0.6262361658856159
|
|
||||||
- 1.4713289344704141
|
|
||||||
- -0.11066274809566562
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
scene_objects:
|
|
||||||
- box1
|
|
||||||
- box2
|
|
||||||
- box3
|
|
||||||
- box4
|
|
||||||
- box5
|
|
||||||
- box6
|
|
||||||
- last
|
|
0
rbs_skill_servers/config/skills.yaml
Normal file
0
rbs_skill_servers/config/skills.yaml
Normal file
456
rbs_skill_servers/include/rbs_skill_servers/base_skill.hpp
Normal file
456
rbs_skill_servers/include/rbs_skill_servers/base_skill.hpp
Normal file
|
@ -0,0 +1,456 @@
|
||||||
|
#include <algorithm>
|
||||||
|
#include <controller_manager_msgs/srv/detail/configure_controller__struct.hpp>
|
||||||
|
#include <controller_manager_msgs/srv/detail/list_controllers__struct.hpp>
|
||||||
|
#include <controller_manager_msgs/srv/detail/load_controller__struct.hpp>
|
||||||
|
#include <controller_manager_msgs/srv/detail/switch_controller__struct.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <rclcpp/callback_group.hpp>
|
||||||
|
#include <rclcpp/node.hpp>
|
||||||
|
#include <rclcpp/node_options.hpp>
|
||||||
|
#include <rclcpp/parameter_client.hpp>
|
||||||
|
#include <rclcpp_action/create_server.hpp>
|
||||||
|
#include <rclcpp_action/server.hpp>
|
||||||
|
#include <rclcpp_action/server_goal_handle.hpp>
|
||||||
|
#include <rmw/qos_profiles.h>
|
||||||
|
#include <string>
|
||||||
|
#include <thread>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
template <typename ActionT> class SkillBase : public rclcpp::Node {
|
||||||
|
public:
|
||||||
|
explicit SkillBase(const std::string &node_name,
|
||||||
|
const std::string &action_server_name,
|
||||||
|
const rclcpp::NodeOptions &options)
|
||||||
|
: Node(node_name, options) {
|
||||||
|
|
||||||
|
auto act_cbg =
|
||||||
|
this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||||
|
|
||||||
|
m_action_server = rclcpp_action::create_server<ActionT>(
|
||||||
|
this, action_server_name,
|
||||||
|
std::bind(&SkillBase::handle_goal, this, std::placeholders::_1,
|
||||||
|
std::placeholders::_2),
|
||||||
|
std::bind(&SkillBase::handle_canceled, this, std::placeholders::_1),
|
||||||
|
std::bind(&SkillBase::handle_accepted, this, std::placeholders::_1));
|
||||||
|
|
||||||
|
m_load_controller_client =
|
||||||
|
this->create_client<controller_manager_msgs::srv::LoadController>(
|
||||||
|
"/controller_manager/load_controller");
|
||||||
|
m_switch_controller_client =
|
||||||
|
create_client<controller_manager_msgs::srv::SwitchController>(
|
||||||
|
"/controller_manager/switch_controller");
|
||||||
|
m_list_controllers_client =
|
||||||
|
create_client<controller_manager_msgs::srv::ListControllers>(
|
||||||
|
"/controller_manager/list_controllers");
|
||||||
|
m_configure_controller_client =
|
||||||
|
create_client<controller_manager_msgs::srv::ConfigureController>(
|
||||||
|
"/controller_manager/configure_controller");
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit SkillBase(const std::string &node_name,
|
||||||
|
const rclcpp::NodeOptions &options)
|
||||||
|
: SkillBase(node_name, node_name, options) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::shared_ptr<const typename ActionT::Goal> m_current_goal;
|
||||||
|
std::shared_ptr<typename ActionT::Result> m_current_result;
|
||||||
|
std::shared_ptr<rclcpp_action::ServerGoalHandle<ActionT>>
|
||||||
|
m_current_goal_handle;
|
||||||
|
|
||||||
|
bool m_interfaces_checked{false};
|
||||||
|
|
||||||
|
virtual rclcpp_action::GoalResponse
|
||||||
|
handle_goal(const rclcpp_action::GoalUUID &uuid,
|
||||||
|
std::shared_ptr<const typename ActionT::Goal> goal) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Received goal request for robot [%s]",
|
||||||
|
goal->robot_name.c_str());
|
||||||
|
(void)uuid;
|
||||||
|
|
||||||
|
m_current_goal = goal;
|
||||||
|
m_current_result = std::make_shared<typename ActionT::Result>();
|
||||||
|
|
||||||
|
return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual rclcpp_action::CancelResponse handle_canceled(
|
||||||
|
const std::shared_ptr<rclcpp_action::ServerGoalHandle<ActionT>>
|
||||||
|
goal_handle) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Received request to cancel goal");
|
||||||
|
(void)goal_handle;
|
||||||
|
return rclcpp_action::CancelResponse::ACCEPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_accepted(
|
||||||
|
const std::shared_ptr<rclcpp_action::ServerGoalHandle<ActionT>>
|
||||||
|
goal_handle) {
|
||||||
|
auto execution_thread = [this, goal_handle]() {
|
||||||
|
this->execute(goal_handle);
|
||||||
|
};
|
||||||
|
std::thread{execution_thread}.detach();
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(const std::shared_ptr<rclcpp_action::ServerGoalHandle<ActionT>>
|
||||||
|
goal_handle) {
|
||||||
|
|
||||||
|
m_current_goal_handle = goal_handle;
|
||||||
|
|
||||||
|
m_required_controllers = requiredStateControllers();
|
||||||
|
m_required_controllers.push_back(requiredActionController());
|
||||||
|
m_required_controllers.erase(std::remove_if(
|
||||||
|
m_required_controllers.begin(), m_required_controllers.end(),
|
||||||
|
[](const std::string &str) { return str.empty(); }));
|
||||||
|
|
||||||
|
if (m_required_controllers.empty()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Required controllers is empty");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
updateControllersMap();
|
||||||
|
|
||||||
|
if (m_controllers_map.count(requiredActionController()) &&
|
||||||
|
m_controllers_map[requiredActionController()] == "inactive") {
|
||||||
|
switchController(requiredActionController());
|
||||||
|
} else if (m_controllers_map.count(requiredActionController()) == 0) {
|
||||||
|
loadConfigureSwitchExecuteController({requiredActionController()});
|
||||||
|
} else if (!checkParameters()) {
|
||||||
|
getRequirementParametersAndExecute(requiredActionController());
|
||||||
|
} else {
|
||||||
|
executeAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateControllersMap() {
|
||||||
|
using namespace std::chrono_literals;
|
||||||
|
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Called list_controllers service to check "
|
||||||
|
"if required controllers are loaded");
|
||||||
|
|
||||||
|
auto list_controllers_request = std::make_shared<
|
||||||
|
controller_manager_msgs::srv::ListControllers::Request>();
|
||||||
|
|
||||||
|
auto list_controllers_future =
|
||||||
|
m_list_controllers_client->async_send_request(list_controllers_request);
|
||||||
|
|
||||||
|
if (list_controllers_future.wait_for(3s) != std::future_status::ready) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Timeout waiting for list_controllers response.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto response = list_controllers_future.get();
|
||||||
|
m_controllers_map.clear();
|
||||||
|
|
||||||
|
std::unordered_set<std::string> loaded_controllers;
|
||||||
|
loaded_controllers.reserve(response->controller.size());
|
||||||
|
for (const auto &controller : response->controller) {
|
||||||
|
m_controllers_map[controller.name] = controller.state;
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (m_missing_controllers.empty()) {
|
||||||
|
// RCLCPP_INFO(this->get_logger(), "All required controllers are
|
||||||
|
// loaded."); m_interfaces_checked = true; return true;
|
||||||
|
// } else {
|
||||||
|
// RCLCPP_WARN(this->get_logger(), "Missing required controllers:");
|
||||||
|
// for (const auto &missing_controller : m_missing_controllers) {
|
||||||
|
// RCLCPP_WARN(this->get_logger(), "\t- %s",
|
||||||
|
// missing_controller.c_str());
|
||||||
|
// }
|
||||||
|
// m_interfaces_checked = false;
|
||||||
|
// return false;
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
void loadConfigureSwitchExecuteController(
|
||||||
|
const std::vector<std::string> &controller_names) {
|
||||||
|
for (auto &controller_name : controller_names) {
|
||||||
|
RCLCPP_WARN(this->get_logger(), "Attempting to load controller [%s]",
|
||||||
|
controller_name.c_str());
|
||||||
|
auto load_request = std::make_shared<
|
||||||
|
controller_manager_msgs::srv::LoadController::Request>();
|
||||||
|
load_request->name = controller_name;
|
||||||
|
|
||||||
|
auto load_future = m_load_controller_client->async_send_request(
|
||||||
|
load_request,
|
||||||
|
[this, controller_name](
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::LoadController>::
|
||||||
|
SharedFuture future) {
|
||||||
|
if (future.get()->ok) {
|
||||||
|
RCLCPP_INFO(this->get_logger(),
|
||||||
|
"Controller %s successfully loaded",
|
||||||
|
controller_name.c_str());
|
||||||
|
configureController(controller_name);
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Failed to load controller %s",
|
||||||
|
controller_name.c_str());
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void configureController(const std::string &controller_name) {
|
||||||
|
auto configure_request = std::make_shared<
|
||||||
|
controller_manager_msgs::srv::ConfigureController::Request>();
|
||||||
|
configure_request->name = controller_name;
|
||||||
|
|
||||||
|
auto configure_future = m_configure_controller_client->async_send_request(
|
||||||
|
configure_request,
|
||||||
|
[this, controller_name](
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::ConfigureController>::
|
||||||
|
SharedFuture future) {
|
||||||
|
if (future.get()->ok) {
|
||||||
|
RCLCPP_INFO(this->get_logger(),
|
||||||
|
"Controller %s successfully configured",
|
||||||
|
controller_name.c_str());
|
||||||
|
switchController(controller_name);
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to configure controller %s",
|
||||||
|
controller_name.c_str());
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void switchController(const std::string &controller_name) {
|
||||||
|
|
||||||
|
detectResourceConflict(controller_name, [this, controller_name](
|
||||||
|
const std::vector<std::string>
|
||||||
|
&conflicted_controllers) {
|
||||||
|
auto switch_request = std::make_shared<
|
||||||
|
controller_manager_msgs::srv::SwitchController::Request>();
|
||||||
|
switch_request->activate_controllers = {controller_name};
|
||||||
|
switch_request->deactivate_controllers = conflicted_controllers;
|
||||||
|
switch_request->strictness =
|
||||||
|
controller_manager_msgs::srv::SwitchController::Request::STRICT;
|
||||||
|
|
||||||
|
auto switch_future = m_switch_controller_client->async_send_request(
|
||||||
|
switch_request,
|
||||||
|
[this, controller_name](
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::SwitchController>::
|
||||||
|
SharedFuture future) {
|
||||||
|
if (future.get()->ok) {
|
||||||
|
RCLCPP_INFO(this->get_logger(),
|
||||||
|
"Controller %s successfully switched",
|
||||||
|
controller_name.c_str());
|
||||||
|
if (!checkParameters()) {
|
||||||
|
getRequirementParametersAndExecute(controller_name);
|
||||||
|
} else {
|
||||||
|
if (controller_name == requiredActionController()) {
|
||||||
|
executeAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Failed to switch controller %s",
|
||||||
|
controller_name.c_str());
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checkParameters() {
|
||||||
|
std::ostringstream missing_params_stream;
|
||||||
|
std::ostringstream empty_params_stream;
|
||||||
|
|
||||||
|
for (const auto &name : requiredParameters()) {
|
||||||
|
if (!this->has_parameter(name)) {
|
||||||
|
missing_params_stream << "\n\t- " << name;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto ¶meter = this->get_parameter(name);
|
||||||
|
if (isEmptyParameter(parameter)) {
|
||||||
|
empty_params_stream << "\n\t- " << name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (missing_params_stream.tellp() > 0) {
|
||||||
|
RCLCPP_WARN(this->get_logger(),
|
||||||
|
"The following required parameters are missing:%s",
|
||||||
|
missing_params_stream.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty_params_stream.tellp() > 0) {
|
||||||
|
RCLCPP_WARN(this->get_logger(),
|
||||||
|
"The following required parameters are empty:%s",
|
||||||
|
empty_params_stream.str().c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
return missing_params_stream.tellp() == 0 &&
|
||||||
|
empty_params_stream.tellp() == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEmptyParameter(const rclcpp::Parameter ¶meter) {
|
||||||
|
switch (parameter.get_type()) {
|
||||||
|
case rclcpp::ParameterType::PARAMETER_STRING:
|
||||||
|
return parameter.as_string().empty();
|
||||||
|
case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
|
||||||
|
return parameter.as_string_array().empty();
|
||||||
|
case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
|
||||||
|
return parameter.as_integer_array().empty();
|
||||||
|
case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
|
||||||
|
return parameter.as_double_array().empty();
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual std::string requiredActionController() = 0;
|
||||||
|
|
||||||
|
virtual std::vector<std::string> requiredStateControllers() { return {""}; }
|
||||||
|
|
||||||
|
virtual std::vector<std::string> requiredParameters() { return {}; }
|
||||||
|
|
||||||
|
virtual void executeAction() = 0;
|
||||||
|
|
||||||
|
void getRequirementParametersAndExecute(const std::string &controller_name) {
|
||||||
|
|
||||||
|
RCLCPP_INFO(this->get_logger(),
|
||||||
|
"Connected to service %s, asking for parameters:",
|
||||||
|
controller_name.c_str());
|
||||||
|
|
||||||
|
for (const auto ¶m : requiredParameters()) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "\t- %s", param.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto parameter_callback =
|
||||||
|
[this, controller_name](
|
||||||
|
const std::shared_future<std::vector<rclcpp::Parameter>> &future) {
|
||||||
|
try {
|
||||||
|
auto parameters = future.get();
|
||||||
|
if (parameters.empty()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"No parameter found or empty array received");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
} else {
|
||||||
|
for (const auto ¶m : parameters) {
|
||||||
|
switch (param.get_type()) {
|
||||||
|
case rclcpp::ParameterType::PARAMETER_BOOL:
|
||||||
|
this->declare_parameter(param.get_name(), param.as_bool());
|
||||||
|
break;
|
||||||
|
case rclcpp::ParameterType::PARAMETER_INTEGER:
|
||||||
|
this->declare_parameter(param.get_name(), param.as_int());
|
||||||
|
break;
|
||||||
|
case rclcpp::ParameterType::PARAMETER_DOUBLE:
|
||||||
|
this->declare_parameter(param.get_name(), param.as_double());
|
||||||
|
break;
|
||||||
|
case rclcpp::ParameterType::PARAMETER_STRING:
|
||||||
|
this->declare_parameter(param.get_name(), param.as_string());
|
||||||
|
break;
|
||||||
|
case rclcpp::ParameterType::PARAMETER_STRING_ARRAY:
|
||||||
|
this->declare_parameter(param.get_name(),
|
||||||
|
param.as_string_array());
|
||||||
|
break;
|
||||||
|
case rclcpp::ParameterType::PARAMETER_INTEGER_ARRAY:
|
||||||
|
this->declare_parameter(param.get_name(),
|
||||||
|
param.as_integer_array());
|
||||||
|
break;
|
||||||
|
case rclcpp::ParameterType::PARAMETER_DOUBLE_ARRAY:
|
||||||
|
this->declare_parameter(param.get_name(),
|
||||||
|
param.as_double_array());
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
RCLCPP_WARN(this->get_logger(),
|
||||||
|
"Unsupported parameter type for parameter '%s'",
|
||||||
|
param.get_name().c_str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (controller_name == requiredActionController()) {
|
||||||
|
executeAction();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Failed to get parameter: %s",
|
||||||
|
e.what());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_parameter_client =
|
||||||
|
std::make_shared<rclcpp::AsyncParametersClient>(this, controller_name);
|
||||||
|
|
||||||
|
auto future = m_parameter_client->get_parameters(
|
||||||
|
requiredParameters(), std::move(parameter_callback));
|
||||||
|
|
||||||
|
RCLCPP_INFO(this->get_logger(),
|
||||||
|
"Asynchronous request sent for required parameters");
|
||||||
|
}
|
||||||
|
|
||||||
|
void detectResourceConflict(
|
||||||
|
const std::string &new_controller,
|
||||||
|
std::function<void(const std::vector<std::string> &)> callback) {
|
||||||
|
|
||||||
|
auto list_controllers_request = std::make_shared<
|
||||||
|
controller_manager_msgs::srv::ListControllers::Request>();
|
||||||
|
|
||||||
|
m_list_controllers_client->async_send_request(
|
||||||
|
list_controllers_request,
|
||||||
|
[this, new_controller,
|
||||||
|
callback](const rclcpp::Client<
|
||||||
|
controller_manager_msgs::srv::ListControllers>::SharedFuture
|
||||||
|
future) {
|
||||||
|
std::vector<std::string> conflicted_controller;
|
||||||
|
auto it_new_controller = std::find_if(
|
||||||
|
future.get()->controller.begin(), future.get()->controller.end(),
|
||||||
|
[&new_controller](
|
||||||
|
const controller_manager_msgs::msg::ControllerState
|
||||||
|
controller) {
|
||||||
|
return controller.name == new_controller;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (it_new_controller != future.get()->controller.end()) {
|
||||||
|
auto new_controller_interface =
|
||||||
|
it_new_controller->required_command_interfaces;
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Received list of controllers");
|
||||||
|
|
||||||
|
for (const auto &controller : future.get()->controller) {
|
||||||
|
if (controller.state == "active") {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Checking controller: %s",
|
||||||
|
controller.name.c_str());
|
||||||
|
|
||||||
|
bool has_conflict = std::any_of(
|
||||||
|
controller.required_command_interfaces.begin(),
|
||||||
|
controller.required_command_interfaces.end(),
|
||||||
|
[&new_controller_interface](const std::string &interface) {
|
||||||
|
return std::find(new_controller_interface.begin(),
|
||||||
|
new_controller_interface.end(),
|
||||||
|
interface) !=
|
||||||
|
new_controller_interface.end();
|
||||||
|
});
|
||||||
|
|
||||||
|
if (has_conflict) {
|
||||||
|
conflicted_controller.push_back(controller.name);
|
||||||
|
RCLCPP_WARN(this->get_logger(), "Conflicted controller: %s",
|
||||||
|
controller.name.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RCLCPP_WARN(this->get_logger(),
|
||||||
|
"New controller not found in loaded controllers");
|
||||||
|
}
|
||||||
|
|
||||||
|
callback(conflicted_controller);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::LoadController>::SharedPtr
|
||||||
|
m_load_controller_client;
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::SwitchController>::SharedPtr
|
||||||
|
m_switch_controller_client;
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::ListControllers>::SharedPtr
|
||||||
|
m_list_controllers_client;
|
||||||
|
rclcpp::Client<controller_manager_msgs::srv::ConfigureController>::SharedPtr
|
||||||
|
m_configure_controller_client;
|
||||||
|
rclcpp::AsyncParametersClient::SharedPtr m_parameter_client;
|
||||||
|
typename rclcpp_action::Server<ActionT>::SharedPtr m_action_server;
|
||||||
|
std::vector<std::string> m_required_controllers{};
|
||||||
|
std::vector<std::string> m_missing_controllers{};
|
||||||
|
std::unordered_map<std::string, std::string> m_controllers_map;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
|
@ -2,82 +2,98 @@ from launch import LaunchDescription
|
||||||
from launch.actions import DeclareLaunchArgument, OpaqueFunction
|
from launch.actions import DeclareLaunchArgument, OpaqueFunction
|
||||||
from launch.conditions import IfCondition
|
from launch.conditions import IfCondition
|
||||||
from launch.substitutions import LaunchConfiguration
|
from launch.substitutions import LaunchConfiguration
|
||||||
from launch_ros.actions import Node
|
from launch_ros.actions import ComposableNodeContainer, Node
|
||||||
from rbs_launch_utils.launch_common import load_yaml
|
from launch_ros.actions.composable_node_container import ComposableNode
|
||||||
|
from rbs_launch_utils.launch_common import load_yaml, load_yaml_abs
|
||||||
|
|
||||||
|
|
||||||
def launch_setup(context, *args, **kwargs):
|
def launch_setup(context, *args, **kwargs):
|
||||||
robot_description_decl = LaunchConfiguration("robot_description")
|
robot_description_content = LaunchConfiguration("robot_description")
|
||||||
robot_description_semantic_decl = LaunchConfiguration("robot_description_semantic")
|
robot_description_semantic_content = LaunchConfiguration("robot_description_semantic")
|
||||||
robot_description_kinematics = LaunchConfiguration("robot_description_kinematics")
|
robot_description_kinematics_filepath = LaunchConfiguration("robot_description_kinematics")
|
||||||
use_sim_time = LaunchConfiguration("use_sim_time")
|
use_sim_time = LaunchConfiguration("use_sim_time")
|
||||||
with_gripper_condition = LaunchConfiguration("with_gripper_condition")
|
use_moveit = LaunchConfiguration("use_moveit")
|
||||||
points_params_filepath_decl = LaunchConfiguration("points_params_filepath")
|
ee_link_name = LaunchConfiguration("ee_link_name").perform(context)
|
||||||
robot_description = {"robot_description": robot_description_decl}
|
base_link_name = LaunchConfiguration("base_link_name").perform(context)
|
||||||
|
# with_gripper_condition = LaunchConfiguration("with_gripper_condition")
|
||||||
|
|
||||||
|
robot_description = {"robot_description": robot_description_content}
|
||||||
robot_description_semantic = {
|
robot_description_semantic = {
|
||||||
"robot_description_semantic": robot_description_semantic_decl
|
"robot_description_semantic": robot_description_semantic_content
|
||||||
}
|
}
|
||||||
namespace = LaunchConfiguration("namespace")
|
namespace = LaunchConfiguration("namespace")
|
||||||
|
|
||||||
points_params = load_yaml("rbs_skill_servers", "config/gripperPositions.yaml")
|
kinematics_yaml = load_yaml_abs(robot_description_kinematics_filepath.perform(context))
|
||||||
|
|
||||||
kinematics_yaml = load_yaml("rbs_arm", "config/kinematics.yaml")
|
|
||||||
|
|
||||||
robot_description_kinematics = {"robot_description_kinematics": kinematics_yaml}
|
robot_description_kinematics = {"robot_description_kinematics": kinematics_yaml}
|
||||||
|
|
||||||
move_topose_action_server = Node(
|
skills_container = ComposableNodeContainer(
|
||||||
package="rbs_skill_servers",
|
name="skills",
|
||||||
executable="move_topose_action_server",
|
|
||||||
namespace=namespace,
|
namespace=namespace,
|
||||||
parameters=[
|
package="rclcpp_components",
|
||||||
robot_description,
|
# prefix=['gdbserver localhost:1234'],
|
||||||
robot_description_semantic,
|
executable="component_container_mt",
|
||||||
robot_description_kinematics,
|
composable_node_descriptions=[
|
||||||
{"use_sim_time": use_sim_time},
|
ComposableNode(
|
||||||
],
|
package="rbs_skill_servers",
|
||||||
)
|
plugin="rbs_skill_actions::MoveToJointStateActionServer",
|
||||||
|
name="mtjs_jtc",
|
||||||
gripper_control_node = Node(
|
parameters=[{"use_sim_time": use_sim_time}],
|
||||||
package="rbs_skill_servers",
|
),
|
||||||
executable="gripper_control_action_server",
|
ComposableNode(
|
||||||
namespace=namespace,
|
package="rbs_skill_servers",
|
||||||
parameters=[
|
plugin="rbs_skill_actions::CartesianMoveToPose",
|
||||||
robot_description,
|
name="mtp_cart",
|
||||||
robot_description_semantic,
|
parameters=[
|
||||||
robot_description_kinematics,
|
{"use_sim_time": use_sim_time},
|
||||||
{"use_sim_time": use_sim_time},
|
{"robot_name": namespace},
|
||||||
],
|
],
|
||||||
condition=IfCondition(with_gripper_condition),
|
),
|
||||||
)
|
ComposableNode(
|
||||||
|
package="rbs_skill_servers",
|
||||||
move_cartesian_path_action_server = Node(
|
plugin="rbs_skill_actions::MoveToPose",
|
||||||
package="rbs_skill_servers",
|
name="mtp_jtc",
|
||||||
executable="move_cartesian_path_action_server",
|
parameters=[
|
||||||
namespace=namespace,
|
{"use_sim_time": use_sim_time},
|
||||||
parameters=[
|
{"robot_name": namespace},
|
||||||
robot_description,
|
robot_description,
|
||||||
robot_description_semantic,
|
],
|
||||||
robot_description_kinematics,
|
),
|
||||||
{"use_sim_time": use_sim_time},
|
ComposableNode(
|
||||||
],
|
package="rbs_skill_servers",
|
||||||
)
|
plugin="rbs_skill_actions::MoveToPoseJtcCartesian",
|
||||||
|
name="mtp_jtc_cart",
|
||||||
cartesian_move_to_pose_action_server = Node(
|
parameters=[
|
||||||
package="rbs_skill_servers",
|
{"use_sim_time": use_sim_time},
|
||||||
executable="move_to_pose.py",
|
{"robot_name": namespace},
|
||||||
namespace=namespace,
|
{"base_link": base_link_name},
|
||||||
parameters=[{"use_sim_time": use_sim_time}, {"robot_name": namespace}],
|
{"robot_ee_link": ee_link_name},
|
||||||
)
|
robot_description,
|
||||||
|
],
|
||||||
move_joint_state_action_server = Node(
|
),
|
||||||
package="rbs_skill_servers",
|
ComposableNode(
|
||||||
executable="move_to_joint_states_action_server",
|
package="rbs_skill_servers",
|
||||||
namespace=namespace,
|
plugin="rbs_skill_actions::MoveitMtp",
|
||||||
parameters=[
|
name="mtp_moveit",
|
||||||
robot_description,
|
parameters=[
|
||||||
robot_description_semantic,
|
robot_description,
|
||||||
robot_description_kinematics,
|
robot_description_semantic,
|
||||||
{"use_sim_time": use_sim_time},
|
robot_description_kinematics,
|
||||||
|
{"use_sim_time": use_sim_time},
|
||||||
|
],
|
||||||
|
condition=IfCondition(use_moveit),
|
||||||
|
),
|
||||||
|
ComposableNode(
|
||||||
|
package="rbs_skill_servers",
|
||||||
|
plugin="rbs_skill_actions::MoveitMtpCart",
|
||||||
|
name="mtp_moveit_cart",
|
||||||
|
parameters=[
|
||||||
|
robot_description,
|
||||||
|
robot_description_semantic,
|
||||||
|
robot_description_kinematics,
|
||||||
|
{"use_sim_time": use_sim_time},
|
||||||
|
],
|
||||||
|
condition=IfCondition(use_moveit),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -90,12 +106,7 @@ def launch_setup(context, *args, **kwargs):
|
||||||
|
|
||||||
nodes_to_start = [
|
nodes_to_start = [
|
||||||
assembly_config,
|
assembly_config,
|
||||||
move_topose_action_server,
|
skills_container,
|
||||||
gripper_control_node,
|
|
||||||
move_cartesian_path_action_server,
|
|
||||||
move_joint_state_action_server,
|
|
||||||
cartesian_move_to_pose_action_server,
|
|
||||||
# grasp_pose_loader
|
|
||||||
]
|
]
|
||||||
return nodes_to_start
|
return nodes_to_start
|
||||||
|
|
||||||
|
@ -116,15 +127,24 @@ def generate_launch_description():
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument("robot_description_kinematics", default_value="")
|
DeclareLaunchArgument("robot_description_kinematics", default_value="")
|
||||||
)
|
)
|
||||||
declared_arguments.append(DeclareLaunchArgument("use_sim_time", default_value=""))
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument("use_sim_time", default_value="false")
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument("use_moveit", default_value="false")
|
||||||
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument("with_gripper_condition", default_value="")
|
DeclareLaunchArgument("with_gripper_condition", default_value="")
|
||||||
)
|
)
|
||||||
declared_arguments.append(
|
declared_arguments.append(
|
||||||
DeclareLaunchArgument("points_params_filepath", default_value="")
|
DeclareLaunchArgument("namespace", default_value="")
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument("ee_link_name", default_value="")
|
||||||
|
)
|
||||||
|
declared_arguments.append(
|
||||||
|
DeclareLaunchArgument("base_link_name", default_value="")
|
||||||
)
|
)
|
||||||
declared_arguments.append(DeclareLaunchArgument("namespace", default_value=""))
|
|
||||||
|
|
||||||
return LaunchDescription(
|
return LaunchDescription(
|
||||||
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
declared_arguments + [OpaqueFunction(function=launch_setup)]
|
||||||
)
|
)
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
<depend>rbs_skill_interfaces</depend>
|
<depend>rbs_skill_interfaces</depend>
|
||||||
<depend>tf2_eigen</depend>
|
<depend>tf2_eigen</depend>
|
||||||
<depend>rbs_utils</depend>
|
<depend>rbs_utils</depend>
|
||||||
|
<depend>rclcpp_components</depend>
|
||||||
|
|
||||||
<test_depend>ament_lint_auto</test_depend>
|
<test_depend>ament_lint_auto</test_depend>
|
||||||
<test_depend>ament_lint_common</test_depend>
|
<test_depend>ament_lint_common</test_depend>
|
||||||
|
|
|
@ -1,164 +0,0 @@
|
||||||
#include <cinttypes>
|
|
||||||
#include <functional>
|
|
||||||
#include <memory>
|
|
||||||
#include <thread>
|
|
||||||
|
|
||||||
#include "rclcpp/rclcpp.hpp"
|
|
||||||
#include "rclcpp/timer.hpp"
|
|
||||||
#include "rclcpp_components/register_node_macro.hpp"
|
|
||||||
|
|
||||||
// action libs
|
|
||||||
#include "rbs_skill_interfaces/action/moveit_send_joint_states.hpp"
|
|
||||||
#include "rclcpp_action/rclcpp_action.hpp"
|
|
||||||
|
|
||||||
#include "geometry_msgs/msg/pose_stamped.hpp"
|
|
||||||
#include "geometry_msgs/msg/quaternion.hpp"
|
|
||||||
#include "geometry_msgs/msg/transform.hpp"
|
|
||||||
|
|
||||||
// moveit libs
|
|
||||||
#include "moveit/move_group_interface/move_group_interface.h"
|
|
||||||
#include "moveit/planning_interface/planning_interface.h"
|
|
||||||
|
|
||||||
/*
|
|
||||||
#include <tf2/LinearMath/Quaternion.h>
|
|
||||||
#include <tf2_geometry_msgs/tf2_geometry_msgs.h>
|
|
||||||
#include <tf2_ros/transform_listener.h>
|
|
||||||
*/
|
|
||||||
// For Visualization
|
|
||||||
// #include <eigen_conversions/eigen_msg.h>
|
|
||||||
#include "moveit_msgs/action/move_group.hpp"
|
|
||||||
#include "moveit_msgs/msg/display_robot_state.hpp"
|
|
||||||
#include "moveit_msgs/msg/display_trajectory.hpp"
|
|
||||||
#include "moveit_msgs/msg/robot_trajectory.hpp"
|
|
||||||
|
|
||||||
namespace rbs_skill_actions {
|
|
||||||
|
|
||||||
class MoveToJointStateActionServer : public rclcpp::Node {
|
|
||||||
public:
|
|
||||||
using MoveitSendJointStates =
|
|
||||||
rbs_skill_interfaces::action::MoveitSendJointStates;
|
|
||||||
|
|
||||||
// explicit MoveToPoseActionServer(const rclcpp::Node::SharedPtr& node)
|
|
||||||
explicit MoveToJointStateActionServer(const rclcpp::Node::SharedPtr &node)
|
|
||||||
: Node("move_to_joint_states_action_server"), node_(node) {
|
|
||||||
// using namespace std::placeholders;
|
|
||||||
// this->action_server_ = rclcpp_action::create_server<MoveitSendPose>(
|
|
||||||
// this->get_node_base_interface(),
|
|
||||||
// this->get_node_clock_interface(),
|
|
||||||
// this->get_node_logging_interface(),
|
|
||||||
// this->get_node_waitables_interface(),
|
|
||||||
// "move_topose",
|
|
||||||
// std::bind(&MoveToPoseActionServer::goal_callback, this, _1, _2),
|
|
||||||
// std::bind(&MoveToPoseActionServer::cancel_callback, this, _1),
|
|
||||||
// std::bind(&MoveToPoseActionServer::accepted_callback, this, _1));
|
|
||||||
}
|
|
||||||
|
|
||||||
void init() {
|
|
||||||
|
|
||||||
action_server_ = rclcpp_action::create_server<MoveitSendJointStates>(
|
|
||||||
node_->get_node_base_interface(), node_->get_node_clock_interface(),
|
|
||||||
node_->get_node_logging_interface(),
|
|
||||||
node_->get_node_waitables_interface(), "move_to_joint_states",
|
|
||||||
std::bind(&MoveToJointStateActionServer::goal_callback, this,
|
|
||||||
std::placeholders::_1, std::placeholders::_2),
|
|
||||||
std::bind(&MoveToJointStateActionServer::cancel_callback, this,
|
|
||||||
std::placeholders::_1),
|
|
||||||
std::bind(&MoveToJointStateActionServer::accepted_callback, this,
|
|
||||||
std::placeholders::_1));
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
rclcpp::Node::SharedPtr node_;
|
|
||||||
rclcpp_action::Server<MoveitSendJointStates>::SharedPtr action_server_;
|
|
||||||
|
|
||||||
using ServerGoalHandle =
|
|
||||||
rclcpp_action::ServerGoalHandle<MoveitSendJointStates>;
|
|
||||||
|
|
||||||
rclcpp_action::GoalResponse
|
|
||||||
goal_callback(const rclcpp_action::GoalUUID &uuid,
|
|
||||||
std::shared_ptr<const MoveitSendJointStates::Goal> goal) {
|
|
||||||
RCLCPP_INFO(this->get_logger(), "Goal received for robot [%s]",
|
|
||||||
goal->robot_name.c_str());
|
|
||||||
(void)uuid;
|
|
||||||
if (false) {
|
|
||||||
return rclcpp_action::GoalResponse::REJECT;
|
|
||||||
}
|
|
||||||
return rclcpp_action::GoalResponse::ACCEPT_AND_EXECUTE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rclcpp_action::CancelResponse
|
|
||||||
cancel_callback(const std::shared_ptr<ServerGoalHandle> goal_handle) {
|
|
||||||
RCLCPP_INFO(this->get_logger(), "Received cancel request");
|
|
||||||
(void)goal_handle;
|
|
||||||
return rclcpp_action::CancelResponse::ACCEPT;
|
|
||||||
}
|
|
||||||
|
|
||||||
void accepted_callback(const std::shared_ptr<ServerGoalHandle> goal_handle) {
|
|
||||||
using namespace std::placeholders;
|
|
||||||
std::thread(std::bind(&MoveToJointStateActionServer::execute, this, _1),
|
|
||||||
goal_handle)
|
|
||||||
.detach();
|
|
||||||
}
|
|
||||||
|
|
||||||
void execute(const std::shared_ptr<ServerGoalHandle> goal_handle) {
|
|
||||||
RCLCPP_INFO(this->get_logger(), "Executing action goal");
|
|
||||||
const auto goal = goal_handle->get_goal();
|
|
||||||
auto result = std::make_shared<MoveitSendJointStates::Result>();
|
|
||||||
|
|
||||||
moveit::planning_interface::MoveGroupInterface move_group_interface(
|
|
||||||
node_, goal->robot_name);
|
|
||||||
move_group_interface.startStateMonitor();
|
|
||||||
|
|
||||||
std::vector<double> joint_states = goal->joint_values;
|
|
||||||
for (auto &joint : joint_states) {
|
|
||||||
RCLCPP_INFO(this->get_logger(), "Joint value %f", joint);
|
|
||||||
}
|
|
||||||
|
|
||||||
move_group_interface.setJointValueTarget(goal->joint_values);
|
|
||||||
move_group_interface.setMaxVelocityScalingFactor(
|
|
||||||
goal->joints_velocity_scaling_factor);
|
|
||||||
move_group_interface.setMaxAccelerationScalingFactor(
|
|
||||||
goal->joints_acceleration_scaling_factor);
|
|
||||||
|
|
||||||
moveit::planning_interface::MoveGroupInterface::Plan plan;
|
|
||||||
bool success = (move_group_interface.plan(plan) ==
|
|
||||||
moveit::core::MoveItErrorCode::SUCCESS);
|
|
||||||
if (success) {
|
|
||||||
RCLCPP_INFO(this->get_logger(), "Planning success");
|
|
||||||
move_group_interface.execute(plan);
|
|
||||||
// move_group_interface.move();
|
|
||||||
} else {
|
|
||||||
RCLCPP_WARN(this->get_logger(), "Failed to generate plan");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (goal_handle->is_canceling()) {
|
|
||||||
goal_handle->canceled(result);
|
|
||||||
RCLCPP_ERROR(this->get_logger(), "Action goal canceled");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
goal_handle->succeed(result);
|
|
||||||
RCLCPP_INFO(this->get_logger(), "Successfully executed action goal");
|
|
||||||
}
|
|
||||||
}; // class MoveToJointStateActionServer
|
|
||||||
|
|
||||||
} // namespace rbs_skill_actions
|
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
|
||||||
rclcpp::init(argc, argv);
|
|
||||||
rclcpp::NodeOptions node_options;
|
|
||||||
node_options.automatically_declare_parameters_from_overrides(true);
|
|
||||||
auto node =
|
|
||||||
rclcpp::Node::make_shared("move_to_joint_states", "", node_options);
|
|
||||||
|
|
||||||
rbs_skill_actions::MoveToJointStateActionServer server(node);
|
|
||||||
std::thread run_server([&server]() {
|
|
||||||
rclcpp::sleep_for(std::chrono::seconds(3));
|
|
||||||
server.init();
|
|
||||||
});
|
|
||||||
|
|
||||||
rclcpp::spin(node);
|
|
||||||
run_server.join();
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
155
rbs_skill_servers/src/mtjs_jtc.cpp
Normal file
155
rbs_skill_servers/src/mtjs_jtc.cpp
Normal file
|
@ -0,0 +1,155 @@
|
||||||
|
#include "control_msgs/action/follow_joint_trajectory.hpp"
|
||||||
|
#include "rbs_skill_servers/base_skill.hpp"
|
||||||
|
#include <memory>
|
||||||
|
#include <rbs_skill_interfaces/action/detail/moveit_send_joint_states__struct.hpp>
|
||||||
|
#include <rclcpp/logging.hpp>
|
||||||
|
#include <rclcpp_action/client.hpp>
|
||||||
|
#include <rclcpp_action/client_goal_handle.hpp>
|
||||||
|
#include <rclcpp_action/create_client.hpp>
|
||||||
|
#include <sensor_msgs/msg/joint_state.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
using MoveitSendJointStates =
|
||||||
|
rbs_skill_interfaces::action::MoveitSendJointStates;
|
||||||
|
using GoalHandleMoveitSendJointStates =
|
||||||
|
rclcpp_action::ServerGoalHandle<MoveitSendJointStates>;
|
||||||
|
using FollowJointTrajectory = control_msgs::action::FollowJointTrajectory;
|
||||||
|
using FollowJointTrajectoryGoalHandle =
|
||||||
|
rclcpp_action::ClientGoalHandle<FollowJointTrajectory>;
|
||||||
|
|
||||||
|
class MoveToJointStateActionServer : public SkillBase<MoveitSendJointStates> {
|
||||||
|
public:
|
||||||
|
explicit MoveToJointStateActionServer(
|
||||||
|
const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
|
||||||
|
: SkillBase<MoveitSendJointStates>("mtjs_jtc", options) {
|
||||||
|
|
||||||
|
m_joint_trajectory_client =
|
||||||
|
rclcpp_action::create_client<FollowJointTrajectory>(
|
||||||
|
this, "/joint_trajectory_controller/follow_joint_trajectory");
|
||||||
|
|
||||||
|
auto cbg =
|
||||||
|
this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||||
|
|
||||||
|
rclcpp::SubscriptionOptions s_options;
|
||||||
|
s_options.callback_group = cbg;
|
||||||
|
|
||||||
|
m_joint_state_subscriber =
|
||||||
|
this->create_subscription<sensor_msgs::msg::JointState>(
|
||||||
|
"/joint_states", 10,
|
||||||
|
std::bind(&MoveToJointStateActionServer::jointStateCallback, this,
|
||||||
|
std::placeholders::_1),
|
||||||
|
s_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string requiredActionController() override {
|
||||||
|
return "joint_trajectory_controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> requiredParameters() override { return {"joints"}; }
|
||||||
|
|
||||||
|
void executeAction() override {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Starting executing action goal");
|
||||||
|
|
||||||
|
auto trajectory_goal = FollowJointTrajectory::Goal();
|
||||||
|
auto joints = this->get_parameters(requiredParameters());
|
||||||
|
m_joint_names = joints.at(0).as_string_array();
|
||||||
|
|
||||||
|
trajectory_goal.trajectory.joint_names = m_joint_names;
|
||||||
|
|
||||||
|
// TODO: Better sync solution
|
||||||
|
while (m_current_joint_positions.empty()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
trajectory_goal.trajectory.points = generate_trajectory(
|
||||||
|
m_current_joint_positions, m_current_goal->joint_values,
|
||||||
|
m_current_goal->duration);
|
||||||
|
|
||||||
|
auto send_goal_options =
|
||||||
|
rclcpp_action::Client<FollowJointTrajectory>::SendGoalOptions();
|
||||||
|
send_goal_options.result_callback =
|
||||||
|
[this](const FollowJointTrajectoryGoalHandle::WrappedResult
|
||||||
|
&wrapped_result) {
|
||||||
|
if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Goal succeeded");
|
||||||
|
m_current_goal_handle->succeed(m_current_result);
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Goal failed");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_joint_trajectory_client->async_send_goal(trajectory_goal,
|
||||||
|
send_goal_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void jointStateCallback(const sensor_msgs::msg::JointState::SharedPtr msg) {
|
||||||
|
if (m_joint_names.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// RCLCPP_INFO(this->get_logger(), "Called joint positions");
|
||||||
|
|
||||||
|
if (m_joint_mame_to_index.empty()) {
|
||||||
|
m_joint_mame_to_index.reserve(m_joint_names.size());
|
||||||
|
for (size_t j = 0; j < m_joint_names.size(); ++j) {
|
||||||
|
auto it =
|
||||||
|
std::find(msg->name.begin(), msg->name.end(), m_joint_names[j]);
|
||||||
|
if (it != msg->name.end()) {
|
||||||
|
size_t index = std::distance(msg->name.begin(), it);
|
||||||
|
m_joint_mame_to_index[m_joint_names[j]] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_current_joint_positions.size() != m_joint_names.size()) {
|
||||||
|
m_current_joint_positions.resize(m_joint_names.size(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < m_joint_names.size(); ++j) {
|
||||||
|
auto index_it = m_joint_mame_to_index.find(m_joint_names[j]);
|
||||||
|
if (index_it != m_joint_mame_to_index.end()) {
|
||||||
|
m_current_joint_positions[j] = msg->position[index_it->second];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<trajectory_msgs::msg::JointTrajectoryPoint>
|
||||||
|
generate_trajectory(const std::vector<double> &start_joint_values,
|
||||||
|
const std::vector<double> &target_joint_values,
|
||||||
|
const double duration) {
|
||||||
|
|
||||||
|
const int num_points = 100;
|
||||||
|
std::vector<trajectory_msgs::msg::JointTrajectoryPoint> points;
|
||||||
|
for (int i = 0; i <= num_points; ++i) {
|
||||||
|
trajectory_msgs::msg::JointTrajectoryPoint point;
|
||||||
|
double t = static_cast<double>(i) / num_points;
|
||||||
|
for (size_t j = 0; j < target_joint_values.size(); ++j) {
|
||||||
|
double position = start_joint_values[j] +
|
||||||
|
t * (target_joint_values[j] - start_joint_values[j]);
|
||||||
|
point.positions.push_back(position);
|
||||||
|
}
|
||||||
|
point.time_from_start = rclcpp::Duration::from_seconds(t * duration);
|
||||||
|
points.push_back(point);
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
rclcpp_action::Client<FollowJointTrajectory>::SharedPtr
|
||||||
|
m_joint_trajectory_client;
|
||||||
|
rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr
|
||||||
|
m_joint_state_subscriber;
|
||||||
|
|
||||||
|
std::vector<double> m_current_joint_positions;
|
||||||
|
std::unordered_map<std::string, size_t> m_joint_mame_to_index;
|
||||||
|
std::vector<std::string> m_joint_names;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
||||||
|
|
||||||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||||||
|
RCLCPP_COMPONENTS_REGISTER_NODE(
|
||||||
|
rbs_skill_actions::MoveToJointStateActionServer);
|
183
rbs_skill_servers/src/mtp_cart.cpp
Normal file
183
rbs_skill_servers/src/mtp_cart.cpp
Normal file
|
@ -0,0 +1,183 @@
|
||||||
|
#include "Eigen/Dense"
|
||||||
|
#include <geometry_msgs/msg/pose_stamped.hpp>
|
||||||
|
#include <rclcpp/logging.hpp>
|
||||||
|
|
||||||
|
// Action libs
|
||||||
|
#include "rbs_skill_interfaces/action/moveit_send_pose.hpp"
|
||||||
|
#include "rbs_skill_servers/base_skill.hpp"
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
using MoveitSendPose = rbs_skill_interfaces::action::MoveitSendPose;
|
||||||
|
using GoalHandleMoveitSendPose =
|
||||||
|
rclcpp_action::ServerGoalHandle<MoveitSendPose>;
|
||||||
|
|
||||||
|
class CartesianMoveToPose : public SkillBase<MoveitSendPose> {
|
||||||
|
public:
|
||||||
|
explicit CartesianMoveToPose(
|
||||||
|
const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
|
||||||
|
: SkillBase<MoveitSendPose>("mtp_cart", options), m_current_step(0) {
|
||||||
|
|
||||||
|
// Initialize publisher for target poses
|
||||||
|
auto cbg =
|
||||||
|
this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||||
|
|
||||||
|
rclcpp::PublisherOptions p_options;
|
||||||
|
p_options.callback_group = cbg;
|
||||||
|
|
||||||
|
m_publisher = this->create_publisher<geometry_msgs::msg::PoseStamped>(
|
||||||
|
"cartesian_motion_controller/target_frame", 10, p_options);
|
||||||
|
|
||||||
|
m_current_pose = std::make_shared<geometry_msgs::msg::PoseStamped>();
|
||||||
|
|
||||||
|
rclcpp::SubscriptionOptions s_options;
|
||||||
|
s_options.callback_group = cbg;
|
||||||
|
|
||||||
|
m_current_pose_subscriber =
|
||||||
|
this->create_subscription<geometry_msgs::msg::PoseStamped>(
|
||||||
|
"cartesian_motion_controller/current_pose", 10,
|
||||||
|
std::bind(&CartesianMoveToPose::on_pose_callback, this,
|
||||||
|
std::placeholders::_1),
|
||||||
|
s_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string requiredActionController() override {
|
||||||
|
return "cartesian_motion_controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> requiredParameters() override {
|
||||||
|
return {"end_effector_link", "robot_base_link"};
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeAction() override {
|
||||||
|
m_base_link = this->get_parameter("robot_base_link").as_string();
|
||||||
|
|
||||||
|
m_trajectory =
|
||||||
|
interpolate(m_current_pose->pose, m_current_goal->target_pose);
|
||||||
|
m_current_step = 0;
|
||||||
|
|
||||||
|
m_total_time = m_current_goal->duration;
|
||||||
|
m_step_time =
|
||||||
|
m_total_time / static_cast<double>(m_trajectory.size()) * 1000.0;
|
||||||
|
|
||||||
|
m_trajectory_timer = this->create_wall_timer(
|
||||||
|
std::chrono::milliseconds(static_cast<int>(m_step_time)),
|
||||||
|
[this]() { adjust_and_publish_pose(); });
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
rclcpp::Publisher<geometry_msgs::msg::PoseStamped>::SharedPtr m_publisher;
|
||||||
|
rclcpp::Subscription<geometry_msgs::msg::PoseStamped>::SharedPtr
|
||||||
|
m_current_pose_subscriber;
|
||||||
|
geometry_msgs::msg::PoseStamped::SharedPtr m_current_pose;
|
||||||
|
std::string m_base_link;
|
||||||
|
double m_threshold_distance = 0.02;
|
||||||
|
|
||||||
|
std::vector<geometry_msgs::msg::Pose> m_trajectory;
|
||||||
|
size_t m_current_step;
|
||||||
|
rclcpp::TimerBase::SharedPtr m_trajectory_timer;
|
||||||
|
double m_total_time;
|
||||||
|
double m_step_time;
|
||||||
|
|
||||||
|
void adjust_and_publish_pose() {
|
||||||
|
if (m_current_step < m_trajectory.size()) {
|
||||||
|
publish_pose(m_trajectory[m_current_step++]);
|
||||||
|
} else {
|
||||||
|
double distance =
|
||||||
|
calculate_distance(m_current_pose->pose, m_current_goal->target_pose);
|
||||||
|
if (distance <= m_threshold_distance) {
|
||||||
|
m_current_result->success = true;
|
||||||
|
m_current_goal_handle->succeed(m_current_result);
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Goal successfully completed");
|
||||||
|
m_trajectory_timer->cancel();
|
||||||
|
} else {
|
||||||
|
publish_pose(m_trajectory.back());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double calculate_distance(const geometry_msgs::msg::Pose &p1,
|
||||||
|
const geometry_msgs::msg::Pose &p2) {
|
||||||
|
Eigen::Vector3d pos1(p1.position.x, p1.position.y, p1.position.z);
|
||||||
|
Eigen::Vector3d pos2(p2.position.x, p2.position.y, p2.position.z);
|
||||||
|
|
||||||
|
double position_distance = (pos1 - pos2).norm();
|
||||||
|
|
||||||
|
Eigen::Quaterniond orient1 = normalize_orientation(p1.orientation);
|
||||||
|
Eigen::Quaterniond orient2 = normalize_orientation(p2.orientation);
|
||||||
|
|
||||||
|
return position_distance + orient1.angularDistance(orient2);
|
||||||
|
}
|
||||||
|
|
||||||
|
Eigen::Quaterniond
|
||||||
|
normalize_orientation(const geometry_msgs::msg::Quaternion &q) {
|
||||||
|
Eigen::Quaterniond orientation(q.w, q.x, q.y, q.z);
|
||||||
|
orientation.normalize();
|
||||||
|
|
||||||
|
if (orientation.norm() == 0) {
|
||||||
|
RCLCPP_FATAL(this->get_logger(),
|
||||||
|
"Quaternion has zero norm; normalization failed.");
|
||||||
|
throw std::runtime_error("Quaternion normalization failed.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<geometry_msgs::msg::Pose>
|
||||||
|
interpolate(const geometry_msgs::msg::Pose &start_pose,
|
||||||
|
const geometry_msgs::msg::Pose &end_pose) {
|
||||||
|
std::vector<geometry_msgs::msg::Pose> trajectory;
|
||||||
|
Eigen::Vector3d start_position(start_pose.position.x, start_pose.position.y,
|
||||||
|
start_pose.position.z);
|
||||||
|
Eigen::Vector3d end_position(end_pose.position.x, end_pose.position.y,
|
||||||
|
end_pose.position.z);
|
||||||
|
|
||||||
|
Eigen::Quaterniond start_orientation =
|
||||||
|
normalize_orientation(start_pose.orientation);
|
||||||
|
Eigen::Quaterniond end_orientation =
|
||||||
|
normalize_orientation(end_pose.orientation);
|
||||||
|
|
||||||
|
double distance = (end_position - start_position).norm();
|
||||||
|
int num_steps = static_cast<int>(distance / 0.01);
|
||||||
|
|
||||||
|
for (int i = 0; i <= num_steps; ++i) {
|
||||||
|
double t = static_cast<double>(i) / num_steps;
|
||||||
|
|
||||||
|
Eigen::Vector3d interpolated_position =
|
||||||
|
start_position + t * (end_position - start_position);
|
||||||
|
Eigen::Quaterniond interpolated_orientation =
|
||||||
|
start_orientation.slerp(t, end_orientation);
|
||||||
|
|
||||||
|
geometry_msgs::msg::Pose interpolated_pose;
|
||||||
|
interpolated_pose.position.x = interpolated_position.x();
|
||||||
|
interpolated_pose.position.y = interpolated_position.y();
|
||||||
|
interpolated_pose.position.z = interpolated_position.z();
|
||||||
|
interpolated_pose.orientation.x = interpolated_orientation.x();
|
||||||
|
interpolated_pose.orientation.y = interpolated_orientation.y();
|
||||||
|
interpolated_pose.orientation.z = interpolated_orientation.z();
|
||||||
|
interpolated_pose.orientation.w = interpolated_orientation.w();
|
||||||
|
|
||||||
|
trajectory.push_back(interpolated_pose);
|
||||||
|
}
|
||||||
|
|
||||||
|
return trajectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
void publish_pose(const geometry_msgs::msg::Pose &pose) {
|
||||||
|
geometry_msgs::msg::PoseStamped tp;
|
||||||
|
tp.pose = pose;
|
||||||
|
tp.header.stamp = this->now();
|
||||||
|
tp.header.frame_id = m_base_link;
|
||||||
|
m_publisher->publish(tp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void on_pose_callback(const geometry_msgs::msg::PoseStamped::SharedPtr msg) {
|
||||||
|
m_current_pose = msg;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
||||||
|
|
||||||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||||||
|
RCLCPP_COMPONENTS_REGISTER_NODE(rbs_skill_actions::CartesianMoveToPose);
|
224
rbs_skill_servers/src/mtp_jtc.cpp
Normal file
224
rbs_skill_servers/src/mtp_jtc.cpp
Normal file
|
@ -0,0 +1,224 @@
|
||||||
|
#include "Eigen/Dense"
|
||||||
|
#include "control_msgs/action/follow_joint_trajectory.hpp"
|
||||||
|
#include "kdl/chainiksolverpos_lma.hpp"
|
||||||
|
#include "rbs_skill_servers/base_skill.hpp"
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
#include <kdl/chain.hpp>
|
||||||
|
#include <kdl/chainiksolver.hpp>
|
||||||
|
#include <kdl/chainiksolvervel_wdls.hpp>
|
||||||
|
#include <kdl/chainjnttojacsolver.hpp>
|
||||||
|
#include <kdl/frames.hpp>
|
||||||
|
#include <kdl/jntarray.hpp>
|
||||||
|
#include <kdl/tree.hpp>
|
||||||
|
#include <kdl_parser/kdl_parser.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <rbs_skill_interfaces/action/detail/moveit_send_pose__struct.hpp>
|
||||||
|
#include <rclcpp/logging.hpp>
|
||||||
|
#include <rclcpp/parameter_client.hpp>
|
||||||
|
#include <rclcpp_action/client.hpp>
|
||||||
|
#include <rclcpp_action/client_goal_handle.hpp>
|
||||||
|
#include <rclcpp_action/create_client.hpp>
|
||||||
|
#include <sensor_msgs/msg/joint_state.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <tf2_eigen/tf2_eigen.hpp>
|
||||||
|
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
using MoveitSendPose = rbs_skill_interfaces::action::MoveitSendPose;
|
||||||
|
using GoalHandleMoveitSendJointStates =
|
||||||
|
rclcpp_action::ServerGoalHandle<MoveitSendPose>;
|
||||||
|
using FollowJointTrajectory = control_msgs::action::FollowJointTrajectory;
|
||||||
|
using FollowJointTrajectoryGoalHandle =
|
||||||
|
rclcpp_action::ClientGoalHandle<FollowJointTrajectory>;
|
||||||
|
|
||||||
|
class MoveToPose : public SkillBase<MoveitSendPose> {
|
||||||
|
public:
|
||||||
|
explicit MoveToPose(
|
||||||
|
const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
|
||||||
|
: SkillBase<MoveitSendPose>("mtp_jtc", options) {
|
||||||
|
|
||||||
|
m_joint_trajectory_client =
|
||||||
|
rclcpp_action::create_client<FollowJointTrajectory>(
|
||||||
|
this, "/joint_trajectory_controller/follow_joint_trajectory");
|
||||||
|
|
||||||
|
auto cbg =
|
||||||
|
this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||||
|
|
||||||
|
rclcpp::SubscriptionOptions s_options;
|
||||||
|
s_options.callback_group = cbg;
|
||||||
|
|
||||||
|
m_joint_state_subscriber =
|
||||||
|
this->create_subscription<sensor_msgs::msg::JointState>(
|
||||||
|
"/joint_states", 10,
|
||||||
|
std::bind(&MoveToPose::jointStateCallback, this,
|
||||||
|
std::placeholders::_1),
|
||||||
|
s_options);
|
||||||
|
this->declare_parameter("robot_description", "");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string requiredActionController() override {
|
||||||
|
return "joint_trajectory_controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> requiredParameters() override { return {"joints"}; }
|
||||||
|
|
||||||
|
void executeAction() override {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Starting executing action goal");
|
||||||
|
|
||||||
|
auto trajectory_goal = FollowJointTrajectory::Goal();
|
||||||
|
auto joints = this->get_parameters(requiredParameters());
|
||||||
|
m_joint_names = joints.at(0).as_string_array();
|
||||||
|
|
||||||
|
trajectory_goal.trajectory.joint_names = m_joint_names;
|
||||||
|
|
||||||
|
// TODO: Better sync solution
|
||||||
|
while (m_current_joint_positions.empty()) {
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> target_joint_values;
|
||||||
|
solveIK(target_joint_values);
|
||||||
|
|
||||||
|
trajectory_goal.trajectory.points =
|
||||||
|
generate_trajectory(m_current_joint_positions, target_joint_values,
|
||||||
|
m_current_goal->duration);
|
||||||
|
|
||||||
|
auto send_goal_options =
|
||||||
|
rclcpp_action::Client<FollowJointTrajectory>::SendGoalOptions();
|
||||||
|
send_goal_options.result_callback =
|
||||||
|
[this](const FollowJointTrajectoryGoalHandle::WrappedResult
|
||||||
|
&wrapped_result) {
|
||||||
|
if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Goal succeeded");
|
||||||
|
m_current_goal_handle->succeed(m_current_result);
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Goal failed");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_joint_trajectory_client->async_send_goal(trajectory_goal,
|
||||||
|
send_goal_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void jointStateCallback(const sensor_msgs::msg::JointState::SharedPtr msg) {
|
||||||
|
if (m_joint_names.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
RCLCPP_WARN(this->get_logger(), "Called joint positions");
|
||||||
|
|
||||||
|
if (m_joint_mame_to_index.empty()) {
|
||||||
|
m_joint_mame_to_index.reserve(m_joint_names.size());
|
||||||
|
for (size_t j = 0; j < m_joint_names.size(); ++j) {
|
||||||
|
auto it =
|
||||||
|
std::find(msg->name.begin(), msg->name.end(), m_joint_names[j]);
|
||||||
|
if (it != msg->name.end()) {
|
||||||
|
size_t index = std::distance(msg->name.begin(), it);
|
||||||
|
m_joint_mame_to_index[m_joint_names[j]] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_current_joint_positions.size() != m_joint_names.size()) {
|
||||||
|
m_current_joint_positions.resize(m_joint_names.size(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < m_joint_names.size(); ++j) {
|
||||||
|
auto index_it = m_joint_mame_to_index.find(m_joint_names[j]);
|
||||||
|
if (index_it != m_joint_mame_to_index.end()) {
|
||||||
|
m_current_joint_positions[j] = msg->position[index_it->second];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<trajectory_msgs::msg::JointTrajectoryPoint>
|
||||||
|
generate_trajectory(const std::vector<double> &start_joint_values,
|
||||||
|
const std::vector<double> &target_joint_values,
|
||||||
|
const double duration) {
|
||||||
|
|
||||||
|
const int num_points = 100;
|
||||||
|
std::vector<trajectory_msgs::msg::JointTrajectoryPoint> points;
|
||||||
|
for (int i = 0; i <= num_points; ++i) {
|
||||||
|
trajectory_msgs::msg::JointTrajectoryPoint point;
|
||||||
|
double t = static_cast<double>(i) / num_points;
|
||||||
|
for (size_t j = 0; j < target_joint_values.size(); ++j) {
|
||||||
|
double position = start_joint_values[j] +
|
||||||
|
t * (target_joint_values[j] - start_joint_values[j]);
|
||||||
|
point.positions.push_back(position);
|
||||||
|
}
|
||||||
|
point.time_from_start = rclcpp::Duration::from_seconds(t * duration);
|
||||||
|
points.push_back(point);
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
void solveIK(std::vector<double> &out) {
|
||||||
|
KDL::JntArray q_in(m_joint_names.size());
|
||||||
|
for (size_t i = 0; i < m_joint_names.size(); ++i) {
|
||||||
|
q_in(i) = m_current_joint_positions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
KDL::JntArray q_out(m_joint_names.size());
|
||||||
|
|
||||||
|
Eigen::Affine3d target_pose;
|
||||||
|
Eigen::fromMsg(m_current_goal->target_pose, target_pose);
|
||||||
|
|
||||||
|
KDL::Frame target_pose_kdl(
|
||||||
|
KDL::Rotation(target_pose(0, 0), target_pose(0, 1), target_pose(0, 2),
|
||||||
|
target_pose(1, 0), target_pose(1, 1), target_pose(1, 2),
|
||||||
|
target_pose(2, 0), target_pose(2, 1), target_pose(2, 2)),
|
||||||
|
KDL::Vector(target_pose.translation().x(),
|
||||||
|
target_pose.translation().y(),
|
||||||
|
target_pose.translation().z()));
|
||||||
|
|
||||||
|
const std::string m_base_link = "base_link";
|
||||||
|
const std::string m_ee_link = "gripper_grasp_point";
|
||||||
|
|
||||||
|
auto robot_description =
|
||||||
|
this->get_parameter("robot_description").as_string();
|
||||||
|
|
||||||
|
KDL::Tree kdl_tree;
|
||||||
|
if (!kdl_parser::treeFromString(robot_description, kdl_tree)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to parse KDL tree from robot description.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDL::Chain kdl_chain;
|
||||||
|
if (!kdl_tree.getChain(m_base_link, m_ee_link, kdl_chain)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to get KDL chain from base to end-effector.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto ik_solver =
|
||||||
|
std::make_unique<KDL::ChainIkSolverPos_LMA>(kdl_chain, 1e-5, 500);
|
||||||
|
|
||||||
|
if (ik_solver->CartToJnt(q_in, target_pose_kdl, q_out) >= 0) {
|
||||||
|
out.resize(q_out.rows());
|
||||||
|
for (size_t i = 0; i < out.size(); i++) {
|
||||||
|
out[i] = q_out(i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "IK solution not found.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rclcpp_action::Client<FollowJointTrajectory>::SharedPtr
|
||||||
|
m_joint_trajectory_client;
|
||||||
|
rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr
|
||||||
|
m_joint_state_subscriber;
|
||||||
|
|
||||||
|
std::vector<double> m_current_joint_positions;
|
||||||
|
std::unordered_map<std::string, size_t> m_joint_mame_to_index;
|
||||||
|
std::vector<std::string> m_joint_names;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
||||||
|
|
||||||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||||||
|
RCLCPP_COMPONENTS_REGISTER_NODE(rbs_skill_actions::MoveToPose);
|
324
rbs_skill_servers/src/mtp_jtc_cart.cpp
Normal file
324
rbs_skill_servers/src/mtp_jtc_cart.cpp
Normal file
|
@ -0,0 +1,324 @@
|
||||||
|
#include "Eigen/Dense"
|
||||||
|
#include "control_msgs/action/follow_joint_trajectory.hpp"
|
||||||
|
#include "kdl/chainfksolverpos_recursive.hpp"
|
||||||
|
#include "kdl/chainiksolverpos_lma.hpp"
|
||||||
|
#include "rbs_skill_servers/base_skill.hpp"
|
||||||
|
#include <Eigen/src/Geometry/Transform.h>
|
||||||
|
#include <cstddef>
|
||||||
|
#include <iterator>
|
||||||
|
#include <kdl/chain.hpp>
|
||||||
|
#include <kdl/chainiksolver.hpp>
|
||||||
|
#include <kdl/chainiksolvervel_wdls.hpp>
|
||||||
|
#include <kdl/chainjnttojacsolver.hpp>
|
||||||
|
#include <kdl/frames.hpp>
|
||||||
|
#include <kdl/jntarray.hpp>
|
||||||
|
#include <kdl/tree.hpp>
|
||||||
|
#include <kdl_parser/kdl_parser.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <rbs_skill_interfaces/action/detail/moveit_send_pose__struct.hpp>
|
||||||
|
#include <rclcpp/logging.hpp>
|
||||||
|
#include <rclcpp/parameter_client.hpp>
|
||||||
|
#include <rclcpp_action/client.hpp>
|
||||||
|
#include <rclcpp_action/client_goal_handle.hpp>
|
||||||
|
#include <rclcpp_action/create_client.hpp>
|
||||||
|
#include <sensor_msgs/msg/joint_state.hpp>
|
||||||
|
#include <string>
|
||||||
|
#include <tf2_eigen/tf2_eigen.hpp>
|
||||||
|
#include <tf2_geometry_msgs/tf2_geometry_msgs.hpp>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
using MoveitSendPose = rbs_skill_interfaces::action::MoveitSendPose;
|
||||||
|
using GoalHandleMoveitSendJointStates =
|
||||||
|
rclcpp_action::ServerGoalHandle<MoveitSendPose>;
|
||||||
|
using FollowJointTrajectory = control_msgs::action::FollowJointTrajectory;
|
||||||
|
using FollowJointTrajectoryGoalHandle =
|
||||||
|
rclcpp_action::ClientGoalHandle<FollowJointTrajectory>;
|
||||||
|
|
||||||
|
class MoveToPoseJtcCartesian : public SkillBase<MoveitSendPose> {
|
||||||
|
public:
|
||||||
|
explicit MoveToPoseJtcCartesian(
|
||||||
|
const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
|
||||||
|
: SkillBase<MoveitSendPose>("mtp_jtc_cart", options) {
|
||||||
|
|
||||||
|
m_joint_trajectory_client =
|
||||||
|
rclcpp_action::create_client<FollowJointTrajectory>(
|
||||||
|
this, "/joint_trajectory_controller/follow_joint_trajectory");
|
||||||
|
|
||||||
|
auto cbg =
|
||||||
|
this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
|
||||||
|
|
||||||
|
rclcpp::SubscriptionOptions s_options;
|
||||||
|
s_options.callback_group = cbg;
|
||||||
|
|
||||||
|
m_joint_state_subscriber =
|
||||||
|
this->create_subscription<sensor_msgs::msg::JointState>(
|
||||||
|
"/joint_states", 10,
|
||||||
|
std::bind(&MoveToPoseJtcCartesian::jointStateCallback, this,
|
||||||
|
std::placeholders::_1),
|
||||||
|
s_options);
|
||||||
|
this->declare_parameter("robot_description", "");
|
||||||
|
this->declare_parameter("base_link", "");
|
||||||
|
this->declare_parameter("robot_ee_link", "");
|
||||||
|
|
||||||
|
auto robot_description =
|
||||||
|
this->get_parameter("robot_description").as_string();
|
||||||
|
KDL::Tree kdl_tree;
|
||||||
|
if (!kdl_parser::treeFromString(robot_description, kdl_tree)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to obtain KDL tree from the robot description.");
|
||||||
|
|
||||||
|
throw std::runtime_error("KDL Tree initialization failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
auto base_link = this->get_parameter("base_link").as_string();
|
||||||
|
auto robot_ee_link = this->get_parameter("robot_ee_link").as_string();
|
||||||
|
if (base_link.empty() or robot_ee_link.empty()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Describe robot end-effector link and base link to continue");
|
||||||
|
throw std::runtime_error("Describe robot end-effector link and base link to continue");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!kdl_tree.getChain(base_link, robot_ee_link, m_kdl_chain)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to obtain KDL chain from base to end-effector.");
|
||||||
|
throw std::runtime_error("KDL Chain initialization failed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
std::string requiredActionController() override {
|
||||||
|
return "joint_trajectory_controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> requiredParameters() override { return {"joints"}; }
|
||||||
|
|
||||||
|
void executeAction() override {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Starting executing action goal");
|
||||||
|
|
||||||
|
auto trajectory_goal = FollowJointTrajectory::Goal();
|
||||||
|
auto joints = this->get_parameters(requiredParameters());
|
||||||
|
m_joint_names = joints.at(0).as_string_array();
|
||||||
|
|
||||||
|
trajectory_goal.trajectory.joint_names = m_joint_names;
|
||||||
|
|
||||||
|
const int max_wait_iterations = 100;
|
||||||
|
int wait_count = 0;
|
||||||
|
while (m_current_joint_positions.empty() &&
|
||||||
|
wait_count++ < max_wait_iterations) {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(10));
|
||||||
|
}
|
||||||
|
if (m_current_joint_positions.empty()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Joint positions were not received in time");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<double> target_joint_values;
|
||||||
|
Eigen::Affine3d target_pose;
|
||||||
|
Eigen::fromMsg(m_current_goal->target_pose, target_pose);
|
||||||
|
if (!solveIK(target_pose, target_joint_values)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"IK solution not found for goal position");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
trajectory_goal.trajectory.points =
|
||||||
|
generate_trajectory(m_current_joint_positions, target_joint_values,
|
||||||
|
m_current_goal->duration);
|
||||||
|
|
||||||
|
auto send_goal_options =
|
||||||
|
rclcpp_action::Client<FollowJointTrajectory>::SendGoalOptions();
|
||||||
|
send_goal_options.result_callback =
|
||||||
|
[this](const FollowJointTrajectoryGoalHandle::WrappedResult
|
||||||
|
&wrapped_result) {
|
||||||
|
if (wrapped_result.code == rclcpp_action::ResultCode::SUCCEEDED) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Goal succeeded");
|
||||||
|
m_current_goal_handle->succeed(m_current_result);
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Goal failed");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
m_joint_trajectory_client->async_send_goal(trajectory_goal,
|
||||||
|
send_goal_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void jointStateCallback(const sensor_msgs::msg::JointState::SharedPtr msg) {
|
||||||
|
if (m_joint_names.empty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (m_joint_name_to_index.empty()) {
|
||||||
|
m_joint_name_to_index.reserve(m_joint_names.size());
|
||||||
|
for (size_t j = 0; j < m_joint_names.size(); ++j) {
|
||||||
|
auto it =
|
||||||
|
std::find(msg->name.begin(), msg->name.end(), m_joint_names[j]);
|
||||||
|
if (it != msg->name.end()) {
|
||||||
|
size_t index = std::distance(msg->name.begin(), it);
|
||||||
|
m_joint_name_to_index[m_joint_names[j]] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_current_joint_positions.size() != m_joint_names.size()) {
|
||||||
|
m_current_joint_positions.resize(m_joint_names.size(), 0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t j = 0; j < m_joint_names.size(); ++j) {
|
||||||
|
auto index_it = m_joint_name_to_index.find(m_joint_names[j]);
|
||||||
|
if (index_it != m_joint_name_to_index.end()) {
|
||||||
|
m_current_joint_positions[j] = msg->position[index_it->second];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<trajectory_msgs::msg::JointTrajectoryPoint>
|
||||||
|
generate_trajectory(const std::vector<double> &start_joint_values,
|
||||||
|
const std::vector<double> &target_joint_values,
|
||||||
|
const double duration) {
|
||||||
|
const int num_points = 100;
|
||||||
|
std::vector<trajectory_msgs::msg::JointTrajectoryPoint> points;
|
||||||
|
|
||||||
|
KDL::Frame start_pose_kdl, target_pose_kdl;
|
||||||
|
if (!getEndEffectorPose(start_joint_values, start_pose_kdl) ||
|
||||||
|
!getEndEffectorPose(target_joint_values, target_pose_kdl)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to get initial or target end-effector pose");
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eigen::Affine3d start_pose = KDLFrameToEigen(start_pose_kdl);
|
||||||
|
Eigen::Affine3d target_pose = KDLFrameToEigen(target_pose_kdl);
|
||||||
|
|
||||||
|
for (int i = 0; i <= num_points; ++i) {
|
||||||
|
trajectory_msgs::msg::JointTrajectoryPoint point;
|
||||||
|
double t = static_cast<double>(i) / num_points;
|
||||||
|
|
||||||
|
Eigen::Vector3d start_translation = start_pose.translation();
|
||||||
|
Eigen::Vector3d target_translation = target_pose.translation();
|
||||||
|
Eigen::Vector3d interpolated_translation =
|
||||||
|
(1.0 - t) * start_translation + t * target_translation;
|
||||||
|
Eigen::Translation3d interpolated_translation_transform(
|
||||||
|
interpolated_translation);
|
||||||
|
|
||||||
|
Eigen::Quaterniond start_quaternion(start_pose.rotation());
|
||||||
|
Eigen::Quaterniond target_quaternion(target_pose.rotation());
|
||||||
|
|
||||||
|
Eigen::Quaterniond interpolated_quaternion =
|
||||||
|
start_quaternion.slerp(t, target_quaternion);
|
||||||
|
|
||||||
|
Eigen::Affine3d interpolated_pose =
|
||||||
|
interpolated_translation_transform * interpolated_quaternion;
|
||||||
|
|
||||||
|
std::vector<double> ik_joint_values;
|
||||||
|
if (!solveIK(interpolated_pose, ik_joint_values)) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "IK solution not found for point %d",
|
||||||
|
i);
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
point.positions = ik_joint_values;
|
||||||
|
point.time_from_start = rclcpp::Duration::from_seconds(t * duration);
|
||||||
|
points.push_back(point);
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool getEndEffectorPose(const std::vector<double> &joint_positions,
|
||||||
|
KDL::Frame &end_effector_pose) {
|
||||||
|
|
||||||
|
if (joint_positions.size() != m_joint_names.size()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Mismatch between provided joint "
|
||||||
|
"positions and expected joint names.");
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Joint pos size: %zu",
|
||||||
|
joint_positions.size());
|
||||||
|
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Joint names size: %zu",
|
||||||
|
m_joint_names.size());
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unordered_set<std::string> available_joints(m_joint_names.begin(),
|
||||||
|
m_joint_names.end());
|
||||||
|
if (available_joints.size() != m_joint_names.size()) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Duplicate joints detected in joint names list.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
KDL::JntArray q_in(joint_positions.size());
|
||||||
|
for (size_t i = 0; i < joint_positions.size(); ++i) {
|
||||||
|
q_in(i) = joint_positions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
KDL::ChainFkSolverPos_recursive fk_solver(m_kdl_chain);
|
||||||
|
if (fk_solver.JntToCart(q_in, end_effector_pose) < 0) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(),
|
||||||
|
"Failed to compute FK for the specified joint positions.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Eigen::Affine3d KDLFrameToEigen(const KDL::Frame &frame) {
|
||||||
|
Eigen::Affine3d transform;
|
||||||
|
for (int i = 0; i < 3; ++i) {
|
||||||
|
for (int j = 0; j < 3; ++j) {
|
||||||
|
transform(i, j) = frame.M(i, j);
|
||||||
|
}
|
||||||
|
transform(i, 3) = frame.p[i];
|
||||||
|
}
|
||||||
|
transform(3, 3) = 1.0;
|
||||||
|
return transform;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool solveIK(const Eigen::Affine3d &target_pose, std::vector<double> &out) {
|
||||||
|
KDL::JntArray q_in(m_joint_names.size());
|
||||||
|
for (size_t i = 0; i < m_joint_names.size(); ++i) {
|
||||||
|
q_in(i) = m_current_joint_positions[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
KDL::JntArray q_out(m_joint_names.size());
|
||||||
|
|
||||||
|
KDL::Frame target_pose_kdl(
|
||||||
|
KDL::Rotation(target_pose(0, 0), target_pose(0, 1), target_pose(0, 2),
|
||||||
|
target_pose(1, 0), target_pose(1, 1), target_pose(1, 2),
|
||||||
|
target_pose(2, 0), target_pose(2, 1), target_pose(2, 2)),
|
||||||
|
KDL::Vector(target_pose.translation().x(),
|
||||||
|
target_pose.translation().y(),
|
||||||
|
target_pose.translation().z()));
|
||||||
|
|
||||||
|
auto ik_solver =
|
||||||
|
std::make_unique<KDL::ChainIkSolverPos_LMA>(m_kdl_chain, 1e-5, 500);
|
||||||
|
|
||||||
|
if (ik_solver->CartToJnt(q_in, target_pose_kdl, q_out) >= 0) {
|
||||||
|
out.resize(q_out.rows());
|
||||||
|
for (size_t i = 0; i < out.size(); i++) {
|
||||||
|
out[i] = q_out(i);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "IK solution not found.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rclcpp_action::Client<FollowJointTrajectory>::SharedPtr
|
||||||
|
m_joint_trajectory_client;
|
||||||
|
rclcpp::Subscription<sensor_msgs::msg::JointState>::SharedPtr
|
||||||
|
m_joint_state_subscriber;
|
||||||
|
|
||||||
|
std::vector<double> m_current_joint_positions;
|
||||||
|
std::unordered_map<std::string, size_t> m_joint_name_to_index;
|
||||||
|
std::vector<std::string> m_joint_names;
|
||||||
|
KDL::Chain m_kdl_chain;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
||||||
|
|
||||||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||||||
|
RCLCPP_COMPONENTS_REGISTER_NODE(rbs_skill_actions::MoveToPoseJtcCartesian);
|
68
rbs_skill_servers/src/mtp_moveit.cpp
Normal file
68
rbs_skill_servers/src/mtp_moveit.cpp
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
#include "moveit/move_group_interface/move_group_interface.h"
|
||||||
|
#include "rbs_skill_interfaces/action/moveit_send_pose.hpp"
|
||||||
|
#include "rbs_skill_servers/base_skill.hpp"
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
using MoveitSendPose = rbs_skill_interfaces::action::MoveitSendPose;
|
||||||
|
|
||||||
|
class MoveitMtp : public SkillBase<MoveitSendPose> {
|
||||||
|
public:
|
||||||
|
explicit MoveitMtp(const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
|
||||||
|
: SkillBase("mtp_moveit", options) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string requiredActionController() override {
|
||||||
|
return "joint_trajectory_controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeAction() override {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Executing action goal");
|
||||||
|
|
||||||
|
moveit::planning_interface::MoveGroupInterface move_group_interface(
|
||||||
|
this->shared_from_this(), m_current_goal->robot_name);
|
||||||
|
move_group_interface.startStateMonitor();
|
||||||
|
|
||||||
|
move_group_interface.setPoseTarget(m_current_goal->target_pose);
|
||||||
|
move_group_interface.setMaxVelocityScalingFactor(
|
||||||
|
m_current_goal->end_effector_velocity);
|
||||||
|
move_group_interface.setMaxAccelerationScalingFactor(
|
||||||
|
m_current_goal->end_effector_acceleration);
|
||||||
|
moveit::planning_interface::MoveGroupInterface::Plan plan;
|
||||||
|
moveit::core::MoveItErrorCode plan_err_code =
|
||||||
|
move_group_interface.plan(plan);
|
||||||
|
if (plan_err_code == moveit::core::MoveItErrorCode::INVALID_MOTION_PLAN) {
|
||||||
|
move_group_interface.plan(plan);
|
||||||
|
}
|
||||||
|
if (plan_err_code == moveit::core::MoveItErrorCode::SUCCESS) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Planning success");
|
||||||
|
// move_group_interface.execute(plan);
|
||||||
|
moveit::core::MoveItErrorCode move_err_code =
|
||||||
|
move_group_interface.execute(plan);
|
||||||
|
if (move_err_code == moveit::core::MoveItErrorCode::SUCCESS) {
|
||||||
|
m_current_result->success = true;
|
||||||
|
m_current_goal_handle->succeed(m_current_result);
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Successfully executed action goal");
|
||||||
|
} else if (move_err_code == moveit::core::MoveItErrorCode::FAILURE) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Failure in move:");
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
RCLCPP_WARN_STREAM(this->get_logger(),
|
||||||
|
"Failed to generate plan because "
|
||||||
|
<< error_code_to_string(plan_err_code));
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_current_goal_handle->is_canceling()) {
|
||||||
|
m_current_goal_handle->canceled(m_current_result);
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Action goal canceled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // class MoveToPoseActionServer
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
||||||
|
|
||||||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||||||
|
RCLCPP_COMPONENTS_REGISTER_NODE(rbs_skill_actions::MoveitMtp);
|
95
rbs_skill_servers/src/mtp_moveit_cart.cpp
Normal file
95
rbs_skill_servers/src/mtp_moveit_cart.cpp
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
#include "moveit/move_group_interface/move_group_interface.h"
|
||||||
|
#include "rbs_skill_interfaces/action/moveit_send_pose.hpp"
|
||||||
|
#include "rbs_skill_servers/base_skill.hpp"
|
||||||
|
#include <moveit/robot_trajectory/robot_trajectory.h>
|
||||||
|
#include <moveit/trajectory_processing/time_optimal_trajectory_generation.h>
|
||||||
|
#include <rclcpp/logging.hpp>
|
||||||
|
|
||||||
|
namespace rbs_skill_actions {
|
||||||
|
|
||||||
|
using MoveitSendPose = rbs_skill_interfaces::action::MoveitSendPose;
|
||||||
|
|
||||||
|
class MoveitMtpCart : public SkillBase<MoveitSendPose> {
|
||||||
|
public:
|
||||||
|
explicit MoveitMtpCart(const rclcpp::NodeOptions &options = rclcpp::NodeOptions())
|
||||||
|
: SkillBase("mtp_moveit_cart", options) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string requiredActionController() override {
|
||||||
|
return "joint_trajectory_controller";
|
||||||
|
}
|
||||||
|
|
||||||
|
void executeAction() override {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Executing action goal");
|
||||||
|
|
||||||
|
moveit::planning_interface::MoveGroupInterface move_group_interface(
|
||||||
|
this->shared_from_this(), m_current_goal->robot_name);
|
||||||
|
move_group_interface.startStateMonitor();
|
||||||
|
|
||||||
|
moveit::core::RobotState start_state(
|
||||||
|
*move_group_interface.getCurrentState());
|
||||||
|
|
||||||
|
std::vector<geometry_msgs::msg::Pose> waypoints;
|
||||||
|
auto current_pose = move_group_interface.getCurrentPose();
|
||||||
|
geometry_msgs::msg::Pose target_pose = m_current_goal->target_pose;
|
||||||
|
waypoints.push_back(target_pose);
|
||||||
|
|
||||||
|
RCLCPP_INFO(this->get_logger(), "New cartesian target pose [%f, %f, %f]",
|
||||||
|
target_pose.position.x, target_pose.position.y,
|
||||||
|
target_pose.position.z);
|
||||||
|
|
||||||
|
moveit_msgs::msg::RobotTrajectory trajectory;
|
||||||
|
const double jump_threshold = 0.0;
|
||||||
|
const double eef_step = 0.001;
|
||||||
|
double fraction = move_group_interface.computeCartesianPath(
|
||||||
|
waypoints, eef_step, jump_threshold, trajectory);
|
||||||
|
|
||||||
|
robot_trajectory::RobotTrajectory rt(
|
||||||
|
move_group_interface.getCurrentState()->getRobotModel(),
|
||||||
|
m_current_goal->robot_name);
|
||||||
|
|
||||||
|
rt.setRobotTrajectoryMsg(*move_group_interface.getCurrentState(), trajectory);
|
||||||
|
|
||||||
|
trajectory_processing::TimeOptimalTrajectoryGeneration tp;
|
||||||
|
|
||||||
|
bool su = tp.computeTimeStamps(rt);
|
||||||
|
if (!su) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Failed to compute timestamp of trajectory");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
rt.getRobotTrajectoryMsg(trajectory);
|
||||||
|
|
||||||
|
moveit::planning_interface::MoveGroupInterface::Plan plan;
|
||||||
|
plan.trajectory_ = trajectory;
|
||||||
|
|
||||||
|
if (fraction > 0) {
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Planning success");
|
||||||
|
moveit::core::MoveItErrorCode execute_err_code =
|
||||||
|
move_group_interface.execute(plan);
|
||||||
|
if (execute_err_code == moveit::core::MoveItErrorCode::SUCCESS) {
|
||||||
|
m_current_result->success = true;
|
||||||
|
m_current_goal_handle->succeed(m_current_result);
|
||||||
|
RCLCPP_INFO(this->get_logger(), "Successfully executed action goal");
|
||||||
|
} else if (execute_err_code == moveit::core::MoveItErrorCode::FAILURE) {
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Failure in move:");
|
||||||
|
}
|
||||||
|
|
||||||
|
// move_group_interface.move();
|
||||||
|
} else {
|
||||||
|
RCLCPP_WARN(this->get_logger(), "Failed to generate plan");
|
||||||
|
m_current_goal_handle->abort(m_current_result);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_current_goal_handle->is_canceling()) {
|
||||||
|
m_current_goal_handle->canceled(m_current_result);
|
||||||
|
RCLCPP_ERROR(this->get_logger(), "Action goal canceled");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}; // class MoveToPoseActionServer
|
||||||
|
|
||||||
|
} // namespace rbs_skill_actions
|
||||||
|
|
||||||
|
#include "rclcpp_components/register_node_macro.hpp"
|
||||||
|
RCLCPP_COMPONENTS_REGISTER_NODE(rbs_skill_actions::MoveitMtpCart);
|
|
@ -1,3 +1,4 @@
|
||||||
|
// FIXME: This code currently not used
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <geometry_msgs/msg/detail/pose_stamped__struct.hpp>
|
#include <geometry_msgs/msg/detail/pose_stamped__struct.hpp>
|
||||||
#include <geometry_msgs/msg/detail/transform_stamped__struct.hpp>
|
#include <geometry_msgs/msg/detail/transform_stamped__struct.hpp>
|
|
@ -21,7 +21,7 @@
|
||||||
<depend>rbs_utils_interfaces</depend>
|
<depend>rbs_utils_interfaces</depend>
|
||||||
<depend>dynmsg</depend>
|
<depend>dynmsg</depend>
|
||||||
<depend>sensor_msgs</depend>
|
<depend>sensor_msgs</depend>
|
||||||
<depend>nlohmann_json</depend>
|
<depend>nlohmann-json-dev</depend>
|
||||||
<depend>rosbag2_cpp</depend>
|
<depend>rosbag2_cpp</depend>
|
||||||
|
|
||||||
<test_depend>ament_lint_auto</test_depend>
|
<test_depend>ament_lint_auto</test_depend>
|
||||||
|
|
37
repos/all-deps.repos
Normal file
37
repos/all-deps.repos
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
repositories:
|
||||||
|
rbs_arm:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/rbs-arm.git
|
||||||
|
version: main
|
||||||
|
robot_builder:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/robot-builder.git
|
||||||
|
version: main
|
||||||
|
rbs_gripper:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/rbs-gripper.git
|
||||||
|
version: main
|
||||||
|
behavior_tree:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/BehaviorTree/BehaviorTree.ROS2.git
|
||||||
|
version: humble
|
||||||
|
dynamic_message_introspection:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/osrf/dynamic_message_introspection.git
|
||||||
|
version: main
|
||||||
|
robot_builder:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/robot-builder.git
|
||||||
|
version: main
|
||||||
|
cartesian_controllers:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/cartesian_controllers.git
|
||||||
|
version: gazebo-simulation
|
||||||
|
ros2_control:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/ros2_control.git
|
||||||
|
version: gz-ros2-cartesian-controllers
|
||||||
|
gz_ros2_control:
|
||||||
|
type: git
|
||||||
|
url: https://github.com/solid-sinusoid/gz_ros2_control.git
|
||||||
|
version: fts-sensor
|
29
repos/requirements.txt
Normal file
29
repos/requirements.txt
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
trimesh
|
||||||
|
pcg-gazebo
|
||||||
|
loguru
|
||||||
|
# markupsafe==2.0.1
|
||||||
|
# Jinja2==2.6
|
||||||
|
|
||||||
|
numpy==1.24.0
|
||||||
|
flask==3.0.3
|
||||||
|
Jinja2>=3.1.2
|
||||||
|
docutils<0.18,>=0.15
|
||||||
|
markdown-it-py<3.0.0,>=1.0.0
|
||||||
|
# setuptools-scm
|
||||||
|
|
||||||
|
dacite>=1.8.1
|
||||||
|
gymnasium==0.29.1
|
||||||
|
numpy>=1.24.0
|
||||||
|
open3d>=0.18.0
|
||||||
|
scipy>=1.14.1
|
||||||
|
tensorflow>=2.17.0
|
||||||
|
torch>=2.4.1
|
||||||
|
torchvision>=0.19.1
|
||||||
|
trimesh>=4.4.9
|
||||||
|
wandb>=0.18.6
|
||||||
|
|
||||||
|
# Packages from devpi custom repository
|
||||||
|
scenario @ https://devpi.solid-sinusoid.duckdns.org/narmak/dev/+f/63e/86b0583c22e52/scenario-1.4.0-cp310-cp310-linux_x86_64.whl#sha256=63e86b0583c22e52c299b9a25e74a26178fc7dbc423f661bf34e4dd26543d11f
|
||||||
|
gym-gz @ https://devpi.solid-sinusoid.duckdns.org/narmak/dev/+f/539/1f448c1391486/gym_gz-1.4.0-py3-none-any.whl#sha256=5391f448c13914860e2a65904f6d0fac7eba71daaa3327d8399d7ae516471a68
|
||||||
|
gym-gz-models @ https://devpi.solid-sinusoid.duckdns.org/narmak/dev/+f/f42/4784934183e88/gym_gz_models-1.2.0-cp310-cp310-linux_x86_64.whl#sha256=f424784934183e88541c703c789315ba6118661bd221a4bf9135c6a0ee012e96
|
||||||
|
rbs_asstss_library @ https://devpi.solid-sinusoid.duckdns.org/narmak/dev/+f/165/dd2476d9dc455/rbs_assets_library-0.1.0-py2.py3-none-any.whl#sha256=165dd2476d9dc455b425a8c8d3e09a9a9541d54c1f900a3a0e63526c6118de6d
|
Loading…
Add table
Add a link
Reference in a new issue