Programarea robotilor virtuali

Sa inveti despre Programarea robotilor virtuali

Atom 1

Programarea robotilor virtuali

🤖 Ce este un robot virtual?

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.

🔮 Tipuri de senzori

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.

👁
Senzor distanta
Masoara distanta pana la cel mai apropiat obstacol (0-100 cm). Folosit pentru evitarea coliziunilor.
🎨
Senzor culoare
Detecteaza culoarea suprafetei (alb, negru, rosu). Folosit pentru urmarirea unei linii trasate pe podea.
🔄
Encoder rotatie
Numara rotatiile rotilor pentru a calcula distanta parcursa cu precizie.
📌
Senzor atingere
Un buton care detecteaza contactul fizic cu un obiect. Returneaza 0 (liber) sau 1 (atins).

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

💻 Algoritmul de evitare a obstacolelor

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

// Pseudocod pentru evitare obstacole CAT TIMP robot_pornit { distanta = citesteSenzorDistanta(); DACA distanta < 20 cm { // Obstacol detectat! opreste(); rotesteDreapta(90 grade); } ALTFEL { mergiInainte(); } }

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.

🎯 Implementare in C++ (simulare)

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.

#include <iostream> #include <cstdlib> // pentru rand() #include <ctime> // pentru srand(time(0)) using namespace std; // Simuleaza senzor distanta (valori random 0-100 cm) int citesteSenzor() { return rand() % 100; } int main() { srand(time(0)); // initializeaza generatorul random int distanta; int pasi = 0; int opriri = 0; cout << "=== Simulare Robot ===" << endl; while (pasi < 10) { distanta = citesteSenzor(); cout << "Pas " << pasi + 1 << ": Distanta = " << distanta << " cm"; if (distanta < 20) { cout << " -> STOP! Rotire..." << endl; opriri++; } else { cout << " -> Merg inainte" << endl; } pasi++; } cout << "=== Statistici ===" << endl; cout << "Total pasi: " << pasi << endl; cout << "Opriri: " << opriri << endl; cout << "Simulare terminata!" << endl; return 0; }

Executie pas cu pas (exemplu cu valori generate):

Pasdistantadistanta < 20?Actiuneopriri
173NuMerg inainte0
212DaSTOP! Rotire1
345NuMerg inainte1
48DaSTOP! Rotire2
591NuMerg inainte2

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

🚀 Ruleaza pe OnlineGDB
🚦 Robot cu 3 niveluri de reactie

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.

#include <iostream> #include <cstdlib> #include <ctime> using namespace std; int citesteSenzor() { return rand() % 100; } int main() { srand(time(0)); int distanta; cout << "=== Robot cu 3 niveluri ===" << endl; for (int i = 0; i < 10; i++) { distanta = citesteSenzor(); cout << "Distanta: " << distanta << " cm -> "; if (distanta < 20) { cout << "STOP + ROTIRE (pericol!)" << endl; } else if (distanta < 50) { cout << "INCETINESTE (atentie)" << endl; } else { cout << "VITEZA MAXIMA (drum liber)" << endl; } } return 0; }

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.

📌 Pozitia si directia robotului

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

DirectieCoddxdyDupa rotire dreapta
Nord (sus)00+1Est (1)
Est (dreapta)1+10Sud (2)
Sud (jos)20-1Vest (3)
Vest (stanga)3-10Nord (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.

// Exemplu complet: robot cu pozitie si directie int x = 0, y = 0; // pozitia initiala int dir = 0; // 0=Nord, 1=Est, 2=Sud, 3=Vest int dx[] = {0, 1, 0, -1}; int dy[] = {1, 0, -1, 0}; // Mergi inainte x += dx[dir]; y += dy[dir]; // Rotire dreapta dir = (dir + 1) % 4; // Rotire stanga dir = (dir + 3) % 4;

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.

🛠 Algoritmul "Mana dreapta" pentru labirint

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.

// Pseudocod: Algoritmul mana dreapta CAT TIMP robot NU a ajuns la iesire { dir_dreapta = (directie + 1) % 4; dir_stanga = (directie + 3) % 4; DACA pot_merge(dir_dreapta) { directie = dir_dreapta; // roteste dreapta mergiInainte(); } ALTFEL DACA pot_merge(directie) { mergiInainte(); // continua inainte } ALTFEL DACA pot_merge(dir_stanga) { directie = dir_stanga; // roteste stanga mergiInainte(); } ALTFEL { directie = (directie + 2) % 4; // 180 grade mergiInainte(); // 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.

🌠 Provocari avansate si rezumat

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:

ConceptIn codFolosit pentru
Pozitia robotuluiint x, y;Coordonatele pe grila
Directiaint dir; (0-3)Nord/Est/Sud/Vest
Senzorrand() % 100Simuleaza citirea mediului
Decizieif/else if/elseAlege actiunea corecta
Repetitiewhile / forRobotul actioneaza continuu
Rotire(dir + 1) % 4Schimbarea 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.

🎯 PRACTICA

Exerseaza gandirea algoritmica

Cursul te invata. Practica te face expert.

0/5
P1. Robot in patrat Usor

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.

Exemplu:
Start (0, 0) orientat Nord
Output Pozitie finala: (0, 0)
Foloseste variabile 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).
🚀 OnlineGDB
P2. Calculeaza distanta Usor

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.

Exemple:
Input FFFBF
Output 5 pasi, pozitia: 3
Input FBFBFB
Output 6 pasi, pozitia: 0
Doua variabile: 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'.
🚀 OnlineGDB
P3. Logica evitare obstacole Mediu

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.

Exemple de output:
Pas 1 dist=15 -> STOP + ROTIRE
Pas 2 dist=35 -> INCETINESTE
Trei contoare: 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.
🚀 OnlineGDB
P4. Navigare simpla in labirint Mediu

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.

Exemplu labirint:
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
Matrice: 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.
🚀 OnlineGDB
🚀 Mini-Proiect: Interpretor comenzi robot Proiect

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.

1 Citeste stringul de comenzi de la tastatura
2 Parseaza fiecare comanda (litera + numar) - ex: "F3" = 3 pasi inainte
3 Simuleaza miscarile: actualizeaza pozitia (x, y) si directia
4 Afiseaza traseul complet si pozitia finala
5 Bonus: Detecteaza daca robotul se intoarce la origine
Parcurge stringul: 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