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