Programarea robotilor virtuali
Sa combini variabile, structuri de decizie si bucle pentru a controla un robot simulat in C++.
- Sa definesti ce este un robot virtual si de ce il simulam in cod
- Sa identifici tipurile de senzori si ce valori returneaza
- Sa implementezi algoritmul de evitare a obstacolelor folosind if/else si while
- Sa codifici pozitia si directia robotului cu variabile si tablouri
- Sa descrii si sa aplici algoritmul "mana dreapta" pentru navigarea in labirint
Programarea robotilor virtuali
Un robot virtual este un program de calculator care simuleaza comportamentul unui robot real. In loc sa construim un robot fizic (care costa bani si necesita piese electronice), putem scrie un program care se comporta ca si cum ar fi un robot: citeste senzori, ia decizii si executa actiuni. Aceasta este o tehnica folosita de inginerii din toata lumea inainte de a construi robotul real.
In programare, un robot virtual este definit de trei elemente fundamentale: pozitia sa (unde se afla pe o grila sau pe o suprafata), directia in care priveste (Nord, Est, Sud, Vest) si senzorii sai (instrumentele cu care percepe mediul inconjurator). Toate aceste elemente sunt reprezentate prin variabile in codul nostru C++.
De ce este important sa inveti programarea robotilor? Industria roboticii creste rapid: roboti de curatenie (iRobot Roomba), roboti industriali in fabrici si chiar roboti chirurgicali in spitale. Toti acesti roboti pornesc de la acelasi principiu de baza pe care il vei invata in aceasta lectie: citeste date de la senzori, ia o decizie, actioneaza. Sistemele reale adauga zeci de senzori si algoritmi avansati, dar nucleul logic ramane acelasi.
💡 Legatura cu ce ai invatat
Programarea robotilor combina tot ce ai invatat in acest modul: variabile (pozitia robotului), structuri de decizie if/else (ce face cand intalneste un obstacol), bucle while si for (repeta actiuni pana atinge un obiectiv) si chiar functii (citesteSenzor, mergiInainte). Este un proiect de sinteza care demonstreaza puterea algoritmilor.
Senzorii sunt "organele de simt" ale robotului. Fiecare senzor masoara un aspect specific al mediului inconjurator si returneaza o valoare pe care programul o poate folosi pentru a lua decizii. In simularea noastra, senzorii sunt functii care returneaza valori numerice.
In simularea noastra C++, fiecare senzor este o functie care returneaza o valoare. De exemplu, citesteSenzorDistanta() returneaza un int intre 0 si 100 (centimetri pana la obstacol). In programul real, aceasta functie ar citi hardware-ul senzorului; in simulare, generam valori aleatorii cu rand().
Cum functioneaza senzorul de distanta in realitate?
Senzorul trimite un semnal (ultrasonic sau infrarosu) spre obiectul din fata. Semnalul loveste obiectul si se intoarce. Senzorul masoara timpul necesar pentru dus-intors si calculeaza distanta: distanta = viteza * timp / 2. Impartim la 2 pentru ca semnalul parcurge drumul de doua ori (dus si intors).
Cel mai simplu si cel mai important algoritm pentru un robot mobil este evitarea obstacolelor. Robotul trebuie sa se deplaseze continuu inainte, dar sa se opreasca si sa schimbe directia cand intalneste un obstacol. Acest algoritm este folosit de aspiratoarele robot si de masinile autonome.
Algoritmul in limbaj natural:
1. Cat timp robotul este pornit, repeta:
2. Citeste distanta pana la cel mai apropiat obstacol
3. Daca distanta este mai mica de 20 cm:
4. Opreste motoarele
5. Roteste robotul 90 de grade la dreapta
6. Altfel:
7. Continua sa mergi inainte
Observa structura: o bucla while care ruleaza continuu, un senzor care citeste mediul si o decizie if/else care alege actiunea. Acest pattern "citeste-decide-actioneaza" este fundamentul oricarui robot autonom, de la un aspirator robot simplu pana la un brat industrial.
⚠ Pragul de 20 cm
De ce 20 cm si nu 5 cm? Pentru ca robotul are nevoie de timp sa se opreasca. La viteza normala, daca detecteaza obstacolul la doar 5 cm, nu are suficient timp sa franeze si va lovi obstacolul. 20 cm ofera o "marja de siguranta". In robotica reala, acest prag depinde de viteza robotului si de timpul de reactie al motoarelor.
Acum sa transformam pseudocodul in cod C++ real. Deoarece nu avem un robot fizic, vom simula senzorul: in loc sa citim hardware-ul, generam valori aleatorii cu functia rand(). Rezultatul arata exact cum s-ar comporta un robot real intr-un mediu cu obstacole asezate aleatoriu.
Executie pas cu pas (exemplu cu valori generate):
| Pas | distanta | distanta < 20? | Actiune | opriri |
|---|---|---|---|---|
| 1 | 73 | Nu | Merg inainte | 0 |
| 2 | 12 | Da | STOP! Rotire | 1 |
| 3 | 45 | Nu | Merg inainte | 1 |
| 4 | 8 | Da | STOP! Rotire | 2 |
| 5 | 91 | Nu | Merg inainte | 2 |
💡 Ce face srand(time(0))?
Functia rand() genereaza numere "pseudo-aleatorii" - adica urmeaza o secventa care pare aleatorie. Dar daca nu initializam generatorul, secventa este aceeasi la fiecare rulare! srand(time(0)) initializeaza generatorul cu timpul curent (care este diferit la fiecare secunda), asa ca obtinem valori diferite la fiecare executie. Fara aceasta linie, robotul nostru ar avea exact aceleasi "experiente" de fiecare data.
Robotul simplu de mai sus are doar doua stari: merge inainte sau se opreste. Un robot mai inteligent ar trebui sa aiba mai multe niveluri de reactie, similar cu modul in care un sofer incetineste treptat cand se apropie de un obstacol, nu franeza brusc in ultimul moment.
Acum robotul are trei comportamente diferite in functie de distanta: oprire de urgenta (sub 20 cm), incetinire preventiva (20-50 cm) si viteza maxima (peste 50 cm). Aceasta abordare cu mai multe praguri se numeste control in trepte si este folosita in robotica reala. Structura if - else if - else este perfecta pentru implementarea acestui tip de logica cu mai multe niveluri.
Analogie din viata reala:
Gandeste-te la semafor: rosu = opreste (distanta < 20), galben = incetineste (distanta 20-50), verde = mergi (distanta > 50). Robotul nostru are propriul "semafor intern" bazat pe distanta pana la obstacol. Masinile autonome folosesc exact acelasi principiu, dar cu zeci de senzori si praguri mult mai fine.
Un robot se deplaseaza pe o grila (ca o tabla de sah). Pozitia sa este definita de doua coordonate: x (coloana - orizontal) si y (randul - vertical). Directia in care priveste robotul determina cum se modifica coordonatele cand merge inainte.
Codificarea directiei:
0 = Nord (sus): y creste cu 1
1 = Est (dreapta): x creste cu 1
2 = Sud (jos): y scade cu 1
3 = Vest (stanga): x scade cu 1
Rotirea robotului inseamna schimbarea directiei. Cand rotim la dreapta, directia creste cu 1 (Nord -> Est -> Sud -> Vest). Trucul matematic este operatorul modulo: directie = (directie + 1) % 4. Daca directia era 3 (Vest) si rotim la dreapta: (3 + 1) % 4 = 0 (Nord) - revenim la inceput. Rotirea la stanga: directie = (directie + 3) % 4 (adaugam 3 in loc de 1, care este echivalent cu scaderea a 1 in aritmetica modulo 4).
| Directie | Cod | dx | dy | Dupa rotire dreapta |
|---|---|---|---|---|
| Nord (sus) | 0 | 0 | +1 | Est (1) |
| Est (dreapta) | 1 | +1 | 0 | Sud (2) |
| Sud (jos) | 2 | 0 | -1 | Vest (3) |
| Vest (stanga) | 3 | -1 | 0 | Nord (0) |
In cod, putem folosi tablouri pentru a stoca deplasarile: int dx[] = {0, 1, 0, -1}; si int dy[] = {1, 0, -1, 0};. Cand robotul merge inainte: x += dx[directie]; y += dy[directie];. Aceasta tehnica elimina nevoia de 4 blocuri if/else si face codul mai elegant.
Avantajul tablourilor dx si dy este ca o singura linie de cod (x += dx[dir]) inlocuieste patru blocuri if/else. Aceasta tehnica se numeste lookup table (tabel de cautare) si este folosita frecvent in programarea jocurilor si a robotilor. Cu cat codul este mai scurt si mai clar, cu atat este mai usor de depanat si de inteles.
Unul dintre cei mai celebri algoritmi din robotica este algoritmul "mana dreapta" (right-hand rule). Regula este simpla: tine mana dreapta pe perete si urmeaza-l. Acest algoritm garanteaza ca robotul va gasi iesirea din orice labirint care are peretii conectati la exterior. Este folosit de roboti reali in competitii de rezolvare a labirintelor.
Algoritmul functioneaza in 4 pasi la fiecare iteratie: (1) Incearca sa mergi la dreapta - daca este liber, roteste la dreapta si fa un pas. (2) Daca nu poti la dreapta, incearca sa mergi inainte. (3) Daca nu poti nici inainte, incearca la stanga. (4) Daca nu poti nicaieri, intoarce-te 180 de grade (inapoi). Prioritatea este mereu: dreapta > inainte > stanga > inapoi.
Functia pot_merge(d) verifica daca celula din directia d este libera (nu este perete si nu este in afara grilei). Observa cum folosim (directie + 1) % 4 pentru dreapta, (directie + 3) % 4 pentru stanga si (directie + 2) % 4 pentru intoarcere completa. Aceasta este matematica modulara in actiune.
⚠ Limitarea algoritmului
Algoritmul "mana dreapta" nu functioneaza in labirinturi cu insule (pereti care nu sunt conectati la marginea labirintului). In astfel de cazuri, robotul poate ramane blocat intr-o bucla infinita, mergand in cerc in jurul insulei. Pentru aceste situatii avansate se folosesc algoritmi mai complecsi precum Pledge sau Tremaux, care tin evidenta drumurilor parcurse.
💡 Aplicatie in viata reala
Daca te pierzi vreodata intr-un labirint real (de exemplu, la o atractie tematica sau intr-o cladire cu coridoare necunoscute), poti aplica regula manei drepte: pune mana dreapta pe perete si nu o ridica niciodata. Vei iesi garantat din labirint, desi drumul nu va fi cel mai scurt. Competitiile internationale de robotica (Micromouse) folosesc exact acest principiu ca punct de plecare.
Acum ca intelegi bazele, iata cateva provocari care iti vor testa si extinde cunostintele. Fiecare provocare adauga un nivel de complexitate algoritmului de baza:
- Urmarire de linie: Robotul urmareste o linie neagra pe un fundal alb. Senzorul de culoare citeste suprafata: daca e negru, merge inainte; daca e alb, se roteste usor pentru a regasi linia.
- Cautare in spirala: Robotul porneste din centru si se deplaseaza in spirala: 1 pas inainte, rotire, 1 pas, rotire, 2 pasi, rotire, 2 pasi, rotire, 3 pasi... Observi pattern-ul? Numarul de pasi creste dupa fiecare doua rotiri.
- Memorie: Robotul tine minte pozitiile unde a mai fost (intr-un tablou). Daca ajunge la o pozitie vizitata, alege o alta directie. Aceasta previne "bucla infinita" in care robotul merge in cerc.
- Labirint: Robotul navigheaza prin un labirint (matrice 2D cu pereti). Foloseste algoritmul "mana dreapta": mereu incearca sa mearga la dreapta; daca nu poate, inainte; daca nu poate, la stanga; daca nu poate, inapoi.
Rezumat al conceptelor cheie din aceasta lectie:
| Concept | In cod | Folosit pentru |
|---|---|---|
| Pozitia robotului | int x, y; | Coordonatele pe grila |
| Directia | int dir; (0-3) | Nord/Est/Sud/Vest |
| Senzor | rand() % 100 | Simuleaza citirea mediului |
| Decizie | if/else if/else | Alege actiunea corecta |
| Repetitie | while / for | Robotul actioneaza continuu |
| Rotire | (dir + 1) % 4 | Schimbarea directiei |
💡 Ce ai invatat in tot modulul
In cele 10 lectii ai parcurs un drum complet: de la variabile simple si operatori, prin structuri de decizie (if/else), bucle (while, do-while, for), pana la aplicatii practice complexe (fizica, geografie, roboti). Acum ai instrumentele necesare pentru a rezolva probleme reale cu ajutorul programarii. Fiecare concept se construieste pe cele anterioare - de aceea este important sa le intelegi pe toate.
Exerseaza gandirea algoritmica
Cursul te invata. Practica te face expert.
Robotul porneste de la pozitia (0,0) orientat spre Nord si trebuie sa mearga in patrat: 3 pasi inainte, rotire dreapta, repeta de 4 ori. Afiseaza coordonatele dupa fiecare pas si pozitia finala.
x, y pentru pozitie si directie (0=N, 1=E, 2=S, 3=W). Tablouri: int dx[] = {0, 1, 0, -1}; int dy[] = {1, 0, -1, 0};. La rotire: directie = (directie + 1) % 4. Doua bucle imbricate: exterioara de 4 ori (laturi), interioara de 3 ori (pasi pe latura).Robotul primeste o secventa de comenzi: 'F' = inainte 1 pas, 'B' = inapoi 1 pas. Calculeaza distanta totala parcursa (numarul total de pasi, nu pozitia finala) si pozitia finala pe axa.
pasi_total (creste mereu cu 1) si pozitie (creste cu 1 la F, scade cu 1 la B). Parcurge stringul: for(int i=0; i < s.length(); i++) si verifica s[i] == 'F' sau s[i] == 'B'.Robotul are senzori care returneaza distanta pana la obstacol (0-100 cm). Simuleaza 15 pasi: citeste distanta aleatorie si aplica logica cu 3 niveluri. La final, afiseaza statisticile: cate opriri, cate incetiniri si cati pasi la viteza maxima.
int opriri=0, incetiniri=0, viteza_max=0;. In bucla for, foloseste if (dist < 20) opriri++; else if (dist < 50) incetiniri++; else viteza_max++;. La final, afiseaza cele trei contoare.Labirintul e o matrice 5x5. Robotul porneste de la (0,0) si trebuie sa ajunga la (4,4). Poate merge doar pe celule cu valoare 0 (1 = perete). Afiseaza traseul parcurs si numarul total de pasi.
0 0 1 0 0 1 0 1 0 1 1 0 0 0 1 1 1 1 0 1 0 0 0 0 0
int lab[5][5]. Verifica limitele: if(x >= 0 && x < 5 && y >= 0 && y < 5 && lab[x][y] == 0). Foloseste while pana ajungi la (4,4). Incearca directiile in ordine: dreapta, inainte, stanga, inapoi.Creeaza un program care parseaza si executa comenzi robot. Format: "F3 R L F2 B1" unde F=inainte, B=inapoi, R=rotire dreapta, L=rotire stanga, urmate de numar de repetari.
for(int i=0; i < cmd.length(); i++). Daca cmd[i] e litera, urmatorul caracter e cifra. Foloseste cmd[i+1] - '0' pentru a converti char la int. Tablouri dx/dy pentru directie.
Felicitari!
Ai completat toate lectiile din Modul 3!
Total: +775 XP
Acum stii sa folosesti: variabile, operatori, if/else, while, do-while, for si sa aplici cunostintele in probleme reale!
Exercitii practice
Nivel Minim
Cerinta: Scrie pseudocodul pentru un robot care se deplaseaza 5 pasi inainte si se roteste la dreapta de fiecare data cand senzorul detecteaza un obstacol la mai putin de 20 cm. Identifica structurile de control folosite (while, if/else).
Nivel Standard
Cerinta: Implementeaza in C++ robotul cu 3 niveluri de reactie (STOP sub 20 cm, INCETINESTE intre 20-50 cm, VITEZA MAXIMA peste 50 cm). Simuleaza 15 pasi cu valori aleatorii si afiseaza la final numarul de opriri, incetiniri si pasi la viteza maxima.
Nivel Performanta
Cerinta: Implementeaza in C++ un robot care navigheaza pe o grila 5x5. Foloseste tablouri dx[] si dy[] pentru directie, aplica algoritmul "mana dreapta" si afiseaza traseul complet (coordonate x, y la fiecare pas) pana cand robotul ajunge la coltul (4, 4).
Recapitulare
Ce am invatat:
- Un robot virtual este un program care simuleaza comportamentul unui robot real folosind variabile pentru pozitie si directie
- Senzorii sunt functii care returneaza valori din mediu (distanta, culoare, atingere) — in simulare folosim
rand() - Algoritmul de evitare a obstacolelor combina o bucla
whilecu structuriif/elsepe baza distantei citite de senzor - Controlul in trepte (3 niveluri: STOP / INCETINESTE / VITEZA MAXIMA) se implementeaza cu
if - else if - else - Pozitia robotului pe grila se stocheaza cu
int x, y; directia cuint dir(0=Nord, 1=Est, 2=Sud, 3=Vest) - Rotirea foloseste aritmetica modulo:
dir = (dir + 1) % 4pentru dreapta,(dir + 3) % 4pentru stanga - Algoritmul "mana dreapta" rezolva orice labirint cu pereti conectati: prioritate dreapta > inainte > stanga > inapoi