Продолжение цикла статей о создании небольшого робота. В этот раз речь пойдет о создании копии робота в симуляции, которую предлагают визуальные ROS-среды rviz и gazebo (далее «редакторы»). Работа в редакторах будет вестись на виртуальной машине, образ которой был ранее предоставлен для скачивания (образ). Так как речь идет о симуляции, построении модели, сам робот-тележка не понадобится.
Предыдущие посты серии:
1. Часть 3
2. Часть 2
3. Часть 1
Создание базовых urdf-файлов
Вообще, процесс создания робота упрощенно состоит как правило из следующих стадий:
1. Создание модели робота.
2. Тестирование модели в симуляции.
3. Создание реальной модели робота.
4. Тестирование реальной модели.
Работая с редакторами ROS, которые предоставляют шикарные возможности как по построению моделей и их тестам в виртуальном мире, надо признать, что реальные модели роботов ведут себя не всегда аналогично своим бестелесным братьям. И здесь время на работу с моделями в виртуальном мире складывается со временем, необходимым на доработку реальной модели.
Такое дарение времени, как говорил один известный человек, могут себе позволить не только лишь все.
В связи с этим, в предыдущих постах была нарушена последовательность роботостроения: сначала была создана реальная модель робота. Теперь же речь пойдет о ее виртуализации, так сказать.
Для того, чтобы в полной мере насладиться симуляцией в Gazebo и протестировать робота, сперва необходимо создать URDF файл для робота.
URDF файл является своеобразным каркасом-скелетом в области визуализации.
Проще говоря, URDF файл — это файл, описывающий робота.
Как ранее было заявлено, работа будет вестись с использованием образа VMWARE Workstation, на котором уже установлена ROS(Ubuntu 16.04, ROS-Kinetic) и визуальные редакторы. Поэтому все действия воспроизводимы в данной системе.
Создадим пакет ROS с названием rosbots_description.
Для того, чтобы это сделать надо войти в папку с catkin_ws/src и выполнить команду создания пакета в ROS:
*Если при выполнении команды roscd; cd ..; cd src; вы не попали в catkin_ws, то возможно у вас несколько сред подобного типа. Для того, чтобы активировать нужную, необходимо зайти в папку catkin_ws и выполнить команду: source devel/setup.bash. Чтобы не заблудиться, если вы работаете с образом, в эту папку можно попасть из корня: cd ~; cd catkin_ws.
Если все прошло успешно, то создастся папка rosbots_description.
Почему так сложно и не проще ли просто создать папку в catkin_ws/src вручную? И что там за rospy?
Вручную создать папку можно, но придется также вручную писать еще два файла, с которыми работает ROS: CMakeLists.txt и package.xml.
Именно они присутствуют в папке после создания:
Их ROS создает самостоятельно. Пока на их содержимом останавливаться не будем.
rospy в конце команды означает создание зависимости, поддержку python.
Движемся дальше.
Внутри вновь созданного пакета rosbots_description создадим папку urdf, а в ней — файл rosbots.xacro.
Прелесть системы ROS в том, что в какой папке системы вы бы не находились, можно сразу попасть в целевую, просто набрав ее название с командой roscd в начале строки.
Теперь поместим во вновь созданный файл следующий код:
Если код не отображается, то все файлы можно скачать в конце поста.
Для кода выше нам также понадобятся ячейки (meches), которые будут подгружаться в процессе запуска пакета.
Meches можно взять здесь
и положить распакованную папку meches в rosbots_description.
Если посмотреть код детально, то можно выяснить, что это стандартный файл xml, состоящий из блоков:
— visual
— collision
— inertial
Каждый блок описывает свою часть: visual — это внешность робота, не более, collision и inertial — это физика робота, как все будет взаимодействовать с внешним миром — столкновения, инерция.
joints — элементы, которые помогают определить движение между частями робота (links). Так например, движение колеса (wheel) влияет на раму в целом (chasis).
origin xyz — это первоначальное расположение объекта по осям x,y,z.
parent link и child link это соответственно родительская и дочерняя связи, что из чего растет.
Также примечательно наличие типов: type=«continuous», type=«fixed». Это определение того, что может вращаться, а что нет. Так колеса имеют тип continuous. А, например, batery_joint — fixed.
Отступы в коде такого же глубоко смысла как в python, где нельзя мешать табы и пробелы, не несут. Но для рая перфекциониста и наглядности лучше их иметь.
Код приведенный выше является по сути моделью робота.
Посмотрим что вышло.
Для этого надо создать файл запуска, который будет запускать пакет ROS.
Для этого в ROS служат так называемые launch файлы. Суть launch файла — позволить запустить ноду, команду или несколько нод одной короткой командой без необходимости указывать в ней все аргументы и прочая.
Создадим в rosbots_description папку launch с файлом rviz.launch:
*В этот и последующие разы уже нет необходимости создавать ROS-пакет как это делалось ранее. Теперь система сама будет «видеть» файлы внутри пакета. Поэтому мы просто создаем директорию.
Наполним файл содержимым —
Здесь видно, что при запуске система будет искать описание модели в rosbots.xacro.
Далее запустит 3-и ноды: joint_state_publisher из пакета joint_state_publisher, robot_state_publisher из robot_state_publisher, rviz из rviz. type -это тип ноды, как правило соответствует одноименному Python или С файлу, но указывается без расширения.
Запустим:
В 1-м терминале запустим ROS-мастер:
Во 2-м:
*Если выдало ошибку
в самом файле bashrc указать ip виртуальной машины (например, такой):
далее перечитать bashrc:
**
Если roslaunch все равно не запускается, то можно попробовать зайти в папку catkin_ws и выполнить: source devel/setup.bash
После выполнения команды, запустится Rviz-редактор и откроется графическая оболочка.
Визуальное представление может отличаться, но в целом вид будет примерно следующим:
Слева в колонке Displays можно наблюдать опции отображения тех или иных элементов, взаимодействующих с нодами ROS, по центру — изображение робота, справа — колонка с камерой вида робота. Сразу надо сказать, что с rviz лучше работать с 3-х колесной мышью, так как все кнопки мыши здесь задействованы. Зажав левую можно повращать пространство в окне с отображением робота, зажав правую — приблизить/отдалить, зажав обе клавиши — перемещать пространство относительно робота.
В основном работа в редакторе ведется в первых двух колонках: Displays и Визуальном представлении робота.
Выберем в строке «Fixed Frame» — «base link»:
И добавим Robot Description в Displays:
Нажмем «Add» и в списке выберем «RobotModel»:
"
Теперь в окне симуляции можно наблюдать робота, который был воспроизведен из модели rviz.xacro:
"
Отлично. С визуальным представлением все ясно. Теперь необходимо понять как запустить симуляцию, потому как rviz лишь визуализация симуляции, но не сама симуляция.
То есть физика здесь не работает.
Сама симуляция живет в редакторе под названием Gazebo.
Чтобы поместить созданную модель в Gazebo, создадим еще один launch файл — spawn.launch в папке launch проекта. Теперь у нас 2 launch файла!
Здесь мы также считываем модель, затем аргументами передаем ее расположение в пространстве по осям x,y,z. Далее запускаем всего лишь одну ноду — mybot_spawn из пакета gazebo_ros.
*Доустанавливать пакеты, упомянутые выше нет необходимости. При желании можно посмотреть на эти пакеты все той же командой: roscd. Например roscd gazebo_ros.
Теперь остановим Ros-мастер в 1-м терминале:
И запустим редактор Gazebo:
Во 2-м терминале запустим вновь созданный файл:
Теперь мы видим нашего робота в симуляции редактора Gazebo:
*Если у вас ошибка:
Это значит, что вы запустили модель без предварительного запуска Gazebo, нарушив очередность запуска.
Теперь добавим в rosbots.xacro следующий код до закрывающего тега :
Симулятор Gazebo можно не закрывать при правках.
Теперь удалим модель из редактора Gazebo:
либо просто перезагрузим редактор.
*Gazebo капризный на виртуальной машине, поэтому даже после закрытия иногда простит CTRL+C дополнительно в терминале.
Заново разместим модель в Gazebo после правок:
Если теперь посмотреть список топиков ROS, то можно увидеть, что среди них есть и
Теперь попробуем поуправлять роботом в симуляции, запустив управление в отдельном терминале:
Находясь в окне с запущенным управлением и нажимая в окне терминала клавиши «i»,«l»,«j»,«k»,"," можно наблюдать движение робота в симуляции редактора Gazebo:
Код — скачать.
Продолжение следует.
Предыдущие посты серии:
1. Часть 3
2. Часть 2
3. Часть 1
Создание базовых urdf-файлов
Вообще, процесс создания робота упрощенно состоит как правило из следующих стадий:
1. Создание модели робота.
2. Тестирование модели в симуляции.
3. Создание реальной модели робота.
4. Тестирование реальной модели.
Работая с редакторами ROS, которые предоставляют шикарные возможности как по построению моделей и их тестам в виртуальном мире, надо признать, что реальные модели роботов ведут себя не всегда аналогично своим бестелесным братьям. И здесь время на работу с моделями в виртуальном мире складывается со временем, необходимым на доработку реальной модели.
Такое дарение времени, как говорил один известный человек, могут себе позволить не только лишь все.
В связи с этим, в предыдущих постах была нарушена последовательность роботостроения: сначала была создана реальная модель робота. Теперь же речь пойдет о ее виртуализации, так сказать.
Создаем urdf
Для того, чтобы в полной мере насладиться симуляцией в Gazebo и протестировать робота, сперва необходимо создать URDF файл для робота.
URDF файл является своеобразным каркасом-скелетом в области визуализации.
Проще говоря, URDF файл — это файл, описывающий робота.
Как ранее было заявлено, работа будет вестись с использованием образа VMWARE Workstation, на котором уже установлена ROS(Ubuntu 16.04, ROS-Kinetic) и визуальные редакторы. Поэтому все действия воспроизводимы в данной системе.
Создадим пакет ROS с названием rosbots_description.
Для того, чтобы это сделать надо войти в папку с catkin_ws/src и выполнить команду создания пакета в ROS:
roscd; cd ..; cd src;
catkin_create_pkg rosbots_description rospy
*Если при выполнении команды roscd; cd ..; cd src; вы не попали в catkin_ws, то возможно у вас несколько сред подобного типа. Для того, чтобы активировать нужную, необходимо зайти в папку catkin_ws и выполнить команду: source devel/setup.bash. Чтобы не заблудиться, если вы работаете с образом, в эту папку можно попасть из корня: cd ~; cd catkin_ws.
Если все прошло успешно, то создастся папка rosbots_description.
Почему так сложно и не проще ли просто создать папку в catkin_ws/src вручную? И что там за rospy?
Вручную создать папку можно, но придется также вручную писать еще два файла, с которыми работает ROS: CMakeLists.txt и package.xml.
Именно они присутствуют в папке после создания:
Их ROS создает самостоятельно. Пока на их содержимом останавливаться не будем.
rospy в конце команды означает создание зависимости, поддержку python.
Движемся дальше.
Внутри вновь созданного пакета rosbots_description создадим папку urdf, а в ней — файл rosbots.xacro.
roscd rosbots_description
mkdir urdf; cd urdf;
touch rosbots.xacro
chmod +x rosbots.xacro
Прелесть системы ROS в том, что в какой папке системы вы бы не находились, можно сразу попасть в целевую, просто набрав ее название с командой roscd в начале строки.
Теперь поместим во вновь созданный файл следующий код:
rosbots.xacro
<?xml version="1.0" encoding="utf-8"?>
<robot name="rosbots" xmlns:xacro="http://www.ros.org/wiki/xacro">
<link name="base_footprint"/>
<joint name="base_joint" type="fixed">
<origin xyz="0 0 0.05" rpy="0 0 0" />
<parent link="base_footprint"/>
<child link="base_link" />
</joint>
<link name="base_link">
<visual>
<geometry>
<mesh filename="package://rosbots_description/meshes/base.dae"/>
</geometry>
<origin xyz="-0.52 -0.4 0.43" rpy="0 0 0"/>
</visual>
<collision>
<geometry>
<mesh filename="package://rosbots_description/meshes/base.dae"/>
</geometry>
<origin xyz="-0.52 -0.4 0.43" rpy="0 0 0"/>
</collision>
<inertial>
<origin xyz="0.0 0 0."/>
<mass value="0.5"/>
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0"
izz="0.03" />
</inertial>
</link>
<joint name="second_level_joint" type="fixed">
<origin xyz="0 0 0.68" rpy="0 0 0" />
<parent link="base_link"/>
<child link="base_second_link" />
</joint>
<link name="base_second_link">
<visual>
<geometry>
<mesh filename="package://rosbots_description/meshes/base.dae"/>
</geometry>
<origin xyz="-0.52 -0.4 0.0" rpy="0 0 0"/>
</visual>
<collision>
<geometry>
<mesh filename="package://rosbots_description/meshes/base.dae"/>
</geometry>
<origin xyz="-0.52 -0.4 0.0" rpy="0 0 0"/>
</collision>
<!--inertial>
<origin xyz="0.01 0 0.7"/>
<mass value="1.0"/>
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0"
izz="0.03" />
</inertial-->
</link>
<joint name="mcu_joint" type="fixed">
<origin xyz="0.02 0.12 0.73" rpy="0 0 0" />
<parent link="base_link"/>
<child link="mcu_link" />
</joint>
<link name="mcu_link">
<visual>
<geometry>
<mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/>
</geometry>
<origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/>
</visual>
<collision>
<geometry>
<mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/>
</geometry>
<origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/>
</collision>
<!-- inertial>
<origin xyz="0.01 0 0"/>
<mass value="1.0"/>
<inertia ixx="0.019995" ixy="0.0" ixz="0.0"
iyy="0.019995" iyz="0.0"
izz="0.03675" />
</inertial-->
</link>
<joint name="mcu_joint_1" type="fixed">
<origin xyz="0.02 0.12 0.83" rpy="0 0 0" />
<parent link="base_link"/>
<child link="mcu_link_1" />
</joint>
<link name="mcu_link_1">
<visual>
<geometry>
<mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/>
</geometry>
<origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/>
</visual>
<collision>
<geometry>
<mesh filename="package://rosbots_description/meshes/rasp.dae" scale="0.14 0.14 0.14"/>
</geometry>
<origin xyz="0.9 -1.25 0" rpy="0 0 1.57"/>
</collision>
<!-- inertial>
<origin xyz="0.01 0 0"/>
<mass value="1.0"/>
<inertia ixx="0.019995" ixy="0.0" ixz="0.0"
iyy="0.019995" iyz="0.0"
izz="0.03675" />
</inertial-->
</link>
<joint name="stand_mcu1_joint" type="fixed">
<origin xyz="0.02 0.25 0.78" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_mcu1_link" />
</joint>
<link name="stand_mcu1_link">
<visual>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
</link>
<joint name="stand_mcu2_joint" type="fixed">
<origin xyz="0.02 -0.1125 0.78" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_mcu2_link" />
</joint>
<link name="stand_mcu2_link">
<visual>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
</link>
<joint name="stand_mcu3_joint" type="fixed">
<origin xyz="0.25 0.25 0.78" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_mcu3_link" />
</joint>
<link name="stand_mcu3_link">
<visual>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
</link>
<joint name="stand_mcu4_joint" type="fixed">
<origin xyz="0.25 -0.1125 0.78" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_mcu4_link" />
</joint>
<link name="stand_mcu4_link">
<visual>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.1" radius="0.01"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
</link>
<joint name="batery_joint" type="fixed">
<origin xyz="1.2 0.2 0.43" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="batery_link" />
</joint>
<link name="batery_link">
<visual>
<geometry>
<mesh filename="package://rosbots_description/meshes/battery.dae" scale="13.0 6.0 6.0"/>
</geometry>
<origin xyz="0 4.5 0.05" rpy="1.57 0 1.57"/>
</visual>
<collision>
<geometry>
<mesh filename="package://rosbots_description/meshes/battery.dae" scale="13.0 6.0 6.0"/>
</geometry>
<origin xyz="0 4.5 0.05" rpy="1.57 0 1.57"/>
</collision>
<!-- inertial>
<origin xyz="0.01 0 0"/>
<mass value="1.0"/>
<inertia ixx="0.01" ixy="0.0" ixz="0.0"
iyy="0.01" iyz="0.0"
izz="0.03" />
</inertial-->
</link>
<joint name="stand_1_joint" type="fixed">
<origin xyz="0.5 0.4125 0.58" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_1_link" />
</joint>
<link name="stand_1_link">
<visual>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
<!--inertial>
<origin xyz="0.0 0 0"/>
<mass value="1.0"/>
<inertia ixx="0.019995" ixy="0.0" ixz="0.0"
iyy="0.019995" iyz="0.0"
izz="0.03675" />
</inertial-->
</link>
<joint name="stand_2_joint" type="fixed">
<origin xyz="0.5 -0.2625 0.58" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_2_link" />
</joint>
<link name="stand_2_link">
<visual>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
<!--inertial>
<origin xyz="0.0 0 0"/>
<mass value="1.0"/>
<inertia ixx="0.019995" ixy="0.0" ixz="0.0"
iyy="0.019995" iyz="0.0"
izz="0.03675" />
</inertial-->
</link>
<joint name="wheel_left_joint" type="continuous">
<parent link="base_link"/>
<child link="wheel_left_link"/>
<origin xyz="0.15 0.4125 0.30" rpy="-1.57 0 0"/>
<axis xyz="0 0 1"/>
</joint>
<link name="wheel_left_link">
<collision>
<geometry>
<cylinder length="0.20" radius="0.23"/>
</geometry>
<origin rpy="0.0 0.0 0" xyz="0 0 0.1"/>
</collision>
<visual name="visual">
<geometry>
<!-- cylinder length="0.0206" radius="0.0550"/-->
<!--cylinder length="0.20" radius="0.26"/-->
<mesh filename="package://rosbots_description/meshes/wheel.dae" scale="8.0 8.0 8.0"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0"/>
</visual>
<inertial>
<mass value="0.4" />
<origin xyz="0 0 0" />
<inertia ixx="0.001" ixy="0.0" ixz="0.0"
iyy="0.001" iyz="0.0"
izz="0.001" />
</inertial>
</link>
<joint name="wheel_right_joint" type="continuous">
<parent link="base_link"/>
<child link="wheel_right_link"/>
<origin xyz="0.15 -0.5625 0.30" rpy="-1.57 0 0"/>
<axis xyz="0 0 1"/>
</joint>
<link name="wheel_right_link">
<collision>
<geometry>
<cylinder length="0.20" radius="0.23"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.195"/>
</collision>
<visual name="visual">
<geometry>
<!--cylinder length="0.20" radius="0.26"/-->
<mesh filename="package://rosbots_description/meshes/wheel.dae" scale="8.0 8.0 8.0"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0"/>
</visual>
<inertial>
<mass value="0.4" />
<origin xyz="0 0.0 0.3" />
<inertia ixx="0.001" ixy="0.0" ixz="0.0"
iyy="0.001" iyz="0.0"
izz="0.001" />
</inertial>
</link>
<joint name="caster_back_joint" type="fixed">
<parent link="base_link"/>
<child link="caster_back_link"/>
<origin xyz="-0.4 0.1 0.26" rpy="0 0 0"/>
</joint>
<link name="caster_back_link">
<collision>
<geometry>
<!-- cylinder length="0.05" radius="0.19"/-->
<sphere radius="0.19"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</collision>
<visual>
<geometry>
<!--cylinder length="0.05" radius="0.19"/-->
<sphere radius="0.19"/>
</geometry>
<origin rpy="0 0 0" xyz="0 0 0"/>
</visual>
<inertial>
<mass value="0.1" />
<origin xyz="0 0 0" />
<inertia ixx="0.001023539" ixy="0.0" ixz="0.0"
iyy="0.001023539" iyz="0.0"
izz="0.001023539" />
</inertial>
</link>
<joint name="stand_3_joint" type="fixed">
<origin xyz="-0.4 0.4125 0.58" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_3_link" />
</joint>
<link name="stand_3_link">
<visual>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
</link>
<joint name="stand_4_joint" type="fixed">
<origin xyz="-0.4 -0.2625 0.58" rpy="0 0 1.57" />
<parent link="base_link"/>
<child link="stand_4_link" />
</joint>
<link name="stand_4_link">
<visual>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</visual>
<collision>
<geometry>
<cylinder length="0.20" radius="0.03"/>
</geometry>
<origin rpy="0.0 0 0" xyz="0 0 0.0"/>
</collision>
</link>
</robot>
Если код не отображается, то все файлы можно скачать в конце поста.
Для кода выше нам также понадобятся ячейки (meches), которые будут подгружаться в процессе запуска пакета.
Meches можно взять здесь
и положить распакованную папку meches в rosbots_description.
Если посмотреть код детально, то можно выяснить, что это стандартный файл xml, состоящий из блоков:
— visual
— collision
— inertial
Каждый блок описывает свою часть: visual — это внешность робота, не более, collision и inertial — это физика робота, как все будет взаимодействовать с внешним миром — столкновения, инерция.
joints — элементы, которые помогают определить движение между частями робота (links). Так например, движение колеса (wheel) влияет на раму в целом (chasis).
origin xyz — это первоначальное расположение объекта по осям x,y,z.
parent link и child link это соответственно родительская и дочерняя связи, что из чего растет.
Также примечательно наличие типов: type=«continuous», type=«fixed». Это определение того, что может вращаться, а что нет. Так колеса имеют тип continuous. А, например, batery_joint — fixed.
Отступы в коде такого же глубоко смысла как в python, где нельзя мешать табы и пробелы, не несут. Но для рая перфекциониста и наглядности лучше их иметь.
Код приведенный выше является по сути моделью робота.
Работа в rviz
Посмотрим что вышло.
Для этого надо создать файл запуска, который будет запускать пакет ROS.
Для этого в ROS служат так называемые launch файлы. Суть launch файла — позволить запустить ноду, команду или несколько нод одной короткой командой без необходимости указывать в ней все аргументы и прочая.
Создадим в rosbots_description папку launch с файлом rviz.launch:
roscd rosbots_description
mkdir launch; cd launch;
touch rviz.launch
*В этот и последующие разы уже нет необходимости создавать ROS-пакет как это делалось ранее. Теперь система сама будет «видеть» файлы внутри пакета. Поэтому мы просто создаем директорию.
Наполним файл содержимым —
rviz.launch
<?xml version="1.0"?>
<launch>
<param name="robot_description" command="cat '$(find rosbots_description)/urdf/rosbots.xacro'"/>
<!-- send fake joint values -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher">
<param name="use_gui" value="False"/>
</node>
<!-- Combine joint values -->
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher"/>
<!-- Show in Rviz -->
<node name="rviz" pkg="rviz" type="rviz" />
</launch>
Здесь видно, что при запуске система будет искать описание модели в rosbots.xacro.
Далее запустит 3-и ноды: joint_state_publisher из пакета joint_state_publisher, robot_state_publisher из robot_state_publisher, rviz из rviz. type -это тип ноды, как правило соответствует одноименному Python или С файлу, но указывается без расширения.
Запустим:
В 1-м терминале запустим ROS-мастер:
roscore
Во 2-м:
roslaunch rosbots_description rviz.launch
*Если выдало ошибку
ROS_MASTER_URI [http://192.168.1....:11311] host is not set to this machine, то надо проверить bashrc — на каком ip запускается ROS:
nano ~/.bashrc
в самом файле bashrc указать ip виртуальной машины (например, такой):
export ROS_MASTER_URI=http://192.168.1.114:11311
далее перечитать bashrc:
source ~/.bashrc
или перезагрузиться.**
Если roslaunch все равно не запускается, то можно попробовать зайти в папку catkin_ws и выполнить: source devel/setup.bash
Погружаемся в Rviz
После выполнения команды, запустится Rviz-редактор и откроется графическая оболочка.
Визуальное представление может отличаться, но в целом вид будет примерно следующим:
Слева в колонке Displays можно наблюдать опции отображения тех или иных элементов, взаимодействующих с нодами ROS, по центру — изображение робота, справа — колонка с камерой вида робота. Сразу надо сказать, что с rviz лучше работать с 3-х колесной мышью, так как все кнопки мыши здесь задействованы. Зажав левую можно повращать пространство в окне с отображением робота, зажав правую — приблизить/отдалить, зажав обе клавиши — перемещать пространство относительно робота.
В основном работа в редакторе ведется в первых двух колонках: Displays и Визуальном представлении робота.
Поработаем с видом робота
Выберем в строке «Fixed Frame» — «base link»:
И добавим Robot Description в Displays:
Нажмем «Add» и в списке выберем «RobotModel»:
"
Теперь в окне симуляции можно наблюдать робота, который был воспроизведен из модели rviz.xacro:
"
Отлично. С визуальным представлением все ясно. Теперь необходимо понять как запустить симуляцию, потому как rviz лишь визуализация симуляции, но не сама симуляция.
То есть физика здесь не работает.
Сама симуляция живет в редакторе под названием Gazebo.
Gazebo
Чтобы поместить созданную модель в Gazebo, создадим еще один launch файл — spawn.launch в папке launch проекта. Теперь у нас 2 launch файла!
spawn.launch
<?xml version="1.0" encoding="UTF-8"?>
<launch>
<param name="robot_description" command="cat '$(find rosbots_description)/urdf/rosbots.xacro'" />
<arg name="x" default="0"/>
<arg name="y" default="0"/>
<arg name="z" default="0.5"/>
<node name="mybot_spawn" pkg="gazebo_ros" type="spawn_model" output="screen"
args="-urdf -param robot_description -model rosbots -x $(arg x) -y $(arg y) -z $(arg z)" />
</launch>
Здесь мы также считываем модель, затем аргументами передаем ее расположение в пространстве по осям x,y,z. Далее запускаем всего лишь одну ноду — mybot_spawn из пакета gazebo_ros.
*Доустанавливать пакеты, упомянутые выше нет необходимости. При желании можно посмотреть на эти пакеты все той же командой: roscd. Например roscd gazebo_ros.
Теперь остановим Ros-мастер в 1-м терминале:
CTRL+C
И запустим редактор Gazebo:
roslaunch gazebo_ros empty_world.launch
Во 2-м терминале запустим вновь созданный файл:
roslaunch rosbots_description spawn.launch
Теперь мы видим нашего робота в симуляции редактора Gazebo:
*Если у вас ошибка:
Waiting for service /gazebo/spawn_urdf_model
Это значит, что вы запустили модель без предварительного запуска Gazebo, нарушив очередность запуска.
Поездим в симуляции gazebo.
Теперь добавим в rosbots.xacro следующий код до закрывающего тега :
код
<gazebo>
<plugin name="differential_drive_controller" filename="libgazebo_ros_diff_drive.so">
<legacyMode>false</legacyMode>
<alwaysOn>true</alwaysOn>
<publishWheelTF>true</publishWheelTF>
<publishTf>1</publishTf>
<publishWheelJointState>true</publishWheelJointState>
<updateRate>100.0</updateRate>
<leftJoint>wheel_left_joint</leftJoint>
<rightJoint>wheel_right_joint</rightJoint>
<wheelSeparation>1.1</wheelSeparation>
<wheelDiameter>0.52</wheelDiameter>
<wheelAcceleration>1.0</wheelAcceleration>
<torque>20</torque>
<commandTopic>/part2_cmr/cmd_vel</commandTopic>
<odometryTopic>odom</odometryTopic>
<odometryFrame>odom</odometryFrame>
<robotBaseFrame>base_link</robotBaseFrame>
</plugin>
</gazebo>
Симулятор Gazebo можно не закрывать при правках.
Теперь удалим модель из редактора Gazebo:
rosservice call /gazebo/delete_model "model_name: 'rosbots'"
либо просто перезагрузим редактор.
*Gazebo капризный на виртуальной машине, поэтому даже после закрытия иногда простит CTRL+C дополнительно в терминале.
Заново разместим модель в Gazebo после правок:
roslaunch rosbots_description spawn.launch
Если теперь посмотреть список топиков ROS, то можно увидеть, что среди них есть и
/part2_cmr/cmd_vel
Теперь попробуем поуправлять роботом в симуляции, запустив управление в отдельном терминале:
rosrun teleop_twist_keyboard teleop_twist_keyboard.py /cmd_vel:=/part2_cmr/cmd_vel
Находясь в окне с запущенным управлением и нажимая в окне терминала клавиши «i»,«l»,«j»,«k»,"," можно наблюдать движение робота в симуляции редактора Gazebo:
Код — скачать.
Продолжение следует.