Aplicație Software de Diagnoză și Testare a Automobilelor cu Autonomie Ridicată

Universitatea “Politehnica” din București

Facultatea de Electronică, Telecomunicații și Tehnologia Informației

Aplicație software de diagnoză și testare a automobilelor cu autonomie ridicată

Ridicată

Lucrare de dizertație

prezentată ca cerință parțială pentru obținerea titlului de

Master în domeniul Inginerie Electronică și Telecomunicații

programul de studii de masterat Microsisteme

Conducător științific Absolvent

Prof. Dr. Ing. Cristian RĂVARIU Ing. Vlad Octavian MOISE

2016

Anexă

Declarație

Cuprins

Listă figuri

Introducere

Proiectul de față propune un studiu asupra sistemelor inteligente ce stau la baza automobilelor cu autonomie ridicată, având drept obiectiv final realizarea unei aplicații software ce va efectua diagnoza și testarea acestora. Inovațiile recente din domeniul auto condiționează reprofilarea către carburanți eco și confort sporit. Pentru că industria constructoare de mașini nu evoluează la fel de repede precum cea a computerelor sau a telefoanelor mobile, schimbările vin mai rar, însă sunt semnificative.

În urmă cu aproximativ 200 de ani, oamenii se bucurau de apariția șinelor feroviare mecanizate, iar la începutul secolului trecut a început producția în masă a autoturismelor. Acum este timpul pentru o nouă schimbare ce va revoluționa transporturile – tranziția către mașinile care se conduc complet singure și care, cum ar spune unii, pun "auto" în "automobil".

Tehnologia curentă a automobilelor autonome oferă posibilitatea de a modifica fundamental transportul. Echiparea vehiculelor cu această tehnologie va reduce numărul accidentelor provocate de erori umane, consumul de energie și poluarea – la toate acestea, adăugăm posibilitatea evitării ambuteiajelor din trafic.

Implementarea vehiculelor autonome nu constituie în principiu o problemă tehnică, ci mai degrabă una psihologică, întrucât pasagerii unei astfel de mașini devin extrem de tensionați atunci când este vorba să își lase viețile pe alte mâini – sondajele efectuate indică faptul că încrederea în această tehnologie este extrem de scăzută. Dintr-un grup de 1000 de adulți care ar putea fi clienți țintă, doar 18% dintre respondenți au declarat că ar cumpăra un vehicul autonom, 22% au considerat că nu ar avea liniște dacă cei dragi ar fi „conduși” de automobile autonome, iar doar 13% ar avea încredere să doarmă la volanul acestora.

Și totuși, întrebarea care apare este “de ce?”. Un astfel de vehicul nu va fi niciodată tentat să forțeze intrarea într-o intersecție pe culoarea roșie a semaforului, nu va depăși pe linia continuă și nici nu va intra pe sens interzis. Primul răspuns la îndemână ar fi lipsa tehnologiei, dar acesta nu este tocmai un argument care să stea în picioare, mulți producători auto având deja la activ experimente încheiate cu succes. Un alt răspuns, mai plauzibil, este dat de frica de schimbare. Prejudecățile și teama aventurării în necunoscut reprezintă modul de operare zilnic al majorității.

Alegerea temei s-a făcut luând în calcul faptul că va îmbina domenii interesante, într-un mod practic. La final, s-au aprofundat și dezvoltat cunoștințele legate de realizarea / mentenanța unei baze de date, programarea în limbajul PHP, utilizarea unui framework, streamuri de date, dar și despre noile tehnologii din industria auto.

roiectarea, realizarea software și testarea pe o baza de date se va face explicitand

toate tools-urile care au fost folosite, apoi modul cum a fost creata fiecare baza de date si

explicarea programului de exploatare a sa, cu multiple exemple de testare, in final.

– Se pornește de la biblioteci de cod, pachete software de gestionare a unei aplicatii pe

net, algoritmi cunoscuți în literatură

Proiectarea, realizarea software și testarea pe o baza de date se va face explicitand

toate tools-urile care au fost folosite, apoi modul cum a fost creata fiecare baza de date si

explicarea programului de exploatare a sa, cu multiple exemple de testare, in final.

– Se pornește de la biblioteci de cod, pachete software de gestionare a unei aplicatii pe

net, algoritmi cunoscuți în literatură.

Proiectarea, realizarea software și testarea aplicației se va face explicitând toate tool-urile care au fost folosite, apoi modul cum a fost creată baza de date și explicarea programului de exploatare a sa, cu multiple exemple de testare, în final. Se pornește de la biblioteci de cod, pachete software de gestionare a unei aplicații web, algoritmi cunoscuți în literatură.

CAPITOLUL 1. Noțiuni teoretice

1.1 Vehicule autonome – Generalități

Tehnologia vehiculelor autonome oferă posibilitatea unei schimbări fundamentale a transportului, având drept scop reducerea accidentelor provocate de erori umane, o economisire reală a consumului, reducerea poluării, creșterea confortului individului, posibilitatea apariției unei noi piețe și oportunități economice.

Această tehnologie este cel mai ușor conceptualizată folosind convenția National Highway Traffic Safety Administration (NHTSA), ce prezintă diverse nivele de automatizare:

Nivelul 0: Conducătorul auto are control deplin asupra funcțiilor vehiculului

Nivelul 1: O funcție este automatizată, dacă sunt mai multe, acestea operează independent una față de cealaltă

Nivelul 2: Mai mult de o funcție este automatizată (de ex. virarea și accelerarea), dar conducătorul auto trebuie sa rămână alert

Nivelul 3: Funcțiile de conducere sunt suficient de automatizate încât să permită șoferului să intrețină alte activități de-a lungul transportului

Nivelul 4: Vehiculul nu are nevoie de factorul uman, se poate conduce singur

Scurt istoric

Între 1980-2003, centre de cercetare ale universităților au lucrat la două concepte pentru automatizarea vehiculelor. Primul consta în automatizarea șoselelor, pe care ar putea circula vehicule “ghidate”. Alte grupuri lucrau la ideea de vehicul autonom (AV), ce nu necesită drumuri speciale.

În perioada 2003-2007 U.S. Defense Advanced Research Projects Agency (DARPA) a susținut trei “mari provocări”, ce au marcat avansări mari in tehnologia AV. Primele două s-au ținut în mediul rural, pe când a treia a avut loc în mediul urban. Fiecare dintre acestea a îndrumat echipele universităților pentru a dezvolta tehnologia.

Recent, companii private au început să își dezvolte propriile proiecte AV. Inițiativa Driverless Car a companiei Google a fost testată cu succes pe o multitudine de vehicule. În 2013, Audi și Toyota și-au dezvăluit propriile viziuni și cercetarea în domeniul AV. Nissan plănuiește să înceapă să vândă AV-uri începând cu anul 2020. [10]

Efectul asupra incidentelor din trafic

Chiar dacă frecvența accidentelor este în declin în Statele Unite, asemenea incidente rămân o problemă majoră pentru sănătatea publică. Mai mult de 4.8 milioane de automobile au fost implicate în accidente în Statele Unite în 2015, rezultând în 2.1 milioane de răniți și 32,000 fatalități. Insurance Institute for Highway Safety (IIHS) a estimat că dacă toate mașinile ar avea sisteme de avertizare pentru coliziune frontală, precum și pentru atenționare de părăsire/depășire a benzii, oferirea asistenței pentru punctul mort și faruri adaptive, aproape o treime dintre accidente ar putea fi prevenite. Sistemele pentru frânare automată atunci când vehiculul detectează un obstacol ar reduce semnificativ numărul de coliziuni. Tehnologiile care permit vehiculelor să fie responsabile în totalitate pentru condus vor reduce și mai mult statisticile accidentelor datorate erorilor umane.

Fig. 1.1 Numărul fatalităților pe șosele / miliard mile parcurse în Statele Unite

Efectul asupra mobilității, congestiei în trafic

Tehnologia AV(autonomous vehicles) de nivel 4 va spori mobilitatea celor care nu pot/doresc să conducă, oferind astfel independență și reducerea izolării sociale, acces la servicii esențiale. Tehnologia de nivel 3 sau mai ridicat va reduce “costul” produs de ambuteiajele din trafic, întrucât conducătorii auto vor putea întreține alte activități în acest timp, dar vor realiza și o eficientizare a consumului de carburant (4-10%), la care se adaugă folosirea combustibililor alternativi.

Costuri/Dezavantaje

Chiar dacă potențialele beneficii sunt substanțiale, dezavantajele implicate sunt la fel de importante. În mod ironic, aceste tehnologii nu aduc doar avantaje: profesiile de șofer, taximetrist vor dispărea, iar dacă numărul accidentelor va scădea, industria auto ar avea de suferit, împreună cu cea a asigurărilor etc. Totul depinde în cele din urmă de nivelul de automatizare care va fi atins.

Tehnologia pare aproape de maturitate, și va permite în curând introducerea în comerț. Fiecare producător auto major este angajat în cercetări avansate în domeniu, iar predicția este că aceasta va apărea pe piață între următorii 5-20 ani. O multitudine de state au înaintat deja legi pentru folosirea AV-urilor.

Unul dintre cele mai dificile obstacole pe care AV-urile trebuie să le depășească este obținerea unei percepții dinamice asupra mediului înconjurător aflat în perpetuă schimbare. Mediul conține o multitudine de elemente:

celelalte autovehicule din trafic, fiecare operând într-un mod dinamic și independent

pietonii, cicliștii, fauna etc.

condițiile meteo

condițiile în care se prezintă infrastructura (condiția șoselelor, drumuri în lucru etc.)

evenimente din trafic (ambuteiaje, accidente)

Acesta este marele avantaj al oamenilor față de roboți, ochii umani sunt sofisticați și ne oferă aproape toate datele senzoriale necesare pentru a conduce. De asemenea, suntem capabili de a interpreta informațiile primite. Chiar dacă ochii noștri sunt senzori pasivi, percepând informații de la lumina reflectată, putem aproxima distanțe, recunoaște forme și clasifica obiectele din trafic (mașini, biciclete, pietonii), vedea într-o gamă variată de condiții. Bineînțeles, suntem departe de a fi perfecți. Văzul și simțurille cognitive asupra informațiilor vizuale variază și pot fi periculos de limitate în anumite situații(condiții ambientale adverse, când suntem distrași, sub influența drogurilor sau alcoolului).

Sistemele bazate pe camere sunt analogii pentru ochii umani si funcțiile cognitive. Acestea nu sunt scumpe și pot oferi informații complete despre tot ceea ce se află în câmpul lor vizual. Însă, există două limitări importante. În primul rând, algoritmii de procesare ai datelor nu sunt nici pe departe la fel de sofisticați ca și capacitatea umană de interpretare a informației. A doua limitare constă în problemele apărute atunci când camerele nu sunt adaptate condițiilor ambientale. [1]

1.1.1 Soluții bazate pe senzori

Industria auto se concentrează pe dezvoltarea soluțiilor ce ar putea spori siguranța la volan în zonele în care eroarea umană este foarte comună – la viteze reduse, când șoferul este prins în trafic, și la viteze mari, când șoferul este pe autostradă. Aceste sisteme, cunoscute sub numele de Advanced Driver Assist Systems (ADAS), folosesc o combinație de senzori avansați, cum ar fi camere stereo, un RADAR de lungimi de undă scurte/lungi, combinat cu actuatori, unități de control și software de integrare, ce permit vehiculului să monitorizeze și răspundă corect împrejurărilor. Unele soluții ADAS, precum cele de menținere a benzii și avertizare, Adaptive Cruise Control (ACC), asistență la parcare/dat cu spatele, toate sunt disponibile în momentul curent, iar multe altele sunt în curs de dezvoltare.

Fig. 1.2 Zonele de viteză țintă pentru sistemele de asistență în trafic

Companiile dezvoltă soluții care folosesc camere stereo și software special, care laolaltă cu algoritmi complexi calculează în timp real geometria 3D a oricărei situații ce poate apărea în fața autovehiculului.

Limitările curente ale acestor sisteme fac ca, în forma curentă, să nu fie capabile de a oferi o soluție completă sau competitivă din punct de vedere al costurilor:

Percepția asupra mediului înconjurător: Până acum, fuziunea dintre senzorii existenți și inteligența artificială nu este capabilă de a “vedea” și înțelege împrejurările în care se află vehiculul la fel de bine precum o face un om. Algoritmii necesari sunt foarte complexi și trebuie să înlocuiască aproximativ 16 ani de învățare umană.

Costurile: Crearea unei perspective de 360 grade a mediului înconjurător necesită o combinație de senzori care costă mai mult decât consumatorii ar fi doritori să plătească. De exemplu, sistemele capabile de a realiza acest lucru, bazate pe Light Detection and Ranging (LIDAR) sunt complexe, scumpe și nu sunt gata pentru a fi folosite pe piață.

1.1.2 Soluții bazate pe conectivitate

Tehnologiile wireless sunt folosite pentru a comunica în timp real de la vehicul la vehicul (V2V),de la vehicul la infrastructură (V2I) și vice-versa. Se estimează că aproximativ 80% din accidente ar putea fi evitate folosind comunicarea în timp real dintre automobile.

Dedicated Short-Range Communication (DSRC), care folosește unde radio, este tehnologia cea mai utilizată în momentul de față pentru comunicația V2V. Operează la o frecvență de 5.9 GHz, folosește standarde precum SAE J2735 și suita IEEE 1609 (protocoale care stabilesc ce mesaje sunt trimise, cum sunt interpretate și structurate) și este testată riguros pentru a vedea dacă poate suporta în totalitate aplicații de siguranță V2V. În momentul de față, DSRC poate fi considerată o soluție de viitor, deoarece oferă următoarele:

achiziție rapidă a semnalului

latență scăzută

prioritate pentru aplicații de siguranță

interoperabilitate

securitate și intimitate

fiabilitate

Pentru a depăși faza de testare, câteva obstacole critice trebuie depășite:

Masa critică: Comunicarea V2V necesită ca celelalte vehiculele să permită primirea și trimiterea semnalelor. Acest lucru va dura destul de mult timp, iar costurile implicate sunt ridicate, întrucât vehiculele deja existente trebuiesc echipate cu această tehnologie.

Modificarea infrastructurii: Comunicarea V2I necesită o infrastructură echipată cu stații de emisie-recepție DSRC, costul aferent reprezentând o problemă. O soluție intermediară ar putea fi concentrarea pe intersecții sau zone cu risc crescut de accidente. Alta constă în folosirea tehnologiei celulare și a infrastructurii curente pentru comunicare la depărtare, iar cea DSRC pentru comunicare la apropiere.

Dependența de senzori: Cu toate că soluțiile de interconectare a vehiculelor pot comunica cu mediul extern, soluțiile bazate pe senzori trebuie să co-existe pentru a acoperi situațiile care includ obstacole, pietoni etc., ce nu sunt conectate cu rețeaua.

1.1.3 Necesitatea convergenței între sisteme

Convergența tehnologiilor bazate pe senzori cu cele bazate pe comunicații ar putea livra siguranță, mobilitate și încredere în capacitatea vehicululelor autonome sporite.

Fig. 1.3 Beneficiile convergenței între sisteme

O convergență satisfăcătoare a sistemelor poate fi realizată daca se obțin următoarele îmbunătățiri ale tehnologiei curente:

Tehnologie de poziționare îmbunătățită: GPS-urile nu sunt suficient de precise, oferind o precizie de doar +/- 10 metri, care nu este destul de bună pentru a fi folosite în aplicații critice pentru siguranța pasagerilor. Tehnologii de corecție a erorilor GPS-urilor, precum RTK(real-time kinematics) vor fi introduse în viitor, întrucât cererea pentru îmbunătățirea acurateții este în creștere, iar curba de costuri permită introducerea pe piață.

Mapare de înaltă rezoluție: Hărțile digitale curente nu conțin suficiente detalii pentru a fi folosite în aplicații ale automobilelor autonome. Dacă o firmă va rezolva problema acurateții, ar ușura puțin din problema modificării infrastructurii, necesitate de tehnologia DSRC.

O interfață mașină-om fiabilă și intuitive (HMI): Interfața dintre șofer și mașina rămâne o problemă complex. Șoferul trebuie să știe când și cum să predea/preia controlul vehiculului. Această trecere trebuie să se facă transparent și intuitiv pentru persoana de la volan.

Standardizare: Regimul pentru vehicule interconectate este destul de matur, bazat pe standardele SAE J2735 și IEEE 1609, dar sunt necesare alte standarde pentru a garanta interoperabilitate completă. [5]

Fig. 1.4 Soluția autonomă a companiei Google

1.2 Tehnologii în curs de dezvoltare

Planificarea rutelor pentru AV-uri, cu un minim de date a-priori încă ridică multe probleme. S-a demonstrat că folosirea soluțiilor convergente joacă un rol important în determinarea automată a rutelor potrivite și cel mai puțin costisitoare. Competițiile Grand Challenge DARPA și Urban Challenge au arătat lumii că AV-urile pot respecta regulile în trafic, evita obstacole statice, interacționa cu vehicule în mișcare. Se va discuta în continuare despre modul în care se pot evita limitările existente în tehnologia curentă, se va descrie baza inteligentă a acestor vehicule. [1]

Fig. 1.5 Soluții inteligente care asistă conducătorul auto

1.2.1 LIDAR – Light Detection and Ranging

Acesta este un sistem senzorial activ, ce utilizează pulsuri laser pentru a măsura distanța până la obiecte, măsurând timpul de deplasare al pulsurilor. Realizează o detecție optică la distanță, ce măsoară distanța până la țintă sau alte proprietăți ale acesteia, prin iluminarea țintei.

LADAR (Laser Detection and Ranging) este alt acronim acceptat. Deși cândva o simplă unealtă pentru măsurare, s-a dovedit a fi acceptat drept senzor cu multiple folosințe. Unele dintre primele utilizări ale tehnologiei LIDAR au fost pe misiunile lunare Apollo 15,16,17, întrucât topografia lunară a fost realizată folosind un altrimetru laser de pe modulele ce orbitau în jurul lunii. Pe măsură ce tehnologia a avansat, sisteme LIDAR aeriene au fost folosite pentru a aduna date batimetrice, determina topografii, măsura diverși parametri. [3]

Toate sistemele LIDAR funcționează pe același principiu. Un puls laser este trimis la un anumit unghi (relativ la senzor), iar timpul pînă când întâlnește un obstacol este măsurat și folosit pentru a determina distanța. Simultan, date despre altitudine și poziționare sunt extrapolate folosind sisteme GPS de acuratețe înaltă, preferabil DGPS. [5]

Fig. 1.6 Senzorul LIDAR

Ambele sisteme, atât scannerul LIDAR, cât și sistemele de poziționare și orientare sunt sincronizate. Datele despre distanță și unghi capturate de LIDAR sunt coordonate cu măsurătorile de poziție și orientare, pentru a realiza geo-referințe pentru ceea ce returnează laserul. Folosirea măsuratorilor directe de poziție și orientare în geo-referire, în loc de a corela datele cu punctele de referință, are numele de geo-referire directă.[6]

Chiar dacă există multe similarități între senzori LIDAR aerieni și cei pentru sol, există și diferențe semnificative. În primul rând, LIDAR pentru sol are în general o acoperire de la câteva zeci de metri la sute de metri. Această limitare este un produs al câmpului vizual lat, cuplat cu o rezoluție angulară mică.În plus, aceste sisteme se bazează pe utilizarea mai multor plane între scanări.

Limitările constau în reducerea zgomotului, probleme de triangulare în spațiu, necesitatea folosirii interpolării pentru a îmbunătăți imaginile obținute.[4]

Cel mai simplu model de senzor LIDAR constă într-un iluminator laser, un telescop colector și un singur fotodetector. Laserul trimite un puls de-a lungul axei telescopului. Pulsul se reflectă de un obiect de-a lungul căii sale, iar pulsurile întoarse sunt concentrate de către telescop pe fotodetector. În momentul în care pulsul este recepționat, este comparat cu momentul de timp în care a fost trimis, iar distanța până la obiect este determinată folosind ecuația:

R este distanța, tr timpul de recepție, tt timpul de emisie, c este viteza luminii

Un astfel de sistem este capabil doar să detecteze obiecte aflate direct pe axa senzorului, orice scanare trebuie făcută prin punerea senzorului pe direcția dorită. Rezoluția este determinată, ca în cazul tuturor LIDAR-urilor, de relația dintre lațimea razer laser, rezoluția telescopului și mărimea pixelului. Atunci când câmpul de detecție (FOV) al pixelului este mai mare sau egal cu zona iluminată de către pulsul laser, pixelul va detecta orice de-a lungul razei, iar rezoluția va fi determinată de lățimea acesteia. Daca FOV-ul pixelului este mai mică decât zona iluminată de către puls, doar obiectele din FOB vor fi detectate. Acest lucru îmbunătățește rezoluția sistemului, dar poate însemna și ca obiectul pentru care se realizează scanarea poate fi iluminat fără a fi detectat.[6]

Fig. 1.7 Tipuri de câmpuri de detecție

Cum am menționat mai sus, acest design este unul simplu, performanțele sistemului putând fi îmbunătățite printr-o multitudine de feluri:

Oglinzile de scanare pot direcționa pulsuri laser către zone țintă ce nu se află pe axă, permițând LIDAR-ului să scaneze fără a trebui să se modifice structura instrumentului.

Expandarea fasciculelor poate fi folosită pentru a concentra raza laser sub un unghi mai mic, sau pentru a scana o zonă mai largă

Folosirea matricilor cu fotodetectori pixel permit creșterea rezoluției

Metoda de iluminare poate fi alterată în diverse feluri, în loc de a trimite câte un puls, se poate opta pentru trimiterea unor trenuri de impusluri, ce vor spori probabilitatea detecției și vor îmbunătăți rezoluția, având drept consecință însă, scanări mai lente și câmpuri vizuale reduse [3,4]

Avantajele folosirii laserelor în senzorii LIDAR

Monocromaticitatea

Se referă la puritatea spectrală a luminii laser. Considerat doar o sursă de lumină, un laser oferă cea mai pură culoare monocromatică ce poate fi produsă de către om. Acest lucru permite obținerea unui raport semnal-zgomot foarte bun, datorită benzii înguste a semnalului. Cele mai multe surse potențiale de zgomot, dintre care cea mai semnificativă este soarele, produc semnale de bandă largă. Cu filtre optice, majoritatea acestui zgomot poate fi eliminat.

Fig. 1.8 Emisia Laser vs. Emisia spontană

Direcționalitatea

Cel mai mare avantaj al laserelor drept sursă de iluminare este direcționalitatea acestora. Cu câteva excepții, ale unor sisteme cu amplificare foarte mare, majoritatea laserelor conțin tuburi care reflectă energia laser între două oglinzi, înainte de a îi permite să scape prin apertură.

Această colimare are efectul practic de a produce o undă de lumină aproape planară, în locul undelor sferice produse de majoritatea surselor de lumină. Aranjarea aproape planară îi permite undei să se propage cu o împrăștiere sub unghiul de divergență, definit de geometria tubului laser și mărimea aperturii. Unghiurile de divergență au valori tipice de ordinul miliradianilor.

Luminozitatea

Luminozitatea unui laser este produsul monocromaticității și direcționalității luminii pe care o produce. Prin concentrarea unei lumini pur-spectrale într-un unghi solid foarte mic, se poate produce lumină foarte luminoasă folosind o putere redusă. Ca rezultat, laserii operând nivele energetice de mai puțin de un mW sunt mai luminoși decât soarele. [5,6,7]

Pentru că cele mai importante variabile – atunci când se vorbește despre senzori LIDAR – sunt gama de detecție și unghiul de divergență (care este pătrat), un estimat al primului ordin de energie / puls necesitat de laser poate fi determinat fără a alege celelalte componente. Această estimare va indica subsetul de lasere ce ar putea fi utilizate cu succes. Considerând lungimile de undă produse, eficiența, complexitatea și fiabilitatea dorită, lista poate fi restrânsă și mai mult. Odată ce deciziile de prim ordin sunt făcute, se pot alege planul focal sau tipul telescopului.

Printre unele dintre cele mai atractive opțiuni de lasere pentru dezvoltatorii de sisteme LIDAR se numără laserele cu fibră optică dopată (lasere solid-state), acestea prezentând eficiență ridicată. Unul dintre cele mai commune tipuri de laser folosit, este cel Nd-YAG. Materialul are proprietăți termice foarte bune și operează cu o eficiență bună.

De asemenea, o opțiune foarte bună, dar aflată încă în dezvoltare, sunt laserele Free-Electron (cu electroni liberi). O rază cu electroni de energie înaltă este trimisă printr-un “agitator”, un câmp magnetic alternant care cauzează vibrația electronilor. Această vibrație de “agitație”. Apoi, acești fotoni sunt colimați, și emiși drept rază laser. Marele avantaj al acestei variante este că pot opera practic la orice frecvență, de la IR la UV, făcându-le ideale pentru senzori LIDAR. [4,6]

Fig. 1.9 Exemplu de captură a senzorului LIDAR

1.2.2 GPS – Global Positioning System

Sistemul de poziționare globală este o constelație de sateliți care oferă utilizatorului o poziționare precisă pe suprafața Terrei. A fost creat de U.S. DoD (Department of Defense) la începutul anilor ’70. Deși dezvoltat inițial pentru aplicații militare, a devenit cu timpul accesibil civililor. Acuratețea oferită este de +/- 10 metri, deloc practică pentru a localiza un obiect de mărimea unui automobil (cu lungime de aproximativ 3 metri).,

Este un sistem unidirecțional, adică utilizatorul poate primi, dar nu și trimite date către satelit. Această configurație este necesară din motive de securitate, cât și pentru a servi unui număr nelimitat de utilizatori.

Sistemele GPS au trei segmente majore:

Segmentul spațial – o constelație de 24 sateliți ce au o orbită fixă în jurul Terrei, care transmit pe două frecvențe purtătoare (coduri digitale și mesaje de navigație).

Segmentul de control – include o rețea care monitorizează în mod permanent orbita sateliților, condițiile atmosferice, oferă compensare a erorilor

Segmentul utilizatorilor – constă în toți utilizatorii civili și militari

Realizarea unui algoritm care preia datele de la un receptor GPS și folosește datele pentru a naviga cu succes printr-un set de puncte cunoscute este segmentată în trei părți, după cum urmează:

vehiculul este situat în poziția de start, receptorul GPS încearcă să fixeze semnalul de la sateliții GPS vizibili și să calculeze latitudinea/longitudinea curentă

algoritmul din unitățile de procesare calculează traseul către punctul destinație și folosind informații de la celelalte sisteme convergente, construiește un traseu către acesta

algoritmul facilitează navigația corectă a vehiculului către destinație și chiar afișarea informațiilor despre aceasta prin diverse metode (audio/video) [17,19]

Fig. 1.10 Segmentele sistemelor GPS

1.2.3 DGPS – Differential Global Positioning System

Tehnicile de corecție ale semnalului sunt folosite pentru a spori calitatea datelor strânse folosind sistemul GPS. Corecția diferențială poate fi aplicată în timp real sau la postprocesarea datelor. Chiar dacă ambele metode se bazează pe aceleași principii, fiecare accesează surse de date diferite și au diverse nivele de acuratețe. Combinare metodelor oferă flexibilitate în timpul colectării de date și crește integritatea datelor. Acuratețea obținută în tehnologia curentă este de 10 cm. Corecția de semnal a DGPS-ului pierde aproximativ 1 metru în acuratețe la fiecare 160 Km. De asemenea, este predispus la bruiaje ce duc la pierderi temporare ale semnalului.

Fig. 1.11 Modul de funcționare al DGPS-ului

Premisa de la care pornește tehnica DGPS este că există un receiver GPS, definit drept stație de bază, instalat într-o locație definită. Receiver-ul de bază calculează poziția sa folosind semnalele de la sateliți și o compară cu locația cunoscută. Diferența este aplicată datelor preluate de GPS-ul din autovehiculul autonom. [18,19]

1.2.4 RTK – RealTime Kinematic

Pentru aplicații care necesită o acuratețe înaltă, apare tehnica de navigație prin satelit RTK, bazată pe folosirea măsurării fazei purtătoarei semnalelor GPS, GLONASS sau Galileo, unde o singură stație de referință oferă corecții în timp real.

Stația de bază retransmite faza purtătoarei măsurate. Unitățile mobile (Rover) compară propriile măsurători de fază cu cele primite de la bază. Erorile rămase provin din surse precum semnalele emise de alți sateliți etc. [18,19]

Fig. 1.12 Modul de funcționare al RTK-ului

1.2.5 Sisteme GIS

Adesea numită cartografiere digitală, maparea digitală este procesul prin care o colecție de date este compilată și formatată într-o imagine virtuală. Funcția primară a acestei tehnologii este de a realiza reprezentări precise ale unei zone specifice, detaliând artere principale și alte puncte de interes. De asemenea, permite calculul distanțelor de la un punct la altul.

Doar anumite părți ale globului au fost mapate (în principiu zonele urbane), și este nevoie de o masă critică de cartografi care au rolul de a valida acuratețea datelor.

Un sistem geografic informațional (GIS) are funcția de a captura, stoca, manipula, analiza toate aspectele geografice ale unui corp de date. Practic, acesta permite vizualizarea sau analizarea unei baze de date și primirea rezultatelor sub forma unei hărți. Întrucât multe tipuri de date au aspecte geografice importante, un GIS poate avea diverse utilizări: analiza vânzărilor, prognoza meteo, predicții despre populație etc. [19]

Într-un GIS, datele geografice sunt stocate sub forma unui grafic vectorial sau rasterizat. Folosind formatul unui vector, date bi-dimensionale sunt stocate drept coordonate pe axele x și y. Informațiile geografice sunt descrise explicit sub formă de coordonate geografice sau implicit sub forma unei adrese, cod postal etc. Permite traducerea unor date geografice implicite (precum o adresă) într-o locație explicită pe hartă. Producătorii sistemelor GIS obțin uneori hărțile de informative din surse publice sau companii care se specializează în colectarea și organizarea informațiilor geografice. Procesul de convertire a datelor geografice implicite în imagini/hărți se numește geocoding (geo-codare). [8]

Un sistem GIS poate realiza următoarele:

acceptă date de intrare sub forma unor hărți / imagini scanate / digitizate

includ un manager de baze de date, de obicei un sistem RDBMS (Relational Database Management System)

includ programe de analiză și vizualizare, pentru a putea obține într-un mod facil datele dorite

oferă răspuns vizual, de obicei grafice sau hărți

manipulează date geografice în diverse scopuri [11,19]

Fig. 1.13 Modelul GIS

1.2.6 Planificarea rutei

Acest domeniu încapsulează o gamă largă de strategii și tehnici. Termenul de plănuire a rutei în robotică poate fi folosit pentru a descrie totul de la determinarea rute de zbor a elicopterelor robot, până la plănuirea mișcării unei mâini robotice de pe o linie de asamblare. Astfel, soluțiile pot varia foarte mult, în funcție de capacitățile vehiculului, mediul de operare și parametrii problemei de planificare efectivi.

Planificarea mișcării este definită drept procesul de determinare al mișcării continue de la o poziție până la alta, printr-o configurație spațială, evitând obstacolele. O configurație spațială este în general definită drept setul de poziții posibile pentru robot. Această abordare pentru planificarea rutei asigură faptul că tot ce înseamnă constrângere kinematică va fi luat în considerare, iar ruta aleasă va putea fi parcursă cu succes.

Întrucât configurația spațială este potențial infinită, discretizarea acesteia este o parte importantă în rezolvarea problemei de planificare. Există două abordări de bază.

Una dintre acestea implică realizarea unei traiectorii prin descompunerea reprezentării matematice a configurației spațiale. Algoritmii bazați pe această abordare vor livra mereu o soluție, dacă există, însă nu sunt ușor de implementat în cazul unei planificări în timp real, cu multe obstacole. Cea de-a doua metodă implică eșantionarea configurației spațiale, iar apoi generarea unei rute de-a lungul unor eșantioane. [9,12]

Chiar dacă există suficiente metode de eșantionare în literatură, în practică sunt folosite reprezentări grilă a configurației spațiale, care este interpretată mai apoi folosind algoritmii A* sau Dijkstra.

Cei mai comuni algoritmi de planificare a mișcării sunt soluții teoretice pentru o problemă bine defnită. Un vehicul autonom trebuie să integreze informație a-priori cu datele preluate în timp real de către senzori, luând în calcul constrângeri asupra timpului de procesare [9]

1.2.7 Algoritmi pentru planificarea rutei

Prima abordare, la care se face uneori referire drept planificarea rutei, găsește drumul cel mai scurt folosind o rețea sau reprezentare grilă a modelului real. Aceste abordări sunt folositoare atunci când setul de soluții algoritmului de rutare trebuie să fie ales dintr-un set fix de rute predefinite. Mai mult de atât, folosind analize bazete pe rețea, nicio rută din afara setului inițial fix nu poate fi luată în considerare. Aplicația pentru acest tip de modelare îl reprezintă de exemplu alegerea celei mai bune rute dintr-o rețea de drumuri. [12,14]

Primul pas în rezolvarea unei probleme prin intermediul algoritmilor euristici de explorare este definirea exactă a problemei, care este bine definită dacă cunoaștem următorii 4 parametri:

Starea inițială a problemei – mai exact configurația de plecare

Funcția de expandare a nodurilor – în general o listă de perechi acțiune – stare rezultat. Astfel, pentru fiecare stare se enumeră totalitatea acțiunilor posibile, precum și starea rezultată în urma aplicării respectivei acțiuni

Predicatul stării finale – o funcție care întoarce adevărat dacă o stare este stare scop și fals altfel

Funcția de cost – atribuie o valoare numerică fiecărei căi generate în procesul de explorare. De obicei, se folosește o funcție de cost pentru fiecare tranziție sau acțiune, atribuind, astfel, o valoare fiecărui arc din graful stărilor

Dacă algoritmul găsește o soluție atunci când mulțimea soluțiilor este nevidă spunem că algoritmul este complet. Dacă acesta găsește și calea de cost minim către starea finală, spunem că este optim.

În cadrul explorării stărilor, fiecare algoritm generează un arbore, care în rădăcină va conține starea inițială. Fiecare nod al arborelui va conține următoarele informații:

Starea conținută

Părintele nodului

Cost cale – costul drumului de la starea inițială până la nod [13]

Algoritmii folosiți pentru rezolvarea acestor probleme au fost realizați la sfârșitul anilor ’50 (Dijkstra 1959 și Moore 1959) și au fost integrați în software de tip GIS pe la mijlocul anilor ’80 (Lupien, Moreland și Dangermond 1987). Algoritmul de bază a fost realizat de Dijkstra.

Fig. 1.14 Algoritmul Djikstra

Algoritmul lui Djikstra este foarte important în plănuirea rutelor deoarece servește drept bază pentru diverși alți algoritmi folosiți în GIS și robotică. Algoritmul A*, împreună cu mulți alți algoritmi de căutare euristici sunt derivați din acesta.

Va găsi probabil cel mai scurt drum de la un punct la altul fără informații adiționale. Însă, în plănuirea rutelor din viața reală, acesta poate fi ineficient din punct de vedere al timpului de calcul, întrucât o structură globală există adesea și poate fi utilizată pentru a îmbunătăți algoritmul. [12]

Algoritmul A* folosește o politică de tip Best-First și evaluează nodurile combinând distanța deja parcursă până la nod cu distanța estimată până la cea mai apropiată stare scop. Cu alte cuvinte, pentru un nod n oarecare, funcția de evaluare reprezintă costul estimat al celei mai bune soluții care trece prin n.

Algoritmul funcționează în modul următor:

Inițial se introduce în mulțimea open (organizată ca o coadă de priorități în funcție de cost) nodul corespunzător stării inițiale

La fiecare pas se extrage din open nodul cu costul minim.

Dacă se dovedește că nodul n conține chiar o stare scop, atunci se întoarce calea de la starea inițială până la nodul n

Dacă nodul nu a fost explorat deja, se expandează

Pentru fiecare stare rezultată, dacă nu a fost generată de alt nod încă (nu este nici în open/closed), atunci se introduce în open

Dacă există un nod corespunzător stării generate în open sau closed, se verifică dacă nu cumva nodul curent produce o cale mai scurtă către starea dorită.

Dacă acest lucru se întâmplă, se setează nodul curent ca părinte al nodului stare dorită și se reevalueaza distanța. Această corectare implică reevaluarea tuturor căilor care trec prin nodul stării dorite, deci va trebui ca nodul să fie reintrodus în open în cazul în care era în closed [20]

Algoritmul va întoarce calea optimă către soluție, dacă o soluție există. Inconvenientul este că sunt necesare reevaluările nodurilor din closed. Această problemă poate fi rezolvată dacă impunem o condiție mai tare asupra euristicii, mai precis ca aceasta să fie monotonă. Pe lângă proprietățile de completitudine și optimalitate A* mai are o calitate care îl face atrăgător: pentru o euristică dată, orice algoritm de căutare complet și optim va explora cel puțin la fel de multe noduri ca A*, ceea ce înseamnă că este optimal din punct de vedere al eficienței. [12]

În practică, însă, A* poate fi de multe ori imposibil de rulat datorită dimensiunii prea mari a spațiului de căutare. Singura modalitate prin care spațiul de căutare poate fi reduse este prin găsirea unei euristici(funcții de căutare) foarte bune – cu cât euristica este mai apropiată de distanță reală față de starea soluție, cu atât spațiul de căutare este mai strâns. S-a demonstrat că spațiul de căutare începe să crească exponential dacă eroarea euristicii față de distanța reală până la soluție nu are o creștere subexponențială.

Fig. 1.15 Volumul spațiului de căutare în funcție de euristica aleasă

În concluzie, deseori singura modalitate de rezolvare a problemelor dificile este de a explora graful stărilor acelei probleme. Algoritmii clasici pe grafuri nu sunt potriviți pentur căutarea în aceste grafuri fie pentru că nu garantează un rezultat fie pentru că sunt ineficienți.

Algoritmii euristici sunt algoritmi ce explorează astfel de grafuri folosindu-se de o informație suplimentară despre modul în care se poate ajunge la o stare scop mai rapid. A* este, cel puțin teoretic, cel mai eficient algoritm de acest tip. În practică însă, pentru probleme foarte dificile, A* implică un consum extrem de memorie și se preferă variante de algoritmi care încearcă să minimizeze consumul de memorie în defavoarea timpului de execuție. [20]

1.3 Odin – Exemplu de platformă autonomă

Ideea de a folosi sisteme GIS împreună cu sistemele ADAS în scopul obținerii unor soluții fiabile pentru planificarea rutei autovehiculelor autonome există de câteva zeci de ani. Primul care a adus problema în atenția celorlalți a fost Zimmerman (1985). În literatură, implementările GIS au servit drept reper de informații geografice pentru navigația AV-urilor și o interfață pentru a suporta operațiile vehiculelor autonome. Bazele de date GIS au fost încorporate în implementări dinamice pentru AV-uri și roboți.

În cadrul DARPA Urban Challenge, un Ford Escape Hybrid a fost modificat pentru a opera autonom. Acest experiment, numit Odin, nu a necesitat respectarea unor comportamente anume în trafic. Vehiculul a fost echipat cu un agregat de senzori ce lucrează împreună pentru a permite condusul autonom. [14]

Pentru poziționare, a folosit un sistem Novatel Propak LB+, ce oferă un sistem de navigare filtrat inerțial și o soluție GPS. În cel mai bun caz, acuratețea localizării este de sub 10 cm. De asemenea, folosește câțiva senzori LIDAR și câțiva telemetri cu 3 / 4 plane, având rolul de a detecta mișcarea și evita obstacolele. Un sistem complex de planificare a mișcării ajută în ocolirea obstacolelelor de pe traseu. [17] Fig. 1.16 Sistemul Novatel Propak LB+

Problema fundamentală a fost urmarea unui traseu (aparținând unei rețele rutiere determinate), având puncte bine definite, în timp ce se evitau obstacolele și respectau legile din trafic. În general, primul pas al operațiilor autonome a fost determinarea unei rute globale prin rețeaua de drumuri (una care vizita cel mai eficient punctele specificate). Odată ce aceasta era determinată, o reprezentare bidimensională a suprafeței drumului a fost convertită în limite pentru o suprafață mică de cost. Obstacolele detectate folosind senzori de la bordul mașinii au fost adăugați la suprafața de cost și un algoritm de planificare a mișcării a fost rulat pentru a calculat comenzile necesitate de vehicul pentru a atinge zonele țintă. După deplasare, procesul a fost reluat până când toate punctele de interes au fost vizitate. [14]

Fig. 1.17 Proiectul Odin

Pentru a realiza experimentul și urma planul traseului în mod corect, datele de ieșire ale algoritmilor de rutare au fost convertite în RNDF (Route Network Definition File) și MDF (Mission Definition File). RNDF specifica un drum virtual cu o singură bandă, având o lărgime echivalentă cu cea a două benzi normale. Acest drum virtual reprezenta traseul de la poziția curentă a vehiculului către destinație. MDF specifica ultimul punct introdus în RNDF drept punct țintă (definea destinația). Conceptual, algoritmul de calculare al traseului definea un coridor de lățime fixă prin care vehiculul putea opera. În acel coridor, tehnicile de ocolire ale obstacolelor integrate în vehicul îl puteau ghida cu succes către destinație.

Implementarea a avut diverse beneficii. În primul rând, era simplă și nu necesita modificarea extensivă a sistemelor vehiculului. Algoritmul de calcul al traseului a putut fi testat independent de restul software-ului utilizat de vehicul. Problemele au constat în faptul că rutinele de evitare ale obstacolelor au fost ajustate pentru o navigare de-a lungul unei șosele, nu condiții off-road. De exemplu, ramurile copacilor, iarba înaltă, gropile erau detectate drept obstacole de către Odin. [15]

Fig. 1.18 Exemplu de generare al suprafeței de cost

Au existat trei componente ale modelului suprafeței de cost utilizate în acest experiment. Una dintre ele era un strat cu cost de bază, derivat din clasele ce calculau pantele. Această componentă a fost derivată folosind datele de elevație extrase cu un senzor LIDAR aerian, special pentru experiment. A doua componentă a fost un strat “drum probabil”, utilizat pentru a reduce costul indus de pante. Aceasta a fost derivată folosind fotografii luate din aer. În modelul final, prezența unui drum a redus costul de bază cu un factor bazat pe densitatea de “drumuri probabile” din acea zonă. Obstacolele au fost identificate și li s-a atribuit o barieră de cost, adăugată costului de bază combinat. Niciuna dintre aceste metode nu este riguroasă, dar arată că utilizarea unei soluții GIS pentru realizarea navigării vehiculelor autonome este posibilă, experimentul atingându-și obiectivele principale. [13,17]

1.4 Cum funcționează autovehiculele autonome

Un nou proiect al companiei suedeze Volvo poartă numele Drive Me și presupune 100 de mașini autonome care vor fi conduse de oameni obișnuiți pe mai multe drumuri din Goetheborg, orașul natal al companiei Volvo. În calitate de prototip va fi noul Volvo XC90, echipa cu un sistem de conducere autonomă pregătit să apară în curând chiar și în producția de serie. Soluția lor autonomă folosește un scanner cu laser LIDAR, patru radare, o cameră trifocală, două radare ativate la distanțe mai mari și 12 senzori ultrasonici. Totodată, sistemul are conexiune 4G la internet, GPS, o hartă digitală 3D și o cameră montată în parbriz, care citește semnele de circulație și vede viitoarele curbe. Câteva sisteme cheie ale acestei implementări:

Sisteme pentru evitarea coliziunilor

Detecție în punctul mort al șoferului

Recunoașterea semnelor de circulație

Avertizare de părăsire / depășire a benzii de circulație

Sisteme de frânare inteligente

Sistem de detecție a pietonilor [21]

Fig. 1.19 Implementarea Volvo pentru autovehiculul autonom

Adaptive Cruise Control

Este un sistem opțional de control al croazierei pentru autovehicule, ce ajustează automat viteza, pentru a păstra o distanță suficientă până la vehiculul din față. Conducătorul auto setează viteza maximă, ca în modul normal de croazieră, apoi un senzor radar urmărește traficul și sistemele mașinii se asigură că se află la 3-4 secunde de cea din față. ACC este ideal pentru transportul realizat la orele de vârf, iar costurile acestui sistem se învârt între 500-2500$.

Fig. 1.20 Adaptive Cruise Control

Parcare inteligentă

Un ansamblu de sisteme (format din radar, o multitudine de senzori, camere) facilitează fie parcarea asistată (de toate tipurile), fie parcarea automată a vehiculului.

Șoferul activează funcția, iar senzori ultrasonici măsoară și identifică un loc de parcare, pe care acesta îl poate accepta sau nu.

Notificări audio-vizuale îl ghidează pe șofer, dacă acesta realizează manual parcarea. De asemenea, procedura poate fi realizată automat, de către vehicul. [16]

Fig. 1.21 Sistemul de parcare inteligentă

Radarele, camerele, senzorii ultrasonici, laserul LIDAR, oferă privirea de 360 grade asupra mediului înconjurător. O rețea de computere procesează cantitatea enormă de informație. Dacă un sistem cedează, există o soluție de back-up, exact ca în cazul aeronavelor (aici fiind incluse computere, senzori, virarea și frâne). Autovehiculul va reacționa aproape în toate situațiile întâlnite mai rapid decât ar face-o un conducător auto, folosindu-se de multitudinea de sisteme de predicție încorporate. [21] Fig. 1.22 Imagine captată de camera frontală

Fig. 1.23 Senzor ultrasonic Fig. 1.24 Cameră video frontală

1.5 Prezentarea soluțiilor software integrate în aplicație

1.5.1 HTML / CSS

Unul dintre elementele fundamentale ale WWW (World Wide Web) este HTML (Hypertext Markup Language), care descrie formatul în care documentele sunt distribuite și văzute pe Web. Multe din trăsăturile lui, cum ar fi independența față de platformă, structurarea formatării și legăturile hipertext, fac din el un foarte bun format pentru documente Web și Internet.

Primele specificații de bază ale Web-ului au fost HTML, HTTP și URL. HTML a fost dezvoltat inițial de Tim Berners-Lee la CERN (1989) și a fost văzut ca o posibilitate pentru fizicienii care utilizează computere diferite și schimbă între ei informație utilizând internetul.

Hipertext înseamnă că orice cuvânt, frază, imagine sau alt element al documentului văzut de un utilizator (client) poate face referință la un alt document, ceea ce ușurează mult navigarea între multiple documente sau chiar în interiorul aceluiași document. Structurarea riguroasă a documentelor permite convertirea acestora dintr-un format în altul, precum și interogarea unor baze de date formate din aceste documente.

Standardul oficial HTML este World Wide Web Consortium (W3C), care este afiliat la Internet Engineering Task Force (IETF). W3C a anunțat câteva versiuni ale specificației HTML, cel mai recent fiind HTML5 (2014).

Documentele HTML sunt documente în format ASCII și prin urmare pot fi create cu orice editor de texte. Au fost de asemenea dezvoltate convertoare care permit formatarea HTML a documentelor generate (și formatate), cu alte editoare. Evident, conversiile nu pot păstra decât parțial formatările anterioare, deoarece limbajul HTML este încă incomplet.

<!DOCTYPE html>

<html>

<head>

<title>Titlul paginii</title>

</head>

<body>

<h1>Primul meu header</h1>

<p>Primul meu paragraf</p>

</body>

</html> Fig. 1.25 Exemplu de pagină HTML

– Declarația DOCTYPE definește tipul documentului drept HTML

– Textul dintre <html> și </html> descrie un document HTML

– Textul dintre <head> și </head> oferă informații despre document

– Textul dintre <title> și </title> dă titlul documentului

– Textul dintre <body> și </body> descrie conținutul paginii

– Textul dintre <h1> / <p> și </h1> / </p> descrie un header / paragraph [23]

CSS este acronimul pentru Cascading Style Sheets și este un limbaj care definește „layout-ul” pentru documentele HTML. CSS acoperă culori, fonturi, margini, înălțimea, lățimea, poziții avansate, imagini de fundal etc.

HTML este adesea folosit necorespunzător pentru a crea layout-ul site-urilor, întrucât CSS oferă mai multe opțiuni și este mai sofisticat. În plus, toate browserele actuale îl suportă. Deci, care este diferența dintre HTML și CSS? HTML este folosit pentru a structura conținutul, în timp ce CSS formatează conținutul.

În perioada de început a web-ului, HTML era folosit numai pentru structura textului. Textul se putea marca cu taguri precum <h1> și <p>, pentru a marca titlul sau un paragraf. Odată cu creșterea popularității web-ului, designerii au început să caute diferite posibilități de a adăuga layout documentelor online, CSS fiind inventat pentru a le furniza acestora numeroase posibilități.

body

{ background-color: #d0e4fe; }

h1

{ color: orange;

text-align: center; }

p

{ font-family: "Times New Roman";

font-size: 20px; }

În codul de mai sus vom seta culoarea fundalului, vom alinia central și colora portocaliu toate header-ele, iar în cele din urmă, vom folosi fontul Times New Roman, de mărime 20px în toate paragrafele. [22]

1.5.2 JavaScript

Acesta este un limbaj de programare care posibil ca paginile web să fie interactive. Este des recunoscut ca făcând parte din categoria limbajelor de scripting. Scripturi JavaScript sunt introduse în pagina HTML și sunt interpretate/executate de browser. Poate fi considerat o unealtă foarte bună dacă doriți să controlați conținutul paginilor în funcție de data, oră, sistemul de operare sau browserul utilizatorilor, să faceți siteuri interactive, care să comunice cu diverșii vizitatori, să validați datele primite prin formulare și multe altele, acestea fiind doar câteva posibilități din ce oferă acest limbaj.

JavaScript poate fi introdus în interiorul paginilor HTML. Pentru a putea fi interpretat în mod corect de către browser, trebuie să marcăm codul astfel:

<script type="text/javascript">

Cod JavaScript

</script>

O altă modalitate de a folosi scripturile javascript este utilizarea scripturilor externe și includerea acestora în eticheta <head> sau <body> a fișierului HTML. JavaScript permite modificarea conținutului HTML, al atributelor, stilului CSS, validarea datelor. [24]

1.5.3 PHP (Hypertext Preprocessor)

PHP (acronim recursiv pentru PHP: Hypertext Preprocessor) este un limbaj de scripting de uz general, cu cod-sursă deschis (open source), utilizat pe scară largă, și care este potrivit în special pentru dezvoltarea aplicațiilor web și poate fi integrat în HTML. Pe scurt, ce este acesta? Ca idee generală, PHP reprezintă un limbaj de programare ce permite modificarea paginilor web înainte ca acestea să fie transmise de server către browserele utilizatorilor.

În locul unei mulțimi de comenzi pentru a afișa HTML, paginile PHP conțin HTML cu cod sursă încorporat. Ceea ce face PHP să difere de un JavaScript de partea clientului este că codul său este executat pe server, generând HTML care este apoi trimis către client. Clientul va primi rezultatele rulării acelui script, fără a putea cunoaște codul-sursă ce stă la bază. Dumneavoastră chiar puteți să configurați web server-ul să proceseze toate fișierele HTML cu PHP, și atunci într-adevăr nu va fi nici o modalitate ca utilizatorii să vă vadă fișierele sursă.

Cel mai bun lucru la PHP este simplitatea extremă pentru un începător, dar totodată existența multor facilități avansate pentru un programator profesionist. Chiar dacă dezvoltarea PHP este axată pe scripting din partea server-ului (backend), se pot realiza mult mai multe cu el.

Modul în care PHP generează conținut pentru o pagină ce va fi afișată de browser este prin instrucțiunile de procesare de început și de sfârșit: “ <?php” și „?>”, care vă permit să intrați și să ieșiți din "modul PHP". Orice se află între aceste tag-uri va fi considerat cod-sursă și va fi executat de interpretorul PHP și înlocuit cu rezultatul execuției. Ceea ce este în afara tag-urilor rămâne neschimbat și este transmis către browser. Spre exemplu, avem o pagină ca cea din stânga jos, rezultatul codului HTML final, transmis de server în urma procesării PHP este în dreapta:

<html> <html>

<body> <body>

Azi este <?php print date( 'd.m.Y' ); ?> Azi este 18.03.2016

</body> <body>

</html> </html>

În sens mai larg, PHP este un limbaj de programare universal, însă s-a impus în zona web, ca limbaj server-side, ce extinde funcționalitatea serverelor web. Din acest motiv, programarea în PHP este denumită și programare web.

1.5.4 RDBMS – Relational Database Management System

Oracle constă într-un set complet de constructori de aplicații și produse pentru utilizatori, căutând să asigure soluții complete în tehnologia informației. Aplicațiile Oracle sunt portabile pe un număr mare de stații de lucru și sisteme de operare, de la PC-uri la workstation-uri.

Oracle este înzestrat cu un Sistem Relațional de Management al Bazelor de Date (RDBMS) – Server Oracle – folosit pentru stocarea și managementul informației utilizate de aplicații.Ultimul Oracle, versiunea 12c, conduce o bază de date cu toate avantajele unei structuri relaționale, având în plus capacitatea de a stoca și executa obiecte de tip bază de date precum proceduri și mecanisme de siguranță.

RDBMS-ul controlează:

Stocarea de date în sfera bazelor de date dedicate

Recuperarea de date pentru aplicații utilizând tehnici de optimizare adecvate

Securitatea bazelor de date și a taskurilor permise pentru anumiți utilizatori

Consistența și protecția datelor, incluzând arhivarea taskurilor și mecanisme de căutare

Comunicarea și integritatea informațiilor, când bazele de date sunt distribuite într-o rețea

Aplicațiile Oracle trebuie rulate pe un computer pe care avem și serverul Oracle. Alternativ, aplicațiile și utilitarele utilizate de ele pot să fie rulate pe un sistem local pentru utilizator (clientul), în timp ce Oracle DBMS rulează pe server. În acest mediu client-server, un număr mare de resurse de calcul pot fi rulate. De exemplu, o aplicație de tip ‘Oracle Forms’ poate rula pe un computer personal client, în timp ce accesarea datelor este condusă conventional de un Server Oracle pe un computer central.

SQL este limbajul utilizat pentru a accesa o bază de date relațională, inclusiv Oracle. Poate fi utilizat de fiecare instrument Oracle, când accesul la baza de date este necesar.

PL/SQL este limbajul procedural Oracle pentru scrierea aplicațiilor și pentru manipularea datelor în afara bazei de date. Poate include un subset al comenzilor SQL, când accesul la baza de date este cerut.

Baza de date relațională este percepută de utilizatorii săi ca o colecție de tabele bidimensionale ușor de înteles. Sunt doar pentru concepte: tabele, coloane, rânduri, câmpuri.

Modelul relațional imită procesele unei ramuri a algebrei cunoscută sub numele de “Algebră relațională”. Aceste procese implică o colecție de obiecte cunoscute sub numele de relații și o mulțime de operatori ce acționează asupra relațiilor pentru a produce noi relații.

Proprietăți ale bazelor de date relaționale:

O bază de date relațională apare ca o colecție de relații către utilizator.

Formatul coloanei/rândului este familiar și usor de vizualizat .

Există o mulțime de operatori pentru partiționarea și combinarea relațiilor (selecția, proiecția, produsul, join, uniunea, intersecția, diferența).

Nu sunt pointeri expliciți; conexiunile sunt făcute numai pe baza datelor.

Limbajul utilizat pentru interogarea bazei de date este non-procedural și similar limbii engleze.

Utilizatorul nu specifică o cale de acces și nu are nevoie să stie aranjarea fizică a informației.

Comenzile pentru refacerea datelor și acelea pentru realizarea schimbărilor în baza de date sunt incluse într-un singur limbaj SQL.

Există o independență totală a datelor.

Proprietațile relațiilor tabelare:

Nu există rânduri duplicate

Nu există nume de coloană duplicate

Ordinea rândurilor este neimportantă

Ordinea coloanelor este neimportantă

Valorile sunt atomice(nedecompozabile) [25]

1.5.5 Laravel Framework

Acesta este un framework PHP open-source, creat de către Taylor Otwell pentru dezvoltarea aplicațiilor web folosind stilul arhitectural model-view-controller (MVC). Unele dintre avantajele acestuia sunt sistemul de împachetare modular, având un manager de dependințe dedicat (Composer), diverse modalități de accesare a bazelor de date relaționale, utilități ce ajută la mentenanța și instalarea aplicațiilor.

Din Martie 2015, Laravel este considerat cel mai popular framework PHP, împreună cu Symfony și CodeIgniter. Codul sursă Laravel este hostat pe GitHub, pentru a putea fi utilizat de utilizatorul de rând, dar și cel specializat.

are Facades (clase ale căror metode pot fi apelate ca și metode statice)

are ORM (mapare obiect-relațională) – se poate obține o bază de date virtuală

are concepte de design solide

CAPITOLUL 2. Realizarea aplicației Connect4

2.1 Prezentarea framework-ului și a noțiunilor de bază

Familiarizarea cu modul de lucru folosit într-un framework poate fi o provocare, dar recompensa este pe măsură. Laravel este un astfel de framework, cu o sintaxă elegantă, expresivă. Realizarea task-urilor recurente, precum autentificarea, rutarea cererilor, caching-ul, redirectarea, menținerea sesiunilor sunt ușor de implementat.

Laravel este puternic, dar prietenos cu utilizatorul, oferind utilitare puternice, necesare unor aplicații robuste. Avem sisteme de migrare, containere de control, dar și suport pentru testare.

Composer este un tool de management al dependințelor în PHP. Acesta permite declararea librăriilor externe de care depinde proiectul, instalarea / actualizarea acestora făcându-se automat. Se poate folosi atât pe Windows cât și pe UNIX, ușurând cu mult pregătirea mediului de producție. Laravel se instalează folosind Composer, iar toate dependințele acestuia vor fi migrate automat de către managerul de dependințe.

Mai trebuie menționat faptul că suportul pentru toate acestea este WampServer, o suită software (de fapt un server stack) ce constă într-un web server Apache, o bază de date de tip MySQL, OpenSSL pentru suport SSL(securitate), plus kitul de dezvoltare PHP. Apache este un server HTTP de tip open source, ce a jucat un rol important în dezvoltarea webului, fiind folosit în prezent în aproximativ 63% din paginile web.

2.1.1 Sistemul de rutare

Majoritatea dezvoltatorilor PHP nu sunt familiari decât cu sistemul natural de rutare (crearea unui director – asociat unei căi pe site). De exemplu, după adăugarea fișierului index.php în directorul /app/, acesta poate fi accesat în browser pe calea localhost/app/index.php. Deși pare ușor, pentru aplicații complexe sunt necesare flexibilitate și control mai bun asupra rutării.

Laravel are o abordare foarte ușor de folosit asupra rutării. De exemplu, vom da un exemplu foarte simplu de afișare a profilului unui utilizator, încercând să urmărim doar partea funcțională a rutării:

Route::get(utilizator/{id}', function($id) {

// găsirea user-ului în baza de date

$utlizator = User::find($id);

// afișarea paginii și transmiterea obiectului utilizator către aceasta

return View::make ( 'utlilizator.profil' )

->with ( 'utilizator', $utlizator );

});

Codul de mai sus poate fi tradus în modul următor – când se va realiza un request către adresa http://localhost/utilizator/1, se va randa pagina utilizator/profil.php, folosind datele utlizatorului cu id-ul “1”. Conținutul paginii în sine nu contează, ci cum ajungem să îl afișăm. Un view reprezintă pagina în sine, sau un template de la care se va porni pentru randare. Recomandat în practică este să se facă partea de pre-procesare în controllere, despre care vom vorbi mai departe.

2.1.2 Controllere

O alternativă a variantei menționate anterior poate fi folosirea controllerelor pentru a executa logica din spate – partea de procesare brută. În fișierul de rute vom regăsi următoarea linie de cod – va apela metoda show aparținând controllerului Utilizatori atunci când se realizează o cerere către tipul de link specificat:

Route::get('utilizator/{id}', ‘ControllerUtilizatori@show');

Acum, fișierul Controllers/ControllerUtilizatori.php va fi responsabil de randarea paginii, în mod specific vorbim de metoda show (este o funcție ce poate accepta parametri). Clasa ControllerUtilizatori extinde clasa Controller (modelul de bază pentru controllere), dar nu vom intra în detalii despre programarea obiect-orientată. Metoda show trebuie să fie publică, altfel rutarea nu va fi realizată corect și vom obține erori de inițializare.

class ControllerUtilizatori extends Controller {

public function show($id){

$utilizator = User::find($id);

return View::make('utilizator.profil')

->with('utilizator', $utilizator); }

}

Controllerele pot grupa logică legată de o rută într-o clasă, și se folosi de avantajele unui framework avansat – precum injecție de dependințe automată. Sunt de obicei stocate în app\Http\Controllers, acest folder fiind înregistrat în opțiunea classmap a fișierului de configurare composer.json .

2.1.3 Mapare obiect-relațională Eloquent

Majoritatea dezvoltatorilor de PHP încep prin a introduce numeroase linii de cod SQL direct în codul PHP, ceea ce duce la îngreunarea citirii, refolosirii acestuia. ORM-ul Eloquent, cu care Laravel vine preinstalat, oferă o implementare ActiveRecord pentru a lucra cu baza de date. Fiecare tabel al bazei de date are un model corespunzător, folosit pentru interacțiuni.

// Colectarea tuturor activităților // Căutarea activității cu id-ul “1”

$activitate = Activitate::all(); $activitate = Activitate::find(1);

// Actualizarea unei activități // Crearea unei activități noi

$activitate = Activitate::find(1); Activitate::create([

$activitate ->nume = ‘Învață PHP'; 'nume' => 'Învață JAVA'

$activitate ->save(); ]);

// Ștergerea activității

Activitate::find(1)->delete();

Considerând relațiile dintre tabele, precum dintre un utilizator și activitățile sale, se pot seta metode de căutare rapide, manage-ui cu ușurință relațiile unu-la-unu.

Pentru a crea un model nou, putem crea în calea /app un fișier nou, Nume_Model.php, sau ne putem folosi de comanda make:model Numele_Modelului. Conținutul fișierului va fi în următorul format:

class Nume_Model extends Model {

//definirea tabelului cu care se va lega modelul

protected $table = ‘Nume_Tabel_Asociat';

}

Eloquent este considerată cea mai bună implementare ActiveRecord în limbajul PHP, aducând numeroase funcționalități cum ar fi implementarea relațiilor între obiecte (one to one, one to many, many to many, relații polimorfice), folosirea scope-urilor (metode ce aparțin doar modelelor în care sunt definite), folosire ușoară a timestamp-urilor, soft delete și multe altele.

2.1.4 Migrări

Migrările pot fi privite drept control al versiunii pentru baza de date. Ce s-ar întâmpla dacă după ziua în care am adăugat un câmp nou tabelei noastre de utilizatori, realizați că acesta nu era necesar. În mod normal, am înlătura câmpul. Dar cum rămâne cu ceilalți dezvoltatori ai echipei? Codul lor ar putea să afișeze erori dacă nu sunt anunțați. Folosind migrări, putem face rollback la migrarea precedentă și problema s-a rezolvat. Folosind comanda migrate, putem încărca cu ușurință actualizarea în producție.

Pentru a crea o migrare, vom executa comanda migration:make CreazăTabelă –table=NumeTabelă –create. Flag-ul create are rolul de a specifica faptul că vom crea o tabelă nouă, nu modificăm una deja existentă în producție. După execuție, vom avea un nou fișier de migrare în aplicația noastră. În continuare, ne vom folosi de clasa Schema pentru a pregăti schema tabelei noastre.

class CreeazăTabelă extends Migration {

// Rulează migrarea

public function up()

{ Schema::create('NumeTabelă', function($NumeTabelă)

{ $NumeTabelă->increments('id');

$NumeTabelă->string('NumeColoană');

});

}

// Rollback migrare – ștergere tabelă

public function down()

{ Schema::drop('NumeTabelă');

}

}

Se poate observa folosirea celor două metode, up() și down(), care specifică ce acțiune va efectua Laravel atunci când execută o migrare sau face rollback. În cazul nostru, up() creează o tabelă nouă, NumeTabelă și îi specifică două câmpuri (id și NumeColoană). Când facem rollback, pur și simplu dăm drop (ștergem) tabelei.

2.1.5 Blade

Engine-ul de template-uri Blade oferă o sintaxă curată pentru view-uri (pagini web). De exemplu, în mod normal, pentru a filtra printr-o listă de persoane în PHP și a afișa numele fiecăruia, vom scrie următorul cod:

<ul>

<?php foreach($people as $p) : ?>

<li><?php echo $p; ?></li>

<?php endforeach; ?>

</ul>

Această sintaxă poate fi aplicată majorității structurilor de control în PHP. Nu arată foarte rău, dar orice view Laravel ce are extensia blade.php va fi parsat automat, deci putem lăsa framework-ul să facă o parte din munca noastră. Drept rezultat, codul scris mai sus poate fi înlocuit cu o variantă simplificată, mai ușor de citit și reprodus:

<ul>

@foreach($people as $p)

<li>{{ $p }}</li>

@endforeach

</ul>

Observați cum variabilele sunt afișate folosind wrappere {{ }} , similar cu sintaxa din JavaScript. Blade este însă folosit pentru a forma layout-uri elegante și pagini principale. Drept exemplu, vom crea mai jos template-ul unei pagini web. De notat faptul că @yield este o cheie, specifică faptul că orice view-uri copil (care extind views/layout.blade.php și conțin id-ul container) se vor așeza în pagină în locul acestuia.Conținutul din secțiunea container se va așeza în locul chemat de cheia yield în layout-ul principal. Evident, putem folosi aceeași sintaxă pentru a importa mai multe secțiuni în layout-ul nostru.

// views/layout.blade.php // views/hello.blade.php

<!doctype html> @extends('layout')

<html> @section('container')

<head> <h1>Hello, {{ $user->name }}!</h1>

<title></title> @endsection

</head>

<body>

<div class="container">

@yield('container')

</div>

</body>

</html>

2.2 Prezentarea sistemului de înregistrare / logare / recuperare a parolei

Aproape toate aplicațiile web prezintă o formă sau alta de autentificare. Laravel oferă o interfață relativ ușor de folosit pentru realizarea acestei funcții. Se începe prin rularea comenzii make:auth, care va crea un table de utilizatori, conținând câmpuri necesare pentru username și parolă, plus template-uri pentru paginile de login / înregistrare / resetare a parolei.

În fișierul de rute avem nevoie de următoarele linii:

Route::auth();

// Rute pentru autentificare

Route::get('password/email', 'Auth\PasswordController@getEmail');

Route::post('password/email', 'Auth\PasswordController@postEmail');

// Rute pentru resetarea parolei

Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');

Route::post('password/reset', 'Auth\PasswordController@postReset');

Controllerul AuthController, ce conține metodele pentru autentificare este complex, ne vom concentra doar pe metodele esențiale.

Metoda validator are rolul de a verifica dacă datele sunt cantitativ și oarecum calitativ corecte – de exemplu dacă parola are minim 6 caractere, adresa de mail este de tip @email.com etc.

Metoda create va stoca în baza de date (virtuală) o nouă instanță a modelului utilizator (utilizator, parolă, e-mail etc.). Dacă autentificarea s-a realizat cu succes, se poate alege calea spre care va fi redirectat utilizatorul, iar id-ul utilizatorului va fi stocat în sesiune, pentru a putea naviga în voie prin aplicație.

Prin conectare la adresa http://dizertatie.app (se realizează automat redirectarea către http://dizertatie.app/login), se poate accesa pagina de login a aplicației. Aici, se poate crea un cont nou de utilizator, realiza conectarea folosind un cont deja existent, sau se poate încerca recuperarea parolei. Toate câmpurile sunt case-sensitive, vom fi atenționați dacă formatul introdus nu este corect etc. Parolele sunt criptate, Laravel punându-ne la dispoziție metoda bcrypt pentru realizarea acestei funcționalități.

Fig. 2.1 Pagina de login

Funcția care verifică efectiv dacă utilizatorul există sau nu în baza de date este stocată în controllerul de autentificare și se numește getFailedLoginMessage. Fațada Lang oferă suport pentru mai multe limbi în care poate fi setată aplicația.

protected function getFailedLoginMessage()

{ return Lang::has('auth.failed')

? Lang::get('auth.failed')

: 'These credentials do not match our records.'; }

Fig. 2.2 Pagina de recuperare a parolei

După cum reiese și din figuri, anumite câmpuri cheie sunt verificate de către metoda validator. Dacă anumite condiții nu sunt întrunite, se returnează mesajele de eroare aferente. De asemenea, dacă s-au realizat 3 încercări de autentificare succesive pentru același user și acestea au eșuat, contul va fi blocat temporar. Tipologia erorilor este stocată în fișierul errorList.blade.php, care utilizează array-ul global errors (se actualizează automat în funcție de vectorul de status al metodei validator):

@if ($errors->any())

<ul style="list-style-type:none" class="alert alert-danger">

@foreach($errors->all() as $error)

<li><b>{{ $error }}</b></li>

@endforeach

</ul>

@endif

Fig. 2.3 Pagina de înregistrare a unui cont nou

2.3 Prezentarea paginii principale

Fig. 2.4 Pagina principală a dashboard-ului

Pagina principală prezintă o secțiune Application Health Check care verifică dacă aplicația rulează în parametri normali. Tab-urile vor indica dacă există fișiere corupte, web serverul (FrontEnd sau BackEnd) are erori în loguri, modulul de autentificare funcționează corect, Socket Stream-urile sunt rutate și nu depășesc pragul de timeout etc.

Fig. 2.5 Verificarea integrității aplicației

În Fig. 2.5 am simulat cum ar arăta tab-ul dacă am avea erori pe fluxul de date, sau este posibil ca aplicația să prezinte fișiere corupte ale framework-ului. Se poate vedea destul de în detaliu unde ar putea fi problema, întrucât făcând hover cu mouse-ul pe unul dintre butoane, vom obține o listă dropdown cu mai multe componente ale acelui “sistem”.

Tab-ul Overall System Status conține un grafic care indică procentul de operabilitate al vehiculului – procentaj calculat folosind statusul tuturor syslink-urilor definite în aplicație. Făcând hover pe fiecare procentaj, vom obține numărul total de syslink-uri ce aparțin acelui status

Trebuie menționat faptul că fiecare utilizator are syslink-uri diferite, iar taburile din Fig. 2.6 sunt populate utilizând datele individului conectat la aplicație.

Fig. 2.6 Privire de ansamblu asupra operabilității sistemelor definite

Individual System Status prezintă intuitiv statusul fiecărui sistem definit. Acesta poate fi “Online” – sistemul funcționează corect, “Down” – există erori, sau “Warning” – poate exista o problemă sau a fost un timeout pe rețea când s-a executat verificarea.

În plus, făcând hover pe fiecare dintre sisteme, putem vedea ultima dată când s-a realizat verificarea, iar dacă dăm clic pe acesta, vom fi redirecționați către o pagină cu mai multe detalii despre acel syslink – nume, status, importanța, ID-ul de Metadata, un grafic ce reprezintă latența conexiunii dintre aplicație și sistemul fizic.

Fig. 2.7 Exemplu pagină de control a unui syslink

Se poate observa existența celor două butoane pe pagină:

“Edit” – permite editarea câmpurilor Nume, Metadata ID și Info. Dacă unul dintre câmpuri este gol sau nu respectă anumite reguli, vom fi notificați prin intermediul unui mesaj de eroare.

“Delete” – permite ștergerea syslink-ului cu pricina din baza de date. Atenție, datele nu sunt recuperabile.

2.3.1 Descrierea codului sursă a paginii principale

Am pornit de la construirea unui template care va fi inclus la încărcarea fiecărei pagini ale aplicației noastre. Acesta se numește layouts.blade.php și fiecare pagină de care vom vorbi de acum încolo este o extensie a template-ului. Rolul acestuia este de a defini librăriile CSS/JavaScript necesare fiecărei pagini, precum și alte fișiere de configurare, la care se adaugă inițializarea header-ului de navigare prin aplicație.

Fig. 2.8 Header-ul de navigare prin aplicație

// Definirea tab-ului “Application Health Check, realizarea unui container pentru acesta

<div class="container"><div class="row">

<div class="col-md-10 col-md-offset-1"><div class="panel panel-default">

<div class="panel-heading"><b>Application Health Check</b></div>

<div class="panel-body">

// Includerea scriptului care verifică dacă aplicația rulează în parametri optimi – realizarea sanity check-ului

@include ('systems._services')

</div></div>

<div class="panel panel-default" style="width:49%;float:left">

// Definirea tab-ului “Overall System Status”și includerea într-un container

<div class="panel-heading"><b>Overall System Status</b></div>

<div id="chart" style="width:100%; height:400px;"></div>

// Inițializarea graficului de tip pie chart, care folosește librăria externă HighCharts

<script type="text/javascript">

$(function () {

$('#chart').highcharts(

{!! json_encode($chart) !!}

); })

</script>

<div class="panel-body">

</div></div>

// Definirea tab-ului “Individual System Status” și încadrarea în container

<div class="panel panel-default" style="width:49%;float:left;margin-left: 2%">

<div class="panel-heading" ><b>Individual System Status</b></div>

@foreach ($systems as $system)

// Verificarea utilizatorului conectat în sesiune, extragerea syslink-urilor acestuia

@if (\Auth::User()->id == $system->user_id)

<h2><a style="text-decoration: none;

font-family: Lato" href="/systems/{{$system->id}}">

// Construirea listei cu statusul sistemelor

@if ($system->status=='up') // statusul este OK

<div class="green" style="margin-left: 2%"><a href="/systems/{{$system->id}}" style="color: #C4CBB7 !important;" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Last update: {{$system->updated_at->diffForHumans()}} ">{{$system->name}}</a></div>

@elseif ($system->status=='down') // statusul este KO

<div class="red" style="margin-left: 2%"><a href="/systems/{{$system->id}}" style="color: #EEE0B7 !important;" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Last update: {{$system->updated_at->diffForHumans()}}">{{$system->name}}</a></div>

@else // statusul este necunoscut

<div class="orange" style="margin-left: 2%"><a href="/systems/{{$system->id}}" style="color: #563200 !important;" target="_blank" data-toggle="tooltip" data-placement="bottom" title="Last update: {{$system->updated_at->diffForHumans()}}">{{$system->name}}</a></div>

@endif @endif

@endforeach

<div class="panel-body"></div><div><div></div></div>

2.4 Prezentarea paginii de management a syslink-urilor

Accesând hyperlink-ul System Management din bara de navigare a aplicației, vom deschide pagina systems.blade.php, care conține opțiunea de verificare a sistemelor, una de ștergere a tuturor sistemelor anexate utilizatorului conectat, lista sistemelor – împreună cu statusul curent, la care se adaugă un hyperlink ce ne va redirecționa către pagina de creare a unui syslink.

Fig. 2.9 Pagina de management a sistemelor

Ideea de la care am pornit a fost că după înregistrare, fiecărui utilizator îi va fi asociat un Metadata ID pentru vehiculul său. Fiecare ID va fi folosit pentru a face referință în sistemele externe, de exemplu într-un service auto etc., la vehiculul utilizatorului.

În Fig. 2.9 avem pagina de creare a unui nou syslink. Numele de syslink vine de la link către un sistem. Fiecare dintre cele trei câmpuri trebuie completate, având un număr minim detrei caractere, altfel vor fi afișate erori.

După salvarea unui nou syslink, vom fi redirectați către pagina de management. De asemenea, în caz că am introdus date greșite, avem opțiunea de editare, pe care o putem accesa cu ușurință pe pagina de control a syslink-ului.

Fig. 2.10 Pagina de creare a unui syslink

2.4.1 Descriere cod sursă pagină management syslink-uri

// Definirea hyperlink-ului către pagina de creare a unui nou syslink

<div class="container1">

<div class="content">

<h1><a href="/systems/create" style="text-decoration: none">Create a new syslink</a></h1>

</div></div><hr>

<div class="container"><div class="content2">

@foreach ($systems as $system)

// Verificarea utilizatorului conectat și identificare sistemelor acestuia

@if (\Auth::User()->id == $system->user_id)

<h2 class="child">

// Afișarea statusului fiecărui syslink folosind coduri de culoare

<a style="text-decoration: none;color:#777" href="/systems/{{$system->id}}">{{ $system->name }} </a>

@if ($system->status=='up')

<i style="color:green" class="fa fa-check"></i>

@elseif ($system->status=='pending')

<i style="color:orange" class="fa fa-exclamation-triangle"></i>

@else

<i style="color:red" class="fa fa-ban"></i>

@endif </h2>

@endif @endforeach

</div></div><hr>

// Crearea butoanelor pentru verificarea și ștergerea sistemelor

<div class="container1">

{!!Form::open(['method'=>'post','style'=>'float:left;margin-left:43%','action'=>['SystemsController@checkAll',\Auth::User()->id]])!!}

<button type="Check" class="btn btn-primary btn">Check</button>

{!!Form::close()!!}

{!!Form::open(['method'=>'delete','style'=>'float:left;margin-bottom:2%;margin-left:1%','action'=>['SystemsController@destroyAll',\Auth::User()->id]])!!}

<button type="submit" class="btn btn-danger">Clean up!</button>

{!!Form::close()!!}

</div><br>

Spre diferență de prima pagină, aici avem nevoie de parte de procesare, care se va realiza în controller-ul system.blade.php. Partea de rutare este definită în routes.php, iar metodele sunt definite după cum urmează, în controller:

// Căutarea syslink-urilor, după dată, descrescător

public function index(){

$systems=System::latest()->get();

return view('systems.system',compact('systems')); }

// Afișarea unui anumit syslink

public function show($id) {

$system=System::findOrFail($id);

return view ('systems.show',compact('system')); }

// Crearea unui syslink

public function create(){

return view ('systems.create'); }

// Stocarea unui syslink și asocierea cu utilizatorul conectat

public function store(\App\Http\Requests\CreateSystemRequest $request){

$system=new System($request->all());

$system->status = $this->pickAnItem();

\Auth::user()->systems()->save($system);

return redirect('systems'); }

// Editarea unui anumit syslink

public function edit($id){

$system=System::findOrFail($id);

return view('systems.edit', compact('system')); }

// Ștergerea unui syslink

public function destroy($id){

$system=System::findOrFail($id);

$system->delete();

return redirect ('systems'); }

// Ștergerea tuturor syslink-urilor asociate utilizatorului

public function destroyAll($user_id){

$system=System::where('user_id',$user_id);

$system->delete();

return redirect ('systems'); }

// Funcția de generare a statusului, probabilistic

public function pickAnItem()

{ $statuses = array(

array('up', 85),

array('down', 5),

array('pending', 10) );

$hat = array();

foreach($statuses as $item)

{ $hat = array_merge($hat, array_fill(0, $item[1], $item[0])); }

return $hat[array_rand($hat)]; }

// Verificarea syslink-urilor asociate utilizatorului

public function checkAll($user_id){

$system=System::where('user_id',$user_id);

$system->each(function ($item){

$item->update(['status'=> $this->pickAnItem() ]); });

return redirect ('/'); }

// Actualizarea unui syslink

public function update($id, \App\Http\Requests\CreateSystemRequest $request){

$system=System::findOrFail($id);

$system->update($request->all());

return redirect ('systems'); }

2.4.2 Descriere cod sursă pagini creare / editare syslink-uri

Pagina de creare

<div class="container1">

<div class="content">

<h1>Insert fault data</h1><hr>

// Butonul de salvare a informațiilor

{!! Form::open(['url' => 'faults']) !!}

@include('faults._form', ['submitButtonText' => 'Add'])

{!! Form::close() !!}

// Afișarea erorilor – dacă există

@include ('errors.list')

</div>

</div>

Pagina de editare

<div class="container1">

<div class="content">

<h1>Update the {{$system->name }} syslink</h1><hr>

// Butonul de salvare a informațiilor introduse în formular

{!! Form::model($system,['method' => 'PATCH','url'=>'systems/'. $system->id]) !!}

@include('systems._form', ['submitButtonText' => 'Edit'])

{!! Form::close() !!}

// Afișarea erorilor – dacă există

@include ('errors.list')

</div>

</div>

// Rutele associate controller-ului SystemsController – definite în routes.php

Route::resource('systems','SystemsController');

Route::delete('systems/{user_id}/deleteall', 'SystemsController@destroyAll');

Route::post('systems/{user_id}/checkall', 'SystemsController@checkAll');

2.5 Prezentarea paginii de inserare a informațiilor despre un defect

Pentru a stoca ușor și intuitiv datele despre defecte în baza de date, dar și pentru a avea acces facil la acestea, am optat pentru folosirea unei interfețe asemnătoare cu cea de creare a syslink-urilor (de fapt, codul sursă este doar puțin ajustat, pentru a se folosi de alte tabele, modele). Accesul se face prin hyperlink-ul din baza de navigare, rubrica “Fault Management”, care va deschide pagina search.blade.php.

Fig. 2.11 Pagina de inserare a informațiilor despre defecte

Întrucât codul sursă folosește în linii mari aceleași metode aflate la baza creării paginii de management a syslink-urilor (dar redenumite), acestea nu vor fi prezentate din nou, fiind atașate în anexă. Fiecare dintre defecte poate fi editat ulterior creării și stocării acestuia în baza de date, datorită

2.6 Prezentarea paginii de căutare a impactelor asociate unui defect

Spre diferență de prima pagină, aici este nevoie de o parte de procesare, care se va realiza în controller-ul IntranetController. Partea de rutare este definită în fișierul routes.php:

Route::get('internal/autocomplete','IntranetController@autocomplete');

Route::get('internal','IntranetController@index');

Route::post('internal','IntranetController@returnResult');

Fig. 2.12 Pagina de căutare a impactelor asociate unui defect

Această pagină facilitează căutarea impactelor determinate de apariția unui defect. De exemplu, dacă un modul apare în status de eroare ,se poate alege din lista de tip dropdown (sau se poate căuta direct în formular) numele acestuia, obținându-se totalitatea impactelor asociate pe baza de date. De reținut este faptul că este posibil să determinăm impactele mai multor defecte cu o singură căutare, întrucât formularul de căutare acceptă input de tip multiplu.

Modelul folosit pentru defecte este definit în fișierul Fault.php:

class Fault extends Model

{ //Tabela asociată modelului pe baza de date – faults

//Câmpurile acesteia sunt id, fault_name, info, created_at, updated_at

protected $table = 'faults';

protected $fillable = [ 'fault_name','info', ];

//Un defect poate avea mai multe impacte

public function impacts(){

return $this->hasMany('App\Impact','fault_impact','fault_id','impact_id');

} }

Modelul folosit pentru impacte este definit în fișierul Impact.php:

class Impact extends Model

{ //Tabela asociată modelului pe baza de date – impacts

//Câmpurile acesteia sunt id, fault_name, info, created_at, updated_at

protected $table = 'impacts';

protected $fillable = [ 'impact_name','info', ];

//Un impact poate fi asociat mai multor defecte

public function faults(){

return $this->hasMany('App\Fault','fault_impact','fault_id','impact_id');

} }

2.6.1 Descriere cod sursă pagină de căutare impacte asociate unui defect

class IntranetController extends Controller

// Căutare pe baza de date pentru a realiza autocomplete-ul form-ului de pe pagină

{ public function autocomplete(){

$term = Input::get('term');

$results = array();

// Interogare bază de date

$queries = DB::table('faults')

->where('fault_name', 'LIKE', '%'.$term.'%')

->orWhere('info', 'LIKE', '%'.$term.'%')

->take(5)->get();

foreach ($queries as $query)

{ $results[] = ['id' => $query->id, 'text' => $query->fault_name ]; }

return Response::json($results); }

// Afișarea paginii de căutare pe baza de date

public function index(){

return view('intranet.search'); }

// Încărcarea conținutului JavaScript asociat rezultatelor obținute

public function returnResult(){

return view('intranet.search'); } }

Informațiile cerute sunt afișate folosind următorul modul, aparținând paginii HTML, care va fi chemat după ce se face un request de tip POST ( adică s-a interogat baza de date, folosind formularul de căutare ):

// Dacă s-a realizat o cerere de tip post, execută codul php și validează

@if (Request::isMethod('post') && !empty(Request::input('faults')) )

// Preia informațiile trimise de formular

<?php $inputs=Request::input('faults');

foreach ($inputs as $input){

// Caută pe baza de date informațiile despre defecte

$found = App\Fault::findOrFail($input);

$impact=$found->info;

// Afișează impactele asociate

echo '<h1 style="color:red">'.$impact.' <i style="color:orange" class="fa fa-exclamation-triangle"></i></h1>'; } ?>

// Dacă nu s-a selectat nimic, se afișează un mesaj de notificare

@elseif (Request::isMethod('post'))

<div><b>Please make a selection</b></div>

@endif

2.7 Prezentarea sistemului de căutare online

Folosind Google Custom Search Engine, în aplicație a fost integrată un engine de căutare personalizat. Se pot pune restricții asupra căutărilor, alege cuvinte cheie, site-urile pe care se vor realiza acestea. Alegând tab-ul Online Search, vom accesa pagina din Fig. 2.12.

Fig. 2.13 Sistemul de căutare online

Integrarea engine-ului se face folosind o următoarea funcție JavaScript:

(function() {

var cx = '003124292959714507557:sy28xeh1vsa';

var gcse = document.createElement('script');

gcse.type = 'text/javascript';

gcse.async = true;

gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +

'//cse.google.com/cse.js?cx=' + cx;

var s = document.getElementsByTagName('script')[0];

s.parentNode.insertBefore(gcse, s);

})();

2.8 Prezentarea sistemului RDBMS

Pentru realizarea aplicației, având în vedere că volumul de date este scăzut, s-a optat pentru crearea unei baze de date folosind SQLite, acesta fiind un utilitar RDBMS care utilizează fișiere pentru stocarea informațiilor. Avantajul este timpul de acces scăzut, dar și faptul că nu a trebuit ridicat/configurat un server ORACLE/MySQL. Bineînțeles, framework-ul Laravel face posibilă migrarea foarte ușoară (atunci când volumul de date crește) pe o altă soluție RDBMS, acesta fiind unul dintre multiplele sale avantaje.

Modelele create (Fault, Impact, System, User) sunt asociate unor tabele stocate pe această bază de date, facilitând popularea ușoară a datelor. Tabelele folosite de aplicație sunt:

Users – Folosită pentru a stoca datele despre utilizatorii aplicației, index pe coloana „id”(pentru a crește viteza de căutare)

Schema::create('users', function (Blueprint $table) {

$table->increments('id'); $table->string('user_id');

$table->string('email')->unique(); $table->string('password');

$table->rememberToken(); $table->timestamps();

});

Systems – Conține informațiile despre sisteme, index pe coloana “id”

Schema::create('systems', function (Blueprint $table) {

$table->increments('id');$table->integer('user_id')->unsigned();

$table->string('name'); $table->string('info');

$table->string('metadata'); $table->timestamps();

$table->foreign('user_id')->references('id')

->on('users')->onDelete('cascade');

});

Faults – Reține informațiile despre defecte

Schema::create('faults', function (Blueprint $table) {

$table->increments('id');

$table->string('fault_name')->unsigned();

$table->string('info'); $table->timestamps();

});

Impacts – Conține informațiile despre impactele asociate diverselor defecte

Schema::create('impacts', function (Blueprint $table) {

$table->increments('id');

$table->string('impact_name')->unsigned();

$table->string('info'); $table->timestamps();

});

Codul php de mai sus se traduce în SQL astfel:

CREATE TABLE "migrations" ("migration" varchar not null, "batch" integer not null);

CREATE TABLE "users" ("id" integer not null primary key autoincrement, "user_id" varchar not null, "email" varchar not null, "password" varchar not null, "remember_token" varchar null, created_at" datetime null, "updated_at" datetime null);

CREATE UNIQUE INDEX "users_email_unique" on "users" ("email");

CREATE TABLE "password_resets" ("email" varchar not null, "token" varchar not null, "created_at" datetime not null);

CREATE INDEX "password_resets_email_index" on "password_resets" ("email");

CREATE INDEX "password_resets_token_index" on "password_resets" ("token");

CREATE TABLE "systems" ("id" integer not null primary key autoincrement, "user_id" integer not null, "name" varchar not null, "info" varchar not null, "metadata" varchar not null, "created_at" datetime null, "updated_at" datetime null, "status" text null, foreign key("user_id") references "users"("id") on delete cascade);

CREATE TABLE "faults" ("id" integer not null primary key autoincrement, "fault_name" varchar not null, "info" varchar not null, "created_at" datetime null, "updated_at" datetime null);

CREATE TABLE "impacts" ("id" integer not null primary key autoincrement, "impact_name" varchar not null, "info" varchar not null, "created_at" datetime null, "updated_at" datetime null);

CREATE TABLE "fault_impact" ("fault_id" integer not null, "impact_id" integer not null, foreign key("fault_id") references "faults"("id") on delete cascade, foreign key("impact_id") references impacts"("id") on delete cascade, primary key("fault_id", "impact_id"));

CREATE INDEX "fault_impact_fault_id_index" on "fault_impact" ("fault_id");

CREATE INDEX "fault_impact_impact_id_index" on "fault_impact" ("impact_id");

2.9 Modalități de îmbunătățire a aplicației

Creșterea capacității de stocare – folosirea unui server RDBMS MySQL sau Oracle

Îmbunătățirea sistemului de căutare online – folosrea unui engine complex

Autentificare folosind token RSA / LDAP – oferit de către service

Îmbunătățirea CSS-ului, introducerea unor tranziții etc.

Reducerea codului HTML, astfel sporind performanțele aplicației – reducerea timpul de încărcare a paginilor

Îmbunătățirea query-urilor pe baza de date, prin adăugare de indexi

Introducerea unei soluții de importare a defectelor, cu impactele asociate – pentru căutarea pe baza de date a acestora

Analiză suplimentară realizată de aplicație – pentru a detecta de ce au apărut anumite probleme

Crearea unui utilizator de tip admin și a unei interfețe de administrare facilă

Concluzii

Prezenta lucrare de dizertație tratează o prezentare a autovehiculelor autonome, cu realizarea unei aplicații care ar putea efectua testarea acestora. S-a structurat două capitole principale, ce evidențiază și delimitează într-un mod precis părțile teoretică, respectiv practică.

În capitolul teoretic s-a realizat o introducere în lumea soluțiilor inteligente, prezentând pe scurt caracteristicile generale ale acestora și tipurile utilizate cel mai des în practică. S-a argumentat necesitatea convergenței dintre sisteme. A urmat prezentarea diverselor tehnologii aflate în curs de dezvoltare (senzori LIDAR, DGPS, RTK, sisteme GIS). Discuția despre planificarea rutelor a fost una mai rigutoasă, intrând în detalii și insistând pe caracteristicile/proprietățile definitorii ale algoritmilor utilizați. Un subcapitol scurt prezintă platforma autonomă ODIN, iar un altul arată modul de funcționare al autovehiculelor autonome. Capitolul din urmă descrie blocurile componente ale sistemelor folosite de către compania Volvo, modul de funcționare și nu în cele din urmă, capturi de imagine. Întrucât tema acestei lucrări este realizarea unei aplicații web, s-au prezentat câteva elemente software. Specific vorbind, s-a discutat despre HTML/CSS, JavaScript, PHP, sisteme de baze de date.

Contribuția proprie la această lucrare constă în studiul, respectiv sistematizarea unui amplu material bibliografic referitor la funcționarea sistemelor inteligente care, agregate, realizează funcția autonomă a autovehiculelor, precum și în realizarea unei aplicații software web ce poate fi cu ușurință îmbunătățită și modificată după dorința proprietarului, diverse modalități de a realiza acest lucru fiind prezentate în subcapitolul 2.9.

Dezavantajul, oarecum ironic, al vehiculelor autonome este dat de faptul că industria auto, cea a asigurărilor, vor avea de suferit după momentul introducerii pe piață. De asemenea, professile de șofer, taximetrist, vor dispărea. Totul depinde de nivelul de automatizare care va fi atins. Tehnologia AV(autonomous vehicles) de nivel 4 va spori mobilitatea celor care nu pot/doresc să conducă, oferind astfel independență și reducerea izolării sociale, acces la servicii esențiale. Tehnologia de nivel 3 sau mai ridicat va reduce “costul” produs de ambuteiajele din trafic, întrucât conducătorii auto vor putea întreține alte activități în acest timp, dar vor realiza și o eficientizare a consumului de carburant (4-10%), la care se adaugă folosirea combustibililor alternativi.

Autovehiculele autonome reprezintă una dintre ramurile aflate în continuă dezvoltare ale tehnologiei din ziua de astăzi, industria auto concentrându-se pe dezvoltarea soluțiilor ce ar putea spori siguranța la volan precum și confortul pasagerilor. Pe parcursul trecerii timpului, încrederea publicului larg în acest nou mod de transport va crește, iar introducerea în masă va deveni posibilă.

Anexă

Codul sursă folosit la realizarea aplicației

Layout-uri / View-uri

Layout principal

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8">

<meta http-equiv="X-UA-Compatible" content="IE=edge">

<meta name="viewport" content="width=device-width, initial-scale=1">

<title>Connect4</title>

<!– Fonts –>

<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.5.0/css/font-awesome.min.css" rel='stylesheet' type='text/css'>

<link href="https://fonts.googleapis.com/css?family=Lato:100,300,400,700" rel='stylesheet' type='text/css'>

<!– JavaScript –>

<script type="text/javascript" src="{{URL::asset('assets/js/jquery-1.12.2.min.js')}}"></script>

<script type="text/javascript" src="{{URL::asset('assets/js/bootstrap.min.js')}}"></script>

{{– <script src="{{ elixir('js/app.js') }}"></script> –}}

<!– Styles –>

<link rel="stylesheet" href="{{URL::asset('assets/css/bootstrap.min.css')}}">

<link rel="stylesheet" href="{{URL::asset('assets/css/bootstrap-theme.min.css')}}">

<link rel="stylesheet" href="{{URL::asset('assets/css/lists.css')}}">

@yield('stylesheet')

{{– <link href="{{ elixir('css/app.css') }}" rel="stylesheet"> –}}

<style>

body {

font-family: 'Lato';

}

.fa-btn {

margin-right: 6px;

}

@yield('style')

</style>

</head>

<body id="app-layout">

<nav class="navbar navbar-default navbar-static-top">

<div class="container">

<div class="navbar-header">

<!– Collapsed Hamburger –>

<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#app-navbar-collapse">

<span class="sr-only">Toggle Navigation</span>

<span class="icon-bar"></span>

<span class="icon-bar"></span>

<span class="icon-bar"></span>

</button>

<!– Branding Image –>

<a class="navbar-brand" href="{{ url('/') }}">

Connect4

</a>

</div>

<div class="collapse navbar-collapse" id="app-navbar-collapse">

<!– Left Side Of Navbar –>

@if (!Auth::guest())

<ul class="nav navbar-nav">

<li><a href="{{ url('/systems') }}">System Management</a></li>

<li><a href="{{ url('/internal') }}">Get Impacts</a></li>

<li><a href="{{ url('/faults') }}">Fault Management</a></li>

<li><a href="{{ url('/search') }}">Online Search</a></li>

</ul>

@endif

<!– Right Side Of Navbar –>

<ul class="nav navbar-nav navbar-right">

@if (!Auth::guest())

<a class="navbar-brand" href="{{ url('/') }}">

Logged in as: <b>{{\Auth::User()->user_id}}</b>

</a>

@endif

<!– Authentication Links –>

@if (Auth::guest())

<li><a href="{{ url('/login') }}">Login</a></li>

<li><a href="{{ url('/register') }}">Register</a></li>

@else

<li class="dropdown">

<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">

{{ Auth::user()->name }} <span class="caret"></span></a>

<ul class="dropdown-menu" role="menu">

<li><a href="{{ url('/logout') }}"><i class="fa fa-btn fa-sign-out"></i>Logout</a></li>

</ul>

</li>

@endif

</ul>

</div>

</div>

</nav>

@yield('content')

</body>

</html>

View pagină de înregistrare

@extends('layouts.app')

@section('content')

<div class="container">

<div class="row">

<div class="col-md-8 col-md-offset-2">

<div class="panel panel-default">

<div class="panel-heading">Register</div>

<div class="panel-body">

<form class="form-horizontal" role="form" method="POST" action="{{ url('/register') }}">

{!! csrf_field() !!}

<div class="form-group{{ $errors->has('user_id') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">Name</label>

<div class="col-md-6">

<input type="text" class="form-control" name="user_id" value="{{ old('user_id') }}">

@if ($errors->has('name'))

<span class="help-block">

<strong>{{ $errors->first('name') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">E-Mail Address</label>

<div class="col-md-6">

<input type="email" class="form-control" name="email" value="{{ old('email') }}">

@if ($errors->has('email'))

<span class="help-block">

<strong>{{ $errors->first('email') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">Password</label>

<div class="col-md-6">

<input type="password" class="form-control" name="password">

@if ($errors->has('password'))

<span class="help-block">

<strong>{{ $errors->first('password') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">Confirm Password</label>

<div class="col-md-6">

<input type="password" class="form-control" name="password_confirmation">

@if ($errors->has('password_confirmation'))

<span class="help-block">

<strong>{{ $errors->first('password_confirmation') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group">

<div class="col-md-6 col-md-offset-4">

<button type="submit" class="btn btn-primary">

<i class="fa fa-btn fa-user"></i>Register

</button>

</div>

</div>

</form>

</div>

</div>

</div>

</div>

</div>

@endsection

View pagină de conectare

@extends('layouts.app')

@section('content')

<div class="container">

<div class="row">

<div class="col-md-8 col-md-offset-2">

<div class="panel panel-default">

<div class="panel-heading">Login</div>

<div class="panel-body">

<form class="form-horizontal" role="form" method="POST" action="{{ url('/login') }}">

{!! csrf_field() !!}

<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">E-Mail Address</label>

<div class="col-md-6">

<input type="email" class="form-control" name="email" value="{{ old('email') }}">

@if ($errors->has('email'))

<span class="help-block">

<strong>{{ $errors->first('email') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">Password</label>

<div class="col-md-6">

<input type="password" class="form-control" name="password">

@if ($errors->has('password'))

<span class="help-block">

<strong>{{ $errors->first('password') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group">

<div class="col-md-6 col-md-offset-4">

<div class="checkbox">

<label>

<input type="checkbox" name="remember"> Remember Me

</label>

</div>

</div>

</div>

<div class="form-group">

<div class="col-md-6 col-md-offset-4">

<button type="submit" class="btn btn-primary">

<i class="fa fa-btn fa-sign-in"></i>Login

</button>

<a class="btn btn-link" href="{{ url('/password/reset') }}">Forgot Your Password?</a>

</div>

</div>

</form>

</div>

</div>

</div>

</div>

</div>

@endsection

View pagină de recuperare a parolei

@extends('layouts.app')

@section('content')

<div class="container">

<div class="row">

<div class="col-md-8 col-md-offset-2">

<div class="panel panel-default">

<div class="panel-heading">Reset Password</div>

<div class="panel-body">

<form class="form-horizontal" role="form" method="POST" action="{{ url('/password/reset') }}">

{!! csrf_field() !!}

<input type="hidden" name="token" value="{{ $token }}">

<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">E-Mail Address</label>

<div class="col-md-6">

<input type="email" class="form-control" name="email" value="{{ $email or old('email') }}">

@if ($errors->has('email'))

<span class="help-block">

<strong>{{ $errors->first('email') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group{{ $errors->has('password') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">Password</label>

<div class="col-md-6">

<input type="password" class="form-control" name="password">

@if ($errors->has('password'))

<span class="help-block">

<strong>{{ $errors->first('password') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group{{ $errors->has('password_confirmation') ? ' has-error' : '' }}">

<label class="col-md-4 control-label">Confirm Password</label>

<div class="col-md-6">

<input type="password" class="form-control" name="password_confirmation">

@if ($errors->has('password_confirmation'))

<span class="help-block">

<strong>{{ $errors->first('password_confirmation') }}</strong>

</span>

@endif

</div>

</div>

<div class="form-group">

<div class="col-md-6 col-md-offset-4">

<button type="submit" class="btn btn-primary">

<i class="fa fa-btn fa-refresh"></i>Reset Password

</button>

</div>

</div>

</form>

</div>

</div>

</div>

</div>

</div>

@endsection

View pagină principală

@extends('layouts.app')

@section ('stylesheet')

<link rel="stylesheet" href="{{URL::asset('assets/css/colored_semaphores.css')}}">

<script src="https://code.highcharts.com/stock/highstock.js"></script>

<script src="https://code.highcharts.com/modules/no-data-to-display.js"></script>

<script src="https://code.highcharts.com/modules/exporting.js"></script>

@stop

@section('content')

<div class="container">

<div class="row">

<div class="col-md-10 col-md-offset-1">

<div class="panel panel-default">

<div class="panel-heading"><b>Application Health Check</b></div>

<div class="panel-body">

@include ('systems._services')

</div></div>

<div class="panel panel-default" style="width:49%;float:left">

<div class="panel-heading"><b>Overall System Status</b></div>

<div id="chart" style="width:100%; height:400px;"></div>

<script type="text/javascript">

$(function () {

$('#chart').highcharts(

{!! json_encode($chart) !!} ); })

</script>

<div class="panel-body"></div></div>

<div class="panel panel-default" style="width:49%;float:left;margin-left: 2%">

<div class="panel-heading" ><b>Individual System Status</b></div>

@foreach ($systems as $system)

@if (\Auth::User()->id == $system->user_id)

<h2><a style="text-decoration: none;font-family: Lato" href="/systems/{{$system->id}}">

@if ($system->status=='up')

<div class="green" style="margin-left: 2%"><a href="#" style="color: #C4CBB7 !important;" target="_blank" data-toggle="tooltip" data-placement="bottom" system-id="{{$system->id}}" class="system" title="Last update: {{$system->updated_at->diffForHumans()}} ">{{$system->name}}</a></div>

@elseif ($system->status=='down')

<div class="red" style="margin-left: 2%"><a href="#" class="system" style="color: #EEE0B7 !important;" target="_blank" data-toggle="tooltip" data-placement="bottom" system-id="{{$system->id}}" title="Last update: {{$system->updated_at ->diffForHumans()}}">{{$system->name}}</a></div>

@else

<div class="orange" style="margin-left: 2%"><a href="#" style="color: #563200 !important;" target="_blank" data-toggle="tooltip" data-placement="bottom" system-id="{{$system->id}}" class="system" title="Last update: {{$system->updated_at ->diffForHumans()}}">{{$system->name}}</a></div>

@endif

</h2>

@endif

@endforeach

<div class="panel-body">

</div></div></div></div></div>

<script>

$(document).delegate(

".system",

'click',

function(e) {

e.preventDefault();

var link = 'modal/systemStatus/'+$(this).attr('system-id');

/*var datele =$(this).html();*/

var datele =$(this).attr('system-id');

console.log(datele);

$.ajax({

context: this,

url: link,

cache: false,

data:{

var : datele

}

}).done(function( result ) {

$("#modalSystem").html(result);

$('#modalSystem').modal('show');

});

});

</script>

<div class="modal fade" id="modalSystem" role="dialog" ></div>

@endsection

Template verificare integritate aplicație

<ul style="background-color:white;margin-left: 5%" class="services">

<li><a href="#"><button type="button" style="font-family:Lato" class="btn btn-success"><i class="fa fa-tachometer"></i></button></a>

<ul class="dropdown">

<li><a href="http://localhost/sqlbuddy/login.php"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Services</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Routing</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Metadata</button></a></li>

</ul>

</li>

<li><a href='#'><button type="button" style="font-family:Lato" class="btn btn-success">Framework <i class="fa fa-cogs"></i></button></a>

<ul class="dropdown">

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">PooledWorkspaceServer</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">MetadataServer</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Setinit</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">eAuth</button></a></li>

<li><a href="http://localhost/phpmyadmin/"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">phpMyAdmin</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Artisan</button></a></li>

</ul>

</li>

<li><a href='#'><button type="button" style="font-family:Lato" class="btn btn-success">Database <i class="fa fa-database"></i></button></a><ul class="dropdown">

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">WorkspaceServer</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">StoredProcessServer</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">PooledWorkspaceServer</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">ContentServer</button></a></li>

<li><a href="http://localhost/sqlbuddy/login.php"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">MySQL</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">RemoteServices</button></a></li>

</ul>

</li>

<li><a href='#'><button type="button" style="font-family:Lato" class="btn btn-success">Backend <i class="fa fa-cloud"></i></button></a><ul class="dropdown">

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">httpd</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">htaccess</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Extensions</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Workspace</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">SocketStream</button></a></li>

</ul>

</li>

<li><a href='http://localhost/'><button type="button" style="font-family:Lato" class="btn btn-success">Frontend <i class="fa fa-edge"></i></button></a>

<ul class="dropdown">

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Apache</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">ContentServer</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">SocketStream</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Extensions</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">RemoteServices</button></a></li>

</ul>

</li>

<li><a href='http://localhost/'><button type="button" style="font-family:Lato" class="btn btn-success">InterConnect <i class="fa fa-joomla"></i></button></a>

<ul class="dropdown">

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">Routing</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">SmartStream</button></a></li>

<li><a href="#"><button type="button" class="btn btn-success btn-xs" style="font-family:Lato;width:155px;height:24px">VehicleConnection</button></a></li>

</ul>

</li>

<li><a href='#'><button type="button" style="font-family:Lato" class="btn btn-success">Authentication <i class="fa fa-users"></i></button></a></li>

</ul>

View pagină management syslink-uri

@extends ('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

.content2 {

text-align: center;

display: block;

font-weight: 100;

font-family: 'Lato';

margin:0 auto;

}

h1,h2{

font-weight: 300;

font-family: 'Lato';

}

.child{

display: inline-block;

margin:10px 0 0 10px;

flex-grow: 1;

height:55px;

width: calc(100% * (1/4) – 10px – 1px);

text-decoration: none;

font-family: Lato;

font-size: 30px;

font-weight: 300

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h1>

<a href="/systems/create" style="text-decoration: none">Create a new syslink</a>

</h1>

</div>

</div>

<div class="container">

<div class="content2">

<div class="panel panel-default" style="width:100%;margin-top:1%">

<div class="panel-heading" ><b>Syslinks</b></div>

@foreach ($systems as $system)

@if (\Auth::User()->id == $system->user_id)

<h2 class="child">

<a style="text-decoration: none;color:#777" href="/systems/{{$system->id}}">{{ $system->name }} </a>

@if ($system->status=='up')

<i style="color:green" class="fa fa-check"></i>

@elseif ($system->status=='pending')

<i style="color:orange" class="fa fa-exclamation-triangle"></i>

@else

<i style="color:red" class="fa fa-ban"></i>

@endif

</h2>

@endif

@endforeach

</div> </div> </div>

<div class="container1">

{!!Form::open(['method'=>'post','style'=>'float:left;margin-left:43%','action'=>['SystemsController@checkAll',\Auth::User()->id]])!!}

<button type="Check" class="btn btn-primary btn">Check</button>

{!!Form::close()!!}

{!!Form::open(['method'=>'delete','style'=>'float:left;margin-bottom:2%;margin-left:1%','action'=>['SystemsController@destroyAll',\Auth::User()->id]])!!}

<button type="submit" class="btn btn-danger">Clean up!</button>

{!!Form::close()!!}

</div>

<br>

@stop

View pagină detalii syslink

@extends('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

vertical-align: middle;

}

.content {

margin-left: 30%;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h3{

font-weight: 300;

font-family: 'Lato';

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h3><b>Name:</b> {{$system->name}}</h3>

<hr>

<h3><b>Info:</b> {{$system->info}}</h3>

<hr>

<h3><b>Status:</b>

@if ($system->status=='up')

<i style="color:green" class="fa fa-check"></i>

@elseif ($system->status=='pending')

<i style="color:orange" class="fa fa-exclamation-triangle"></i>

@else

<i style="color:red" class="fa fa-ban"></i>

@endif

</h3>

<hr>

<h3><b>Metadata ID:</b> {{$system->metadata}}</h3>

<hr>

<h3><b>Last check:</b> {{$system->updated_at->diffForHumans()}}</h3>

<hr>

</div>

</div>

<div style="text-align: center">

{!!Form::open(['method'=>'delete','action'=>['SystemsController@destroy',$system->id]])!!} <a href="/systems/{{$system->id}}/edit"><button type="button" class="btn btn-primary" style="font-family:Lato"> Edit </button></a>

<button type="submit" class="btn btn-warning">Delete</button>

{!!Form::close()!!}

</div>

@stop

View pagină creare syslink

@extends('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h1{

font-weight: 300;

font-family: 'Lato';

}

.form-control{

font-weight:900

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h1>Create a new syslink</h1>

<hr>

{!! Form::open(['url' => 'systems']) !!}

@include('systems._form', ['submitButtonText' => 'Add'])

{!! Form::close() !!}

@include ('errors.list')

</div>

</div>

@stop

View pagină editare syslink

@extends('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h1{

font-weight: 300;

font-family: 'Lato';

}

.form-control{

font-weight:900

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h1>Update the {{$system->name }} syslink</h1>

<hr>

{!! Form::model($system,['method' => 'PATCH','url'=>'systems/'. $system->id]) !!}

@include('systems._form', ['submitButtonText' => 'Edit'])

{!! Form::close() !!}

@include ('errors.list')

</div>

</div>

@stop

View pagină creare asociere defect-impact

@extends('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h1{

font-weight: 300;

font-family: 'Lato';

}

.form-control{

font-weight:900

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h1>Insert fault data</h1>

<hr>

{!! Form::open(['url' => 'faults']) !!}

@include('faults._form', ['submitButtonText' => 'Add'])

{!! Form::close() !!}

@include ('errors.list')

</div>

</div>

@stop

View pagină editare asociere defect-impact

@extends('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h1{

font-weight: 300;

font-family: 'Lato';

}

.form-control{

font-weight:900

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h1>Fault update: {{$fault->fault_name }}</h1>

<hr>

{!! Form::model($fault,['method' => 'PATCH','url'=>'faults/'. $fault->id]) !!}

@include('faults._form', ['submitButtonText' => 'Edit'])

{!! Form::close() !!}

@include ('errors.list')

</div>

</div>

@stop

View pagină detalii asociere defect-impact

@extends('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

vertical-align: middle;

}

.content {

margin-left: 30%;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h3{

font-weight: 300;

font-family: 'Lato';

}

.edit{

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h3><b>Description:</b> {{$fault->fault_name}}</h3>

<hr>

<h3><b>Impact/Info:</b> {{$fault->info}}</h3>

<hr>

<h3><b>Last update:</b> {{$fault->updated_at->diffForHumans()}}</h3>

<hr>

</div>

</div>

<div style="text-align: center">

{!!Form::open(['method'=>'delete','action'=>['FaultController@destroy',$fault->id]])!!}

<a href="/faults/{{$fault->id}}/edit"><button type="button" class="btn btn-primary" style="font-family:Lato"> Edit </button></a>

<button type="submit" class="btn btn-warning">Delete</button>

{!!Form::close()!!}

</div>

@stop

View pagină management asocieri defect-impact

@extends ('layouts.app')

@section('stylesheet')

<link rel="stylesheet" href="{{–URL::asset('assets/css/main.css')–}}">

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

.content2 {

text-align: center;

display: block;

font-weight: 100;

font-family: 'Lato';

margin:0 auto;

}

h1,h2{

font-weight: 300;

font-family: 'Lato';

}

.child{

display: inline-block;

margin:10px 0 0 10px;

flex-grow: 1;

height:55px;

width: calc(100% * (1/8) – 10px – 1px);

text-decoration: none;

font-family: Lato;

font-size: 30px;

font-weight: 300

}

@stop

@section('content')

<div class="container1">

<div class="content">

<h1>

<a href="/faults/create" style="text-decoration: none">Insert fault data</a>

</h1>

</div>

</div>

<div class="container">

<div class="content2">

<div class="panel panel-default" style="width:100%;margin-top:1%">

<div class="panel-heading" ><b>Known faults</b></div>

@foreach ($faults as $fault)

<h2 class="child">

<a style="text-decoration: none;color:#777" href="/faults/{{$fault->id}}">{{ $fault->fault_name }} </a>

</h2>

@endforeach

</div>

</div>

</div>

<div class="container1">

{!!Form::open(['method'=>'delete','action'=>['FaultController@destroyAll']])!!}

<button type="submit" class="btn btn-danger">Clean up!</button>

{!!Form::close()!!}

</div>

@stop

View pagină căutare impacte

@extends('layouts.app')

@section ('stylesheet')

<link rel="stylesheet" href="{{URL::asset('assets/css/colored_semaphores.css')}}">

<link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2/css/select2.min.css" rel="stylesheet" >

<script src="https://code.highcharts.com/stock/highstock.js"></script>

<script src="https://code.highcharts.com/modules/no-data-to-display.js"></script>

<script src="https://code.highcharts.com/modules/exporting.js"></script>

@stop

@section('style')

.container {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h1{

font-weight: 300;

font-family: 'Lato';

}

.child{

display: inline-block;

margin:10px 0 0 10px;

flex-grow: 1;

height:55px;

width: calc(100% * (1/2) – 10px – 1px);

text-decoration: none;

font-family: Lato;

font-size: 30px;

font-weight: 300

}

@stop

@section('content')

<div class="container">

<div class="row">

<div class="col-md-10 col-md-offset-1">

<script type="text/javascript" src="{{URL::asset('assets/js/jquery-1.12.2.min.js')}}"></script>

<script type="text/javascript" src="{{URL::asset('assets/js/jquery-ui.js')}}"></script>

{!!Form::open(['url' => 'internal']) !!}

<select name ="faults[]" class="selectfault" multiple="multiple" style="width:250px"></select>

{!! Form::submit('Search', array('class' => 'btn btn-default')) !!}

{!! Form::close() !!}

<script>

$(function(){

$('.selectfault').select2({

width: 'resolve',

allowClear: true,

placeholder: 'Select encountered faults',

selectOnClose: false,

escapeMarkup: function (markup) { return markup; },

templateResult: function(item){

return "<b>"+item.text+"</b>";

},

ajax: {

dataType: 'json',

url: '{{ url("internal/autocomplete") }}',

data: function(params) {

return {

term: params.term

}

},

processResults: function (data, page) {

return {

results: data

}; }, } });

});

</script>

<script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.2/js/select2.min.js"></script>

@if (Request::isMethod('post') && !empty(Request::input('faults')) )

<br>

<?php

echo '<div class="panel panel-default" style="width:100%;">

<div class="panel-heading" ><b>Impacts</b></div>';

$inputs=Request::input('faults');

foreach ($inputs as $input){

$found = App\Fault::findOrFail($input);

$impact=$found->info;

echo '<h1 class="child" style="color:#777">'.$impact.' <i style="color:#B60606" class="fa fa-exclamation-triangle"></i></h1>';

}

echo '<h1></h1></div>';

?>

@elseif (Request::isMethod('post'))

<div><b>Please make a selection</b></div>

@endif

<div class="panel panel-default" style="width:100%;margin-top:2%">

<div class="panel-heading" ><b>System Status</b></div>

<?php $systems=App\System::latest()->get(); ?>

@foreach ($systems as $system)

@if (\Auth::User()->id == $system->user_id)

<h2><a style="text-decoration: none;font-family: Lato" href="/systems/{{$system->id}}">

@if ($system->status=='up')

<div class="green" style="margin-left: 2%"><a href="#" style="color: #C4CBB7 !important;" data-toggle="tooltip" data-placement="bottom" title="{{$system->info}}">{{$system->name}}</a></div>

@elseif ($system->status=='down')

<div class="red" style="margin-left: 2%"><a href="#" style="color: #EEE0B7 !important;" data-toggle="tooltip" data-placement="bottom" title="{{$system->info}}">{{$system->name}}</a></div>

@else

<div class="orange" style="margin-left: 2%"><a href="#" style="color: #563200 !important;" data-toggle="tooltip" data-placement="bottom" title="{{$system->info}}">{{$system->name}}</a></div>

@endif

</h2>

@endif

@endforeach

<div class="panel-body">

</div>

</div>

</div>

</div>

</div>

@endsection

View pagină căutare online

@extends('layouts.app')

@section ('stylesheet')

<link rel="stylesheet" href="{{URL::asset('assets/css/colored_semaphores.css')}}">

<script src="https://code.highcharts.com/highcharts.js"></script>

<script src="https://code.highcharts.com/modules/no-data-to-display.js"></script>

<script src="https://code.highcharts.com/modules/exporting.js"></script>

@stop

@section('style')

.container1 {

text-align: center;

vertical-align: middle;

}

.content {

text-align: center;

display: inline-block;

font-weight: 100;

font-family: 'Lato';

}

h3{

font-weight: 300;

font-family: 'Lato';

}

@stop

@section('content')

<div class="container">

<div class="row">

<div class="col-md-10 col-md-offset-1">

<script>

(function() {

var cx = '003124292959714507557:sy28xeh1vsa';

var gcse = document.createElement('script');

gcse.type = 'text/javascript';

gcse.async = true;

gcse.src = (document.location.protocol == 'https:' ? 'https:' : 'http:') +

'//cse.google.com/cse.js?cx=' + cx;

var s = document.getElementsByTagName('script')[0];

s.parentNode.insertBefore(gcse, s);

})();

</script>

<gcse:search></gcse:search>

</div>

</div>

</div>

@endsection

Modele relaționale

Modelul System

namespace App;

use Illuminate\Database\Eloquent\Model;

class System extends Model

{

protected $fillable = [

'name',

'status',

'info',

'user_id',

'metadata',

'urgency',

'reason'];

public function scopeDown($query)

{

$query->where('status','down');

}

public function scopeUp($query)

{

$query->where('status','up');

}

public function user(){

return $this->belongsTo('App\User');

}

}

Modelul Fault

namespace App;

use Illuminate\Database\Eloquent\Model;

class Fault extends Model

{

protected $table = 'faults';

protected $fillable = [

'fault_name','info',

];

public function impacts(){

return $this->hasMany('App\Impact','fault_impact','fault_id','impact_id');

}

}

Modelul User

namespace App;

use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable

{

protected $fillable = [

'user_id', 'email', 'password',

];

protected $hidden = [

'password', 'remember_token',

];

public function systems(){

return $this->hasMany('App\System');

}

}

Kernel

namespace App\Http;

use Illuminate\Foundation\Http\Kernel as HttpKernel;

class Kernel extends HttpKernel

{

protected $middleware = [

\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,

];

protected $middlewareGroups = [

'web' => [

\App\Http\Middleware\EncryptCookies::class,

\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,

\Illuminate\Session\Middleware\StartSession::class,

\Illuminate\View\Middleware\ShareErrorsFromSession::class,

\App\Http\Middleware\VerifyCsrfToken::class,

],

'api' => [

'throttle:60,1',

],

];

protected $routeMiddleware = [

'auth' => \App\Http\Middleware\Authenticate::class,

'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,

'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,

'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,

];

}

Configurarea interfeței cu baza de date

return [

'fetch' => PDO::FETCH_CLASS,

'default' => env('DB_CONNECTION', 'sqlite'),

'connections' => [

'sqlite' => [

'driver' => 'sqlite',

'database' => database_path('database.sqlite'),

'prefix' => '',

],

'mysql' => [

'driver' => 'mysql',

'host' => env('DB_HOST', 'localhost'),

'port' => env('DB_PORT', '3306'),

'database' => env('DB_DATABASE', 'forge'),

'username' => env('DB_USERNAME', 'forge'),

'password' => env('DB_PASSWORD', ''),

'charset' => 'utf8',

'collation' => 'utf8_unicode_ci',

'prefix' => '',

'strict' => false,

'engine' => null,

],

'pgsql' => [

'driver' => 'pgsql',

'host' => env('DB_HOST', 'localhost'),

'port' => env('DB_PORT', '5432'),

'database' => env('DB_DATABASE', 'forge'),

'username' => env('DB_USERNAME', 'forge'),

'password' => env('DB_PASSWORD', ''),

'charset' => 'utf8',

'prefix' => '',

'schema' => 'public',

],

],

'migrations' => 'migrations',

'redis' => [

'cluster' => false,

'default' => [

'host' => env('REDIS_HOST', 'localhost'),

'password' => env('REDIS_PASSWORD', null),

'port' => env('REDIS_PORT', 6379),

'database' => 0,

],

],

];

Listener sesiuni

namespace Symfony\Component\HttpKernel\EventListener;

use Symfony\Component\HttpKernel\Event\GetResponseEvent;

use Symfony\Component\HttpKernel\KernelEvents;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;

abstract class SessionListener implements EventSubscriberInterface

{

public function onKernelRequest(GetResponseEvent $event)

{

if (!$event->isMasterRequest()) {

return;

}

$request = $event->getRequest();

$session = $this->getSession();

if (null === $session || $request->hasSession()) {

return;

}

$request->setSession($session);

}

public static function getSubscribedEvents()

{

return array(

KernelEvents::REQUEST => array('onKernelRequest', 128),

);

}

abstract protected function getSession();

}

Ghidare sesiuni

namespace Illuminate\Auth;

use RuntimeException;

use Illuminate\Support\Str;

use Illuminate\Http\Response;

use Illuminate\Contracts\Events\Dispatcher;

use Illuminate\Contracts\Auth\UserProvider;

use Illuminate\Contracts\Auth\StatefulGuard;

use Symfony\Component\HttpFoundation\Request;

use Illuminate\Contracts\Auth\SupportsBasicAuth;

use Illuminate\Contracts\Cookie\QueueingFactory as CookieJar;

use Symfony\Component\HttpFoundation\Session\SessionInterface;

use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;

class SessionGuard implements StatefulGuard, SupportsBasicAuth

{

use GuardHelpers;

protected $name;

protected $lastAttempted;

protected $viaRemember = false;

protected $session;

protected $cookie;

protected $request;

protected $events;

protected $loggedOut = false;

protected $tokenRetrievalAttempted = false;

public function __construct($name,

UserProvider $provider,

SessionInterface $session,

Request $request = null)

{

$this->name = $name;

$this->session = $session;

$this->request = $request;

$this->provider = $provider;

}

public function user()

{

if ($this->loggedOut) {

return;

}

if (! is_null($this->user)) {

return $this->user;

}

$id = $this->session->get($this->getName());

$user = null;

if (! is_null($id)) {

$user = $this->provider->retrieveById($id);

}

$recaller = $this->getRecaller();

if (is_null($user) && ! is_null($recaller)) {

$user = $this->getUserByRecaller($recaller);

if ($user) {

$this->updateSession($user->getAuthIdentifier());

$this->fireLoginEvent($user, true);

}

}

return $this->user = $user;

}

public function id()

{

if ($this->loggedOut) {

return;

}

$id = $this->session->get($this->getName(), $this->getRecallerId());

if (is_null($id) && $this->user()) {

$id = $this->user()->getAuthIdentifier();

}

return $id;

}

protected function getUserByRecaller($recaller)

{

if ($this->validRecaller($recaller) && ! $this->tokenRetrievalAttempted) {

$this->tokenRetrievalAttempted = true;

list($id, $token) = explode('|', $recaller, 2);

$this->viaRemember = ! is_null($user = $this->provider->retrieveByToken($id, $token));

return $user;

}

}

protected function getRecaller()

{

return $this->request->cookies->get($this->getRecallerName());

}

protected function getRecallerId()

{

if ($this->validRecaller($recaller = $this->getRecaller())) {

return head(explode('|', $recaller));

}

}

protected function validRecaller($recaller)

{

if (! is_string($recaller) || ! Str::contains($recaller, '|')) {

return false;

}

$segments = explode('|', $recaller);

return count($segments) == 2 && trim($segments[0]) !== '' && trim($segments[1]) !== '';

}

public function once(array $credentials = [])

{

if ($this->validate($credentials)) {

$this->setUser($this->lastAttempted);

return true;

}

return false;

}

public function validate(array $credentials = [])

{

return $this->attempt($credentials, false, false);

}

public function basic($field = 'email', $extraConditions = [])

{

if ($this->check()) {

return;

}

if ($this->attemptBasic($this->getRequest(), $field, $extraConditions)) {

return;

}

return $this->getBasicResponse();

}

public function onceBasic($field = 'email', $extraConditions = [])

{

$credentials = $this->getBasicCredentials($this->getRequest(), $field);

if (! $this->once(array_merge($credentials, $extraConditions))) {

return $this->getBasicResponse();

}

}

protected function attemptBasic(Request $request, $field, $extraConditions = [])

{

if (! $request->getUser()) {

return false;

}

$credentials = $this->getBasicCredentials($request, $field);

return $this->attempt(array_merge($credentials, $extraConditions));

}

protected function getBasicCredentials(Request $request, $field)

{

return [$field => $request->getUser(), 'password' => $request->getPassword()];

}

protected function getBasicResponse()

{

$headers = ['WWW-Authenticate' => 'Basic'];

return new Response('Invalid credentials.', 401, $headers);

}

public function attempt(array $credentials = [], $remember = false, $login = true)

{

$this->fireAttemptEvent($credentials, $remember, $login);

$this->lastAttempted = $user = $this->provider->retrieveByCredentials($credentials);

if ($this->hasValidCredentials($user, $credentials)) {

if ($login) {

$this->login($user, $remember);

}

return true;

}

return false;

}

protected function hasValidCredentials($user, $credentials)

{

return ! is_null($user) && $this->provider->validateCredentials($user, $credentials);

}

protected function fireAttemptEvent(array $credentials, $remember, $login)

{

if (isset($this->events)) {

$this->events->fire(new Events\Attempting(

$credentials, $remember, $login

));

}

}

public function attempting($callback)

{

if (isset($this->events)) {

$this->events->listen(Events\Attempting::class, $callback);

}

}

public function login(AuthenticatableContract $user, $remember = false)

{

$this->updateSession($user->getAuthIdentifier());

if ($remember) {

$this->createRememberTokenIfDoesntExist($user);

$this->queueRecallerCookie($user);

}

$this->fireLoginEvent($user, $remember);

$this->setUser($user);

}

protected function fireLoginEvent($user, $remember = false)

{

if (isset($this->events)) {

$this->events->fire(new Events\Login($user, $remember));

}

}

protected function updateSession($id)

{

$this->session->set($this->getName(), $id);

$this->session->migrate(true);

}

public function loginUsingId($id, $remember = false)

{

$this->session->set($this->getName(), $id);

$this->login($user = $this->provider->retrieveById($id), $remember);

return $user;

}

public function onceUsingId($id)

{

if (! is_null($user = $this->provider->retrieveById($id))) {

$this->setUser($user);

return true;

}

return false;

}

protected function queueRecallerCookie(AuthenticatableContract $user)

{

$value = $user->getAuthIdentifier().'|'.$user->getRememberToken();

$this->getCookieJar()->queue($this->createRecaller($value));

}

protected function createRecaller($value)

{

return $this->getCookieJar()->forever($this->getRecallerName(), $value);

}

public function logout()

{

$user = $this->user();

$this->clearUserDataFromStorage();

if (! is_null($this->user)) {

$this->refreshRememberToken($user);

}

if (isset($this->events)) {

$this->events->fire(new Events\Logout($user));

}

$this->user = null;

$this->loggedOut = true;

}

protected function clearUserDataFromStorage()

{

$this->session->remove($this->getName());

if (! is_null($this->getRecaller())) {

$recaller = $this->getRecallerName();

$this->getCookieJar()->queue($this->getCookieJar()->forget($recaller));

}

}

protected function refreshRememberToken(AuthenticatableContract $user)

{

$user->setRememberToken($token = Str::random(60));

$this->provider->updateRememberToken($user, $token);

}

protected function createRememberTokenIfDoesntExist(AuthenticatableContract $user)

{

if (empty($user->getRememberToken())) {

$this->refreshRememberToken($user);

}

}

public function getCookieJar()

{

if (! isset($this->cookie)) {

throw new RuntimeException('Cookie jar has not been set.');

}

return $this->cookie;

}

public function setCookieJar(CookieJar $cookie)

{

$this->cookie = $cookie;

}

public function getDispatcher()

{

return $this->events;

}

public function setDispatcher(Dispatcher $events)

{

$this->events = $events;

}

public function getSession()

{

return $this->session;

}

public function getProvider()

{

return $this->provider;

}

public function setProvider(UserProvider $provider)

{

$this->provider = $provider;

}

public function getUser()

{

return $this->user;

}

public function setUser(AuthenticatableContract $user)

{

$this->user = $user;

$this->loggedOut = false;

}

public function getRequest()

{

return $this->request ?: Request::createFromGlobals();

}

public function setRequest(Request $request)

{

$this->request = $request;

return $this;

}

public function getLastAttempted()

{

return $this->lastAttempted;

}

public function getName()

{

return 'login_'.$this->name.'_'.sha1(static::class);

}

public function getRecallerName()

{

return 'remember_'.$this->name.'_'.sha1(static::class);

}

public function viaRemember()

{

return $this->viaRemember;

}

}

Controllere

Controllerul pentru syslinkuri

namespace App\Http\Controllers;

use \App\System;

use \App\Http\Requests;

use Request;

class SystemsController extends Controller

{

public function index(){

$systems=System::latest()->get();

return view('systems.system',compact('systems'));

}

public function show($id) {

$system=System::findOrFail($id);

return view ('systems.show',compact('system'));

}

public function create(){

return view ('systems.create');

}

public function store(\App\Http\Requests\CreateSystemRequest $request){

$system=new System($request->all());

$system->status = $this->pickAnItem();

$system->urgency = $this->pickUrgency();

$system->reason = $this->pickReason();

\Auth::user()->systems()->save($system);

return redirect('systems');

}

public function edit($id){

$system=System::findOrFail($id);

return view('systems.edit', compact('system'));

}

public function destroy($id){

$system=System::findOrFail($id);

$system->delete();

return redirect ('systems');

}

public function destroyAll($user_id){

$system=System::where('user_id',$user_id);

$system->delete();

return redirect ('systems');

}

public function pickAnItem()

{

$statuses = array(

array('up', 85),

array('down', 5),

array('pending', 10)

);

$hat = array();

foreach($statuses as $item)

{

$hat = array_merge($hat, array_fill(0, $item[1], $item[0]));

}

return $hat[array_rand($hat)];

}

public function pickUrgency()

{

$statuses = array(

array('Low', 60),

array('Medium', 30),

array('Critical', 10)

);

$hat = array();

foreach($statuses as $item)

{

$hat = array_merge($hat, array_fill(0, $item[1], $item[0]));

}

return $hat[array_rand($hat)];

}

public function pickReason()

{

$statuses = array(

array('Physical Failure', 60),

array('Software Failure', 30),

array('Connectivity Timeout', 10)

);

$hat = array();

foreach($statuses as $item)

{

$hat = array_merge($hat, array_fill(0, $item[1], $item[0]));

}

return $hat[array_rand($hat)];

}

public function checkAll($user_id){

$system=System::where('user_id',$user_id);

$system->each(function ($item){

$item->update(['status' => $this->pickAnItem(),

'urgency' => $this->pickUrgency(),

'reason' => $this->pickReason()]);

});

return redirect ('/');

}

public function update($id, \App\Http\Requests\CreateSystemRequest $request){

$system=System::findOrFail($id);

$system->update($request->all());

return redirect ('systems');

}

}

Controllerul pentru defecte

namespace App\Http\Controllers;

use \App\Fault;

use \App\Http\Requests;

use Request;

class FaultController extends Controller

{

public function index(){

$faults=Fault::latest()->get();

return view('faults.faults',compact('faults'));

}

public function destroyAll(){

$faults=Fault::get();

$faults->delete();

return redirect ('faults');

}

public function show($id) {

$fault=Fault::findOrFail($id);

return view ('faults.show',compact('fault'));

}

public function destroy($id){

$fault=Fault::findOrFail($id);

$fault->delete();

return redirect ('faults');

}

public function create(){

return view ('faults.create');

}

public function edit($id){

$fault=Fault::findOrFail($id);

return view('faults.edit', compact('fault'));

}

public function store(\App\Http\Requests\CreateFaultRequest $request){

$fault=new Fault($request->all());

$fault->save();

return redirect('faults');

}

public function update($id, \App\Http\Requests\CreateFaultRequest $request){

$fault=Fault::findOrFail($id);

$fault->update($request->all());

return redirect ('faults');

}

}

Controllerul paginii de căutare a impactelor asociate defectelor

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;

use App\Http\Controllers\Controller;

use Illuminate\Support\Facades\Input;

use Auth;

use DB;

use Response;

class IntranetController extends Controller

{

public function autocomplete(){

$term = Input::get('term');

$results = array();

$queries = DB::table('faults')

->where('fault_name', 'LIKE', '%'.$term.'%')

->orWhere('info', 'LIKE', '%'.$term.'%')

->take(5)->get();

foreach ($queries as $query)

{

$results[] = ['id' => $query->id, 'text' => $query->fault_name ];

}

return Response::json($results);

}

public function index(){

return view('intranet.search');

}

public function returnResult(){

return view('intranet.search');

}

}

Controllerul căsuței de pop-up (detalii suplimentare syslink)

namespace App\Http\Controllers;

use \App\System;

use App\Http\Requests;

use Illuminate\Http\Request;

class ModalController extends Controller

{

public function systemStatus($id);

$system=\App\System::findOrFail($id);

return view('modals.system',compact('system'));

}

}

Controllerul paginii principale

namespace App\Http\Controllers;

use App\Http\Requests;

use Illuminate\Http\Request;

use App\System;

class HomeController extends Controller

{

public function __construct()

{

$this->middleware('auth');

}

public function index()

{

$systems=System::get();

$user=\Auth::User()->id;

$count_ok=System::where('user_id',$user)->where('status','up')->count();

$count_notok=System::where('user_id',$user)->where('status','down')->count();

$count_warn=System::where('user_id',$user)->where('status','pending')->count();

$array_count = [ array ("name" => "Online", "y" => $count_ok, "color" => "#09634C" ),

array ("name" => "Down", "y" => $count_notok, "color"=>"#AA3233"),

array ("name" => "Warning", "y" => $count_warn, "color"=>"#DC9015") ];

if ($count_ok==0 && $count_warn==0 && $count_warn==0 ){

$array_count=[];

}

$chart["chart"] = array("type" => "pie",

"plotBackgroundColor" => null,

"plotBorderWidth" => null,

"plotShadow" => false);

$chart["title"] = array("text" => "Syslinks");

$chart["series"] = [

array("name" => "Total count",

"colorByPoint" => true,

"data" => $array_count)

];

$chart["plotOptions"] = array ( "pie" =>

array( "allowPointSelect" => true,

"cursor" => "pointer",

"showInLegend" => true,

'dataLabels' => array ( "enabled" => true,

"format" => "<b>{point.name}</b>: {point.percentage:.1f} %" )

)

);

$chart["credits"]=["enabled" => false ];

return view('home',compact('systems','chart'));

}

}

Controllerul paginii de căutare online

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;

use App\System;

class SearchController extends Controller

{

public function index()

{

return view('why.search');

}

}

Controllerul de autentificare

namespace App\Http\Controllers\Auth;

use App\User;

use Validator;

use App\Http\Controllers\Controller;

use Illuminate\Foundation\Auth\ThrottlesLogins;

use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers;

namespace App\Http\Controllers\Auth;

use Illuminate\Foundation\Auth\ResetsPasswords;

class PasswordController extends Controller

{

use ResetsPasswords;

public function __construct()

{

$this->middleware('guest');

}

}

class AuthController extends Controller

{

use AuthenticatesAndRegistersUsers, ThrottlesLogins;

protected $redirectTo = '/systems';

public function __construct()

{

$this->middleware($this->guestMiddleware(), ['except' => 'logout']);

}

protected function validator(array $data)

{

return Validator::make($data, [

'user_id' => 'required|max:255',

'email' => 'required|email|max:255|unique:users',

'password' => 'required|min:6|confirmed',

]);

}

protected function create(array $data)

{

return User::create([

'user_id' => $data['user_id'],

'email' => $data['email'],

'password' => bcrypt($data['password']),

]);

}

}

Fișierul de rute

Route::group(['middleware' => ['web']], function () {

Route::resource('systems','SystemsController');

Route::delete('systems/{user_id}/deleteall', 'SystemsController@destroyAll');

Route::post('systems/{user_id}/checkall', 'SystemsController@checkAll');

Route::resource('search','SearchController@index');

Route::get('internal/autocomplete','IntranetController@autocomplete');

Route::get('internal','IntranetController@index');

Route::post('internal','IntranetController@returnResult');

Route::controllers([

'auth' => 'Auth\AuthController',

'password' => 'Auth\PasswordController',

]);

Route::auth();

Route::get('/', 'HomeController@index');

Password reset link request routes…

Route::get('password/email', 'Auth\PasswordController@getEmail');

Route::post('password/email', 'Auth\PasswordController@postEmail');

Route::get('password/reset/{token}', 'Auth\PasswordController@getReset');

Route::post('password/reset', 'Auth\PasswordController@postReset');

Route::delete('faults/deleteall', 'FaultController@destroyAll');

Route::resource('faults','FaultController');

Route::get('modal/systemStatus/{id}','ModalController@systemStatus');

});

Fișierul htaccess

<IfModule mod_rewrite.c>

<IfModule mod_negotiation.c>

Options -MultiViews

</IfModule>

RewriteEngine On

# Redirect Trailing Slashes If Not A Folder…

RewriteCond %{REQUEST_FILENAME} !-d

RewriteRule ^(.*)/$ /$1 [L,R=301]

# Handle Front Controller…

RewriteCond %{REQUEST_FILENAME} !-d

RewriteCond %{REQUEST_FILENAME} !-f

RewriteRule ^ index.php [L]

# Handle Backend

RewriteCond %{HTTP:Authorization} .

RewriteRule .* – [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

</IfModule>

Fișierul de configurare a mediului de lucru

APP_ENV=local

APP_DEBUG=true

APP_KEY=4z4KYmr2x4Qqgq0K8UzgxyF9o3zGayeW

APP_URL=http://dizertatie.app

DB_HOST=127.0.0.1

DB_PORT=3306

DB_DATABASE=homestead

DB_USERNAME=homestead

DB_PASSWORD=secret

CACHE_DRIVER=file

SESSION_DRIVER=file

QUEUE_DRIVER=sync

REDIS_HOST=127.0.0.1

REDIS_PASSWORD=null

REDIS_PORT=6379

MAIL_DRIVER=smtp

MAIL_HOST=smtp.gmail.com

MAIL_PORT=587

MAIL_USERNAME=[anonimizat]

MAIL_PASSWORD=*********

Fișierul de configurare a mapării bază de date – MVC

return [

'fetch' => PDO::FETCH_CLASS,

'default' => env('DB_CONNECTION', 'sqlite'),

'connections' => [

'sqlite' => [

'driver' => 'sqlite',

'database' => database_path('database.sqlite'),

'prefix' => '',

],

'mysql' => [

'driver' => 'mysql',

'host' => env('DB_HOST', 'localhost'),

'port' => env('DB_PORT', '3306'),

'database' => env('DB_DATABASE', 'forge'),

'username' => env('DB_USERNAME', 'forge'),

'password' => env('DB_PASSWORD', ''),

'charset' => 'utf8',

'collation' => 'utf8_unicode_ci',

'prefix' => '',

'strict' => false,

'engine' => null,

],

'pgsql' => [

'driver' => 'pgsql',

'host' => env('DB_HOST', 'localhost'),

'port' => env('DB_PORT', '5432'),

'database' => env('DB_DATABASE', 'forge'),

'username' => env('DB_USERNAME', 'forge'),

'password' => env('DB_PASSWORD', ''),

'charset' => 'utf8',

'prefix' => '',

'schema' => 'public',

],

],

'migrations' => 'migrations',

'redis' => [

'cluster' => false,

'default' => [

'host' => env('REDIS_HOST', 'localhost'),

'password' => env('REDIS_PASSWORD', null),

'port' => env('REDIS_PORT', 6379),

'database' => 0,

],

],

];

Bibliografie

[1] Self-Driving Cars: The next revolution, https://www.kpmg.com/US/en/IssuesAndInsights/ArticlesPublications/Documents/self-driving-cars-next-revolution.pdf

[2] Cum functioneaza sistemul autonom proiectat de VOLVO,

http://www.autostrada.md/tehnologii/volvo-ne-explica-cum-functioneaza-sistemul-autonom-al-modelelor-sale-video

[3] Lidar Design for Situational Awareness,

http://faculty.nps.edu/agrawal/docs/theses/gast_MS.pdf

[4] Abrams, Mark C. and David M. Tratt. “Progress in Laser Sources for Lidar Applications: Laser Sources for 3D Imaging Remote Sensing,” Proceedings of SPIE 5653 (2005): 241-248.

[5] Carlson, A.Bruce, et al. Communication Systems. Boston: McGraw Hill, 2002.

[6] Kuhn, Kelin J. Laser Engineering. Upper Saddle River, NJ: Prentice Hall, 1998.

[7] Smith Warren J. Modern Optical Engineering. New York: McGraw-Hill, 2000.

[8] What is GIS, http://www.esri.com/what-is-gis

[9] Aaron J. Dalton, Autonomous Vehicle Path Planning with Remote Sensing Data, 2008,

https://theses.lib.vt.edu/theses/available/etd-12162008-152233/unrestricted/Thesis-Final.pdf

[10] Reinholtz, Charles. "DARPA Urban Challenge Technical Paper." Technical Report, Virginia Tech, 2007.

[11] Lupien, Anthony W., William H. Moreland, and Jack Dangermond. "Network Analysis in Geographic Information Systems." Photogrammetric Engineering and Remote Sensing 53 (1987)

[12] Hart, PE, NJ Nilsson, and B. Raphael. "A Formal Basis for the Heuristic Determination of Minimum Cost Paths." Systems Science and Cybernetics, IEEE Transactions on 4 (1968): 100-107.

[13] LaValle, S.M. Planning Algorithms. Cambridge University Press, 2006

[14] Institute of Navigation. "Behind the Schenes at DARPA's Urban Challenge." Institute of Navigation Newsletter, Winter 2008: 9-11.

[15] Bacha, Andrew, et al. "Odin: Team VictorTango's entry in the DARPA Urban Challenge." Journal of Field Robotics 25, no. 8 (August 2008): 467-492

[16] What is adaptive cruise control and how does it work,

http://www.extremetech.com/extreme/what-is-adaptive-cruise-control-and-how-does-it-work

[17] An overview of development GPS navigation for autonomous cars,

http://ieeexplore.ieee.org/xpls/icp.jsp?arnumber=6566533

[18] Differential and RTK GPS explained,

http://www.esri.com/news/arcuser/0103/differential1of2.html

[19] An introduction to GNSS,

http://www.novatel.com/an-introduction-to-gnss/chapter-5-resolving-errors/real-time-kinematic-rtk

[20] Algoritmi euristici de explorare a grafurilor. A*,

http://clubcisco.ro/cursuri/2pa/%2011%20-%20AStar.pdf

[21] Ce este CSS,

http://www.e-learn.ro/tutorial/css/ce-este-css-a/67/1/37.htm

[22] Ce este HTML,

http://invatahtmlake.3x.ro/ceestehtml.html

[23] Tutorial complet JavaScript,

http://etutoriale.ro/articles/1771/1/Tutorial-complet-JavaScript-(prima-parte)/

[24] Baze de date relationale,

http://cursuri.cs.pub.ro/~radulescu/bd/sql7/oracle1.html

Similar Posts