Simülasyonu başlatın. Simülasyona bağlanan, ekrana Hello car! yazan ve bağlantıyı kapatan bir program yazın.
Simülasyon kapalıyken programı bir kez daha çalıştırın ve ekranda ne yazdığına bakın.
Her programın ilk işi bağlanmaktır. sim_connect() 0 döndürmezse simülasyon açık değildir; bu durumda program 1 ile biter ve kütüphane "Start the simulation first" uyarısını yazar. Program bitmeden sim_disconnect() ile bağlantı kapatılır.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1; // 0 = connected
printf("Hello car!\n");
sim_disconnect();
return 0;
}
from otonom import *
if sim_connect() != 0: # 0 = connected
exit(1)
print("Hello car!")
sim_disconnect()
Aracı 2 saniye ileri sürün ve durdurun. Araç pistte biraz yukarı gitmeli ve çizgilere çarpmadan durmalı.
drive() sadece bir komut yazar ve hemen geri döner; araç, biz DRIVE_STOP yazana kadar gitmeye devam eder. Bu yüzden iki komut arasında 2 saniye bekleriz. Araç 2 saniyede yaklaşık 64 birim yol alır.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD); // start moving
Sleep(2000); // keep going for 2 s
drive(DRIVE_STOP); // stop
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD) # start moving
time.sleep(2) # keep going for 2 s
drive(DRIVE_STOP) # stop
sim_disconnect()
Aracı 2 saniye ileri sürün, 1 saniye durdurun, sonra 2 saniye geri sürün ve durdurun. Araç başladığı yere yakın bir yerde durmalı.
Komutlar yukarıdan aşağıya sırayla çalışır. İleri ve geri hız aynı olduğu için 2 saniye ileri + 2 saniye geri aracı başladığı yere geri getirir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD);
Sleep(2000);
drive(DRIVE_STOP);
Sleep(1000);
drive(DRIVE_BACKWARD);
Sleep(2000);
drive(DRIVE_STOP);
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD)
time.sleep(2)
drive(DRIVE_STOP)
time.sleep(1)
drive(DRIVE_BACKWARD)
time.sleep(2)
drive(DRIVE_STOP)
sim_disconnect()
Menüden Elle Kontrol panelini açın. Araç dururken direksiyonu 30° sola çevirin, 2 saniye bekleyin, 30° sağa çevirin, 2 saniye bekleyin ve düzeltin (0°).
Paneldeki direksiyon sürgüsünün ve açı değerinin değiştiğini görmelisiniz. Araç yerinden oynuyor mu?
steer() sadece direksiyon açısını ayarlar, motoru çalıştırmaz. Bu yüzden araç yerinde kalır; açı sadece araç giderken etkili olur. Artı değerler sola, eksi değerler sağa çevirir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
steer(30); // 30 degrees left
Sleep(2000);
steer(-30); // 30 degrees right
Sleep(2000);
steer(0); // straight
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
steer(30) # 30 degrees left
time.sleep(2)
steer(-30) # 30 degrees right
time.sleep(2)
steer(0) # straight
sim_disconnect()
Direksiyonu 30° sola çevirin, sonra aracı 3 saniye ileri sürün ve durdurun. En sonda direksiyonu düzeltin.
Araç bir yay çizerek sola dönmeli ve çizgilere çarpmamalı.
Direksiyon açısı ve sürüş komutu birlikte aracın yolunu belirler. Direksiyon 30° soldayken araç bir çemberin parçası üzerinde gider; 3 saniyede yaklaşık 45° döner.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
steer(30); // wheels to the left
drive(DRIVE_FORWARD);
Sleep(3000);
drive(DRIVE_STOP);
steer(0); // straighten
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
steer(30) # wheels to the left
drive(DRIVE_FORWARD)
time.sleep(3)
drive(DRIVE_STOP)
steer(0) # straighten
sim_disconnect()
Aracı bu sırayla sürün:
1 saniye düz, 2 saniye 20° sola, 2 saniye 20° sağa, 1 saniye düz, sonra dur.
Araç S harfine benzeyen bir yol çizmeli.
Motor bir kez çalıştırılır ve sonra sadece direksiyon değiştirilir. Her Sleep bir parçanın süresini belirler. Programın davranışı zaman sırasıyla yazılmış komutlardan oluşur; buna zamanlı dizi denir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
steer(0);
drive(DRIVE_FORWARD);
Sleep(1000); // straight
steer(20);
Sleep(2000); // left
steer(-20);
Sleep(2000); // right
steer(0);
Sleep(1000); // straight
drive(DRIVE_STOP);
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
steer(0)
drive(DRIVE_FORWARD)
time.sleep(1) # straight
steer(20)
time.sleep(2) # left
steer(-20)
time.sleep(2) # right
steer(0)
time.sleep(1) # straight
drive(DRIVE_STOP)
sim_disconnect()
Yenile'ye basın. Lidarın ön (90°) ve sağ (0°) ölçümünü okuyup ekrana yazdırın:
Front: ... ve Right: ...
Sağ için yaklaşık 15, ön için 0 görmelisiniz. Önde 0 ne anlama geliyor?
Lidar her açı için en yakın çizgiye olan mesafeyi verir. Sağdaki çizgi 15 birim uzakta. Önde ise 100 birim içinde çizgi olmadığı için değer 0'dır: 0 "çok yakın" değil, "hiçbir şey görmüyorum" demektir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int front = lidar_read(90);
int right = lidar_read(0);
printf("Front: %d\n", front);
printf("Right: %d\n", right);
sim_disconnect();
return 0;
}
from otonom import *
if sim_connect() != 0:
exit(1)
front = lidar_read(90)
right = lidar_read(0)
print("Front:", front)
print("Right:", right)
sim_disconnect()
Sağ (0°), ön (90°), sol (180°) ve arka (270°) mesafeleri okuyup yazdırın. Sonra sağ ve sol mesafeyi toplayarak yolun genişliğini hesaplayın ve Lane width: ... olarak yazdırın.
Başlangıç konumunda yaklaşık 15, 0, 52, 0 ve genişlik olarak 67 görmelisiniz.
Aracın sağından soluna (0°'den 180°'ye) 10 derecede bir lidar mesafesini okuyup her satıra bir açı yazdırın, örneğin 40 deg: 19.
Hangi açılarda 0 görüyorsunuz? Bu açılar aracın neresine bakıyor?
Döngü değişkeni açıyı tutar ve her turda 10 artar. Sağdaki çizgi yakın olduğu için küçük açılarda küçük sayılar görülür; önü gösteren 90° civarında yol 100 birimden uzun olduğu için 0 okunur.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
for (int angle = 0; angle <= 180; angle += 10)
{
printf("%d deg: %d\n", angle, lidar_read(angle));
}
sim_disconnect();
return 0;
}
from otonom import *
if sim_connect() != 0:
exit(1)
for angle in range(0, 181, 10):
print(angle, "deg:", lidar_read(angle))
sim_disconnect()
Direksiyonu 25° sola çevirin ve aracı ileri sürün. 1 saniye sonra drive_read() ve steer_read() değerlerini yazdırın (1 ve 25 görmelisiniz).
Sonra aracı durdurun, direksiyonu düzeltin ve iki değeri tekrar yazdırın (0 ve 0).
Okuma fonksiyonları simülasyondaki güncel durumu verir. Bu değerler bizim yazdığımız komutlardır, ama simülasyon da değiştirebilir: örneğin çarpışmada aracı durdurur (Görev 13). Elle Kontrol panelinden yapılan değişiklikler de burada görünür.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
steer(25);
drive(DRIVE_FORWARD);
Sleep(1000);
printf("Drive: %d Steer: %d\n", drive_read(), steer_read());
drive(DRIVE_STOP);
steer(0);
printf("Drive: %d Steer: %d\n", drive_read(), steer_read());
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
steer(25)
drive(DRIVE_FORWARD)
time.sleep(1)
print("Drive:", drive_read(), " Steer:", steer_read())
drive(DRIVE_STOP)
steer(0)
print("Drive:", drive_read(), " Steer:", steer_read())
sim_disconnect()
Sağ (0°) ve sol (180°) mesafeyi okuyun. Sağ daha yakınsa Right line is closer, sol daha yakınsa Left line is closer, eşitse Centered yazdırın.
Başlangıçta sağ daha yakındır. Sonra Elle Kontrol paneliyle aracı biraz sola sürüp durdurun ve programı tekrar çalıştırın.
Daha küçük mesafe daha yakın çizgi demektir. if ilk doğru koşulun bloğunu çalıştırır; hiçbiri doğru değilse else çalışır. Bu karşılaştırma, ileride aracı yolun ortasında tutmanın temelidir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int right = lidar_read(0);
int left = lidar_read(180);
printf("Right: %d Left: %d\n", right, left);
if (right < left)
printf("Right line is closer\n");
else if (left < right)
printf("Left line is closer\n");
else
printf("Centered\n");
sim_disconnect();
return 0;
}
from otonom import *
if sim_connect() != 0:
exit(1)
right = lidar_read(0)
left = lidar_read(180)
print("Right:", right, " Left:", left)
if right < left:
print("Right line is closer")
elif left < right:
print("Left line is closer")
else:
print("Centered")
sim_disconnect()
Aracı 9,5 saniye düz ileri sürüp durdurun. Sonra ön mesafeyi okuyun ve:
0 ise Nothing ahead (more than 100),
50'den küçükse Line ahead is close: ...,
değilse Line ahead: ... yazdırın.
Program önce 0 kontrolünü yapmazsa ne olurdu?
Önce collision_read() değerini yazdırın (0 olmalı). Sonra aracı düz ileri sürün ve 12 saniye bekleyin. Bekleme bitince collision_read() ve drive_read() değerlerini yazdırın.
Araç yaklaşık 10. saniyede üst virajın dış çizgisine çarpar. Ekranda hangi değerleri görüyorsunuz? Araç neden durdu?
Çarpışma olunca simülasyon kendisi sürüş komutunu 0 yapar ve çarpışma bayrağını 1 yapar; bu yüzden collision_read() 1, drive_read() 0 olur. Bayrak, araç tekrar hareket edince 0'a döner. Çarpışma sadece önündeki 66°–114° bölgesinde 25 birimden yakın bir çizgi varken ileri gidilirse olur; yandaki çizgiler çarpışma saymaz.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
printf("Collision: %d\n", collision_read());
drive(DRIVE_FORWARD);
Sleep(12000);
printf("Collision: %d\n", collision_read());
printf("Drive: %d\n", drive_read());
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
print("Collision:", collision_read())
drive(DRIVE_FORWARD)
time.sleep(12)
print("Collision:", collision_read())
print("Drive:", drive_read())
sim_disconnect()
Aracı düz ileri sürün. Ön mesafe 0'dan büyük ve 80'den küçük olana kadar bekleyin, sonra aracı durdurun ve son ön mesafeyi yazdırın.
Araç çarpmadan, yaklaşık 9,5 saniye sonra durmalı. Neden 25 değil de 80 kullandığımızı Görev 13'ü düşünerek açıklayın.
Döngü, koşul doğru olduğu sürece (önde hiçbir şey yok ya da çizgi hâlâ uzak) dönmeye devam eder. Viraj sağa doğru kıvrıldığı için dış çizgi önce aracın sağ önüne (66° civarı) yaklaşır; 90° ışını 80'i gördüğünde sağ önteki çizgi yaklaşık 30 birimdedir. 25'i beklesek araç çoktan çarpmış olurdu.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD);
int front = lidar_read(90);
while (front == 0 || front >= 80) // nothing seen or still far
{
Sleep(20);
front = lidar_read(90);
}
drive(DRIVE_STOP);
printf("Stopped. Front: %d\n", front);
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD)
front = lidar_read(90)
while front == 0 or front >= 80: # nothing seen or still far
time.sleep(0.02)
front = lidar_read(90)
drive(DRIVE_STOP)
print("Stopped. Front:", front)
sim_disconnect()
Görev 14'ü değiştirin: döngüde 100 ms bekleyin ve döngünün kaç kez döndüğünü sayın. Araç durunca Stopped after ... s yazdırın (sayaç × 0,1).
Yaklaşık 9,5 saniye görmelisiniz. Aynı programı birkaç kez çalıştırın (her seferinde Yenile): sonuç aynı mı?
Her döngü turu yaklaşık 0,1 saniye sürdüğü için tur sayısı × 0,1 geçen süreyi verir. Okumalar 100 ms arayla yapıldığından araç her seferinde birkaç birim farklı yerde durabilir; sonuç ±0,1 saniye değişebilir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int steps = 0;
drive(DRIVE_FORWARD);
int front = lidar_read(90);
while (front == 0 || front >= 80)
{
Sleep(100);
steps++; // one more 0.1 s
front = lidar_read(90);
}
drive(DRIVE_STOP);
printf("Stopped after %.1f s\n", steps * 0.1);
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
steps = 0
drive(DRIVE_FORWARD)
front = lidar_read(90)
while front == 0 or front >= 80:
time.sleep(0.1)
steps += 1 # one more 0.1 s
front = lidar_read(90)
drive(DRIVE_STOP)
print(f"Stopped after {steps * 0.1:.1f} s")
sim_disconnect()
Aracı ileri sürün ve bir döngüde sağ (0°) ve sol (180°) mesafeyi okuyun:
sol, sağdan 5'ten fazla büyükse 15° sola, sağ, soldan 5'ten fazla büyükse 15° sağa dönün, yoksa düz gidin.
Döngü collision_read() 1 olunca bitsin ve Crash! yazsın. Döngüde 50 ms bekleyin.
Araç düzlükte ortaya gelir. Peki virajda ne oluyor? Nerede çarptığına dikkat edin.
Görev 16'da 0° ve 180° yerine çapraz ışınları kullanın: sağ ön 45°, sol ön 135°.
Bu sefer sadece iki durum olsun: sol ön daha uzaksa 20° sola, değilse 20° sağa.
Araç zikzak çizerek virajları dönmeli ve turlamaya devam etmeli. Programı Ctrl+C ile durdurun, aracı Dur düğmesiyle durdurun.
45° ve 135° ışınları aracın önündeki yolu görür. Virajda dış çizgi sağ önde yaklaşır, iç çizgi sol önde uzaklaşır; araç bu farkı görüp virajdan önce dönmeye başlar. Pistte bu iki ışın her zaman bir çizgi görür (0 olmaz). Sadece iki durum olduğu için direksiyon sürekli sağ-sol yapar; bir tur yaklaşık 2 dakika sürer.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD);
while (1) // Ctrl+C to stop
{
int right = lidar_read(45); // front right
int left = lidar_read(135); // front left
if (left > right)
steer(20);
else
steer(-20);
Sleep(50);
}
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD)
while True: # Ctrl+C to stop
right = lidar_read(45) # front right
left = lidar_read(135) # front left
if left > right:
steer(20)
else:
steer(-20)
time.sleep(0.05)
Görev 17'ye üçüncü bir durum ekleyin: sol ön ile sağ ön arasındaki fark 5 veya daha azsa düz gidin (0°).
Araç düzlüklerde zikzak yapmadan gitmeli. Bir turu kronometreyle ölçün: yaklaşık 72 saniye olmalı (Görev 17'de yaklaşık 2 dakika).
Küçük farklar için direksiyonu hiç oynatmamak (ölü bölge) zikzakı keser. Bu simülasyonda araç dönerken düz giderken olduğundan daha az yol alır ve direksiyon açısı her değiştiğinde araç o adımda ilerlemez. Bu yüzden daha az direksiyon hareketi daha hızlı bir tur demektir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD);
while (1) // Ctrl+C to stop
{
int right = lidar_read(45);
int left = lidar_read(135);
if (left - right > 5)
steer(20);
else if (right - left > 5)
steer(-20);
else
steer(0); // small difference: straight
Sleep(50);
}
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD)
while True: # Ctrl+C to stop
right = lidar_read(45)
left = lidar_read(135)
if left - right > 5:
steer(20)
elif right - left > 5:
steer(-20)
else:
steer(0) # small difference: straight
time.sleep(0.05)
Görev 18'deki sürücüyü sonsuz yerine 600 tur (yaklaşık 30 saniye) çalıştırın. Her turda hangi kararın verildiğini sayın: sola, sağa, düz.
Sonunda aracı durdurun ve üç sayıyı yazdırın. 30 saniyede araç düzlüğü ve üst virajın çoğunu geçer; hangi sayı en büyük çıkıyor, neden?
Pistteki bütün virajlar sola döner, bu yüzden sol sayısı açık ara en büyüktür. Düz sayısı düzlükte gidilen süreyi, sağ sayısı ise küçük düzeltmeleri gösterir. Programın ne yaptığını sayılarla görmek, hata ararken çok işe yarar.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int lefts = 0, rights = 0, straights = 0;
drive(DRIVE_FORWARD);
for (int i = 0; i < 600; i++)
{
int right = lidar_read(45);
int left = lidar_read(135);
if (left - right > 5) { steer(20); lefts++; }
else if (right - left > 5) { steer(-20); rights++; }
else { steer(0); straights++; }
Sleep(50);
}
drive(DRIVE_STOP);
steer(0);
printf("Left: %d Right: %d Straight: %d\n", lefts, rights, straights);
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
lefts = rights = straights = 0
drive(DRIVE_FORWARD)
for i in range(600):
right = lidar_read(45)
left = lidar_read(135)
if left - right > 5:
steer(20)
lefts += 1
elif right - left > 5:
steer(-20)
rights += 1
else:
steer(0)
straights += 1
time.sleep(0.05)
drive(DRIVE_STOP)
steer(0)
print("Left:", lefts, " Right:", rights, " Straight:", straights)
sim_disconnect()
Görev 18'i iki fonksiyonla yeniden yazın:
distance(angle): lidarı okur, 0 gelirse 100 döndürür (0 = 100'den uzak).
follow_lane(): 45° ve 135° mesafelerini distance() ile alır ve direksiyonu Görev 18'deki gibi ayarlar.
Ana döngüde sadece follow_lane() ve bekleme kalsın. Araç Görev 18'deki gibi sürmeli.
Fonksiyonlar, bir işi bir kez yazıp her yerde aynı isimle kullanmamızı sağlar. distance() 0 tuzağını (Görev 12) tek bir yerde çözer: "hiçbir şey yok" en uzak mesafe gibi davranır. Bu iki fonksiyonu sonraki görevlerde tekrar kullanacağız.
#include "otonom.h"
// Lidar distance; 0 (nothing within 100) is returned as 100
int distance(int angle)
{
int d = lidar_read(angle);
if (d == 0) return 100;
return d;
}
// Steer towards the side with more room
void follow_lane(void)
{
int right = distance(45);
int left = distance(135);
if (left - right > 5) steer(20);
else if (right - left > 5) steer(-20);
else steer(0);
}
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD);
while (1) // Ctrl+C to stop
{
follow_lane();
Sleep(50);
}
}
from otonom import *
import time
def distance(angle):
"""Lidar distance; 0 (nothing within 100) is returned as 100."""
d = lidar_read(angle)
if d == 0:
return 100
return d
def follow_lane():
"""Steer towards the side with more room."""
right = distance(45)
left = distance(135)
if left - right > 5:
steer(20)
elif right - left > 5:
steer(-20)
else:
steer(0)
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD)
while True: # Ctrl+C to stop
follow_lane()
time.sleep(0.05)
Aracın sağından soluna (0°–180°) bütün ışınları (2 derecede bir, 91 değer) bir diziye okuyun. Dizide 0 olmayan en küçük mesafeyi ve açısını bulun, Closest: 0 deg, 15 gibi yazdırın ve açı 90'dan küçükse (right), büyükse (left) ekleyin.
Bunu yarım saniyede bir tekrarlayın. Program çalışırken aracı Elle Kontrol paneliyle sürün ve değerlerin nasıl değiştiğini izleyin.
Önce bütün ölçümler diziye alınır, sonra dizi bir kez gezilerek en küçük değer ve yeri tutulur. 0 değerleri atlanır çünkü 0 "yakın" değil "yok" demektir. Başlangıçta en yakın çizgi sağdadır (0°, 15 birim). Bu program aracı sürmez; sadece izler, bu yüzden elle sürmek güvenlidir.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int scan[91]; // scan[i] = distance at 2*i degrees
while (1) // Ctrl+C to stop
{
for (int i = 0; i < 91; i++)
scan[i] = lidar_read(2 * i);
int best = 101, best_angle = -1;
for (int i = 0; i < 91; i++)
{
if (scan[i] > 0 && scan[i] < best)
{
best = scan[i];
best_angle = 2 * i;
}
}
if (best_angle < 0)
printf("No line within 100\n");
else
printf("Closest: %d deg, %d %s\n", best_angle, best,
best_angle < 90 ? "(right)" : "(left)");
Sleep(500);
}
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
while True: # Ctrl+C to stop
scan = [] # scan[i] = distance at 2*i degrees
for i in range(91):
scan.append(lidar_read(2 * i))
best, best_angle = 101, -1
for i in range(91):
if 0 < scan[i] < best:
best = scan[i]
best_angle = 2 * i
if best_angle < 0:
print("No line within 100")
else:
side = "(right)" if best_angle < 90 else "(left)"
print(f"Closest: {best_angle} deg, {best} {side}")
time.sleep(0.5)
Tek bir ışına güvenmek yerine birkaç ışının ortalamasını kullanın. average(from, to) fonksiyonu yazın: from ile to arasındaki açıları 2 derecede bir distance() ile okuyup ortalamasını döndürsün.
Görev 20'deki sürücüde sağ ön için average(30, 60), sol ön için average(120, 150) kullanın. Araç yine turlamalı.
Şimdiye kadar direksiyon sadece -20, 0 veya +20 oldu. Şimdi açıyı hataya orantılı yapın:
hata = sol ön (135°) − sağ ön (45°), açı = 0,5 × hata.
Açıyı -60…+60 arasında tutan bir limit() fonksiyonu yazın. Araç zikzak yapmadan, yumuşakça turlamalı.
Orantılı (P) kontrolde düzeltme, hatanın büyüklüğüyle orantılıdır; 0,5 kazançtır. Yol yumuşak olur ama bu simülasyonda tur daha uzun sürer (yaklaşık 105 saniye): açı neredeyse her turda biraz değişir ve araç direksiyon açısının değiştiği her adımda ilerlemez. Kazancı (0,5) değiştirip etkisini deneyin.
#include "otonom.h"
int distance(int angle)
{
int d = lidar_read(angle);
if (d == 0) return 100;
return d;
}
// Keep the value between -max and +max
int limit(int value, int max)
{
if (value > max) return max;
if (value < -max) return -max;
return value;
}
int main(void)
{
if (sim_connect() != 0) return 1;
drive(DRIVE_FORWARD);
while (1) // Ctrl+C to stop
{
int error = distance(135) - distance(45);
int angle = (int)(0.5 * error); // gain = 0.5
steer(limit(angle, 60));
Sleep(50);
}
}
from otonom import *
import time
def distance(angle):
d = lidar_read(angle)
if d == 0:
return 100
return d
def limit(value, max_value):
"""Keep the value between -max_value and +max_value."""
if value > max_value:
return max_value
if value < -max_value:
return -max_value
return value
if sim_connect() != 0:
exit(1)
drive(DRIVE_FORWARD)
while True: # Ctrl+C to stop
error = distance(135) - distance(45)
angle = int(0.5 * error) # gain = 0.5
steer(limit(angle, 60))
time.sleep(0.05)
Görev 23'te hatayı doğrudan kullanmak yerine son 4 hatanın ortalamasını kullanın. Son 4 hatayı 4 elemanlı bir dizide tutun; her turda en eski hatanın yerine yenisini yazın.
Direksiyon daha sakin değişmeli ve tur birkaç saniye kısalmalı (yaklaşık 105 yerine 95 saniye).
Görev 16'daki yan ışınlı sürücü virajda çarpıyordu. Ona bir kurtarma davranışı ekleyin: collision_read() 1 olursa çarpışma sayısını artırın, direksiyonu 30° sağa (-30) çevirin, 1 saniye geri gidin ve sonra yeniden ileri sürmeye devam edin.
Program 60 saniye (1200 tur × 50 ms) çalışsın ya da 5 çarpışmada dursun; sonda aracı durdurup çarpışma sayısını yazdırın. Araç virajı çarpa çarpa da olsa geçebiliyor mu?
Çarpışmada simülasyon aracı durdurur; ileri komutu tekrar verilse bile çizgi hâlâ 25 birimden yakın olduğu için araç hemen yeniden durur. Bu yüzden önce geri gidilir; araç hareket edince çarpışma bayrağı 0 olur. Sağa çevrili direksiyonla geri gitmek burnu virajın yönüne (sola) çevirir; denememizde araç bir kez çarptı, geri çekildi ve üst virajı geçti. Sürücü yine zayıftır ama hata durumundan çıkabilen bir program, takılıp kalandan çok daha kullanışlıdır.
#include "otonom.h"
int main(void)
{
if (sim_connect() != 0) return 1;
int crashes = 0;
drive(DRIVE_FORWARD);
for (int i = 0; i < 1200 && crashes < 5; i++)
{
if (collision_read() == 1)
{
crashes++;
printf("Crash %d, backing up\n", crashes);
steer(-30); // nose swings left while backing
drive(DRIVE_BACKWARD);
Sleep(1000);
drive(DRIVE_FORWARD);
}
int right = lidar_read(0);
int left = lidar_read(180);
if (left - right > 5) steer(15);
else if (right - left > 5) steer(-15);
else steer(0);
Sleep(50);
}
drive(DRIVE_STOP);
steer(0);
printf("Crashes: %d\n", crashes);
sim_disconnect();
return 0;
}
from otonom import *
import time
if sim_connect() != 0:
exit(1)
crashes = 0
drive(DRIVE_FORWARD)
for i in range(1200):
if crashes >= 5:
break
if collision_read() == 1:
crashes += 1
print("Crash", crashes, "backing up")
steer(-30) # nose swings left while backing
drive(DRIVE_BACKWARD)
time.sleep(1)
drive(DRIVE_FORWARD)
right = lidar_read(0)
left = lidar_read(180)
if left - right > 5:
steer(15)
elif right - left > 5:
steer(-15)
else:
steer(0)
time.sleep(0.05)
drive(DRIVE_STOP)
steer(0)
print("Crashes:", crashes)
sim_disconnect()
Aracın sağ önüne bakan 76° ışını düzlükte 0 okur (çizgi 100'den uzak), virajda ise dış çizgiyi görür.
Görev 20'deki sürücüyü çalıştırırken bu ışınla aracın virajda mı düzlükte mi olduğunu takip edin ve sadece durum değiştiğinde CURVE ya da STRAIGHT yazdırın.
Ani tek okumalara aldanmamak için: 76° > 0 olunca hemen CURVE, ama STRAIGHT için 76° art arda 20 okuma (yaklaşık 1 saniye) 0 olmalı.
Bir turda iki CURVE ve iki STRAIGHT görmelisiniz. Program başlar başlamaz bir STRAIGHT daha görünür, çünkü araç bir virajın hemen çıkışında başlar.
Program bir durum (viraj / düzlük) hatırlar ve sadece durum değiştiğinde bir şey yapar; buna olay algılama denir. Sayaç (quiet), virajın içinde ışının tek bir kez 0 okumasıyla yanlışlıkla "düzlük" denmesini önler; buna titreşim önleme (debounce) denir. Tur saymak için bu dedektörü kullanacağız.
#include "otonom.h"
int distance(int angle)
{
int d = lidar_read(angle);
if (d == 0) return 100;
return d;
}
void follow_lane(void)
{
int right = distance(45);
int left = distance(135);
if (left - right > 5) steer(20);
else if (right - left > 5) steer(-20);
else steer(0);
}
int main(void)
{
if (sim_connect() != 0) return 1;
int in_curve = lidar_read(76) > 0; // state at the start
int quiet = 0; // 0 readings in a row
drive(DRIVE_FORWARD);
while (1) // Ctrl+C to stop
{
follow_lane();
if (lidar_read(76) > 0)
{
quiet = 0;
if (!in_curve) { in_curve = 1; printf("CURVE\n"); }
}
else
{
quiet++;
if (in_curve && quiet >= 20) { in_curve = 0; printf("STRAIGHT\n"); }
}
Sleep(50);
}
}
from otonom import *
import time
def distance(angle):
d = lidar_read(angle)
if d == 0:
return 100
return d
def follow_lane():
right = distance(45)
left = distance(135)
if left - right > 5:
steer(20)
elif right - left > 5:
steer(-20)
else:
steer(0)
if sim_connect() != 0:
exit(1)
in_curve = lidar_read(76) > 0 # state at the start
quiet = 0 # 0 readings in a row
drive(DRIVE_FORWARD)
while True: # Ctrl+C to stop
follow_lane()
if lidar_read(76) > 0:
quiet = 0
if not in_curve:
in_curve = True
print("CURVE")
else:
quiet += 1
if in_curve and quiet >= 20:
in_curve = False
print("STRAIGHT")
time.sleep(0.05)
Görev 26'daki viraj dedektörünü kullanarak aracı tam bir tur sürün ve başladığı yere yakın bir yerde durdurun.
Araç başlangıçta sağ düzlüktedir; bir tur = üst viraj + sol düzlük + alt viraj. İkinci virajdan çıkıldığında (ikinci STRAIGHT) tur bitmiştir.
Durunca One lap done! yazdırın. Araç hiç çarpmamalı ve yaklaşık 72 saniyede durmalı.
Görev 27'ye süre ölçümü ekleyin: tur bitince Lap time: ... s yazdırın (C'de GetTickCount(), Python'da time.time()).
Dönüş açısını (20) programın başında TURN adlı bir sabite taşıyın ve 20, 30, 45 ve 60 için tur süresini ölçün.
Hedef: hiç çarpmadan 70 saniyenin altı. 20° ile yaklaşık 72 saniye, 45° ile yaklaşık 66 saniye görmelisiniz.
Görev 28'deki sürücüyle 3 tur atın ve her turun süresini ayrı yazdırın (Lap 1: ... s).
Sürücüye Görev 25'teki kurtarmayı ekleyin: çarpışma olursa sayın, 1 saniye -30° direksiyonla geri gidin ve devam edin. Sonda toplam süreyi ve çarpışma sayısını yazdırın.
İyi bir sürücüde çarpışma 0 olmalı; kurtarma sadece bir şeyler ters giderse (örneğin Elle Kontrol ile müdahale edilirse) devreye girer.
Her şeyi birleştiren son programı yazın:
1. Program kullanıcıdan tur sayısı istesin (1–5). Geçersiz bir sayı girilirse tekrar sorsun.
2. Araç Görev 29'daki gibi sürsün ve çarpışmadan kurtulsun.
3. Her saniye bir durum satırı yazdırsın: Lap 1/3 | CURVE | 23 s | crashes 0.
4. İstenen tur sayısı tamamlanınca aracı durdursun ve bir özet yazdırsın: her turun süresi, en hızlı tur ve toplam çarpışma.