Taksi tak berawak mengendarai bebek karet kuning di sekitar kota! Modul pemeriksaan masalah untuk platform Gym-Duckietown

Pada 2040, sebagian besar kota besar di dunia akan mengendarai mobil tanpa pengemudi, kata para analis . Tapi untuk bersantai di jalan 20 tahun dari sekarang, kita perlu melakukan beberapa pekerjaan bagus pada algoritme mengemudi otonom. Untuk melakukan ini, MIT mengembangkan platform Duckietown , yang memungkinkan Anda melakukan ini dengan biaya minimal. Di Duckietown, robot seluler berbiaya rendah mengangkut bebek karet kuning dalam model kota yang diperkecil. Atas dasar platform ini, AI Driving Olympics diadakan dan kursus diluncurkan di universitas tentang penggunaan teknologi kecerdasan buatan dalam pengelolaan kendaraan tak berawak.



Pada artikel ini saya akan berbicara tentang proyek kursus saya, yang saya kerjakan bersama dengan Laboratorium Algoritma Robot Seluler JetBrains Research : About the Issue Checker yang saya tulis untuk emulator Gym-Duckietown . Kami akan berbicara tentang sistem pengujian dan integrasi sistem ini dengan platform online pendidikan yang menggunakan teknologi Pemeringkat Eksternal - misalnya, dengan platform Stepik.org .









tentang Penulis



Nama saya Daniil Plushenko, dan saya adalah mahasiswa tahun pertama (kedua) dari program Master " Pemrograman dan Analisis Data " di St. Petersburg HSE. Pada 2019, saya menyelesaikan gelar Sarjana Matematika Terapan dan Ilmu Komputer di universitas yang sama.



Platform Duckietown



Duckietown adalah proyek penelitian kendaraan otonom . Penyelenggara proyek telah menciptakan platform yang membantu menerapkan pendekatan baru untuk pembelajaran di bidang kecerdasan buatan dan robotika. Semuanya dimulai sebagai kursus di MIT pada tahun 2016, tetapi secara bertahap menyebar ke seluruh dunia dan di berbagai tingkat pendidikan, dari sekolah menengah hingga program magister.



Platform Duckietown memiliki dua bagian. Pertama, ini adalah model lingkungan transportasi perkotaan yang diperkecil dengan jalan, bangunan, rambu jalan, dan rintangan. Kedua, transportasi. Robot seluler kecil (Duckiebots) yang menjalankan Raspberry Pi menerima informasi tentang dunia di sekitar mereka melalui kamera dan mengangkut penduduk kota - bebek karet kuning - di sepanjang jalan.







Saya telah bekerja dengan emulator Duckietown. Itu disebutGym-Duckietown , dan ini adalah proyek sumber terbuka yang ditulis dengan Python. Emulator menempatkan bot Anda di dalam kota, mengubah posisinya tergantung pada algoritme yang Anda gunakan (atau pada tombol yang Anda tekan), menggambar ulang gambar dan menulis posisi bot saat ini ke log.  



Jika Anda tertarik untuk mencoba, saya sarankan untuk mengkloning repositori Anda sendiri dan menjalankan manual_control.py : dengan cara ini bot dapat dikontrol menggunakan panah pada keyboard.



Tangkapan layar dari emulator



Emulator dapat digunakan sebagai lingkungan untuk menjalankan tugas. Mari kita atur masalah berikut: pada peta tertentu, yang terdiri dari satu jalur, Anda perlu mengemudi satu meter dalam garis lurus.







Untuk mengatasi masalah tersebut, Anda dapat menggunakan algoritma berikut:



for _ in range(25):
    env.step([1, 0])
    env.render()


Variabel ini envmenyimpan keadaan lingkungan.

Metode langkah mengambil masukan action: daftar dua elemen yang menjelaskan tindakan bot. Elemen pertama mengatur kecepatan, yang kedua - sudut rotasi. Metode rendermenggambar ulang gambar, dengan mempertimbangkan posisi baru bot. Jumlah langkah dan kecepatan dipilih secara empiris: ini adalah nilai yang diperlukan bot untuk berjalan tepat satu meter dalam garis lurus.



Jika Anda ingin menggunakan potongan ini di manual_control.py, tempelkan di sini . Kode hingga saat ini memuat lingkungan. Untuk kesederhanaan, Anda dapat menggunakannya kembali, dan kemudian menambahkan solusi di atas ke masalah tersebut.



Sistem pengujian



Saya ingin dapat memeriksa tugas-tugas tersebut secara otomatis: melakukan implementasi algoritma kontrol bot, mensimulasikan perjalanan dan melaporkan apakah algoritma yang diusulkan melakukan tugas dengan benar. Sistem pengujian semacam itu akan memungkinkan untuk menggunakan lingkungan selama persiapan kompetisi dalam kendali transportasi otonom, serta untuk tujuan pendidikan: untuk mengeluarkan serangkaian masalah kepada siswa dan memeriksa solusi mereka secara otomatis. Saya terlibat dalam pengembangannya saat mengerjakan proyek kursus dan di bawah ini saya akan memberi tahu Anda tentang apa yang saya dapatkan.



Urutan langkah saat memeriksa solusi terlihat seperti ini:







Anda dapat menambahkan sendiri tugas ke sistem pengujian atau merujuk ke tugas yang saya lakukan. Setiap tugas memiliki generator kondisi - kelas yang menghasilkan status lingkungan. Ini berisi nama peta dan posisi awal bot di dalam sel awal. Koordinat target juga ditetapkan: dalam hal ini, titik satu meter dari posisi awal.



class Ride1MTaskGenerator(TaskGenerator):
    def __init__(self, args):
        super().__init__(args)

    def generate_task(self):
        env_loader = CVTaskEnv if self.args.is_cv_task else TrackingDuckietownEnv
        env = env_loader(
            map_name="straight_road",
            position_on_initial_road_tile=PositionOnInitialRoadTile(
                x_coefficient=0.5,
                z_coefficient=0.5,
                angle=0,
            ),
        )
        self.generated_task['target_coordinates'] = [[env.road_tile_size * 0.5 + 1, 0, env.road_tile_size * 0.5]]
        self.generated_task['env'] = env
        env.render()
        return self.generated_task


Berikut TrackingDuckietownEnvdan CVTaskEnvadalah kelas pembungkus yang digunakan untuk menyimpan informasi tentang perjalanan untuk analisa lebih lanjut. 



class TrackingDuckietownEnv:
    def __init__(self, **kwargs):
        self.__wrapped = DuckietownEnv(**kwargs)
    def step(self, action):
        obs, reward, done, misc = self.__wrapped.step(action)
        message = misc['Simulator']['msg']
        if 'invalid pose' in message.lower():
            raise InvalidPoseException(message)
        for t in self.trackers:
            t.track(self)
        return obs, reward, done, misc


Pelacak mengumpulkan informasi tentang keadaan saat ini, seperti posisi bot.



CVTaskEnvini digunakan jika solusi diperlukan hanya dengan menggunakan informasi dari kamera ("computer vision"), dan bukan fungsi emulator: misalnya, jika Anda perlu mengetahui seberapa jauh bot dari pusat strip atau di mana objek terdekat yang terlihat. CVTaskEnvMemanggil fungsi emulator dapat menyederhanakan tugas, dan class membatasi pemanggilan metode emulator. Ini digunakan saat bendera ditampilkan is_cv_task



class CVTaskEnv:
    def __init__(self, **kwargs):
        self.__wrapped = TrackingDuckietownEnv(**kwargs)

    def __getattr__(self, item):
        if item in self.__wrapped.overriden_methods:
            return self.__wrapped.__getattribute__(item)
        ALLOWED_FOR_CV_TASKS = [
            'render', '_CVTaskEnv__wrapped', '_TrackingDuckietownEnv__wrapped',
            'road_tile_size', 'trip_statistics'
        ]
        if item in ALLOWED_FOR_CV_TASKS:
            return self.__wrapped.__getattr__(item)
        else:
            raise AttributeError(item + " call is not allowed in CV tasks")


Setelah eksekusi keputusan selesai - asalkan tidak diganggu oleh batas waktu - informasi perjalanan diteruskan melalui urutan checker. Jika semua checker berhasil, masalah dianggap terselesaikan dengan benar. Jika tidak, putusan penjelasan akan ditampilkan - misalnya, bot macet, keluar dari jalan raya, dll.



Berikut adalah salah satu checker standar. Dia memeriksa bahwa bot telah kembali ke titik awal di akhir perjalanan. Ini dapat berguna jika, misalnya, dalam suatu tugas Anda perlu mengemudi ke titik tertentu dan kemudian kembali lagi.



class SameInitialAndFinalCoordinatesChecker(Checker):
    def __init__(self, maximum_deviation=0.1, **kwargs):
        super().__init__(**kwargs)
        self.maximum_deviation = maximum_deviation

    def check(self, generated_task, trackers, **kwargs):
        trip_statistics = next(x for x in trackers if isinstance(x, TripStatistics))
        trip_data = trip_statistics.trip_data
        if len(trip_data) == 0:
            return True
        initial_coordinates = trip_data[0].position.coordinates
        final_coordinates = trip_data[-1].position.coordinates
        return np.linalg.norm(initial_coordinates - final_coordinates) < self.maximum_deviation


Sistem pengujian semacam itu dapat digunakan dalam mode manual, yaitu memulai pengujian secara manual, dan kemudian mempelajari putusan secara visual. Jika kami ingin, misalnya, meluncurkan kursus online tentang transportasi otonom di Stepik.org , kami memerlukan integrasi dengan platform tersebut. Ini akan dibahas di bagian artikel selanjutnya.



Integrasi dengan platform online



Untuk tugas pengujian, sering digunakan teknologi External Grader, yang dikembangkan oleh platform edX .



Saat menggunakan External Grader, platform pendidikan tidak memeriksa tugasnya sendiri, tetapi menghasilkan antrian paket yang dikirim ke perangkat lain. Fungsionalitas koneksi antrian diimplementasikan dalam proyek xqueue-watcher . Xqueue-watcher mengambil parsel dan kemudian diuji oleh validator (yang biasanya melakukan lebih banyak tindakan non-sepele daripada perbandingan teks / angka). Setelah itu, putusan verifikasi dikirim kembali ke sisi platform pendidikan.



Mari pertimbangkan secara lebih detail saat menghubungkan ke antrian. Setelah platform pendidikan menyediakan data koneksi, mereka perlu ditambahkan kefile konfigurasi , dan dalam metode kelas , terapkan peluncuran verifikasi secara langsung. Instruksi lebih rinci dapat ditemukan di sini dan di sini .



Xqueue-watcher memanggil get_submission titik akhir , yang akan mengambil paket dari antrian jika memungkinkan. Setelah itu, dia pergi untuk pengujian. Pengamat xqueue kemudian memanggil put_result untuk mengembalikan putusan.



Anda dapat memulai xqueue-watcher seperti ini:



make requirements && python -m xqueue_watcher -d conf.d/


Katakanlah kita ingin menggunakan teknologi Pengukur Eksternal, tetapi tidak ingin menjalankan kursus di platform online. Xqueue-watcher diimplementasikan dengan asumsi bahwa ada beberapa penyimpanan file di mana file dengan solusi diunggah (platform memiliki penyimpanan seperti itu). Kita bisa memodifikasi Xqueue sehingga penyimpanan file tidak lagi dibutuhkan, dan sistem seperti itu bisa dijalankan, secara umum, bahkan di laptop kita.



Pertama, Anda perlu mempelajari cara mengelola antrean parsel itu sendiri. Fungsionalitas antrian disediakan oleh proyek xqueue .





Gambar diambil dari dokumentasi .



Anda dapat menjalankannya seperti ini:



apt-get install libaio1 libaio-dev
apt-get install libmysqlclient-dev
pip3 install -r requirements.txt
python3 manage.py migrate
python3 manage.py runserver $xqueue_address


Anda mungkin perlu membuat file ~ / edx / edx.log



Secara default, xqueue memberi xqueue-watcher bukan konten dari paket, yaitu file dengan solusi untuk masalah, tetapi link ke file ini di penyimpanan file. Agar tidak bergantung pada penyimpanan file, Anda dapat membuat file itu sendiri dikirim dan menyimpannya di mesin yang sama yang menjalankan xqueue-watcher. 



Berikut cara kode sumber perlu dimodifikasi untuk mencapai ini:



Penerapan metode _upload di lms_interface.py diganti dengan yang ini:



def _upload(file_to_upload, path, name):
    '''
    Upload file using the provided keyname.
    Returns:
        URL to access uploaded file
    '''
    full_path = os.path.join(path, name)
    return default_storage.save(full_path, file_to_upload)


Jika tidak ada penyimpanan file yang terhubung, maka metode ini akan menyimpan file dengan solusi ke jalur $ queue_name / $ file_to_upload_hash.



Dalam implementasi get_sumbission di file ext_interface.py, alih-alih baris ini, tulis:



xqueue_files = json.loads(submission.urls)
for xqueue_file in xqueue_files.keys():
    with open(xqueue_files[xqueue_file], 'r') as f:
        xqueue_files[xqueue_file] = f.readlines()


Mari kita transfer bukan tautan (jalur) ke file, tetapi isinya.



Setiap solusi dijalankan dalam kontainer buruh pelabuhan "satu kali" dengan sumber daya terbatas, yaitu, wadah terpisah dibuat untuk eksekusi setiap solusi, yang dihapus setelah pengujian selesai. Untuk membuat kontainer seperti itu dan menjalankan perintah di dalamnya, portainer-api digunakan (pada kenyataannya, sebagai pembungkus di atas Docker API).



Hasil



Dalam artikel ini, saya berbicara tentang bagaimana sistem pengujian dan tugas untuk transportasi otonom dibuat, serta integrasi sistem ini dengan platform pendidikan online yang menggunakan teknologi Pengukur Eksternal. Saya berharap kursus yang menggunakan sistem ini segera diluncurkan, dan bagian tentang integrasi dengan platform online akan bermanfaat bagi mereka yang ingin membuat kursus offline atau online mereka sendiri.



All Articles