]> rtime.felk.cvut.cz Git - hubacji1/iamcar.git/blob - base/main.cc
5a6d4f4193d2cba7d9104b3f1c7da2eaa31edeaa
[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         if (jvi["init"] == Json::nullValue) {
142                 std::cerr << "I need `init` in JSON input scenario";
143                 std::cerr << std::endl;
144                 return 1;
145         }
146
147         if (jvi["goal"] == Json::nullValue) {
148                 std::cerr << "I need `goal` in JSON input scenario";
149                 std::cerr << std::endl;
150                 return 1;
151         }
152
153         PLANNER p(
154                 new RRTNode(
155                         jvi["init"][0].asFloat(),
156                         jvi["init"][1].asFloat(),
157                         jvi["init"][2].asFloat()
158                 ),
159                 new RRTNode(
160                         jvi["goal"][0].asFloat(),
161                         jvi["goal"][1].asFloat(),
162                         jvi["goal"][2].asFloat()
163                 )
164         );
165         p.firsts().push(p.goal());
166         jvo["init"][0] = p.root()->x();
167         jvo["init"][1] = p.root()->y();
168         jvo["init"][2] = p.root()->h();
169         jvo["goal"][0] = jvi["goal"][0].asFloat();
170         jvo["goal"][1] = jvi["goal"][1].asFloat();
171         jvo["goal"][2] = jvi["goal"][2].asFloat();
172
173         if (jvi["goals"] != Json::nullValue) {
174                 for (auto g: jvi["goals"]) {
175                         p.goals().push_back(new RRTNode(
176                                 g[0].asFloat(),
177                                 g[1].asFloat(),
178                                 g[2].asFloat()
179                         ));
180                 }
181         }
182
183         if (jvi["slot"] != Json::nullValue) {
184                 jvo["slot"] = jvi["slot"];
185         }
186
187         std::vector<CircleObstacle> co;
188         std::vector<SegmentObstacle> so;
189         p.HMIN = p.root()->x();
190         p.HMAX = p.root()->x();
191         p.VMIN = p.root()->y();
192         p.VMAX = p.root()->y();
193         j = 0;
194         for (auto o: jvi["obst"]) {
195                 float tmpx;
196                 float tmpy;
197                 float tmpr;
198                 float tmps;
199                 for (i = 0; i < o.size() - 1; i++) {
200                         tmpx = o[i][0].asFloat();
201                         tmpy = o[i][1].asFloat();
202                         tmpr = o[i + 1][0].asFloat();
203                         tmps = o[i + 1][1].asFloat();
204                         so.push_back(SegmentObstacle(
205                                 new RRTNode(tmpx, tmpy, 0),
206                                 new RRTNode(tmpr, tmps, 0)
207                         ));
208                         p.frame().add_bnode(so.back().init());
209                         if (tmpx < p.HMIN) p.HMIN = tmpx;
210                         if (tmpx > p.HMAX) p.HMAX = tmpx;
211                         if (tmpy < p.VMIN) p.VMIN = tmpy;
212                         if (tmpy > p.VMAX) p.VMAX = tmpy;
213                         if (tmpr < p.HMIN) p.HMIN = tmpr;
214                         if (tmpr > p.HMAX) p.HMAX = tmpr;
215                         if (tmps < p.VMIN) p.VMIN = tmps;
216                         if (tmps > p.VMAX) p.VMAX = tmps;
217
218                         // output
219                         jvo["obst"][j][i][0] = tmpx;
220                         jvo["obst"][j][i][1] = tmpy;
221                 }
222                 jvo["obst"][j][i][0] = tmpr;
223                 jvo["obst"][j][i][1] = tmps;
224                 j++;
225         }
226         p.defaultSamplingInfo();
227         p.link_obstacles(&co, &so);
228         p.ocost(p.root());
229         p.ocost(p.goal());
230
231 #ifdef USE_LOADF
232         std::vector<RRTNode *> steered;
233         for (auto jn: jvi["traj"][0]) {
234                 steered.push_back(new RRTNode(
235                                         jn[0].asFloat(),
236                                         jn[1].asFloat(),
237                                         jn[2].asFloat(),
238                                         jn[3].asFloat(),
239                                         jn[4].asFloat()));
240         }
241         std::reverse(steered.begin(), steered.end());
242         RRTNode *pn = p.root();
243         for (auto n: steered) {
244                 if (IS_NEAR(pn, n))
245                         continue;
246                 pn->add_child(n, p.cost(pn, n));
247                 pn = n;
248                 p.glplot();
249         }
250         pn->add_child(p.goal(), p.cost(pn, p.goal()));
251         p.goal_found(true);
252         p.tlog(p.findt());
253         if (p.opt_path()) {
254                 p.tlog(p.findt());
255                 p.glplot();
256         }
257         p.glplot();
258         sleep(2);
259 #elif defined USE_INTERRUPT
260         signal(SIGINT, hint);
261         signal(SIGTERM, hint);
262         p.tstart();
263         while (run_planner) {
264                 p.next();
265                 p.tend();
266                 if (p.opt_path())
267                         p.tlog(p.findt());
268                 p.glplot();
269         }
270 #elif defined USE_TMAX
271         p.tstart();
272         p.tend();
273         while (!p.goal_found() && p.elapsed() < TMAX) {
274                 p.next();
275                 p.tend();
276                 if (p.opt_path()) {
277                         p.tlog(p.findt());
278                 }
279         }
280         p.tend();
281         jvo["time"] = p.elapsed();
282 #elif defined USE_PTHREAD
283         bool gf = false;
284         RRTNode *ron = nullptr;
285         RRTNode *gon = nullptr;
286         float mc = 9999;
287         pthread_t rt; // root thread
288         pthread_t gt; // goal thread
289         pthread_t ct; // connect thread
290
291         struct next_arg ra;
292         ra.gf = &gf;
293         ra.p = &p.p_root_;
294
295         struct next_arg ga;
296         ga.gf = &gf;
297         ga.p = &p.p_goal_;
298
299         p.tstart();
300         p.p_root_.tstart();
301         p.p_goal_.tstart();
302         pthread_create(&rt, NULL, &next_run, (void *) &ra);
303         pthread_create(&gt, NULL, &next_run, (void *) &ga);
304         int tol = 0;
305         int ndl = 0;
306         bool ndone = true;
307         while (!gf && p.elapsed() < TMAX &&
308                         p.p_root_.nodes().size() < NOFNODES &&
309                         p.p_goal_.nodes().size() < NOFNODES) {
310                 // overlap trees
311                 ndone = true;
312                 for (int i = 0; i < IXSIZE; i++) {
313                 for (int j = 0; j < IYSIZE; j++) {
314                         if (p.p_root_.ixy_[i][j].changed() &&
315                                         p.p_goal_.ixy_[i][j].changed()) {
316 ndone = false;
317 for (auto rn: p.p_root_.ixy_[i][j].nodes()) {
318 for (auto gn: p.p_goal_.ixy_[i][j].nodes()) {
319         if (rn->ccost() + gn->ccost() < mc &&
320                         IS_NEAR(rn, gn)) {
321                 gf = true;
322                 p.goal_found(true);
323                 ron = rn;
324                 gon = gn;
325                 mc = rn->ccost() + gn->ccost();
326         }
327 }}
328                         }
329                         tol++;
330                         if (ndone)
331                                 ndl++;
332                         p.tend();
333                         if (p.elapsed() >= TMAX)
334                                 goto escapeloop;
335                 }}
336                 // end of overlap trees
337                 p.tend();
338         }
339 escapeloop:
340         pthread_join(rt, NULL);
341         pthread_join(gt, NULL);
342         float nodo = ((float) ndl / (float) tol);
343         std::cerr << "nothing done is " << 100.0 * nodo;
344         std::cerr << "%" << std::endl;
345         //std::cerr << "rgf is " << p.p_root_.goal_found() << std::endl;
346         //std::cerr << "ggf is " << p.p_goal_.goal_found() << std::endl;
347         //std::cerr << "cgf is " << p.goal_found() << std::endl;
348         if (p.p_root_.goal_found() && p.p_root_.goal()->ccost() < mc) {
349                 ron = p.p_root_.goal()->parent();
350                 gon = p.p_root_.goal();
351                 mc = p.p_root_.goal()->ccost();
352         }
353         if (p.p_goal_.goal_found() && p.p_goal_.goal()->ccost() < mc) {
354                 ron = p.p_goal_.goal();
355                 gon = p.p_goal_.goal()->parent();
356                 mc = p.p_goal_.goal()->ccost();
357         }
358         p.root()->remove_parent();  // needed if p.p_goal_.goal_found()
359         p.root()->ccost(0);
360         p.goal()->children().clear();
361         // connect trees
362         if (gf) {
363         while (gon != p.goal()) {
364                 p.p_root_.nodes().push_back(new RRTNode(
365                                 gon->x(),
366                                 gon->y(),
367                                 gon->h()));
368                 ron->add_child(
369                                 p.p_root_.nodes().back(),
370                                 p.p_root_.cost(
371                                                 ron,
372                                                 p.p_root_.nodes().back()));
373                 ron = p.p_root_.nodes().back();
374                 gon = gon->parent();
375         }
376         ron->add_child(p.goal(), p.p_root_.cost(ron, p.goal()));
377         }
378         // end of connect trees
379         if (gf)
380                 p.tlog(p.findt());
381         if (p.opt_path())
382                 p.tlog(p.findt());
383 #endif
384         TEND();
385         TPRINT("RRT");
386         jvo["rrte"] = ELAPSED;
387 #ifdef JSONLOGEDGES
388         p.logr(p.root());
389 #endif
390
391         // statistics to error output
392         std::cerr << "TELAPSED is " << TELAPSED << std::endl;
393         std::cerr << "Elapsed is " << p.elapsed() << std::endl;
394         std::cerr << "Goal found is " << p.goal_found() << std::endl;
395         std::cerr << "#nodes is " << p.nodes().size() << std::endl;
396         std::cerr << "#samples is " << p.samples().size() << std::endl;
397         std::cerr << "`tlog` size is " << p.tlog().size() << std::endl;
398         std::cerr << "trajectories costs:" << std::endl;
399         for (j = 0; j < p.clog().size(); j++)
400                 std::cerr << "- " << p.clog()[j] << std::endl;
401         std::cerr << "RRT #nodes:" << std::endl;
402         for (j = 0; j < p.nlog().size(); j++)
403                 std::cerr << "- " << p.nlog()[j] << std::endl;
404         std::cerr << "trajectories seconds:" << std::endl;
405         for (j = 0; j < p.slog().size(); j++)
406                 std::cerr << "- " << p.slog()[j] << std::endl;
407         std::cerr << "RRT edges (from root) log size: " << p.rlog().size();
408         std::cerr << std::endl;
409         for (auto edges: p.rlog())
410                 std::cerr << "- " << edges.size() << std::endl;
411
412         // JSON output
413         jvo["elap"] = TELAPSED;
414 #ifdef USE_PTHREAD
415         jvo["nodo"][0] = nodo;
416 #endif
417         // log cost
418         for (j = 0; j < p.clog().size(); j++)
419                 jvo["cost"][j] = p.clog()[j];
420         // log #nodes
421         for (j = 0; j < p.nlog().size(); j++)
422                 jvo["node"][j] = p.nlog()[j];
423         // log seconds
424         for (j = 0; j < p.slog().size(); j++)
425                 jvo["secs"][j] = p.slog()[j];
426         // log traj
427         i = 0;
428         j = 0;
429         for (auto traj: p.tlog()) {
430                 i = 0;
431                 for (auto n: traj) {
432                         jvo["traj"][j][i][0] = n->x();
433                         jvo["traj"][j][i][1] = n->y();
434                         jvo["traj"][j][i][2] = n->h();
435                         jvo["traj"][j][i][3] = n->t();
436                         jvo["traj"][j][i][4] = n->s();
437                         i++;
438                 }
439                 if (j == p.tlog().size() - 1) {
440                         i = 0;
441                         for (auto n: traj) {
442                                 jvo["path"][i][0] = n->x();
443                                 jvo["path"][i][1] = n->y();
444                                 jvo["path"][i][2] = n->h();
445                                 i++;
446                         }
447                 }
448                 j++;
449         }
450         jvo["goals"][0][0] = p.tlog()[p.tlog().size() - 1].front()->x();
451         jvo["goals"][0][1] = p.tlog()[p.tlog().size() - 1].front()->y();
452         jvo["goals"][0][2] = p.tlog()[p.tlog().size() - 1].front()->h();
453 #ifdef JSONLOGEDGES
454         i = 0;
455         j = 0;
456         for (auto edges: p.rlog()) {
457                 j = 0;
458                 for (auto e: edges) {
459                         jvo["edge"][i][j][0][0] = e->init()->x();
460                         jvo["edge"][i][j][0][1] = e->init()->y();
461                         jvo["edge"][i][j][0][2] = e->init()->h();
462                         jvo["edge"][i][j][1][0] = e->goal()->x();
463                         jvo["edge"][i][j][1][1] = e->goal()->y();
464                         jvo["edge"][i][j][1][2] = e->goal()->h();
465                         j++;
466                 }
467                 i++;
468         }
469 #endif
470 #ifdef JSONLOGSAMPLES
471         i = 0;
472         j = 0;
473         for (auto s: p.samples()) {
474                 jvo["samp"][j][0] = s->x();
475                 jvo["samp"][j][1] = s->y();
476                 jvo["samp"][j][2] = s->h();
477                 j++;
478         }
479 #endif
480         // print output
481         std::cout << jvo << std::endl;
482
483 #if USE_GL > 0
484         SDL_DestroyWindow(gw);
485         SDL_Quit();
486 #endif
487
488         // free mem
489         for (auto o: so) {
490                 delete o.init();
491                 delete o.goal();
492         }
493         return 0;
494 }
495
496 #if USE_GL > 0
497 bool init()
498 {
499         if (SDL_Init(SDL_INIT_VIDEO) < 0) {
500                 std::cerr << "SDL could not initialize! SDL_Error: ";
501                 std::cerr << SDL_GetError();
502                 std::cerr << std::endl;
503                 return false;
504         }
505         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
506         SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
507         gw = SDL_CreateWindow(
508                         "I am car",
509                         SDL_WINDOWPOS_UNDEFINED,
510                         SDL_WINDOWPOS_UNDEFINED,
511                         SCREEN_WIDTH,
512                         SCREEN_HEIGHT,
513                         SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
514         if (gw == NULL) {
515                 std::cerr << "Window could not be created! SDL_Error: ";
516                 std::cerr << SDL_GetError();
517                 std::cerr << std::endl;
518                 return false;
519         }
520         gc = SDL_GL_CreateContext(gw);
521         if (gc == NULL) {
522                 std::cerr << "OpenGL context couldn't be created! SDL Error: ";
523                 std::cerr << SDL_GetError();
524                 std::cerr << std::endl;
525                 return false;
526         }
527         if (SDL_GL_SetSwapInterval(1) < 0) {
528                 std::cerr << "Warning: Unable to set VSync! SDL Error: ";
529                 std::cerr << SDL_GetError();
530                 std::cerr << std::endl;
531                 return false;
532         }
533         if (!initGL()) {
534                 std::cerr << "Unable to initialize OpenGL!";
535                 std::cerr << std::endl;
536                 return false;
537         }
538         return true;
539 }
540
541 bool initGL()
542 {
543         GLenum error = GL_NO_ERROR;
544         glMatrixMode(GL_PROJECTION);
545         glLoadIdentity();
546         error = glGetError();
547         if (error != GL_NO_ERROR) {
548                 std::cerr << "Error initializing OpenGL! ";
549                 std::cerr << gluErrorString(error);
550                 std::cerr << std::endl;
551                 return false;
552         }
553         glMatrixMode(GL_MODELVIEW);
554         glLoadIdentity();
555         error = glGetError();
556         if (error != GL_NO_ERROR) {
557                 std::cerr << "Error initializing OpenGL! ";
558                 std::cerr << gluErrorString(error);
559                 std::cerr << std::endl;
560                 return false;
561         }
562         glClearColor(1, 1, 1, 1);
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         return true;
571 }
572 #endif