Navigasi otonom dari robot seluler

Ada banyak cara di mana robot dapat menerima informasi dari dunia luar untuk berinteraksi dengannya. Juga, tergantung pada tugas yang diberikan kepadanya, metode pemrosesan informasi ini berbeda. Dalam artikel ini saya akan menjelaskan tahapan utama pekerjaan yang dilakukan sebagai bagian dari proyek sekolah, yang tujuannya adalah untuk mensistematisasikan informasi tentang berbagai metode navigasi robot otonom dan menerapkan pengetahuan yang diperoleh dalam proses pembuatan robot untuk kompetisi "RTK Cup".



pengantar


Di kompetisi "RTK Cup" ada satu blok tugas yang harus diselesaikan tanpa campur tangan operator. Saya percaya bahwa banyak peserta yang secara tidak adil menghindari tugas-tugas ini, karena tampaknya kerumitan membuat desain robot dan menulis sebuah program menyembunyikan sebagian besar tugas yang disederhanakan dari disiplin ilmu kompetitif lainnya, digabungkan dalam satu tempat pelatihan. Dengan proyek saya, saya ingin menunjukkan solusi yang mungkin untuk masalah seperti itu, dengan mempertimbangkan sebagai contoh berikut ini.

Untuk mencapai tujuan proyek, tugas perantara berikut dirumuskan:

  • Analisis aturan kompetisi "RTK Cup"
  • Analisis algoritma yang ada untuk orientasi otonom robot seluler
  • Pembuatan perangkat lunak

Analisis aturan kompetisi "RTK Cup"


Pada kompetisi "RTK Cup", peserta diberikan tempat pelatihan di mana bagian-bagian dengan berbagai kompleksitas dimodelkan. Kompetisi ini bertujuan untuk merangsang robot muda untuk menciptakan perangkat yang dapat bekerja dalam kondisi ekstrem, mengatasi hambatan, di bawah kendali manusia, atau secara mandiri.



secara singkat tentang unsur-unsur yang membentuk poligon
«» , . , , (), , (), ..

:



:



– , «» ( ) , . , , , , .

. , , , , , , .

Kompetisi dibagi menjadi dua yang secara fundamental berbeda dari masing-masing nominasi lainnya: "Seeker" dan "Extreme". Ini untuk memastikan bahwa kompetisi diadakan antara peserta dengan perbedaan usia minimum dan pengalaman dalam mengembangkan sistem robot: Pencari untuk tingkat yang lebih muda, dan Ekstrim untuk peserta dari usia 14 tahun ke atas. Dalam nominasi "Pencari", operator dapat dengan bebas bergerak di sekitar tempat pelatihan dan melakukan kontak mata langsung dengan mesin, sedangkan nominasi "Ekstrim" mengasumsikan bahwa robot memiliki sistem komunikasi video dan / atau visi komputer, karena operator harus menavigasi dalam labirin, hanya mengandalkan labirin. kamera dan sensor dibangun ke dalam robot, sambil berada di belakang layar khusus.

Untuk lolos dalam kompetisi, robot harus melewati tugas untuk kendali jarak jauh dari manipulator, atau melakukan salah satu elemen otonomi. Dalam kerangka proyek, tugas ditetapkan untuk memenuhi tugas otonomi, karena mereka memberikan poin terbanyak dengan biaya terendah dari operator. Unsur-unsur otonomi meliputi:

  • Berkendara di sepanjang garis dengan sensor cahaya sekitar atau sistem garis pandang
  • Pengambilan suar mandiri menggunakan sensor jarak atau sistem penglihatan
  • Gerakan di sepanjang lintasan yang kompleks (misalnya, naik / turun tangga) di sepanjang garis menggunakan kompas, giroskop, akselerometer, sistem penglihatan, atau metode gabungan

Juga, poin untuk mengatasi rintangan digandakan jika robot melewatinya secara mandiri.

Dalam kerangka kerja proyek ini, solusi untuk yang pertama dari tugas akan dipertimbangkan - pergerakan sepanjang garis. Metode yang paling umum digunakan saat bergerak di sepanjang garis adalah sensor cahaya dan kamera. Kelebihan dari sensor termasuk kesederhanaan membuat program - banyak dari mereka dilengkapi dengan tuning resistor, sehingga dengan mengatur sensor untuk pencahayaan latar belakang, itu akan memberikan 0 atau 1, tergantung pada apakah itu di telepon atau tidak. Untuk alasan yang sama, sensor cahaya tidak menuntut kekuatan pemrosesan dari pengontrol yang digunakan. Selain itu, karena ini, menyelesaikan masalah dengan bantuan sensor cahaya adalah yang paling murah - biaya sensor paling sederhana adalah 35 rubel, dan untuk pengendaraan yang relatif stabil di sepanjang jalur, tiga sensor sudah cukup (satu dipasang pada garis, dan dua di sisi). Namun,Salah satu kelemahan utama dari sensor tersebut adalah pembatasan pemasangan. Idealnya, sensor harus dipasang tepat di tengah, pada jarak kecil dari lantai, jika tidak maka akan memberikan nilai yang salah. Ini bukan masalah dalam kompetisi khusus, di mana robot harus mengemudi secepat mungkin di sepanjang lintasan, tetapi, dalam kondisi kompetisi "RTK Cup", semua kekurangan sensor yang disebutkan di atas dapat menjadi sangat penting - pemasangannya terutama membutuhkan kehadiran komponen mekanis tambahan pada robot yang menaikkan dan menurunkan sensor, dan ini membutuhkan ruang tambahan pada robot, mesin terpisah menggerakkan sensor, dan juga merupakan tempat kerusakan potensial dan meningkatkan massa robot.jika tidak maka akan memberikan nilai yang salah. Ini bukan masalah dalam kompetisi khusus di mana robot harus mengemudi secepat mungkin di sepanjang lintasan, tetapi, dalam kondisi kompetisi "RTK Cup", semua kekurangan sensor yang disebutkan di atas dapat menjadi sangat penting - pemasangannya terutama membutuhkan kehadiran komponen mekanis tambahan pada robot yang menaikkan dan menurunkan sensor, dan ini membutuhkan ruang tambahan pada robot, mesin terpisah menggerakkan sensor, dan juga merupakan tempat kerusakan potensial dan meningkatkan massa robot.jika tidak maka akan memberikan nilai yang salah. Ini bukan masalah dalam kompetisi khusus di mana robot harus mengemudi secepat mungkin di sepanjang lintasan, tetapi, dalam kondisi kompetisi "RTK Cup", semua kekurangan sensor yang disebutkan di atas dapat menjadi sangat penting - pemasangannya terutama membutuhkan kehadiran komponen mekanis tambahan pada robot yang menaikkan dan menurunkan sensor, dan ini membutuhkan ruang tambahan pada robot, mesin terpisah menggerakkan sensor, dan juga merupakan tempat kerusakan potensial dan meningkatkan massa robot.semua kekurangan sensor yang disebutkan di atas dapat menjadi kritis - pemasangannya terutama membutuhkan kehadiran bagian mekanik tambahan pada robot yang menaikkan dan menurunkan sensor, dan ini membutuhkan ruang tambahan pada robot, motor terpisah yang menggerakkan sensor, dan juga merupakan tempat kerusakan potensial dan meningkatkan massa robot .semua kekurangan sensor yang disebutkan di atas dapat menjadi sangat penting - pemasangannya terutama membutuhkan kehadiran robot pada bagian mekanik tambahan yang menaikkan dan menurunkan sensor, dan ini membutuhkan ruang tambahan pada robot, motor terpisah yang menggerakkan sensor, dan juga merupakan tempat kerusakan potensial dan meningkatkan massa robot .



Kamera, pada gilirannya, memiliki keuntungan sebagai berikut: ia memiliki jari-jari pengukuran praktis yang tidak terbatas (dibandingkan dengan sensor), yaitu hanya satu modul kamera yang dapat secara bersamaan melihat garis, baik secara langsung di bawah robot, dan pada jarak yang cukup dari itu, yang memungkinkan, misalnya, untuk mengevaluasi kelengkungannya dan memilih tindakan kontrol proporsional. Pada saat yang sama, modul kamera tidak mengganggu kemajuan robot di bagian lain dari TPA yang tidak memerlukan otonomi, karena kamera diperbaiki pada jarak dari lantai. Kerugian utama dari kamera adalah bahwa pemrosesan video membutuhkan kompleks komputasi yang kuat di papan robot, dan perangkat lunak yang dikembangkan membutuhkan penyetelan yang lebih baik, karena kamera menerima urutan informasi lebih besar dari dunia luar daripada tiga sensor cahaya, sementara kamera dan komputermampu memproses informasi yang diterima berkali-kali lebih dari tiga sensor dan "arduins".

Bagi saya pribadi jawabannya jelas bagi saya - dalam nominasi "ekstrem" robot harus memiliki kamera pengarah, yang dengannya operator akan menavigasi. Jika Anda menggunakan solusi FPV siap pakai, maka total biaya "sensor" bisa lebih tinggi, sementara itu membutuhkan instalasi perangkat tambahan. Selain itu, robot dengan raspberry pi dan kamera memiliki potensi lebih besar untuk pengembangan gerakan otonom, karena kamera dapat memecahkan berbagai masalah dan dapat digunakan tidak hanya dalam gerakan garis, sementara tidak terlalu menyulitkan desain.

Analisis algoritma visi komputer yang ada


Visi komputer adalah teori tentang menciptakan perangkat yang dapat menerima gambar dari objek dunia nyata, memproses dan menggunakan data yang diperoleh untuk memecahkan berbagai macam masalah yang diterapkan tanpa campur tangan manusia.

Sistem visi komputer terdiri dari:

  • satu atau lebih kamera
  • komplek komputer
  • Perangkat lunak yang menyediakan alat pengolah gambar
  • Saluran komunikasi untuk mengirimkan target dan informasi telemetri.

Seperti yang ditulis sebelumnya, ada banyak cara untuk mengidentifikasi objek yang menarik bagi kita. Dalam hal mengemudi sepanjang garis, perlu untuk memisahkan garis itu sendiri dari latar belakang yang kontras (garis hitam pada latar belakang putih atau garis putih pada latar belakang hitam untuk garis terbalik). Algoritma yang menggunakan sistem visi komputer dapat dibagi menjadi beberapa "langkah" untuk memproses gambar asli:

Pengambilan gambar: gambar digital diperoleh langsung dari kamera, dari aliran video yang dikirim ke perangkat, atau sebagai gambar terpisah. Nilai piksel biasanya sesuai dengan intensitas cahaya (warna atau gambar skala abu-abu), tetapi dapat dikaitkan dengan berbagai pengukuran fisik, seperti, misalnya, suhu dari kamera pencitraan termal.

Pemrosesan awal: Sebelum metode visi komputer dapat diterapkan ke data video, pra-pemrosesan diperlukan untuk memperkenalkan kondisi tertentu, tergantung pada metode yang digunakan. Contohnya adalah:

  • Menghapus kebisingan atau distorsi yang disebabkan oleh sensor yang digunakan
  • Gambar buram digunakan untuk menghilangkan artefak kecil yang terjadi selama operasi kamera, elemen dekompresi, noise, dll.
  • Memperbaiki kontras sehingga informasi yang tepat dapat dideteksi lebih mungkin
  • Ubah eksposur ke bayangan tanaman atau sorotan
  • Penskalaan atau pemangkasan untuk membedakan lebih baik antara struktur dalam gambar.
  • Mengubah gambar menjadi monokrom atau mengubah resolusinya untuk kinerja sistem yang lebih cepat

Menyoroti detail : detail gambar dari berbagai tingkat kesulitan diekstraksi dari data video. Contoh tipikal dari detail tersebut adalah garis, batas, tepi, titik individual, area yang merupakan karakteristik untuk fitur apa pun.
Deteksi : pada tahap tertentu pekerjaan program, informasi yang relevan dengan program dipisahkan dari gambar lainnya. Contohnya adalah:

  • Pemilihan satu set tertentu tempat menarik dalam warna, jumlah piksel terisolasi yang serupa dalam beberapa cara (kelengkungan gambar, warna, kecerahan, dll.)
  • Segmentasi satu atau beberapa bagian gambar yang berisi objek karakteristik.

Pemrosesan tingkat tinggi : pada langkah ini, kelimpahan informasi dari gambar dikurangi menjadi ukuran yang dapat dengan mudah diproses, misalnya, sekumpulan piksel tertentu atau koordinat bagian gambar di mana objek yang diinginkan seharusnya berada. Contohnya adalah:

  • Memfilter nilai berdasarkan kriteria apa pun
  • Evaluasi parameter seperti dimensi fisik objek, bentuk, lokasinya dalam bingkai atau relatif terhadap objek karakteristik lainnya
  • Klasifikasi

Selanjutnya, perlu memilih perpustakaan berdasarkan program yang akan dibuat. Faktor kunci dalam pilihan saya adalah:

  • Dukungan perpustakaan untuk antarmuka Python karena kemudahan relatif dalam mempelajari bahasa ini oleh seorang pemula, adalah sintaksis sederhana, yang memiliki efek menguntungkan pada keterbacaan program.
  • Portabilitas, mis. kemampuan untuk menjalankan program menggunakan perpustakaan ini pada raspberry pi3.
  • Prevalensi perpustakaan, yang menjamin komunitas programmer yang berkembang dengan baik yang mungkin telah mengalami masalah yang mungkin timbul selama pekerjaan Anda.

Di antara opsi yang saya periksa, saya menyoroti OpenCV open computer vision library, karena mendukung Python, memiliki dokumentasi online yang luas. Ada banyak artikel dan instruksi di Internet yang menjelaskan semua seluk-beluk bekerja dengan perpustakaan ini. Ada forum resmi dari pengembang tempat siapa pun dapat mengajukan pertanyaan tentangnya. Juga, perpustakaan ini diimplementasikan dalam bahasa C / C ++, yang menjamin kinerja sistem, dan strukturnya mendukung berbagai modul yang dapat dinonaktifkan untuk meningkatkan kinerja.

Pengembangan perangkat lunak


Setelah menginstal OS dan konfigurasi awal Raspberry pi, tetapi sebelum Anda mulai membuat program, Anda harus menginstal semua paket yang diperlukan untuk itu. Sebagian besar paket ini, pada gilirannya, diinstal menggunakan manajer paket pip (dalam kasus Python 3, pip3)

$ sudo apt install python3-pip

Pustaka berikut diinstal, seperti:

  • picamera - perpustakaan untuk bekerja dengan kamera raspberry pi
  • numpy - perpustakaan untuk bekerja dengan array data multidimensi, sebagai gambar

$ sudo pip3 install picamera
$ sudo pip3 install numpy

cmake - Utilitas untuk membangun program secara otomatis dari kode sumber
cmake-curses-gui - Paket GUI (antarmuka grafis) untuk cmake

$ sudo apt-get install cmake cmake-curses-gui libgtk2.0-dev
$ sudo apt-get install cmake cmake-curses-gui libgtk2.0-dev

perpustakaan untuk bekerja dengan berbagai format gambar dan video dan banyak lagi

$ sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev libv4l-dev libx264-dev libxvidcore-dev
$ sudo apt-get install libjpeg-dev libpng12-dev libtiff5-dev libjasper-dev
$ sudo apt-get install gfortran libatlas-base-dev

Untuk mengirimkan data video dari robot ke komputer, GStreamer akan digunakan - kerangka kerja yang dirancang untuk menerima, memproses dan mengirimkan data multimedia:

$ sudo apt install libgstreamer1.0-0 gstreamer1.0-plugins-base gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 gstreamer1.0-pulseaudio

Langkah selanjutnya adalah menginstal perpustakaan openCV itu sendiri dari sumber, mengkonfigurasi dan membangunnya. Untuk melakukan ini, folder kerja terbuka dibuat.

$ mkdir opencv
$ cd opencv

Untuk mengunduh versi terbaru perpustakaan, wget digunakan - program konsol untuk mengunduh file dari jaringan. Pada saat pembuatan program, versi stabil openCV terbaru adalah 4.1.0, jadi unduh dan bongkar sumbernya:

$ wget https://github.com/opencv/opencv/archive/4.1.0.zip -O opencv_source.zip
$ unzip opencv_source.zip
$ wget https://github.com/opencv/opencv_contrib/archive/4.1.0.zip -O opencv_contrib.zip
$ unzip opencv_contrib.zip

Setelah proses pembongkaran selesai, arsip sumber dapat dihapus.

$ rm opencv_source.zip
$ rm opencv_contrib.zip

Direktori dibuat untuk perakitan dan konfigurasi.

$ cd /home/pi/opencv/opencv-4.1.0
$ mkdir build
$ cd build

Parameter build dikonfigurasikan menggunakan utilitas cmake. Untuk melakukan ini, semua parameter signifikan dilewatkan sebagai variabel utilitas, bersama dengan nilai yang diberikan:

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local -D INSTALL_PYTHON_EXAMPLES=ON -D INSTALL_C_EXAMPLES=OFF -D BUILD_opencv_python2=OFF -D WITH_GSTREAMER=ON -D BUILD_EXAMPLES=ON -DENABLE_VFPV3=ON -DENABLE_NEON=ON -DCPU_BASELINE=NEON ..

Setelah mengatur konfigurasi, utilitas akan menampilkan semua parameter. Selanjutnya, Anda perlu mengkompilasi perpustakaan. Untuk melakukan ini, gunakan perintah console make –jN, di mana N adalah jumlah core yang akan terlibat dalam proses kompilasi. Untuk raspberry pi 3, jumlah core adalah 4, tetapi Anda pasti dapat mengetahui nomor ini dengan menuliskan perintah nproc di konsol.

$ make –j4

Karena sumber daya raspberry yang terbatas, kompilasi dapat memakan waktu cukup lama. Dalam beberapa kasus, raspberry bahkan dapat membeku, tetapi jika Anda kemudian masuk ke folder build dan mendaftar ulang make, pekerjaan akan dilanjutkan. Jika ini terjadi, ada baiknya mengurangi jumlah core yang terlibat, namun kompilasi saya berjalan tanpa masalah. Juga, pada tahap ini, ada baiknya memikirkan pendinginan aktif raspberry, karena meskipun dengan itu suhu prosesor mencapai sekitar 75 derajat.

Ketika kompilasi berhasil, perpustakaan perlu diinstal. Ini juga dilakukan dengan menggunakan utilitas make. Kemudian kita akan membentuk semua koneksi yang diperlukan dengan utilitas ldconfig:

$ sudo make install
$ sudo ldconfig

Kami memverifikasi instalasi dengan menulis perintah berikut dalam mode interaktif python:

import cv2
print(cv2.getBuildInformation())

Kesimpulan program berikut akan menjadi bukti pemasangan yang benar.



Perlu dicatat bahwa prosedur kompilasi perpustakaan di atas harus dilakukan baik pada robot dan pada PC dari yang direncanakan untuk mengendalikan robot dan dari mana siaran dari robot akan diterima.

Membuat skema distribusi video

Sebelum Anda mulai menulis kode, Anda perlu mengembangkan skema yang sesuai dengan algoritma akan berfungsi. Dalam hal ini, pengembangan perangkat lunak robot yang dibuat untuk berpartisipasi dalam kompetisi Piala RTK dalam nominasi Ekstrim, seluruh program akan dibagi menjadi dua bagian: robot dan remote control, yang akan dimainkan oleh komputer dengan OS Linux yang diinstal. Salah satu tugas paling penting di sini adalah membuat skema perkiraan tentang bagaimana data video akan dikirimkan antara berbagai bagian algoritma. Wi-Fi akan digunakan sebagai saluran komunikasi antara kedua perangkat. Paket data yang menyediakan kontrol robot dan data umpan balik akan dikirim dari satu perangkat ke perangkat lain menggunakan protokol UDP yang diimplementasikan dalam menggunakan perpustakaan soket. Data videokarena keterbatasan ukuran paket UDP akan dikirim menggunakan GStreamer. Untuk kenyamanan debugging, dua stream video akan diterapkan:

  • aliran video utama - mentransfer data video langsung dari kamera robot ke komputer untuk memastikan penundaan kontrol minimal.
  • aliran video tambahan - mentransfer data video yang diproses oleh robot, yang diperlukan untuk mengatur dan men-debug program yang mengimplementasikan visi komputer.

Dua aliran video akan secara bersamaan aktif pada robot, dan komputer akan menampilkan gambar yang diinginkan tergantung pada mode drive yang diaktifkan. Robot, pada gilirannya, tergantung pada apakah mode otonomi dihidupkan atau dimatikan, akan menggunakan data kontrol yang diterima dari komputer atau yang dihasilkan oleh prosesor gambar.



Remote control robot akan dilakukan karena pekerjaan dua aliran paralel pada robot dan di komputer:

  • "Konsol" dalam satu siklus mensurvei semua perangkat input yang tersedia dan membentuk paket data kontrol yang terdiri dari data itu sendiri dan checksum (pada saat membuat perubahan akhir pada artikel, saya menolak untuk membuat checksum untuk mengurangi keterlambatan, tetapi dalam sumber, yang saya diletakkan di bagian akhir kode ini dibiarkan) - dari nilai tertentu yang dihitung dari data yang ditetapkan oleh operasi beberapa algoritma yang digunakan untuk menentukan integritas data selama transmisi
  • Robot - Menunggu akses data dari komputer. Membuka paket data, menghitung ulang checksum dan membandingkannya dengan yang dikirim dan dihitung di sisi komputer. Jika checksum cocok, data ditransfer ke program utama.

Sebelum parsing algoritma deteksi garis, saya sarankan Anda membiasakan diri dengan fitur desain robot:

tentang robot
.

— . (3 ) . , . 6 , . . . . , - . «» rasberry pi 3 b — .

, , , , Solidworks petg . , raspberry .

ubiquiti bullet M5 hp. ( ) , . , «» .


: «» thingiverse. , , , , .


, , . , . , , , , . , , , .





- ( - 200 ) , , 90 70 ( ), , « ». , VL53L0X , .


«» , , (rds3115). — , , , , .


, , , :


- , , , . . raspberry, , . , .

, USB. , , .




Pembuatan algoritma deteksi garis menggunakan metode pustaka OpenCV


I. Memperoleh data

Karena fakta bahwa pemroses gambar tidak menerima data video langsung dari kamera, tetapi dari arus utama, perlu untuk memindahkannya dari format yang digunakan untuk terjemahan ke format yang digunakan untuk pemrosesan gambar, yaitu, array numpy yang terdiri dari nilai merah , hijau dan biru untuk masing-masing piksel. Untuk melakukan ini, Anda memerlukan data awal - bingkai yang diterima dari modul kamera raspberry pi.

Cara termudah untuk mendapatkan bingkai dari kamera c untuk diproses lebih lanjut adalah dengan menggunakan perpustakaan picamera. Sebelum Anda mulai, Anda harus mengizinkan akses ke kamera melalui raspi-config -> interfacing options camera -> pilih yes.

sudo raspi-config

bagian kode selanjutnya dihubungkan ke kamera raspberry dan dalam satu siklus dengan frekuensi yang diterima menerima bingkai dalam bentuk array yang siap digunakan oleh pustaka pembuka.

from picamera.array import PiRGBArray
from picamera import PiCamera
import cv2
#   
camera = PiCamera()
camera.resolution = (640, 480) 
camera.framerate = 30
cap = PiRGBArray(camera, size=(640, 480))

for frame in camera.capture_continuous(cap , format="bgr", use_video_port=True):
	new_frame = frame.array
	cap.truncate(0)
	if False: #   -   
		break

Penting juga dicatat bahwa metode ini menangkap bingkai, meskipun ini adalah yang paling sederhana, tetapi memiliki kelemahan serius: itu tidak terlalu efektif jika Anda perlu menyiarkan frame melalui GStreamer, karena ini membutuhkan beberapa kali untuk menyandikan ulang video, yang mengurangi kecepatan program. Cara yang jauh lebih cepat untuk mendapatkan gambar adalah dengan menghasilkan bingkai dari aliran video atas permintaan prosesor gambar, namun, tahapan lebih lanjut dari pemrosesan gambar tidak akan tergantung pada metode yang digunakan.

Contoh gambar dari kamera robot tanpa pemrosesan:


II Pra-pemrosesan

Saat mengemudi di jalur, akan sangat mudah untuk memisahkan area titik yang paling kontras dengan warna latar belakang. Metode ini cocok untuk kompetisi Piala RTK, karena menggunakan garis hitam pada latar belakang putih (atau garis putih pada latar belakang hitam untuk bagian terbalik). Untuk mengurangi jumlah informasi yang perlu diproses, Anda dapat menerapkan algoritma binarisasi untuknya, yaitu, mengonversi gambar ke format monokrom, di mana hanya ada dua jenis piksel - gelap dan terang. Sebelum ini, gambar harus diterjemahkan ke dalam skala abu-abu, dan juga mengaburkannya untuk memotong cacat kecil dan noise yang tak terhindarkan muncul selama pengoperasian kamera. Untuk mengaburkan gambar, filter Gaussian digunakan.

gray = cv2.cvtColor(self._frame, cv2.COLOR_RGB2GRAY)
blur = cv2.GaussianBlur(gray, (ksize, ksize), 0)

di mana ksize adalah ukuran inti Gaussian, yang meningkat, Anda dapat meningkatkan tingkat blur.

Contoh gambar setelah terjemahan dalam skala abu-abu dan kabur:


AKU AKU AKU. Memilih detail

Setelah gambar diterjemahkan dalam skala abu-abu, perlu untuk membuat binarize pada batas yang ditentukan. Tindakan ini memungkinkan Anda untuk lebih mengurangi jumlah data. Nilai ambang ini akan disesuaikan sebelum setiap keberangkatan robot di tempat baru, atau ketika kondisi pencahayaan berubah. Idealnya, tugas kalibrasi adalah untuk memastikan bahwa garis garis didefinisikan pada gambar, tetapi pada saat yang sama, tidak boleh ada detail lain pada gambar yang bukan garis:

thresh = cv2.threshold(blur, self._limit, 255, cv2.THRESH_BINARY_INV)[1]

Di sini, semua piksel lebih gelap dari nilai ambang (self._limit) diganti dengan 0 (hitam), lebih terang - oleh 255 (putih).

Setelah diproses, gambar tampak sebagai berikut:


Seperti yang Anda lihat, program telah mengidentifikasi beberapa bagian gambar yang paling gelap. Namun, setelah mengkalibrasi nilai ambang untuk benar-benar "menangkap" headphone, elemen putih lainnya muncul di layar di samping mereka. Tentu saja, Anda dapat menyempurnakan ambang, dan di tempat latihan kompetitif kamera akan melihat ke bawah, tidak membiarkan elemen yang tidak perlu ke dalam bingkai, tetapi saya menganggap perlu bagi saya untuk memisahkan garis dari yang lainnya.

IV.Deteksi

Pada gambar yang dipasangkan, saya menerapkan algoritma pencarian perbatasan. Dibutuhkan untuk menentukan tempat berdiri bebas dan mengubahnya menjadi array nyaman nilai koordinat titik yang membentuk perbatasan. Dalam kasus opencv, seperti yang tertulis dalam dokumentasi, algoritma standar untuk menemukan loop menggunakan algoritma Suzuki85 (saya tidak dapat menemukan referensi ke algoritma dengan nama ini di mana pun kecuali untuk dokumentasi opencv, tetapi saya akan berasumsi bahwa ini adalah algoritma Suzuki-Abe ).

contours = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)[0]

Dan inilah bingkai yang diperoleh pada tahap ini:


V. Pemrosesan Tingkat Tinggi

Setelah menemukan semua kontur dalam bingkai, kontur dengan area terbesar dipilih dan diambil sebagai kontur garis. Mengetahui koordinat semua titik kontur ini, koordinat pusatnya ditemukan. Untuk ini, apa yang disebut "momen gambar" digunakan. Momen adalah karakteristik total kontur, dihitung dengan menjumlahkan koordinat semua piksel kontur. Ada beberapa jenis momen - hingga urutan ketiga. Untuk masalah ini, hanya momen orde nol (m00) yang diperlukan - jumlah semua titik yang membentuk kontur (perimeter kontur), momen orde pertama (m10), yang merupakan jumlah koordinat X dari semua titik, dan m01 adalah jumlah koordinat Y dari semua titik. Dengan membagi jumlah koordinat titik di sepanjang salah satu sumbu dengan jumlah mereka, rata-rata aritmatika diperoleh - koordinat perkiraan pusat kontur. Selanjutnya, penyimpangan robot dari kursus dihitung:Tentu saja "langsung" sesuai dengan koordinat titik pusat sepanjang X dekat dengan lebar bingkai dibagi dua. Jika koordinat pusat garis dekat dengan pusat bingkai, maka tindakan kontrol minimal, dan, karenanya, robot mempertahankan jalurnya saat ini. Jika robot menyimpang dari salah satu sisi, maka tindakan kontrol yang sebanding dengan penyimpangan akan diperkenalkan sampai kembali.

mainContour = max(contours, key = cv2.contourArea)
M = cv2.moments(mainContour)
if M['m00'] != 0:#     (..   -  )
    cx = int(M['m10']/M['m00'])
    cy = int(M['m01']/M['m00'])

Di bawah ini adalah gambar skematis dari posisi robot relatif terhadap garis dan bingkai, dengan hasil program ditumpangkan pada mereka: kontur "utama", garis-garis yang melewati pusat kontur, dan juga titik yang terletak di pusat untuk memperkirakan penyimpangan. Elemen-elemen ini ditambahkan menggunakan kode berikut:

cv2.line(frame, (cx, 0), (cx, self.height), (255, 0, 0), 1)    #    
cv2.line(frame, (0, cy), (self.width, cy), (255, 0, 0), 1)                  
cv2.circle(frame, (self.width//2, self.height//2), 3, (0, 0, 255), -1) #  
cv2.drawContours(frame, mainContour, -1, (0, 255, 0), 2, cv2.FILLED) #   

Untuk kenyamanan debugging, semua elemen yang dijelaskan sebelumnya ditambahkan ke bingkai mentah:





Dengan demikian, setelah mendorong frame melalui algoritma pemrosesan, kami mendapat koordinat X dan Y dari pusat objek yang menarik bagi kami, serta gambar debug. Selanjutnya, posisi robot relatif terhadap garis ditampilkan secara skematis, serta gambar yang telah melewati algoritma pemrosesan.


Langkah selanjutnya dalam program ini adalah mengubah informasi yang diperoleh pada langkah sebelumnya menjadi nilai daya dua motor.

Cara termudah untuk mengkonversi perbedaan antara pergeseran pusat titik warna relatif ke tengah bingkai adalah regulator proporsional (Ada juga regulator relai, tetapi, karena fitur operasinya, tidak cocok untuk mengemudi di sepanjang garis). Prinsip operasi dari algoritma semacam itu adalah bahwa pengontrol menghasilkan aksi kontrol pada objek secara proporsional dengan besarnya kesalahan. Selain pengontrol proporsional, ada juga yang integral, di mana seiring waktu komponen integral "menumpuk" kesalahan dan yang diferensial, prinsip yang didasarkan pada penerapan pengaruh peraturan hanya dengan perubahan yang cukup dalam variabel yang dikendalikan. Dalam praktiknya, pengontrol P, I, D yang paling sederhana ini digabungkan menjadi pengontrol dari tipe PI, PD, PID.

Perlu disebutkan bahwa pada robot saya, saya mencoba "memulai" kontroler PID, tetapi penggunaannya tidak memberikan keuntungan serius dibandingkan dengan kontroler proporsional yang biasa. Saya akui bahwa saya tidak dapat mengatur regulator dengan benar, tetapi ada juga kemungkinan bahwa keuntungannya tidak begitu jelas terlihat dalam kasus robot berat yang tidak dapat secara fisik mengembangkan kecepatan tinggi. Dalam versi terbaru dari program pada saat penulisan, regulator proporsional sederhana digunakan, tetapi dengan fitur kecil yang memungkinkan Anda untuk menggunakan lebih banyak informasi dari kamera: ketika menghasilkan nilai kesalahan, tidak hanya posisi horizontal dari titik tengah tempat diperhitungkan, tetapi juga secara vertikal, yang memungkinkan berbagai cara menanggapi elemen garisterletak "di kejauhan" dan langsung di depan atau di bawah robot (kamera robot memiliki sudut pandang yang besar, jadi dengan memutarnya hanya 45 derajat ke bawah, Anda sudah dapat melihat bagian penting dari bidang di bawah robot).

error= cx / (self.width/2) - 1  
#  ( 0   )  [-1; 1]
error*= cy / self.height + self.gain #

Paling sering, dalam kondisi kompetisi "RTK Cup", peserta menggunakan apa yang disebut "sirkuit tangki" - satu atau lebih mesin mengendalikan satu sisi robot, dan bekerja baik dengan trek maupun roda. Dengan menggunakan skema ini, Anda dapat menyingkirkan elemen transmisi kompleks yang meningkatkan kemungkinan kerusakan (diferensial atau poros cardan), dapatkan radius putar sekecil mungkin, yang memberikan keuntungan dalam poligon terbatas. Skema ini melibatkan kontrol paralel dari dua "sisi" untuk gerakan di sepanjang jalur yang kompleks. Untuk melakukan ini, program ini menggunakan dua variabel - kekuatan motor kanan dan kiri. Kekuatan ini tergantung pada kecepatan dasar (BASE_SPEED), bervariasi dalam kisaran dari 0 hingga 100.Kesalahan (kesalahan) - perbedaan antara pusat frame dan koordinat tengah garis dan koefisien efek proporsional (self._koof), yang dikalibrasi oleh operator. Nilai absolutnya mempengaruhi seberapa cepat robot akan mencoba menyelaraskan dirinya dengan garis. Karena kenyataan bahwa pada satu mesin aksi kontrol dikurangi dari kecepatan dasar, dan pada yang lain - ditambahkan, giliran dilakukan ketika menyimpang dari jalur. Arah di mana pembalikan akan dilakukan dapat disesuaikan dengan mengubah tanda variabel self._koof. Juga, Anda mungkin memperhatikan bahwa sebagai akibat dari bagian kode berikutnya, nilai daya mungkin muncul lebih dari 100, tetapi dalam program saya, kasus tersebut diproses lebih lanjut nanti.Nilai absolutnya mempengaruhi seberapa cepat robot akan mencoba menyelaraskan dirinya dengan garis. Karena kenyataan bahwa pada satu mesin aksi kontrol dikurangi dari kecepatan dasar, dan pada yang lain - ditambahkan, giliran dilakukan ketika menyimpang dari jalur. Arah di mana pembalikan akan dilakukan dapat disesuaikan dengan mengubah tanda variabel self._koof. Juga, Anda mungkin memperhatikan bahwa sebagai hasil dari bagian kode berikutnya, nilai daya mungkin muncul lebih dari 100, tetapi dalam program saya kasus-kasus semacam itu juga diproses lebih lanjut.Nilai absolutnya mempengaruhi seberapa cepat robot akan mencoba menyelaraskan dirinya dengan garis. Karena kenyataan bahwa pada satu mesin aksi kontrol dikurangi dari kecepatan dasar, dan pada yang lain - ditambahkan, giliran dilakukan ketika menyimpang dari jalur. Arah di mana pembalikan akan dilakukan dapat disesuaikan dengan mengubah tanda variabel self._koof. Juga, Anda mungkin memperhatikan bahwa sebagai hasil dari bagian kode berikutnya, nilai daya mungkin muncul lebih dari 100, tetapi dalam program saya kasus-kasus semacam itu juga diproses lebih lanjut.di mana pembalikan akan dilakukan, Anda dapat menyesuaikan dengan mengubah tanda variabel self._koof. Juga, Anda mungkin memperhatikan bahwa sebagai hasil dari bagian kode berikutnya, nilai daya mungkin muncul lebih dari 100, tetapi dalam program saya kasus-kasus semacam itu juga diproses lebih lanjut.di mana pembalikan akan dilakukan, Anda dapat menyesuaikan dengan mengubah tanda variabel self._koof. Juga, Anda mungkin memperhatikan bahwa sebagai hasil dari bagian kode berikutnya, nilai daya mungkin muncul lebih dari 100, tetapi dalam program saya kasus-kasus semacam itu juga diproses lebih lanjut.

#if lineFound:
leftSpeed = round(self.base_speed + error*self.koof)
rightSpeed = round(self.base_speed - error*self.koof)

Kesimpulan


Setelah menguji program yang dihasilkan, saya dapat mengatakan bahwa momen sulit utama dalam mengatur program adalah kalibrasi algoritma ke fitur pencahayaan. Karena tahap pembuatan artikel bertepatan dengan isolasi diri yang dinyatakan, saya harus membuat video dengan demonstrasi pekerjaan di sebuah ruangan kecil. Ini membuat saya kesulitan:

  • -, , ( , ), . , , , . , , , ,
  • -, — , ,

Terlepas dari kenyataan bahwa kedua masalah ini tidak ada dalam kondisi kompetisi nyata, saya akan mengambil langkah-langkah untuk memastikan bahwa pekerjaan program minimal tergantung pada faktor-faktor eksternal.
Juga, di masa depan, direncanakan untuk terus bekerja pada implementasi algoritma menggunakan metode visi komputer, menciptakan perangkat lunak yang mampu melewati elemen-elemen otonomi yang tersisa yang dijelaskan di bagian pertama artikel (penangkapan suar otonom, pergerakan sepanjang jalur yang kompleks). Direncanakan untuk memperluas fungsionalitas robot dengan menambahkan sensor tambahan: pengintai, giroskop-accelerometer, kompas. Terlepas dari kenyataan bahwa penerbitan artikel ini akan mengakhiri pekerjaan saya pada proyek sebagai mata pelajaran wajib sekolah, saya berencana untuk terus menggambarkan di sini tahap pengembangan selanjutnya. Karena itu, saya ingin menerima komentar tentang karya ini.

Setelah menerapkan semua langkah yang ditujukan untuk menyelesaikan masalah proyek, aman untuk mengatakan bahwa penggunaan algoritma visi komputer, dengan semua kompleksitas relatifnya dalam pemrograman dan debugging, memberikan keuntungan terbesar pada tahap kompetisi itu sendiri. Dengan dimensi kamera yang kecil, kamera ini memiliki potensi yang sangat besar dalam hal pengembangan perangkat lunak, karena kamera memungkinkan Anda mengganti beberapa sensor "tradisional" sekaligus, sambil menerima lebih banyak informasi dari dunia luar. Dimungkinkan untuk mewujudkan tujuan proyek - untuk membuat program yang menggunakan visi komputer untuk menyelesaikan masalah navigasi otonom robot dalam kondisi kompetisi "RTK Cup", serta menggambarkan proses pembuatan program dan tahapan utama dalam pemrosesan gambar.

Seperti yang saya katakan sebelumnya, tidak mungkin untuk membuat ulang lintasan kompleks garis rumah, dan contoh ini menunjukkan bagaimana algoritma memenuhi putaran. Ketebalan garis di sini sesuai dengan yang sesuai dengan peraturan, dan kurva paling lilitan kira-kira mencerminkan kelengkungan rotasi sebesar 90 derajat pada poligon:


Anda dapat melihat kode program, serta memantau pekerjaan lebih lanjut pada proyek, pada github saya atau di sini, jika saya melanjutkan.

All Articles