]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/main.cc
Add default sampling info setter
[hubacji1/iamcar.git] / base / main.cc
1 /*
2 This file is part of I am car.
3
4 I am car is nree software: you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation, either version 3 of the License, or
7 (at your option) any later version.
8
9 I am car is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with I am car. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18 #include <algorithm>
19 #include <chrono>
20 #include <cmath>
21 #include <cstdlib>
22 #include <iostream>
23 #include <jsoncpp/json/json.h>
24 #include <pthread.h>
25 #include <signal.h>
26 #include <unistd.h>
27 #include "compile.h"
28 #include "obstacle.h"
29 #include "rrtplanner.h"
30 #include "slotplanner.h"
31
32 #if USE_GL > 0
33 // OpenGL
34 #include <GL/gl.h>
35 #include <GL/glu.h>
36 #include <SDL2/SDL.h>
37 #endif
38
39 // debug
40 //#define JSONLOGEDGES
41 //#define JSONLOGSAMPLES
42
43 #if USE_GL > 0
44         #define USE_INTERRUPT
45 #else
46         // choose
47         //#define USE_INTERRUPT
48         // or
49         #define USE_TMAX
50         // or
51         //#define USE_LOADF
52         // or
53         //#define USE_PTHREAD
54 #endif
55
56 // OpenGL window size
57 #define SCREEN_WIDTH 1000
58 #define SCREEN_HEIGHT 1000
59
60 std::chrono::high_resolution_clock::time_point TSTART_;
61 std::chrono::high_resolution_clock::time_point TEND_;
62 float TELAPSED = 0;
63 float ELAPSED = 0;
64 void TSTART() {TSTART_ = std::chrono::high_resolution_clock::now();}
65 void TEND() {
66         std::chrono::duration<float> DT_;
67         TEND_ = std::chrono::high_resolution_clock::now();
68         DT_ = std::chrono::duration_cast<std::chrono::duration<float>>(
69                 TEND_ - TSTART_
70         );
71         TELAPSED += DT_.count();
72         ELAPSED = DT_.count();
73 }
74 void TPRINT(const char *what) {
75         std::chrono::duration<float> DT_;
76         DT_ = std::chrono::duration_cast<std::chrono::duration<float>>(
77                 TEND_ - TSTART_
78         );
79         std::cerr << what << ": " << DT_.count() << std::endl;
80 }
81
82 bool run_planner = true;
83
84 #if USE_GL > 0
85 SDL_Window* gw = NULL;
86 SDL_GLContext gc;
87
88 bool init();
89 bool initGL();
90 #endif
91
92 void hint(int)
93 {
94         run_planner = false;
95 }
96
97 #ifdef USE_PTHREAD
98 struct next_arg {
99         bool *gf;
100         T2 *p;
101 };
102
103 void *next_run(void *arg)
104 {
105         struct next_arg *na = (struct next_arg *) arg;
106         T2 *lp = (T2 *) na->p;
107         bool *gf = na->gf;
108         while (!*gf && lp->elapsed() < TMAX) {
109                 if (lp->next())
110                         *gf = true;
111                 lp->tend();
112         }
113         pthread_exit(NULL);
114         return NULL;
115 }
116 #endif
117
118 RRTNode *sa_tmp()
119 {
120         float new_x = 1 + static_cast<float>(rand()) /
121                 static_cast<float>(RAND_MAX / (6.6 - 1 - 1));
122         float new_y = 1;
123         float new_h = M_PI / 2;
124         return new RRTNode(new_x, new_y, new_h);
125 }
126
127 int main()
128 {
129         srand(static_cast<unsigned>(time(0)));
130 #if USE_GL > 0
131         init();
132 #endif
133
134         Json::Value jvi; // JSON input
135         Json::Value jvo; // JSON output
136         unsigned int i = 0;
137         unsigned int j = 0;
138         std::cin >> jvi;
139         std::string encoding = jvi.get("encoding", "UTF-8" ).asString();
140
141         PLANNER p(
142                         new RRTNode(
143                                 jvi["init"][0].asFloat(),
144                                 jvi["init"][1].asFloat(),
145                                 jvi["init"][2].asFloat()),
146                         new RRTNode(
147                                 jvi["goal"][0].asFloat(),
148                                 jvi["goal"][1].asFloat(),
149                                 jvi["goal"][2].asFloat()));
150         jvo["init"][0] = p.root()->x();
151         jvo["init"][1] = p.root()->y();
152         jvo["init"][2] = p.root()->h();
153         std::vector<CircleObstacle> co;
154         std::vector<SegmentObstacle> so;
155         p.HMIN = p.root()->x();
156         p.HMAX = p.root()->x();
157         p.VMIN = p.root()->y();
158         p.VMAX = p.root()->y();
159         for (auto o: jvi["obst"]) {
160                 float tmpx;
161                 float tmpy;
162                 float tmpr;
163                 float tmps;
164                 if (o["circle"] != Json::nullValue) {
165                         tmpx = o["circle"][0].asFloat();
166                         tmpy = o["circle"][1].asFloat();
167                         tmpr = o["circle"][2].asFloat();
168                         co.push_back(CircleObstacle(tmpx, tmpy, tmpr));
169                         if (tmpx < p.HMIN) p.HMIN = tmpx;
170                         if (tmpx > p.HMAX) p.HMAX = tmpx;
171                         if (tmpy < p.VMIN) p.VMIN = tmpy;
172                         if (tmpy > p.VMAX) p.VMAX = tmpy;
173                 }
174                 if (o["segment"] != Json::nullValue) {
175                         tmpx = o["segment"][0][0].asFloat();
176                         tmpy = o["segment"][0][1].asFloat();
177                         tmpr = o["segment"][1][0].asFloat();
178                         tmps = o["segment"][1][1].asFloat();
179                         so.push_back(SegmentObstacle(
180                                 new RRTNode(tmpx, tmpy, 0),
181                                 new RRTNode(tmpr, tmps, 0)
182                         ));
183                         p.frame().add_bnode(so.back().init());
184                         if (tmpx < p.HMIN) p.HMIN = tmpx;
185                         if (tmpx > p.HMAX) p.HMAX = tmpx;
186                         if (tmpy < p.VMIN) p.VMIN = tmpy;
187                         if (tmpy > p.VMAX) p.VMAX = tmpy;
188                         if (tmpr < p.HMIN) p.HMIN = tmpr;
189                         if (tmpr > p.HMAX) p.HMAX = tmpr;
190                         if (tmps < p.VMIN) p.VMIN = tmps;
191                         if (tmps > p.VMAX) p.VMAX = tmps;
192                 }
193         }
194         p.defaultSamplingInfo();
195         p.link_obstacles(&co, &so);
196         p.ocost(p.root());
197         p.ocost(p.goal());
198
199         ParallelSlot ps = ParallelSlot();
200         if (
201                 jvi["slot"] != Json::nullValue &&
202                 jvi["slot"]["polygon"] != Json::nullValue
203         ) {
204                 for (auto xy: jvi["slot"]["polygon"]) {
205                         ps.slot().add_bnode(new RRTNode(
206                                 xy[0].asFloat(),
207                                 xy[1].asFloat()
208                         ));
209                 }
210                 for (auto e: ps.slot().frame())
211                         so.push_back(SegmentObstacle(e->init(), e->goal()));
212         }
213 #ifdef USE_SLOTPLANNER
214         TSTART();
215         if (ps.slot().bnodes().size() > 0)
216                 ps.fip(co, so);
217         TEND();
218         jvo["ppse"] = ELAPSED;
219         TPRINT("ParallelSlot");
220 #endif
221         if (ps.slot().bnodes().size() > 0) {
222                 ps.setAll();
223                 //if (ps.getMidd() != nullptr)
224                 //        p.setSamplingInfo(ps.getSamplingInfo());
225         }
226         if (ps.cusp().size() > 0) {
227                 p.goal(ps.getMidd());
228                 p.slot_cusp(ps.cusp().front()); // use first found solution
229                 p.goals(ps.goals());
230                 jvo["midd"][0] = p.goal()->x();
231                 jvo["midd"][1] = p.goal()->y();
232                 jvo["midd"][2] = p.goal()->h();
233                 jvo["goal"][0] = p.slot_cusp().back()->x();
234                 jvo["goal"][1] = p.slot_cusp().back()->y();
235                 jvo["goal"][2] = p.slot_cusp().back()->h();
236         } else {
237                 jvo["goal"][0] = p.goal()->x();
238                 jvo["goal"][1] = p.goal()->y();
239                 jvo["goal"][2] = p.goal()->h();
240         }
241         TSTART();
242         std::cerr << "Slot Info:" << std::endl;
243         if (ps.slotSide() == LEFT)
244                 std::cerr << "- LEFT" << std::endl;
245         else
246                 std::cerr << "- RIGHT" << std::endl;
247         if (ps.slotType() == PARALLEL)
248                 std::cerr << "- PARALLEL" << std::endl;
249         else
250                 std::cerr << "- PERPENDICULAR" << std::endl;
251 #ifdef USE_LOADF
252         std::vector<RRTNode *> steered;
253         for (auto jn: jvi["traj"][0]) {
254                 steered.push_back(new RRTNode(
255                                         jn[0].asFloat(),
256                                         jn[1].asFloat(),
257                                         jn[2].asFloat(),
258                                         jn[3].asFloat(),
259                                         jn[4].asFloat()));
260         }
261         std::reverse(steered.begin(), steered.end());
262         RRTNode *pn = p.root();
263         for (auto n: steered) {
264                 if (IS_NEAR(pn, n))
265                         continue;
266                 pn->add_child(n, p.cost(pn, n));
267                 pn = n;
268                 p.glplot();
269         }
270         pn->add_child(p.goal(), p.cost(pn, p.goal()));
271         p.goal_found(true);
272         p.tlog(p.findt());
273         if (p.opt_path()) {
274                 p.tlog(p.findt());
275                 p.glplot();
276         }
277         p.glplot();
278         sleep(2);
279 #elif defined USE_INTERRUPT
280         signal(SIGINT, hint);
281         signal(SIGTERM, hint);
282         p.tstart();
283         while (run_planner) {
284                 p.next();
285                 p.tend();
286                 if (p.opt_path())
287                         p.tlog(p.findt());
288                 p.glplot();
289         }
290 #elif defined USE_TMAX
291         p.tstart();
292         p.tend();
293         while (!p.goal_found() && p.elapsed() < TMAX) {
294                 p.next();
295                 p.tend();
296                 if (p.opt_path()) {
297                         p.tlog(p.findt());
298                 }
299         }
300         if (p.goal_found() && ps.slotType() == PARALLEL)
301                 p.tlog(p.findt(p.slot_cusp().back()));
302 #elif defined USE_PTHREAD
303         bool gf = false;
304         RRTNode *ron = nullptr;
305         RRTNode *gon = nullptr;
306         float mc = 9999;
307         pthread_t rt; // root thread
308         pthread_t gt; // goal thread
309         pthread_t ct; // connect thread
310
311         struct next_arg ra;
312         ra.gf = &gf;
313         ra.p = &p.p_root_;
314
315         struct next_arg ga;
316         ga.gf = &gf;
317         ga.p = &p.p_goal_;
318
319         p.tstart();
320         p.p_root_.tstart();
321         p.p_goal_.tstart();
322         pthread_create(&rt, NULL, &next_run, (void *) &ra);
323         pthread_create(&gt, NULL, &next_run, (void *) &ga);
324         int tol = 0;
325         int ndl = 0;
326         bool ndone = true;
327         while (!gf && p.elapsed() < TMAX &&
328                         p.p_root_.nodes().size() < NOFNODES &&
329                         p.p_goal_.nodes().size() < NOFNODES) {
330                 // overlap trees
331                 ndone = true;
332                 for (int i = 0; i < IXSIZE; i++) {
333                 for (int j = 0; j < IYSIZE; j++) {
334                         if (p.p_root_.ixy_[i][j].changed() &&
335                                         p.p_goal_.ixy_[i][j].changed()) {
336 ndone = false;
337 for (auto rn: p.p_root_.ixy_[i][j].nodes()) {
338 for (auto gn: p.p_goal_.ixy_[i][j].nodes()) {
339         if (rn->ccost() + gn->ccost() < mc &&
340                         IS_NEAR(rn, gn)) {
341                 gf = true;
342                 p.goal_found(true);
343                 ron = rn;
344                 gon = gn;
345                 mc = rn->ccost() + gn->ccost();
346         }
347 }}
348                         }
349                         tol++;
350                         if (ndone)
351                                 ndl++;
352                         p.tend();
353                         if (p.elapsed() >= TMAX)
354                                 goto escapeloop;
355                 }}
356                 // end of overlap trees
357                 p.tend();
358         }
359 escapeloop:
360         pthread_join(rt, NULL);
361         pthread_join(gt, NULL);
362         float nodo = ((float) ndl / (float) tol);
363         std::cerr << "nothing done is " << 100.0 * nodo;
364         std::cerr << "%" << std::endl;
365         //std::cerr << "rgf is " << p.p_root_.goal_found() << std::endl;
366         //std::cerr << "ggf is " << p.p_goal_.goal_found() << std::endl;
367         //std::cerr << "cgf is " << p.goal_found() << std::endl;
368         if (p.p_root_.goal_found() && p.p_root_.goal()->ccost() < mc) {
369                 ron = p.p_root_.goal()->parent();
370                 gon = p.p_root_.goal();
371                 mc = p.p_root_.goal()->ccost();
372         }
373         if (p.p_goal_.goal_found() && p.p_goal_.goal()->ccost() < mc) {
374                 ron = p.p_goal_.goal();
375                 gon = p.p_goal_.goal()->parent();
376                 mc = p.p_goal_.goal()->ccost();
377         }
378         p.root()->remove_parent();  // needed if p.p_goal_.goal_found()
379         p.root()->ccost(0);
380         p.goal()->children().clear();
381         // connect trees
382         if (gf) {
383         while (gon != p.goal()) {
384                 p.p_root_.nodes().push_back(new RRTNode(
385                                 gon->x(),
386                                 gon->y(),
387                                 gon->h()));
388                 ron->add_child(
389                                 p.p_root_.nodes().back(),
390                                 p.p_root_.cost(
391                                                 ron,
392                                                 p.p_root_.nodes().back()));
393                 ron = p.p_root_.nodes().back();
394                 gon = gon->parent();
395         }
396         ron->add_child(p.goal(), p.p_root_.cost(ron, p.goal()));
397         }
398         // end of connect trees
399         if (gf)
400                 p.tlog(p.findt());
401         if (p.opt_path())
402                 p.tlog(p.findt());
403 #endif
404         TEND();
405         TPRINT("RRT");
406         jvo["rrte"] = ELAPSED;
407 #ifdef JSONLOGEDGES
408         p.logr(p.root());
409 #endif
410
411         // statistics to error output
412         std::cerr << "TELAPSED is " << TELAPSED << std::endl;
413         std::cerr << "Elapsed is " << p.elapsed() << std::endl;
414         std::cerr << "Goal found is " << p.goal_found() << std::endl;
415         std::cerr << "#nodes is " << p.nodes().size() << std::endl;
416         std::cerr << "#samples is " << p.samples().size() << std::endl;
417         std::cerr << "`tlog` size is " << p.tlog().size() << std::endl;
418         std::cerr << "trajectories costs:" << std::endl;
419         for (j = 0; j < p.clog().size(); j++)
420                 std::cerr << "- " << p.clog()[j] << std::endl;
421         std::cerr << "RRT #nodes:" << std::endl;
422         for (j = 0; j < p.nlog().size(); j++)
423                 std::cerr << "- " << p.nlog()[j] << std::endl;
424         std::cerr << "trajectories seconds:" << std::endl;
425         for (j = 0; j < p.slog().size(); j++)
426                 std::cerr << "- " << p.slog()[j] << std::endl;
427         std::cerr << "RRT edges (from root) log size: " << p.rlog().size();
428         std::cerr << std::endl;
429         for (auto edges: p.rlog())
430                 std::cerr << "- " << edges.size() << std::endl;
431
432         // JSON output
433         jvo["elap"] = TELAPSED;
434 #ifdef USE_PTHREAD
435         jvo["nodo"][0] = nodo;
436 #endif
437         // log cost
438         for (j = 0; j < p.clog().size(); j++)
439                 jvo["cost"][j] = p.clog()[j];
440         // log #nodes
441         for (j = 0; j < p.nlog().size(); j++)
442                 jvo["node"][j] = p.nlog()[j];
443         // log seconds
444         for (j = 0; j < p.slog().size(); j++)
445                 jvo["secs"][j] = p.slog()[j];
446         // log traj
447         i = 0;
448         j = 0;
449         for (auto traj: p.tlog()) {
450                 i = 0;
451                 for (auto n: traj) {
452                         jvo["traj"][j][i][0] = n->x();
453                         jvo["traj"][j][i][1] = n->y();
454                         jvo["traj"][j][i][2] = n->h();
455                         jvo["traj"][j][i][3] = n->t();
456                         jvo["traj"][j][i][4] = n->s();
457                         i++;
458                 }
459                 j++;
460         }
461 #ifdef JSONLOGEDGES
462         i = 0;
463         j = 0;
464         for (auto edges: p.rlog()) {
465                 j = 0;
466                 for (auto e: edges) {
467                         jvo["edge"][i][j][0][0] = e->init()->x();
468                         jvo["edge"][i][j][0][1] = e->init()->y();
469                         jvo["edge"][i][j][0][2] = e->init()->h();
470                         jvo["edge"][i][j][1][0] = e->goal()->x();
471                         jvo["edge"][i][j][1][1] = e->goal()->y();
472                         jvo["edge"][i][j][1][2] = e->goal()->h();
473                         j++;
474                 }
475                 i++;
476         }
477 #endif
478 #ifdef JSONLOGSAMPLES
479         i = 0;
480         j = 0;
481         for (auto s: p.samples()) {
482                 jvo["samp"][j][0] = s->x();
483                 jvo["samp"][j][1] = s->y();
484                 jvo["samp"][j][2] = s->h();
485                 j++;
486         }
487 #endif
488         // print output
489         std::cout << jvo << std::endl;
490
491 #if USE_GL > 0
492         SDL_DestroyWindow(gw);
493         SDL_Quit();
494 #endif
495
496         // free mem
497         for (auto o: so) {
498                 delete o.init();
499                 delete o.goal();
500         }
501         return 0;
502 }
503
504 #if USE_GL > 0
505 bool init()
506 {
507         if (SDL_Init(SDL_INIT_VIDEO) < 0) {
508                 std::cerr << "SDL could not initialize! SDL_Error: ";
509                 std::cerr << SDL_GetError();
510                 std::cerr << std::endl;
511                 return false;
512         }
513         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
514         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
515         gw = SDL_CreateWindow(
516                         "I am car",
517                         SDL_WINDOWPOS_UNDEFINED,
518                         SDL_WINDOWPOS_UNDEFINED,
519                         SCREEN_WIDTH,
520                         SCREEN_HEIGHT,
521                         SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
522         if (gw == NULL) {
523                 std::cerr << "Window could not be created! SDL_Error: ";
524                 std::cerr << SDL_GetError();
525                 std::cerr << std::endl;
526                 return false;
527         }
528         gc = SDL_GL_CreateContext(gw);
529         if (gc == NULL) {
530                 std::cerr << "OpenGL context couldn't be created! SDL Error: ";
531                 std::cerr << SDL_GetError();
532                 std::cerr << std::endl;
533                 return false;
534         }
535         if (SDL_GL_SetSwapInterval(1) < 0) {
536                 std::cerr << "Warning: Unable to set VSync! SDL Error: ";
537                 std::cerr << SDL_GetError();
538                 std::cerr << std::endl;
539                 return false;
540         }
541         if (!initGL()) {
542                 std::cerr << "Unable to initialize OpenGL!";
543                 std::cerr << std::endl;
544                 return false;
545         }
546         return true;
547 }
548
549 bool initGL()
550 {
551         GLenum error = GL_NO_ERROR;
552         glMatrixMode(GL_PROJECTION);
553         glLoadIdentity();
554         error = glGetError();
555         if (error != GL_NO_ERROR) {
556                 std::cerr << "Error initializing OpenGL! ";
557                 std::cerr << gluErrorString(error);
558                 std::cerr << std::endl;
559                 return false;
560         }
561         glMatrixMode(GL_MODELVIEW);
562         glLoadIdentity();
563         error = glGetError();
564         if (error != GL_NO_ERROR) {
565                 std::cerr << "Error initializing OpenGL! ";
566                 std::cerr << gluErrorString(error);
567                 std::cerr << std::endl;
568                 return false;
569         }
570         glClearColor(1, 1, 1, 1);
571         error = glGetError();
572         if (error != GL_NO_ERROR) {
573                 std::cerr << "Error initializing OpenGL! ";
574                 std::cerr << gluErrorString(error);
575                 std::cerr << std::endl;
576                 return false;
577         }
578         return true;
579 }
580 #endif