Differences

This shows you the differences between two versions of the page.

Link to this comparison view

pm:prj2023:dene:dancingstickman [2023/05/25 22:15]
daniel.nastase2109 [Software Design]
pm:prj2023:dene:dancingstickman [2023/05/30 04:36] (current)
daniel.nastase2109 [Concluzii]
Line 4: Line 4:
 Proiectul presupune crearea pe un ecran LCD a unui stickman care sa imite mișcările unei persoane aflate in fata unui XBOX 360 Kinect. Proiectul presupune crearea pe un ecran LCD a unui stickman care sa imite mișcările unei persoane aflate in fata unui XBOX 360 Kinect.
  
-Consider ​ca proiectul meu reprezintă un POC pentru o idee care ar putea fi aplicată pe semafoarele din zonele turistice ​+Consider ​că proiectul meu reprezintă un POC pentru o idee care ar putea fi aplicată pe semafoarele din zonele turistice ​
 urmând: urmând:
-  * sa încurajeze respectarea semnelor de circulație,​ fapt care este adesea o problemă in astfel de zone;+  * să încurajeze respectarea semnelor de circulație,​ fapt care este adesea o problemă in astfel de zone;
   * să anime un semafor de altfel anost.   * să anime un semafor de altfel anost.
 Au fost deja implementate astfel de proiecte având efectele precizate anterior. Aveți un exemplu [[https://​www.youtube.com/​watch?​v=w82j_m-qr2g&​ab_channel=AsliSachin|aici]]. Au fost deja implementate astfel de proiecte având efectele precizate anterior. Aveți un exemplu [[https://​www.youtube.com/​watch?​v=w82j_m-qr2g&​ab_channel=AsliSachin|aici]].
Line 188: Line 188:
 <note tip> <note tip>
 O altă soluție pe care am  luat-o în considerare ar fi fost transmiterea a doi octeți pentru fiecare coordonată,​ însă aceasta ar adăuga complexitate programului și, cel mai important, ar dubla dimensiunea mesajului, îngreunând treaba plăcuței Arduino. O altă soluție pe care am  luat-o în considerare ar fi fost transmiterea a doi octeți pentru fiecare coordonată,​ însă aceasta ar adăuga complexitate programului și, cel mai important, ar dubla dimensiunea mesajului, îngreunând treaba plăcuței Arduino.
 +</​note>​
 +
 +Mesajele plăcuței vor fi mereu de 31 de octeți dintre care primul va fi folosit pentru recunoașterea mesajului:
 +  * ''​BYTE_RECOGNISED''​ - Kinect-ul a detectat jucătorul;
 +  * ''​BYTE_START_PLAYING''​ - Kinect-ul a detectat gestul de wave și semnalează începerea jocului;
 +  * ''​BYTE_LOST''​ - Kinect-ul nu mai detectează jucătorul;
 +  * ''​BYTE_START''​ - Kinect-ul trimite coordonatele curente ale scheletului utilizatorului;​
 +  * ''​BYTE_NOT_RECOGNISED''​ - Valore dată coordonatelor punctelor de pe schelet care nu sunt vizibile pentru Kinect.
 +
 +<note tip>
 +Codul este scris astfel încât coordonatele punctelor de pe schelet sunt considerate în aceeași ordine de ambele dispozitive,​ de la cap (''​SKEL_HEAD''​) la tălpi (''​SKEL_LEFT_FOOT'',​ ''​SKEL_RIGHT_FOOT''​);​
 +</​note>​
 +
 +Pentru desenarea corpului pe display-ul LCD se vor folosi din biblioteca ''​LCDWIKI_GUI''​ funcțiile:
 +  * ''​Fill_Circle(int16_t x, int16_t y, int16_t radius)'';​
 +  * ''​Fill_Triangle(int16_t x0, int16_t y0, int16_t x1, int16_t y1,int16_t x2, int16_t y2)'';​
 +  * ''​Draw_Line(int16_t x1, int16_t y1, int16_t x2, int16_t y2)''​.
 +
 +Acestea sunt utilizate în funcții wrapper pentru a desena corpul stickman-ului care va imita utilizatorul:​
 +<code c>
 +void drawHead() {
 +  lcd.Fill_Circle(skeletonPoints[SKEL_HEAD].x,​ skeletonPoints[SKEL_HEAD].y,​ 25);
 +}
 +</​code>​
 +<code c>
 +void drawBodyPart(int firstIndex, int secondIndex,​ int thirdIndex) {
 +  PVector p1 = skeletonPoints[firstIndex];​
 +  PVector p2 = skeletonPoints[secondIndex];​
 +  PVector p3 = skeletonPoints[thirdIndex];​
 +
 +  lcd.Fill_Triangle(p1.x,​ p1.y, p2.x, p2.y, p3.x, p3.y);
 +}
 +</​code>​
 +<code c>
 +void drawLimb(int firstIndex, int secondIndex) {
 +  PVector p1 = skeletonPoints[firstIndex];​
 +  if (p1.x == BYTE_NOT_DETECTED && p1.y == BYTE_NOT_DETECTED) {
 +    return;
 +  }
 +
 +  PVector p2 = skeletonPoints[secondIndex];​
 +  if (p2.x == BYTE_NOT_DETECTED && p2.y == BYTE_NOT_DETECTED) {
 +    return;
 +  }
 +
 +  lcd.Draw_Line(p1.x,​ p1.y, p2.x, p2.y);
 +  /* Draw around the point for thicker lines */
 +  for (int i = 1; i <= 2; i++) {
 +    lcd.Draw_Line(p1.x + i, p1.y, p2.x + i, p2.y);
 +    lcd.Draw_Line(p1.x - i, p1.y, p2.x - i, p2.y);
 +    lcd.Draw_Line(p1.x,​ p1.y + i, p2.x, p2.y + i);
 +    lcd.Draw_Line(p1.x,​ p1.y - i, p2.x, p2.y - i);
 +  }
 +}
 +</​code>​
 +<note tip>
 +Pentru a desena mai gros liniile dintre punctele de pe schelet, desenăm mai multe linii cu punctele limită adiacente cu sursa. Totuși, este important de ținut minte că această tehnică nu trebuie folosită excesiv, deoarece poate îngreuna foarte mult plăcuța, rezultând într-un aspect neplăcut și timpi de așteptare excesivi.
 +</​note>​
 +<code c>
 +void drawSkeleton() {
 +  lcd.Fill_Screen(BLACK);​
 +  drawHead();
 +
 +  /* Draw a circle for each skeleton point */
 +  for (int i = 1; i < NUM_SKEL_POINTS;​ i++) {
 +    PVector p = skeletonPoints[i];​
 +    lcd.Fill_Circle(p.x,​ p.y, 4);
 +  }
 +
 +  drawLimb(SKEL_HEAD,​ SKEL_NECK);
 +
 +  drawLimb(SKEL_NECK,​ SKEL_LEFT_SHOULDER);​
 +  drawLimb(SKEL_LEFT_SHOULDER,​ SKEL_LEFT_ELBOW);​
 +  drawLimb(SKEL_LEFT_ELBOW,​ SKEL_LEFT_HAND);​
 +
 +  drawLimb(SKEL_NECK,​ SKEL_RIGHT_SHOULDER);​
 +  drawLimb(SKEL_RIGHT_SHOULDER,​ SKEL_RIGHT_ELBOW);​
 +  drawLimb(SKEL_RIGHT_ELBOW,​ SKEL_RIGHT_HAND);​
 +
 +  drawLimb(SKEL_LEFT_SHOULDER,​ SKEL_TORSO);​
 +  drawLimb(SKEL_RIGHT_SHOULDER,​ SKEL_TORSO);​
 +  ​
 +  drawLimb(SKEL_TORSO,​ SKEL_LEFT_HIP);​
 +  drawLimb(SKEL_LEFT_HIP,​ SKEL_LEFT_KNEE);​
 +  drawLimb(SKEL_LEFT_KNEE,​ SKEL_LEFT_FOOT);​
 +  ​
 +  drawLimb(SKEL_TORSO,​ SKEL_RIGHT_HIP);​
 +  drawLimb(SKEL_RIGHT_HIP,​ SKEL_RIGHT_KNEE);​
 +  drawLimb(SKEL_RIGHT_KNEE,​ SKEL_RIGHT_FOOT);​
 +
 +  drawLimb(SKEL_LEFT_HIP,​ SKEL_RIGHT_HIP);​
 +
 +  drawBodyPart(SKEL_LEFT_SHOULDER,​ SKEL_RIGHT_SHOULDER,​ SKEL_TORSO);​
 +  drawBodyPart(SKEL_LEFT_HIP,​ SKEL_RIGHT_HIP,​ SKEL_TORSO);​
 +}
 +</​code>​
 +
 +<note tip>
 +Ultima problemă cu care m-am confruntat(care din păcate este cea mai evidentă) a fost refresh rate-ul foarte mic al display-ului LCD. Mai mult decât atât, plăcuța nu poate ține pasul cu mesajele trimise de Kinect. Din acest motiv nu am putut obține actualizare în timp real, folosind în schimb un timer pentru a limita intervalul de timp în care se trimit coordonate de schelet. O soluție posibilă ar fi putut să fie utilizarea tehnicii de double buffer și a algoritmulului Bresenham pentru desenarea liniilor, însă memoria limitată a plăcuței nu a făcut posibilă alocarea unui buffer.
 </​note>​ </​note>​
 ===== Rezultate Obţinute ===== ===== Rezultate Obţinute =====
  
 ===== Concluzii ===== ===== Concluzii =====
 +Ma bucur că am descoperit cum funcționează tehnologiile folosite de Kinect (depth image, skeleton recognition) și am reușit să creez un proiect fun și relativ unic. Sper că acest proiect va motiva viitorii studenți să încerce și ei includerea unui Kinect în proiectul lor. Este mult mai ușor decât pare, iar eu am încercat în această documentație să menționez toate blocajele pe care le-am avut în timpul fazei de setup pentru a trece mult mai repede la partea creativă. 
 +Singurul regret pe care îl am este că display-ul meu nu a avut un refresh rate suficient de mare încât să pot reda imagini în timp real.
 ===== Download ===== ===== Download =====
-  * Driver Kinect pentru PC: https://​k2vr.tech/​docs/​notready +  * [[https://​github.com/​RoundRaccoon/​dancing-stickman|Proiect Github]] 
-  * simple-openni: https://​code.google.com/​archive/​p/​simple-openni/​downloads +  * [[https://​k2vr.tech/​docs/​notready|Driver Kinect pentru PC]] 
-  * std::vector pentru Arduino: ​https://reference.arduino.cc/reference/en/libraries/vector/+  * [[https://​processing.org/​download|Processing IDE]] 
 +    * [[https://​code.google.com/​archive/​p/​simple-openni/​downloads|SimpleOpenNI]] 
 +  * [[https://www.arduino.cc/​en/​donate/|Arduino IDE]] 
 +    * [[http://​www.lcdwiki.com/​3.5inch_Arduino_Display-UNO|LCDWIKI_GUI și LCDWIKI_KBV]]
 ===== Jurnal ===== ===== Jurnal =====
 <note tip> <note tip>
 Am deci să folosesc această rubrică pentru a scoate în evidență blocajele pe care le-am avut și ce mi-aș fi dorit să știu înainte de a începe să lucrez la acest proiect, în speranța ca viitori studenți care folosesc Kinect pentru proiectul lor să treacă mult mai repede peste problemele de configurare. Am deci să folosesc această rubrică pentru a scoate în evidență blocajele pe care le-am avut și ce mi-aș fi dorit să știu înainte de a începe să lucrez la acest proiect, în speranța ca viitori studenți care folosesc Kinect pentru proiectul lor să treacă mult mai repede peste problemele de configurare.
 </​note>​ </​note>​
-Dacă doriți să creați un proiect folosind Kinect și Arduino, următoarele idei s-ar putea să vă salveze destul de mult timp: +Dacă doriți să creați un proiect folosind Kinect și Arduino, următoarele idei s-ar putea să vă salveze destul de mult timp
-  * La momentul scrierii, nu există o librărie open-source ​de Kinect ​pentru calculatoarele cu arhitectură ARM, care să ofere toate funcționalitațile disponibile.+ 
 +Setup Kinect
 +  * Pentru versiunile mai vechi de Kinect ​veți avea nevoie de power adapterCele mai noi pot fi direct conectate la calculator (e.g. Kinect for Windows);
   * Dacă folosiți un power adapter, acesta trebuie obligatoriu conectat la laptop printr-un port USB 3.0.   * Dacă folosiți un power adapter, acesta trebuie obligatoriu conectat la laptop printr-un port USB 3.0.
 +  * În funcție de calculator, este sau nu posibil ca Kinect-ul să pornească imediat (verificați LED-ul verde din față). Dacă nu, instalați driver-ul pentru Kinect (link la Downloads).
 +  * La momentul scrierii, nu există o librărie open-source de Kinect pentru calculatoarele cu arhitectură ARM, care să ofere toate funcționalitațile disponibile. Recomand folosirea Windows, Linux sau OSX cu Intel.
 +
 +Programare Kinect și comunicare cu Arduino:
 +  * În literatura de specialitate se folosesc în mare parte versiuni de simple-openni dinainte de 1.96, care acum sunt outdated;
 +  * Chiar dacă versiunile de SimpleOpenNI spun că sunt pentru o versiune specifică de Processing, este posibil ca totuși să puteți folosi și versiuni mai noi de processing (e.g. SimpleOpenNI for Processing 3.5.3 cu Processing 4.2);
   * Atunci când stabiliți conexiunea serială între calculator și Arduino, verificați în codul de Processing dacă portul serial folosit este cel corect.   * Atunci când stabiliți conexiunea serială între calculator și Arduino, verificați în codul de Processing dacă portul serial folosit este cel corect.
     * Toate tutorialele spun că numele portului care trebuie folosit este Serial.list()[0],​ dar în cazul meu acest port era ocupat de căștile cu Bluetooth.     * Toate tutorialele spun că numele portului care trebuie folosit este Serial.list()[0],​ dar în cazul meu acest port era ocupat de căștile cu Bluetooth.
     * Pentru mine, Serial.list()[2] a fost numele portului serial.     * Pentru mine, Serial.list()[2] a fost numele portului serial.
-  * În literatura de specialitate se folosesc în mare parte versiuni de simple-openni dinainte de 1.96, care acum sunt outdated. 
-    * Schimbările nu sunt atât de evidente între versiuni. Recomand folosirea celei mai noi versiuni plecând de la exemplele oferite. 
  
-Probleme ​întâmpinate+Alte probleme ​întâmpinate de mine:
-  * Deoarece comunicarea seriala este bazata octet pe octet, va fi nevoie sa folosesc valori intre 0 si 255 si sa imi creez minimal un protocol ​de comunicație.+
   * Display-ul LCD nu are un refresh rate suficient de mare pentru a capta imagini în timp real. La momentul scrierii display-ul afișeaza poziția utilizatorului o dată la 1.6 secunde.   * Display-ul LCD nu are un refresh rate suficient de mare pentru a capta imagini în timp real. La momentul scrierii display-ul afișeaza poziția utilizatorului o dată la 1.6 secunde.
 +  * Deoarece comunicarea seriala este bazata octet pe octet, va fi nevoie sa folosesc valori intre 0 si 255 si sa imi creez minimal un protocol de comunicație.
 +  * Memoria limitată a plăcuței Arduino face imposibilă utilizarea tehnicii double buffer pentru un display de 320x420.
 ===== Bibliografie/​Resurse ===== ===== Bibliografie/​Resurse =====
  
pm/prj2023/dene/dancingstickman.1685042148.txt.gz · Last modified: 2023/05/25 22:15 by daniel.nastase2109
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0