- Lab
Czyli prawdziwy i ładny model robota.
Czyli prosty przykład edukacyjny z dwoma tylnymi napętami i obrotowym pasywnym kołem z przodu.
Tworzymy nowy pusty ROSject na platformie The Construct, wersja ROS Noetic.
Kompletny workspace z zajęć znajduje się w katalogu tortoisebot_ws.
Tworzymy nowy workspace lub korzystamy z obecnie dostępnego (np. catkin_ws):
mkdir -p tortoisebot_ws/src
cd tortoisebot_ws
catkin_makeWszystkie paczki w naszym projekcie powinny znajdować się w katalogu <nazwa workspace'a>/src/.... Tworzymy nową paczkę tortoisebot:
catkin_create_pkg tortoisebot rospy std_msgs actionlib_msgs message_generationNastępnie przechodzimy do katalogu głownego i wpisujemy*:
catkin_make
source ./devel/setup.bash* Zamiast setup.bash możemy wykonać inny skrypt np. setup.sh, setup.zsh w zależności od naszego interpretera.
- Decyzja o wykorzystywnaiu ROS'a.
- Niskopoziomowe oprogramowanie do sterowania silnikami.
- Modelu struktury fizycznej robota.
- Rozszerzony model z parametrami fizycznymi (w celu jego symulacji).
- Sensory.
- Algorytmy.
W prawdzimym robocie musielibyśmy zaimplementować niskopoziomowy interfejs do obsługi silników. Jest to bardzo zależne od sprzetu jaki posiadamy. Na potrzeby tego kursu pomijamy ten punkt i będziemy korzystać tylko z symulacji Gazebo.
Package, który dostarcza odpowiedzi na pytania takie jak:
- Jakie było położenie względem siebie dwóch układów 5 sekund temu?
- Jaka jest pozycja obiektu w chwytaku manipulatora względem danego układu?
- Jaka jest aktualna pozycja danego układu względem układu mapy?
ROS'owy launch to plik pozwalający na uruchamianie wielu nodów oraz ich konfiguracji za pomocą jednego polecenia:
roslaunch package_name file.launchWykorzystywane są w tym celu pliki w formacie XML z rozszerzeniem .launch. Przykładowy launch:
<launch>
<!-- run main panorama node -->
<node pkg="panorama" type="panorama.py" name="panorama" output="screen">
<!-- remaps for each input -->
<remap from="/cam_left" to="/panorama_dummy/cam_left/image_raw"/>
<remap from="/cam_right" to="/panorama_dummy/cam_right/image_raw"/>
</node>
</launch>Często wykorzystywane tagi:
<node><include><remap><env><param><group><test><arg>
Podczas pracy nad naszym robotem będziemy wykorzystywać standardowe message:
geometry_msgs/Twistgeometry_msgs/Vector3 linear float64 x float64 y float64 z geometry_msgs/Vector3 angular float64 x float64 y float64 z
nav_msgs/Odometrystd_msgs/Header header uint32 seq time stamp string frame_id string child_frame_id geometry_msgs/PoseWithCovariance pose geometry_msgs/Pose pose geometry_msgs/Point position float64 x float64 y float64 z geometry_msgs/Quaternion orientation float64 x float64 y float64 z float64 w float64[36] covariance geometry_msgs/TwistWithCovariance twist geometry_msgs/Twist twist geometry_msgs/Vector3 linear float64 x float64 y float64 z geometry_msgs/Vector3 angular float64 x float64 y float64 z float64[36] covariance
- URDF (Unified Robot Description Format)
<link>- Bryła sztywna.<joint>- Łączy dwa link'i ze sobą, definuje rodzaj ruchu między nimi.
- W paczce
tortoisebottworzymy katalogurdf(obok katalogusrc). - Tworzymy w nim nowy plik
tortoisebot.urdf.
Do tortoisebot.urdf wrzucamy prosty XML z jedną bryłą:
<?xml version="1.0"?>
<robot name="tortoisebot">
<link name="base_link">
<visual>
<geometry>
<box size="0.6 0.3 0.3"/>
</geometry>
<material name="silver">
<color rgba="0.75 0.75 0.75 1"/>
</material>
</visual>
</link>
</robot>Korzystając z paczki urdf_tutorial możemy łatwo wyświetlić naszego URDF'a w RViz'ie:
roslaunch urdf_tutorial display.launch model:=tortoisebot.urdfMożemy też wygenerować graf relacji pomiędzy link'ami i join'ami URDF'a:
urdf_to_graphiz tortoisebot.urdf-
Dodajemy link połaczony joint'em z base_link'iem. Kod wrzucamy tak, aby był dzieckiem
<robot> ... </robot>, (type="continuous"definiuje w jaki sposób linki mogą się ruszać względem siebie, dostępnych jest oczywiście więcej typów):<link name="front_caster"> <visual> <geometry> <box size="0.1 0.1 0.3"/> </geometry> <material name="silver"/> </visual> </link> <joint name="front_caster_joint" type="continuous"> <axis xyz="0 0 1"/> <parent link="base_link"/> <child link="front_caster"/> <origin rpy="0 0 0" xyz="0.3 0 0"/> </joint>
-
Dodajemy przednie koło:
<link name="front_wheel"> <visual> <geometry> <cylinder length="0.05" radius="0.035"/> </geometry> <material name="black"/> </visual> </link> <joint name="front_wheel_joint" type="continuous"> <axis xyz="0 0 1"/> <parent link="front_caster"/> <child link="front_wheel"/> <origin rpy="-1.5708 0 0" xyz="0.05 0 -.15"/> </joint>
-
Sprawdzamy w RViz'ie czy wszystko działa:
roslaunch urdf_tutorial display.launch model:=tortoisebot.urdf
-
Dodając argument
gui:=Truemożemy wyświetlić okienko pozwalające nam ręcznie ruszać join'ami:roslaunch urdf_tutorial display.launch model:=tortoisebot.urdf gui:=True
-
Dodajemy link'i i join'y do tylnych kół w taki sposób, aby były dziećmi
<robot> ... </robot>.<link name="right_wheel"> <visual> <geometry> <cylinder length="0.05" radius="0.035"/> </geometry> <material name="black"> <color rgba="0 0 0 1"/> </material> </visual> </link> <joint name="right_wheel_joint" type="continuous"> <axis xyz="0 0 1"/> <parent link="base_link"/> <child link="right_wheel"/> <origin rpy="-1.5708 0 0" xyz="-0.2825 -0.125 -.15"/> </joint> <link name="left_wheel"> <visual> <geometry> <cylinder length="0.05" radius="0.035"/> </geometry> <material name="black"/> </visual> </link> <joint name="left_wheel_joint" type="continuous"> <axis xyz="0 0 1"/> <parent link="base_link"/> <child link="left_wheel"/> <origin rpy="-1.5708 0 0" xyz="-0.2825 0.125 -.15"/> </joint>
-
Weryfikujamy czy wszystko ok:
roslaunch urdf_tutorial display.launch model:=tortoisebot.urdf gui:=True
Tag <collision> - rozmiar i kształt bryły dla wykrywanie kolizji w symulacji. Nie musi być tożsamy z <visual>.
-
Dodajemy kolizję dla
base_linkbazując na tagu<visual>.<collision> <geometry> <box size="0.6 0.3 0.3"/> </geometry> </collision>
ostatecznie
base_linkpowinien wyglądać tak:<link name="base_link"> <visual> <geometry> <box size="0.6 0.3 0.3"/> </geometry> <material name="silver"> <color rgba="0.75 0.75 0.75 1"/> </material> </visual> <collision> <geometry> <box size="0.6 0.3 0.3"/> </geometry> </collision> </link>
-
Dodajemy kolizję dla caster'a:
<collision>
<geometry>
<box size="0.1 0.1 0.3"/>
</geometry>
</collision>- Na podstawie tagów
<visual>definiujemy kolizje dla wszystkich 3 kół:- koło przednie:
<collision> <geometry> <cylinder length="0.05" radius="0.035"/> </geometry> </collision>
- koło lewe i prawe:
<collision> <geometry> <cylinder length="0.05" radius="0.035"/> </geometry> </collision>
- koło przednie:
Tag <inertial> definiuje moment bezwładności bryły dla obliczeń symulacji fizycznych. Przydatne wzory i obrazki.
- base_link:
<inertial> <mass value="1.0"/> <inertia ixx="0.015" iyy="0.0375" izz="0.0375" ixy="0" ixz="0" iyz="0"/> </inertial>
- caster:
<inertial> <mass value="0.1"/> <inertia ixx="0.00083" iyy="0.00083" izz="0.000167" ixy="0" ixz="0" iyz="0"/> </inertial>
- koło przednie:
<inertial> <mass value="0.1"/> <inertia ixx="5.1458e-5" iyy="5.1458e-5" izz="6.125e-5" ixy="0" ixz="0" iyz="0"/> </inertial>
- koła tylne:
<inertial> <mass value="0.1"/> <inertia ixx="5.1458e-5" iyy="5.1458e-5" izz="6.125e-5" ixy="0" ixz="0" iyz="0"/> </inertial>
Możemy ponownie wygenerować graf relacji pomiędzy link'ami i join'ami URDF'a:
urdf_to_graphiz tortoisebot.urdfDodajemy differential_drive_controller plugin Gazebo, pozwalający na niskopoziomowe sterowanie kołami naszego robota. Gazebo zajmie się tłumaczeniem komend prędkości publikowanych na topic /cmd_vel na ruch robota.
<gazebo>
<plugin name="differential_drive_controller"
filename="libgazebo_ros_diff_drive.so">
<leftJoint>left_wheel_joint</leftJoint>
<rightJoint>right_wheel_joint</rightJoint>
<robotBaseFrame>base_link</robotBaseFrame>
<wheelSeparation>0.25</wheelSeparation>
<wheelDiameter>0.07</wheelDiameter>
<publishWheelJointState>true</publishWheelJointState>
</plugin>
</gazebo>-
Tworzymy katalog
launchw naszej paczce. -
Dodajemy do niego plik
tortoisebot.launch:<launch> <param name="robot_description" textfile="$(find tortoisebot)/urdf/tortoisebot.urdf" /> <include file="$(find gazebo_ros)/launch/empty_world.launch"/> <node name="spawn_urdf" pkg="gazebo_ros" type="spawn_model" args="-param robot_description -urdf -model tortoisebot" /> </launch>
-
Uruchamiamy launch:
roslaunch tortoisebot tortoisebot.launch
-
Wyświetlona zostanie symulacja Gazebo.
- Aby sterować robotem możemy publikować na topic
/cmd_velwiadomościgeometry_msgs/Twist. - Możemy skorzystać z dobrodziejstw paczki
teleop_twist_keyboard, która implementuje sterowanie robotem za pomocą klawiatury. Node zbiera input od użytkownika i również publikuje na/cmd_vel:rosrun teleop_twist_keyboard teleop_twist_keyboard.py



