Programarea robotilor virtuali
Sa inveti despre Programarea robotilor virtuali
- Sa intelegi conceptele din Programarea robotilor virtuali
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), masini autonome (Tesla Autopilot), roboti industriali in fabrici si chiar roboti chirurgicali in spitale. Toti acesti roboti functioneaza pe baza acelorasi principii algoritmice pe care le vei invata in aceasta lectie: citeste date de la senzori, ia o decizie si actioneaza.
💡 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 simplu pana la o masina Tesla.
⚠ 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, intr-un labirint de porumb la un festival), 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!
Practica
Nivel Minim
Exercitiu minim: Descrie pe scurt ce ai invatat in aceasta lectie.
Nivel Standard
Exercitiu standard: Aplica conceptele din lectie intr-un exemplu practic.
Nivel Performanta
Exercitiu performanta: Creeaza un proiect care demonstreaza cunostintele dobandite.
Recapitulare
Ce am invatat:
- Am invatat despre Programarea robotilor virtuali