Dalam beberapa tahun terakhir, perkembangan teknologi otomasi di berbagai sektor industri semakin pesat. Salah satu inovasi yang mulai banyak diterapkan adalah penggunaan Autonomous Guided Vehicle atau AGV. Kendaraan tanpa awak ini hadir sebagai solusi cerdas untuk memindahkan barang secara otomatis dengan efisiensi tinggi dan minim intervensi manusia.
AGV bukan sekadar mobil robot yang bisa bergerak sendiri — ia merupakan bagian penting dari transformasi digital di bidang logistik, manufaktur, hingga gudang penyimpanan. Dengan kemampuan navigasi mandiri menggunakan sensor, laser, atau sistem visi komputer, AGV mampu menggantikan proses manual yang sebelumnya memakan banyak waktu dan tenaga kerja.
Kehadiran AGV juga semakin relevan di tengah tuntutan industri akan produktivitas, akurasi, serta keamanan kerja yang lebih baik. Selain itu, dengan adanya pandemi beberapa tahun belakangan, banyak perusahaan mulai beralih ke sistem otomatis untuk mengurangi ketergantungan pada tenaga kerja langsung — dan AGV menjadi salah satu jawaban utama.
Setelah saya berhasil mengubah mobil RC 27mhz menjadi ber - WiFi ( baca disini ), maka langkah awal yang saya lakukan untuk menjadikannya bisa mengikuti rute terpendek seperti gambar animasi diatas adalah dengan membuat marking kode di tiap koordinatnya menggunakan kode AruCo. Untuk itu saya menambahkan kamera CCTV IP diatas mobil-mobilan remote yang saya sudah modifikasi.
Saya pilihkan IP CCTV merek Ezviz H1C yang paling cocok karena bisa digunakan dalam mode offline (tanpa butuh internet), dibanding awalnya saya menggunakan merek bardi yang sejenis namun harus terhubung internet baru bisa di akses RTSP streamnya. Untuk mengakses stream CCTV ezviz cukup butuh password securitynya (6 buah huruf) yang biasanya terdapat di bawah dudukan kameranya (atau bisa diubah lewat aplikasi ezviz) serta IP yang didapatnya. Contoh nya alamat seperti ini :
rtsp://admin:XXXXXX@192.168.1.178:554/Streaming/Channels/101
Alamat paling belakang merupakan mode resolusi dimana 101 = HD 1080 dan jika 102 ber resolusi SD 480.
Logika yang saya gunakan untuk percobaan kali ini sebagai berikut :
1. CCTV ip diakses stream nya oleh python-opencv dan kemudian mencari kode ArUco pada frame yang ditangkap yang sudah ditentukan kode ID nya
2. Layar gambar dibagi menjadi 3 bagian yaitu kanan tengah dan kiri. Apabila kodenya terdapat ditengah maka akan mengirmkan perintah maju ke RC melalui pengiriman pesan UDP, begitu pula untuk kanan dan kiri.
3. Mobil RC kemudian akan bergerak sesuai dengan animasi paling atas tulisan ini. Jika tidak ada kode yang terdeteksi selama 10 detik maka mobil akan mundur untuk mencari kemungkinan kode terlewati
4. Langkah selanjutnya akan di desain pendeteksi urutan gerak RC sesuai ID marker yang sudah disusun berdasarkan rute terpendek
Koding pythonnya seperti berikut :
import cv2 import socket import time # Konfigurasi UDP sesuaikan dengan koding mobil RC wifi UDP_IP = "192.168.1.177" UDP_PORT = 4210 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) def send_udp(data): sock.sendto(data.encode(), (UDP_IP, UDP_PORT)) print(f"[UDP] Terkirim: {data}") # URL RTSP dari kamera IP rtsp_url = "rtsp://admin:XXXXXX@192.168.1.178:554/Streaming/Channels/102" # Inisialisasi detector ArUco aruco_dict = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_APRILTAG_36H11) parameters = cv2.aruco.DetectorParameters() detector = cv2.aruco.ArucoDetector(aruco_dict, parameters) target_id = 32 last_send_time = time.time() last_detection_time = time.time() # Untuk hitung mundur mundur send_data = "0" action_text = "Tidak Ada Deteksi" has_sent_stop = False # Hanya kirim "2" sekali per siklus # Fungsi untuk menulis teks dan kotak def draw_overlay(frame, text): font = cv2.FONT_HERSHEY_SIMPLEX cv2.putText(frame, f"Aksi: {text}", (10, 60), font, 1, (0, 255, 255), 2, cv2.LINE_AA) cap = cv2.VideoCapture(rtsp_url) while True: ret, frame = cap.read() if not ret: print("Tidak dapat menerima frame. Keluar...") break current_time = time.time() detected = False # --- DETEKSI APRILTAG --- corners, ids, rejected = detector.detectMarkers(frame) if ids is not None: for i in range(len(ids)): if ids[i][0] == target_id: corner = corners[i][0] # Gambar kotak di sekitar tag cv2.polylines(frame, [corner.astype(int)], True, (0, 255, 0), 2) # Hitung titik tengah cX = int((corner[0][0] + corner[2][0]) / 2) width = frame.shape[1] zona_kiri = width // 3 zona_tengah = 2 * width // 3 # Tentukan zona dan aksi if cX < zona_kiri: action_text = "Kiri" send_data = "3" elif cX < zona_tengah: action_text = "Maju" send_data = "1" else: action_text = "Kanan" send_data = "4" # Reset timer mundur last_detection_time = current_time has_sent_stop = False detected = True # Titik tengah cY = int((corner[0][1] + corner[2][1]) / 2) cv2.circle(frame, (cX, cY), 5, (0, 0, 255), -1) # Garis pembatas zona cv2.line(frame, (zona_kiri, 0), (zona_kiri, frame.shape[0]), (255, 0, 0), 1) cv2.line(frame, (zona_tengah, 0), (zona_tengah, frame.shape[0]), (255, 0, 0), 1) break # --- LOGIKA TIMER MUNDUR --- if not detected: elapsed_no_detection = current_time - last_detection_time if elapsed_no_detection >= 10 and not has_sent_stop: send_data = "2" action_text = "Mundur" send_udp(send_data) print("[INFO] Mengirim '2' (mundur)") has_sent_stop = True # Tandai bahwa sudah dikirim else: action_text = "Tidak Ada Deteksi" send_data = "0" else: last_detection_time = current_time # Reset timer jika ada deteksi has_sent_stop = False # Reset agar bisa kirim ulang "2" di masa depan # --- KIRIM DATA SETIAP 2 DETIK --- if current_time - last_send_time >= 2: send_udp(send_data) last_send_time = current_time # --- TAMPILKAN DI LAYAR --- draw_overlay(frame, action_text) cv2.imshow('AprilTag Detection', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break # --- BERSIHKAN --- cap.release() cv2.destroyAllWindows()