Cevaplara bakmadan önce görevi kendiniz çözmeyi deneyin. Aynı sonucu veren farklı çözümler de doğrudur.

1 Başlangıç

Bağlanma, çıkışları açıp kapatma ve bekleme.
01

Bağlan ve ayrıl

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.

sim_connect()sim_disconnect()printf / print
#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()
02

İleri git ve dur

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.

drive()DRIVE_FORWARDDRIVE_STOPSleep
#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()
03

İleri, bekle, geri

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.

drive()DRIVE_BACKWARDSleep
#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()
04

Direksiyonu çevir

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.

steer()+ left / - right
#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()
05

Sola doğru kıvrıl

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.

steer()drive()Sleep
#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()
06

S şeklinde yol

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.

steer()drive()sequence
#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()

2 Temel

Sensör okuma, ekrana yazdırma ve if/else ile karar verme.
07

İlk lidar okuması

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.

lidar_read()variableprintf / print
#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()
08

Dört yön ve şerit genişliği

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.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
09

Lidar taraması

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.

forlidar_read()
#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()
10

Komutları geri oku

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.

drive_read()steer_read()
#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()
11

Hangi çizgi daha yakın?

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.

if / elsecompare
#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()
12

0 tuzağı

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?

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
13

Çarpışma sensörü

Ö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.

collision_read()drive_read()
#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()

3 Orta

Döngüler, sürekli kontrol ve durum takibi.
14

Çizgiyi görünce dur

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.

whilelidar_read()&& / and
#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()
15

Süreyi say

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.

counterwhile
#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()
16

Ortada kal (yan ışınlar)

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.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
17

İleriye bak

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.

look aheadlidar_read(45)lidar_read(135)
#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)
18

Ölü bölge ekle

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.

dead zoneif / else if / else
#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)
19

Sağ, sol, düz: say

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.

forcounters
#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()

4 İleri

Fonksiyonlar, zamanlama, durum makineleri ve hataya dayanıklılık.
20

Fonksiyonlarla düzenle

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.

functionreturn
#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)
21

En yakın çizgiyi bul

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.

arrayminimumfor
#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)
22

Tek ışın yerine ortalama

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ı.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
23

Orantılı direksiyon (P kontrol)

Ş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.

P controllergainlimit
#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)
24

Hatayı yumuşat

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).

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
25

Çarpınca kurtul

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.

collision_read()DRIVE_BACKWARDrecovery
#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()
26

Viraj dedektörü

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.

statechange detectiondebounce
#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)

5 Proje

Her şeyi birleştiren tam sistemler.
27

Bir tur at ve dur

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ı.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
28

Daha hızlı tur

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.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
29

Dayanıklı sürücü: 3 tur

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.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.
30

Proje: otonom yarış görevi

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.

Cevap sende

Bu görevin cevabı verilmiyor. Önceki görevlerin cevaplarındaki fikirleri birleştirerek kendiniz çözün; çalışan programınız sizin cevabınızdır.