Selamat siang, para pembaca Habr! Ini adalah artikel kedua dalam serangkaian artikel tentang penggunaan praktis ROS pada Raspberry Pi. Dalam artikel pertama dalam seri ini, saya menjelaskan cara menginstal komponen ROS yang diperlukan dan mengatur lingkungan kerja untuk bekerja.Pada bagian kedua dari seri ini, kita akan mulai menggunakan fitur ROS pada platform Raspberry Pi. Khususnya, dalam artikel ini saya akan berbicara tentang menggunakan Dewan Kamera Raspberry Pi pada Raspberry Pi bersama dengan ROS untuk menyelesaikan masalah penglihatan komputer. Siapa yang tertarik, silakan, di bawah kucing.Kamera RPi Papan Kamera
Untuk bekerja, kita membutuhkan kamera Papan Kamera Raspberry Pi:
Kamera ini terhubung langsung ke GPU melalui konektor CSi di papan, yang memungkinkan Anda untuk merekam dan menyandikan gambar dari kamera tanpa menggunakan waktu prosesor. Kabel ZIF digunakan untuk menghubungkan kamera. Konektor kabel di papan terletak di antara port Ethernet dan HDMI:
Instalasi Perpustakaan
Jadi mari kita lanjutkan untuk menginstal perpustakaan yang diperlukan. Pertama, instal OpenCV:$ sudo apt-get install libopencv-dev
Untuk menggunakan Kamera Raspberry Pi, kita akan membutuhkan perpustakaan raspicam. Unduh arsip dari sini .Selanjutnya, instal perpustakaan:$ tar xvzf raspicamxx.tgz
$ cd raspicamxx
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
$ sudo ldconfig
Anda perlu mengaktifkan dukungan kamera di Raspbian melalui program raspi-config:$ sudo raspi-config
Pilih opsi 5 - Aktifkan kamera, simpan pilihan dan reboot sistem.Memulai dengan ROS
Untuk kenyamanan, buat bengkel catkin baru untuk paket kami:$ mkdir -p ~/driverobot_ws/src
$ cd ~/driverobot_ws/src
$ catkin_init_workspace
$ cd ~/driverobot_ws
$ catkin_make
Buat paket ROS baru:$ cd src/
$ catkin_create_pkg raspi_cam_ros image_transport cv_bridge roscpp std_msgs sensor_msgs compressed_image_transport opencv2
Spesifikasi dari perintah catkin_create_pkg adalah sebagai berikut: catkin_create_pkg <package_name> [depend1] [depend2], dimana Anda dapat menentukan dependensi apa pun di bawah pustaka - perpustakaan yang akan digunakan paket.Perintah ini menciptakan kerangka kerja proyek ROS: direktori src kosong untuk skrip simpul dan file konfigurasi CMakeLists.txt dan package.xml.Saya menemukan skrip sederhana yang menerima bingkai dari kamera dan menerbitkannya menggunakan "penerbit" (penerbit), dan mengadaptasinya untuk ROS Indigo. Anda dapat mengunduhnya dari sini .Untuk menggunakannya, Anda harus menginstal driver kamera Raspberry Pi UV4L:$ curl http://www.linux-projects.org/listing/uv4l_repo/lrkey.asc | sudo apt-key add -
Tambahkan baris berikut ke file /etc/apt/sources.listdeb http://www.linux-projects.org/listing/uv4l_repo/raspbian/ wheezy main
perbarui paket dan instal:$ sudo apt-get update
$ sudo apt-get install uv4l uv4l-raspicam
Untuk mengunduh driver, pada setiap boot sistem, kami juga menginstal paket opsional:$ sudo apt-get install uv4l-raspicam-extras
Mari beralih ke mengedit paket. Rekatkan baris dari sini ke file CMakeLists.txt Anda .Baris paling penting dalam file CMakeLists.txt:link_directories(/usr/lib/uv4l/uv4lext/armv6l/)
…
target_link_libraries(capture ${catkin_LIBRARIES} uv4lext)
Jadi, kami menambahkan tautan ke driver uv4l, yang diperlukan untuk mengkompilasi paket.Di akhir file, kami menetapkan garis khusus untuk simpul kami:add_executable(capture src/capturer.cpp)
target_link_libraries(capture ${catkin_LIBRARIES} uv4lext)
Baris add_executable membuat biner untuk diluncurkan dan target_link_lbraries menautkan perpustakaan tambahan untuk menangkap biner.Tempelkan baris yang hilang dari sini ke file package.xml sehingga terlihat seperti ini:<?xml version="1.0"?>
<package>
<name>raspi_cam_ros</name>
<version>0.0.0</version>
<description>The raspi_cam_ros package</description>
<maintainer email="pi@todo.todo">pi</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>cv_bridge</build_depend>
<build_depend>image_transport</build_depend>
<build_depend>roscpp</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>sensor_msgs</build_depend>
<build_depend>opencv2</build_depend>
<build_depend>compressed_image_transport</build_depend>
<run_depend>cv_bridge</run_depend>
<run_depend>image_transport</run_depend>
<run_depend>roscpp</run_depend>
<run_depend>std_msgs</run_depend>
<run_depend>sensor_msgs</run_depend>
<run_depend>opencv2</run_depend>
<run_depend>compressed_image_transport</run_depend>
</package>
Pada baris pertama, parameter dasar dari node adalah set - nama, versi, deskripsi, informasi tentang pembuat. Baris build_depend menentukan dependensi pustaka yang diperlukan untuk mengkompilasi paket, dan baris run_depend menentukan dependensi yang diperlukan untuk menjalankan kode dalam paket.Buat file capturer.cpp di dalam folder src dan tempelkan baris dari sini . Di sini, di metode main (), simpul diinisialisasi dan dimulai dalam satu loop:ros::init(argc, argv,"raspi_cam_ros");
ros::NodeHandle n;
UsbCamNode a(n);
a.spin();
Seluruh logika skrip adalah bahwa kita mendapatkan gambar dari kamera menggunakan OpenCV, membungkusnya dalam pesan untuk ROS dalam metode fillImage dan menerbitkannya ke topik. Di sini paket image_transport digunakan untuk membuat gambar "penerbit".Luncurkan driver uv4l dengan menjalankan perintah:$ uv4l --driver raspicam --auto-video_nr --width 640 --height 480 --nopreview
apa yang akan membuat streaming MJPEG.Kompilasi simpul ROS kami:$ roscore
$ cd ~/driverobot_ws
$ catkin_make
Periksa nilai variabel ROS_PACKAGE_PATH:echo $ROS_PACKAGE_PATH
/opt/ros/indigo/share:/opt/ros/indigo/stacks
Nilai variabel ROS_PACKAGE_PATH harus menyertakan jalur ke ruang kerja kami. Tambahkan ruang lokakarya kami ke jalur:$ source devel/setup.bash
Sekarang menjalankan perintah echo $ ROS_PACKAGE_PATH lagi kita akan melihat output yang sama:/home/youruser/catkin_ws/src:/opt/ros/indigo/share:/opt/ros/indigo/stacks
, di mana / home / <user_name> / catkin_ws / src adalah path ke ruang kerja kami. Ini berarti bahwa ROS dapat "melihat" simpul-simpul kita dibuat di catkin_ws dan kita dapat menjalankannya melalui rosrun.Jalankan simpul ROS kami:$ rosrun raspi_cam_ros capture
Jalankan program grafis rqt_image_view untuk menampilkan aliran video dari topik:$ rosrun rqt_image_view rqt_image_view
Pilih topik image_raw di jendela rqt_image_view.
Ketika memulai node, kesalahan "Gtk-PERINGATAN **: tidak dapat membuka tampilan: -1" dapat terjadi ketika bekerja melalui ssh atau "GdkGLExt-PERINGATAN **: Sistem jendela tidak mendukung OpenGL." saat berjalan dalam mode Remote Desktop VNC. Solusinya adalah terhubung ke Raspberry Pi melalui SSH dengan penerusan X11:$ ssh -X pi@<host_pi>
Anda dapat mengetahui seberapa sering posting diposting ke topik menggunakan perintah rostopic:rostopic hz image_raw
Perintah ini menghitung frekuensi menerima pesan per topik setiap detik dan menampilkannya di konsol.Untuk model B +, saya punya kesimpulan seperti ini:average rate: 7.905
min: 0.075s max: 0.249s std dev: 0.02756s
Seperti yang Anda lihat, frekuensi posting adalah 8 Hz.Saya juga memeriksa frekuensi penerbitan gambar dari kamera pada model RPi 2. Di sini hasilnya berkali-kali lebih baik:average rate: 30.005
min: 0.024s max: 0.043s std dev: 0.00272s
Pesan sudah diterbitkan pada frekuensi 30 Hz, yang merupakan peningkatan kecepatan yang cukup baik dibandingkan dengan model B +.Kontrol robot berbasis visual dengan OpenCV dan ROS
Sekarang kita akan menulis paket ROS kecil untuk menggunakan visi komputer pada robot dengan Raspberry Pi, yang akan melakukan algoritma pengenalan (dalam kasus kami, orientasi visual menggunakan metode garis berikut) dan mempublikasikan nilai dari robot yang diperlukan diimbangi dengan topik. Di sisi lain, simpul kendali gerak robot akan berlangganan ke topik ini dan mengirim perintah kendali gerak ke Arduino.Sekarang mari kita tambahkan "penerbit" ke skrip capturer.cpp, yang akan menerbitkan nilai shift. Pertama, aktifkan definisi tipe pesan untuk nilai shift - std_msgs / Int16.#include <std_msgs/Int16.h>
rosserial mengambil file pesan msg khusus dan menghasilkan kode sumber untuknya. Templat ini digunakan: Kode sumber untuk pesan umum standar disimpan di folder package_name di dalam direktori ros_lib. Selanjutnya, kami menginisialisasi pesan untuk jenis ini:package_name/msg/Foo.msg → package_name::Foo
std_msgs::Int16 shift_msg;
Buat "penerbit":ros::Publisher shift_pub;
dan di dalam konstruktor UsbCamNode kami memberikan definisi:shift_pub = nh.advertise<std_msgs/Int16>(“line_shift”, 1);
Di sini kita mengatur jenis pesan dan nama topik untuk publikasi.Selanjutnya, tambahkan logika untuk menghitung nilai pergeseran baris menggunakan OpenCV dan menerbitkannya ke topik line_shift di metode take_and_send_image () sebelum baris #ifdef OUTPUT_ENABLED:
shift_msg.data = offset;
shift_pub.publish(shift_msg);
Saya tidak memiliki algoritme mengikuti-baris yang sudah jadi, sehingga pembaca bebas menulis logikanya sendiri di sini.Bahkan, data dalam pesan disimpan di bidang data. Struktur pesan dapat dilihat menggunakan perintah:$ rosmsg show std_msgs/Int16
Sekarang jalankan node:$ rosrun raspi_cam_ros capturer
Kami menggunakan perintah echo rostopic untuk menampilkan data yang dipublikasikan ke topik line_shift:$ rostopic echo line_shift
Sekarang tambahkan "pelanggan" ke simpul kontrol robot. Aktifkan definisi jenis pesan:#include <std_msgs/UInt16.h>
Kemudian kami menambahkan fungsi panggilan balik yang dieksekusi ketika pesan diterima dari topik.void messageCb(const std_msgs::UInt16& message)
{
int shift_val = int(message.data);
char* log_msg;
if(shift_val < 0) log_msg = "Left";
else if(shift_val > 0 ) log_msg = "Right";
else log_msg = "Forward";
nh.loginfo(log_msg);
}
Fungsi callback harus bertipe batal dan mengambil referensi const tipe pesan sebagai argumen.Untuk mempermudah, saya mencatat pesan tentang arah offset baris. Di sini Anda dapat menambahkan logika gerakan robot Anda sendiri untuk skenario Anda.Buat pelanggan pesan dari topik line_shift.ros::Subscriber<std_msgs::UInt16> sub("line_shift", &messageCb);
Di sini kita mengatur nama topik dan tautan ke fungsi panggilan balik.Berikutnya adalah metode sketsa standar untuk rosserial_arduino:void setup()
{
nh.initNode();
nh.subscribe(sub);
Serial.begin(57600);
}
void loop()
{
nh.spinOnce();
delay(100);
}
Satu-satunya perbedaan adalah bahwa kami menambahkan nh.subscribe (sub) untuk membuat "langganan" sebenarnya dari situs ke topik.Sketsa untuk mengendalikan robot dapat diunduh dari sini .Trik kecil! Di ROS, ada file peluncuran khusus yang memungkinkan Anda untuk meluncurkan node sebagai proses terpisah secara otomatis dengan parameter tertentu. file peluncuran dibuat dalam format xml dan sintaksnya memungkinkan Anda untuk menjalankan banyak node sekaligus. Namun, file peluncuran tidak menjamin bahwa node akan diluncurkan dalam urutan yang ditentukan.Anda dapat membuat file peluncuran untuk membuat server rosserial_python lebih mudah untuk memulai.$ cd <catkin_ws>/src
$ catkin_create_pkg rosserial_controller
$ cd src/rosserial_controller
$ vim rosserial_controller.launch
Kami menulis file peluncuran dengan konten berikut:<launch>
<node pkg="rosserial_python" type="serial_node.py" name="arduino_serial">
<param name="port" value="/dev/ttyACM0"/>
</node>
</launch>
Kompilasi dan jalankan:$ cd ~/<catkin_ws>
$ catkin_make
$ source devel/setup.bash
$ roslaunch rosserial_controller rosserial_controller.launch
Kita dapat memvisualisasikan nilai-nilai yang diterbitkan dalam tema line_shift menggunakan utilitas rqt_plot, seperti yang dilakukan dalam artikel :$ rqt_plot line_shift
Sekarang Anda dapat memanfaatkan sepenuhnya Raspberry Pi Camera dan perpustakaan OpenCV dalam skenario Anda untuk orientasi visual robot, pengenalan objek, pelacakan, dan banyak lainnya. Bebaskan imajinasi Anda!Lain kali kita akan berbicara tentang mengendalikan robot dalam mode teleoperasi dengan menekan tombol pada keyboard.PS. Jaringan memiliki lembar cheat berguna - Lembar Cheat ROS. Untuk versi ROS Indigo, ini dapat diunduh dari sini .