mission_planning_client.cpp
Go to the documentation of this file.
1 /**************************************************************************************************
2  Software License Agreement (BSD License)
3 
4  Copyright (c) 2011-2015, LAR toolkit developers - University of Aveiro - http://lars.mec.ua.pt
5  All rights reserved.
6 
7  Redistribution and use in source and binary forms, with or without modification, are permitted
8  provided that the following conditions are met:
9 
10  *Redistributions of source code must retain the above copyright notice, this list of
11  conditions and the following disclaimer.
12  *Redistributions in binary form must reproduce the above copyright notice, this list of
13  conditions and the following disclaimer in the documentation and/or other materials provided
14  with the distribution.
15  *Neither the name of the University of Aveiro nor the names of its contributors may be used to
16  endorse or promote products derived from this software without specific prior written permission.
17 
18  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
19  IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
20  FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
21  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
24  IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
25  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 ***************************************************************************************************/
27 
28 /*
29 @file
30 @brief
31 This is the client file, it will establish a connection with the gps receiver , a database and comunicate with the mission_planning_node
32 */
33 #include <iostream>
34 #include <ros/ros.h>
35 #include <sensor_msgs/NavSatFix.h>
36 
37 #include<mission_planning/Path.h>
38 
39 #include <vector>
40 #include <math.h>
41 
42 #include <postgresql/libpq-fe.h>
43 #include <string>
44 
45 #include <utility> //std::pair
46 
47 #define d2r (M_PI / 180.0) //degree to radians
48 
49 /*
50 @brief
51 The following object is the pointer that will handle a connection to a database
52 @param user
53 This is the user that has access to the database
54 @param password
55 Password required to establish a connection to the database
56 @param dbname
57 Name of the database that hold our tables
58 @param hostaddr
59 Ip of our database server, in this case because it is on our computer and launched as localhost, it will be 127.0.0.1
60 @param port
61 The port to connect to the database
62 */
63 //PGconn *conn = PQconnectdb("user=ivan password=ivanferreira dbname=ivan hostaddr=127.0.0.1 port=5432");
64 PGconn *conn = PQconnectdb("user=atlas password=atlascar dbname=atlas_navigation hostaddr=127.0.0.1 port=5432");
65 
66 /*
67 @brief
68 Function to disconnect from the database
69 @param conn
70 connection handle
71 @return void
72 */
73 /* Close connection to database */
74 void CloseConn(PGconn *conn)
75 {
76  PQfinish(conn);
77  printf("Database Disconnected - OK\n");
78  //getchar(); //waits for user input
79  exit(1); //terminates program -- remove later
80 }
81 /*
82 @brief
83 Establishes a connection to a database, in case success or fail a message appears in the console
84 @return conn
85 */
86 /* Establish connection to database */
87 PGconn *ConnectDB()
88 {
89  PGconn *conn = NULL;
90 
91  // Make a connection to the database
92  //conn = PQconnectdb("user=ivan password=ivanferreira dbname=ivan hostaddr=127.0.0.1 port=5432");
93  conn = PQconnectdb("user=atlas password=atlascar dbname=atlas_navigation hostaddr=127.0.0.1 port=5432");
94 
95  // Check to see that the backend connection was successfully made
96  if (PQstatus(conn) != CONNECTION_OK)
97  {
98  printf("Connection to database failed");
99  CloseConn(conn);
100  }
101 
102  printf("Connection to database - OK\n");
103 
104  return conn;
105 }
106 
107 void DBConnectionCheck(PGconn *conn){
108 
109  // Check to see that the backend connection was successfully made
110  if (PQstatus(conn) != CONNECTION_OK)
111  {
112  printf("Connection to database failed");
113  CloseConn(conn);
114  }
115 
116  printf("Connection to database - OK\n");
117 }
118 /*
119 @brief
120 An example function. Is not used.
121 */
122 /* Append SQL statement and insert record into specific table, NOT used, serves as an example */
123 void InsertEmployeeRec(PGconn *conn, double fname)//void InsertEmployeeRec(PGconn *conn, char * fname, char * lname)
124 {
125  // Append the SQL statment
126  /* std::string sSQL;
127  sSQL.append("INSERT INTO closest_waypoint_table VALUES ('");
128  sSQL.append(fname);
129  sSQL.append("')");*/
130  // std::string sSQL = "INSERT INTO closest_waypoint_table (closest_index) VALUES ('"+ std::to_string(fname) + "')";
131  std::string sSQL = "INSERT INTO random (rand_stuff) VALUES ("+ std::to_string(fname) + ")";
132  // Execute with sql statement
133  PGresult *res = PQexec(conn, sSQL.c_str());
134 
135  if (PQresultStatus(res) != PGRES_COMMAND_OK)
136  {
137  printf("Insert employee record failed");
138  PQclear(res);
139  CloseConn(conn);
140  }
141 
142  printf("Insert employee record - OK\n");
143 
144  // Clear result
145  PQclear(res);
146 }
147 
148 /* Erase all record in specific table, NOT used, serves as an example */
150 {
151  // Execute with sql statement
152  PGresult *res = PQexec(conn, "DELETE FROM random");
153 
154  if (PQresultStatus(res) != PGRES_COMMAND_OK)
155  {
156  printf("Delete employees record failed.");
157  PQclear(res);
158  CloseConn(conn);
159  }
160 
161  printf("\nDelete employees record - OK\n");
162 
163  // Clear result
164  PQclear(res);
165 }
166 /*
167 @brief
168 Function to insert the gps coordinates into the table named gps_coord_table
169 @param conn
170 Connection handler
171 @param sensor_msgs::NavSatFixPtr
172 Contains the coordinates from the gps
173 @return void
174 */
175 // Insert gps coordinates into table
176 void InsertGpsCoordRec(PGconn *conn, const sensor_msgs::NavSatFixPtr &gps)
177 {
178  std::string sSQL = "INSERT INTO gps_coord_table (gps_lat,gps_lon) VALUES ("+ std::to_string(gps->latitude) + "," +std::to_string(gps->longitude)+ ")";
179 
180  PGresult *res = PQexec(conn, sSQL.c_str());
181 
182  if (PQresultStatus(res) != PGRES_COMMAND_OK)
183  {
184  printf("Insert gps coordinates record failed");
185  PQclear(res);
186  CloseConn(conn);
187  }
188 
189  printf("Insert gps coordinates record - OK\n");
190 
191  // Clear result
192  PQclear(res);
193 }
194 /*
195 @brief
196 Function that inserts the waypoints into the table named waypoint_table
197 @param conn
198 connection handler
199 @param mission_planning::Path::Response
200 contains the waypoints and instructions sent by the mission_planning_node
201 @return void
202 */
203 // Insert Waypoint into table //NEEDS REWORK INCOMPATIBLE TYPES
204 
205 void InsertWaypointsRec(PGconn *conn, const mission_planning::Path::Response &resp)
206 {
207  for (int i = 0; i < resp.lat.size(); ++i)
208  {
209  double glat = resp.lat[i];
210  double glon = resp.lon[i];
211  std::string ginst = resp.instruction[i];
212  // std::string sSQL = "INSERT INTO waypoint_table (way_lat,way_lon,instruction) VALUES ("+ std::to_string(resp.lat[i]) + "," + std::to_string(resp.lon[i])+ "," + std::to_string(resp.instruction[i]) + ")";
213  std::string sSQL = "INSERT INTO waypoint_table (way_lat,way_lon,instruction) VALUES ("+ std::to_string(glat) + "," + std::to_string(glon)+ ",'" + ginst + "')";
214 
215  PGresult *res = PQexec(conn, sSQL.c_str());
216 
217  if (PQresultStatus(res) != PGRES_COMMAND_OK)
218  {
219  printf("Insert waypoints record failed: %s", PQerrorMessage(conn));
220  PQclear(res);
221  CloseConn(conn);
222  }
223 
224  printf("Insert waypoints record - OK\n");
225 
226  // Clear result
227  PQclear(res);
228  }
229 
230 }
231 /*
232 @brief
233 Insert the closest waypoint into the table named closest_waypoint_table
234 @param conn
235 connection handler
236 @param closestwaypoint
237 contains the closest waypoint
238 @return void
239 */
240 //Insert Closest Waypoint into table
241 void InsertClosestWaypointRec(PGconn *conn, int closestwaypoint)
242 {
243  std::string sSQL = "INSERT INTO closest_waypoint_table (closest_index) VALUES ("+ std::to_string(closestwaypoint) +")";
244 
245  PGresult *res = PQexec(conn, sSQL.c_str());
246 
247  if (PQresultStatus(res) != PGRES_COMMAND_OK)
248  {
249  printf("Insert Closest Waypoint record failed");
250  PQclear(res);
251  CloseConn(conn);
252  }
253 
254  printf("Insert Closest Waypoint - OK\n");
255 
256  // Clear result
257  PQclear(res);
258 }
259 /*
260 @brief
261 Function that inserts the next instruction into the table named next_inst_table
262 @param conn
263 connection handler
264 @param mission_planning::Path::Response
265 contains the waypoints and instructions sent by the mission_planning_node
266 @param nextinstruction
267 contains the next instruction that needs to be executed
268 @return void
269 */
270 //Insert Next Instruction into table BETA
271 void InsertNextInstructionRec (PGconn *conn, const mission_planning::Path::Response &resp, int nextinstruction)
272 {
273  std::string ginst = resp.instruction[nextinstruction];
274  std::string sSQL = "INSERT INTO next_inst_table (next_inst) VALUES ('" + ginst + "')";
275  PGresult *res = PQexec(conn, sSQL.c_str());
276 
277  if (PQresultStatus(res) != PGRES_COMMAND_OK)
278  {
279  printf("Insert Next Instruction record failed");
280  PQclear(res);
281  CloseConn(conn);
282  }
283 
284  printf("Insert Next Instruction - OK\n");
285 
286  // Clear result
287  PQclear(res);
288 }
289 /*
290 @brief
291 This function deletes all values from all tables
292 @param conn
293 connection handler
294 @return void
295 */
296 /* Erase all record in all tables */
298 {
299  //--------------------- Table I ---------------
300  // Execute with sql statement
301  PGresult *res1 = PQexec(conn, "DELETE FROM closest_waypoint_table");
302 
303  if (PQresultStatus(res1) != PGRES_COMMAND_OK)
304  {
305  printf("Delete closest waypoint record failed.");
306  PQclear(res1);
307  CloseConn(conn);
308  }
309 
310  printf("\nDelete closest waypoint record - OK\n");
311 
312  // Clear result
313  PQclear(res1);
314 
315  //--------------------- Table II ---------------
316  // Execute with sql statement
317  PGresult *res2 = PQexec(conn, "DELETE FROM waypoint_table");
318 
319  if (PQresultStatus(res2) != PGRES_COMMAND_OK)
320  {
321  printf("Delete waypoint table record failed.");
322  PQclear(res2);
323  CloseConn(conn);
324  }
325 
326  printf("\nDelete waypoint table record - OK\n");
327 
328  // Clear result
329  PQclear(res2);
330 
331  //--------------------- Table III ---------------
332  // Execute with sql statement
333  PGresult *res3 = PQexec(conn, "DELETE FROM gps_coord_table");
334 
335  if (PQresultStatus(res3) != PGRES_COMMAND_OK)
336  {
337  printf("Delete gps coordinates record failed.");
338  PQclear(res3);
339  CloseConn(conn);
340  }
341 
342  printf("\nDelete gps coordinates record - OK\n");
343 
344  // Clear result
345  PQclear(res3);
346 
347  //--------------------- Table IV ---------------
348  // Execute with sql statement
349  PGresult *res4 = PQexec(conn, "DELETE FROM next_inst_table");
350 
351  if (PQresultStatus(res4) != PGRES_COMMAND_OK)
352  {
353  printf("Delete next instruction record failed.");
354  PQclear(res4);
355  CloseConn(conn);
356  }
357 
358  printf("\nDelete next instruction record - OK\n");
359 
360  // Clear result
361  PQclear(res4);
362 }
363 /*
364 @brief
365 Example function to fetch a result from a database. This function is not beeing used.
366 */
367 /* Fetch destination record and return a vector containing the data */
368 std::vector<std::string> FetchEmployeeRec(PGconn *conn){
369 
370  PGresult *res = PQexec(conn,"SELECT * FROM destination_table ORDER BY dest_id DESC LIMIT 1;");
371  int rec_count;
372 
373  if (PQresultStatus(res) != PGRES_TUPLES_OK) {
374  printf("No data in table, make sure you submited a valid destination from the Webpage ! Try again");
375  PQclear(res);
376  CloseConn(conn);
377  }
378 
379  rec_count = PQntuples(res);
380 
381  printf("Obtained %d records.\n", rec_count);
382 
383  std::vector<std::string> destRecord;
384 
385  for (int row=0; row<rec_count; row++) {
386 
387  //printf("%s\t", PQgetvalue(res, row, col));
388  destRecord.push_back(PQgetvalue(res, row, 1)); //dest_lat
389  destRecord.push_back(PQgetvalue(res, row, 2)); //dest_lon
390  std::cout << destRecord[0] << std::endl;
391  std::cout << destRecord[1] << std::endl;
392  }
393 
394  PQclear(res);
395  return destRecord;
396 
397 }
398 /*
399 @brief
400 Function that calculates the haversine distance between two gps coordinates.
401 Returns the distance calculated in km.
402 @param lat1
403 actual latitude
404 @param lon1
405 actual longitude
406 @param lat2
407 next latitude
408 @param lon2
409 next longitude
410 @return d Distance in kilometers
411 */
412 //calculate haversine distance for linear distance (distance between two gps coordinates)
413 double haversine_km(double lat1, double lon1, double lat2, double lon2)
414 {
415  double dlon = (lon2 - lon1) * d2r;
416  double dlat = (lat2 - lat1) * d2r;
417  double a = pow(sin(dlat/2.0), 2) + cos(lat1*d2r) * cos(lat2*d2r) * pow(sin(dlon/2.0), 2);
418  double c = 2 * atan2(sqrt(a), sqrt(1-a));
419  double d = 6371 * c; //mean earth radius 6371KM
420 
421  return d; //returns distance in km
422 }
423 /*
424 @brief
425 Function that calculates the shortest distance between the current position and all waypoints.
426 Returns the index of the shortest distance in the waypoints array.
427 @param sensor_msgs::NavSatFixPtr
428 contains the current gps coordinates
429 @param mission_planning::Path::Response
430 contains the waypoints and instructions sent by the mission_planning_node
431 @return min_index index of the shortest distance in the waypoints array
432 */
433 //euclidian Distance function
434 double shortestDistance(const sensor_msgs::NavSatFixPtr &gps,const mission_planning::Path::Response& resp){
435 
436  //new vector to hold all calculated distances
437  std::vector<double> allDists;
438  //clear all elements in vector allDists ! Guess its not required ... the destructor does the job .
439  allDists.clear();
440 
441  //loop through all elements in the response and calculate the minimum distance (euclidian distance) between the
442  // actual gps point and all waypoints. store the distances in the allDist vector
443  for (int i = 0; i < resp.lat.size(); ++i) {
444  /*
445  double x = resp.lat.at(i) - gps->latitude;
446  double y = resp.lon.at(i) - gps->longitude;
447  // double x = resp.lat.at(i) - 40.634062;//40.63179
448  // double y = resp.lon.at(i) - -8.657999;//-8.65712
449  double dist = pow(x,2) + pow(y,2);
450  dist = sqrt(dist);
451  */
452  double dist = haversine_km(resp.lat.at(i),resp.lon.at(i),gps->latitude,gps->longitude);
453  allDists.push_back(dist);
454  }
455 
456  //get the index of the smallest element in the allDist vector
457  int min_index = std::min_element(allDists.begin(), allDists.end()) - allDists.begin();
458  /*
459  //recommended usage
460  int indexOfSmallestElement = distance(vec.begin(),min_element(vec.begin(),vec.end()));
461  //returns the smallest element found in the allDist vector
462  return allDists.at(min_index);//checks for out_of_bounds
463  */
464  //std::cout << "Closest waypoint to the current gps location is: " << resp.lat[min_index] << resp.lon[min_index] << std::endl;
465  //return allDists[min_index];//faster access
466 
467  return min_index;//return only min_index !!!! access out of this function to the resp.lat[min_index]
468 
469 }
470 /*
471 @brief
472 Function that checks if the car went out of route.
473 If the car goes away from the next two waypoints and the distance increases and passes the 75m, this function will trigger.
474 @param sensor_msgs::NavSatFixPtr
475 contains the current gps coordinates
476 @param mission_planning::Path::Response
477 contains the waypoints and instructions sent by the mission_planning_node
478 @return current instruction or next instruction
479 */
480 //checks if from the closest waypoint to 75 further if there is any instruction BETA
481 double nextInst(const sensor_msgs::NavSatFixPtr &gps,const mission_planning::Path::Response& resp){
482  //new vector to hold all calculated distances
483  std::vector<double> allDists;
484  //clear all elements in vector allDists ! Guess its not required ... the destructor does the job .
485  allDists.clear();
486 
487  //loop through all elements in the response and calculate the minimum distance (euclidian distance) between the
488  // actual gps point and all waypoints. store the distances in the allDist vector
489  for (int i = 0; i < resp.lat.size(); ++i) {
490 
491  double dist = haversine_km(resp.lat.at(i),resp.lon.at(i),gps->latitude,gps->longitude);
492 
493  allDists.push_back(dist); //fazer push back apenas se a distancia for inferior ou igual a 75m !
494 
495  }
496 
497  //get the index of the smallest element in the allDist vector
498  int min_index = std::min_element(allDists.begin(), allDists.end()) - allDists.begin();
499 
500 
501  std::vector<double> smallerthan (allDists.size()); //will hold all distances shorter than 75m
502 
503  // copy only numbers smaller than 75meters into smallerthan vector , starting at the next waypoint after the smallest distance
504  auto it = std::copy_if (allDists.begin()+min_index+1, allDists.end(), smallerthan.begin(), [](int i){return (i<=0.075);} );
505  smallerthan.resize(std::distance(smallerthan.begin(),it)); // shrink container to new size
506  //vector smallerthan contains now the distances shorter than 75meters
507 
508  std::vector<int> posis; //will contain the index of the instructions under 75meter
509 
510  for(int i=0; i<smallerthan.size(); ++i)
511  {
512  auto it2=find(allDists.begin(),allDists.end(),smallerthan[i]); //gets the index in foo of the distances in bar
513  //it++;
514  int pos = distance(allDists.begin(), it2);
515  //std::cout <<"position index in foo " <<pos << "\n";
516  posis.push_back(pos);
517  }
518 
519  //WHAT IF THERE IS NO VALID INSTRUCTION ?, WHAT IF ALL ARE EMPTY ? WHAT DO I RETURN ?
520  std::vector<int> validinstr; //will hold any valid instructions , not empty ones
521 
522  if(posis.size() > 0){ //make sure there is any instruction ( any distance under 75m)
523  for (int i=0;i<posis.size();i++) { //scann all instructions
524  if(!resp.instruction[posis[i]].empty()) //if string in instructions is not empty return it
525  {
526  std::cout << "Return this instruction, or better, return the index that contains the instruction" << "\n";
527  validinstr.push_back(posis[i]);
528  }
529  }
530  }
531  if (validinstr.size() > 0) //if the vector contains any instruction
532  {
533  int valid_inst = validinstr[0];
534  return valid_inst; //this is the index that contains the first next valid instruction
535  }
536  else
537  {
538  return min_index; //case there are no instructions return the current instruction
539  }
540 
541 }
542 /*
543 @brief
544 Function that calculates the distance between the current and the next waypoint
545 @param sensor_msgs::NavSatFixPtr
546 contains the current gps coordinates
547 @param mission_planning::Path::Response
548 contains the waypoints and instructions sent by the mission_planning_node
549 @param minimumIndex
550 current closest waypoint
551 @return pair of the closest distance and next distance
552 */
553 std::pair<double,double> wrongDirection (const sensor_msgs::NavSatFixPtr &gps, const mission_planning::Path::Response &resp, int minimumIndex){
554 
555  double distance1 = 0;
556  double distance2 = 0;
557 
558  if(minimumIndex+1 <= resp.lat.size()){
559 
560  distance1 = haversine_km(resp.lat.at(minimumIndex),resp.lon.at(minimumIndex),gps->latitude,gps->longitude); //ponto actual mais proximo
561  distance2 = haversine_km(resp.lat.at(minimumIndex+1),resp.lon.at(minimumIndex+1),gps->latitude,gps->longitude); //ponto seguinte mais proximo
562  }
563 
564  return std::make_pair(distance1,distance2);
565  //return std::make_pair(-1,-1); ou 0,0 !!!
566 }
567 
568 /*
569 bool wrongDirection (const sensor_msgs::NavSatFixPtr &gps, const mission_planning::Path::Response &resp){
570  //new vector to hold all calculated distances
571  std::vector<double> allDistsNow;
572  std::vector<double> allDistsNext;
573  //loop through all elements in the response and calculate the minimum distance (euclidian distance) between the
574  // actual gps point and all waypoints. store the distances in the allDist vector
575  for (int i = 0; i < resp.lat.size()-1; ++i) {
576 
577  double distance1 = haversine_km(resp.lat.at(i),resp.lon.at(i),gps->latitude,gps->longitude); //ponto actual mais proximo
578  double distance2 = haversine_km(resp.lat.at(i+1),resp.lon.at(i+1),gps->latitude,gps->longitude); //ponto seguinte mais proximo
579 
580  allDistsNow.push_back(distance1);
581  allDistsNext.push_back(distance2);
582 
583  if (allDistsNow.size()>2 && allDistsNext.size()>2)
584  {
585  //check if moving in wrong direction
586  for (int j = 0; j < allDistsNow.size()-1; ++j) {
587  if (allDistsNow[j+1] > allDistsNow[j] && allDistsNext[j+1] > allDistsNext[j])
588  {
589  //Need to check for a specific distance or wait some time before recalculating
590  // if(allDistsNow[j+1]>=0.1 && allDistsNext[j+1]>=0.1); //distance greater than 100M
591  if(allDistsNow[j]>=0.1 && allDistsNext[j]>=0.1); //distance greater than 100M
592  std::cout << "Moving into wrong direction...Recalculating path..." << std::endl;
593  return true;
594  }
595  else
596  {
597  return false;
598  }
599  }
600  }
601  }
602 }
603 */
604 /*
605 @brief
606 Class that handles the connection with the gps (subscribes to the topic where the gps publishes data).
607 Everytime a new coordinate arrives from the gps, the gpscallback function is called and the code inside it is executed.
608 Contains the console menu, that accepts a user input.
609 */
610 class GpsTest
611 {
612 public:
613 
614  // Constructor
615  GpsTest(ros::NodeHandle nh_) : n(nh_) //n vai ser uma copia do nodehandle da class gpsTest
616  {
617  hasData = false; //checks if response contains data
618  client = n.serviceClient<mission_planning::Path>("return_path"); //initialize client
619  // Subscribing to the topic /fix (novatel lib -> topic /gps_fix)
620  gps_sub = n.subscribe("/gps_fix_psr", 100, &GpsTest::gpsCallback, this);//vai ser criada uma nova instacia gps_sub, que subscreve o topico /gps_fix_psr e chama a função gpsCallback
621  }
622 
623  // Callback Function for the GPS
624  void gpsCallback(const sensor_msgs::NavSatFixPtr &msg)
625  {
626  if(!hasData){
627  //Request class
628  mission_planning::Path::Request req;
629 
630  //ASK THE USER WHERE HE WANTS TO GO
631  std::cout << "Choose locations or insert coordinates Lat/Lon " << std::endl;
632  std::cout << "Option 1: DEM " << std::endl;
633  std::cout << "Option 2: IT " << std::endl;
634  std::cout << "Option 3: CRASTO " << std::endl;
635  std::cout << "Option 4: REITORIA " << std::endl;
636  std::cout << "Option 5: GARAGEM " << std::endl;
637  std::cout << "Option 6: PRAIA DA BARRA " << std::endl;
638  std::cout << "Option 7: CUSTOM DESTINATION (ex: 40.629418 ; -8.658260)" << std::endl;
639  std::cout << "Option 8: DESTINATION FROM WEBPAGE, SELECT A VALID DESTINATION FROM THE WEBPAGE FIRST THEN PRESS 8 " << std::endl;
640  int anwser; int customLat; int customLon;
641  std::cin >> anwser ;
642  switch (anwser) {
643  case 1:
644  req.destLat = 40.629418;
645  req.destLon = -8.658260;
646  break;
647  case 2:
648  req.destLat = 40.643282;
649  req.destLon = -8.659614;
650  break;
651  case 3:
652  req.destLat = 40.623604;
653  req.destLon = -8.657467;
654  break;
655  case 4:
656  req.destLat = 40.631689;
657  req.destLon = -8.657190;
658  break;
659  case 5:
660  req.destLat = 40.634114;
661  req.destLon = -8.657181;
662  break;
663  case 6:
664  req.destLat = 40.633250;
665  req.destLon = -8.745934;
666  break;
667  case 7:
668  std::cin >> customLat ;
669  std::cout << "\n" ;
670  std::cin >> customLon ;
671  req.destLat = customLat;//user input
672  req.destLon = customLon;//user input
673  break;
674  case 8:
675  //coords invalidas 40.637885, -8.655428
676  std::string::size_type sz; // alias of size_t
677  req.destLat = std::stod (FetchEmployeeRec(conn)[0],&sz); //converts string to double
678  req.destLon = std::stod (FetchEmployeeRec(conn)[1],&sz);
679  break;
680 
681  default: //Garagem
682  req.destLat = 40.635114;
683  req.destLon = -8.656467;
684  break;
685  }
686 
687  //if the coordinates are diferent than lat=0.0000 and lon=0.0000 allow to process data else print
688  // "Waiting for GPS fix!"
689  req.gpsLat = msg->latitude;
690  req.gpsLon = msg->longitude;
691 
692  //while(req.gpsLat == 0 && req.gpsLon == 0){ printf("Waiting for gps fix ..."); }
693 
694 
695  //if the request to the server is successfull
696  if(client.call(req,resp)){
697  hasData = true;
698 
699  InsertWaypointsRec(conn,resp); //Placed here because it should only write to this database when a new route is generated
700  }//if client call
701  }//if(!hasData)
702 
703  //calls processData function
704  if(hasData)
705  processData(msg,resp);
706 
707  //std::cout << "Current Latitude: " << msg->longitude << std::endl;
708  //std::cout << "Current Longitude " << msg->latitude << std::endl;
709  /*
710  std::cout << "Lat Response Size" << resp.lat.size() <<std::endl;
711  std::cout << "Lon Response Size" << resp.lon.size() <<std::endl;
712  std::cout << "Instruction Response Size" << resp.instruction.size() <<std::endl;
713  */
714 
715  //shortestDistance(msg,resp);
716  double minIndex = shortestDistance(msg,resp);
717  // std::cout << "Closest waypoint to the current gps location is: " << resp.lat[minIndex] <<" "<<resp.lon[minIndex] << std::endl;
718  printf("Closest waypoint to the current gps location is: %10.6f %10.6f \n",resp.lat[minIndex],resp.lon[minIndex]);
719  std::cout << "Instruction TODO: " << resp.instruction[minIndex] << std::endl;
720 
721 
722  //next instruction BETA
723  double nextInstruction = nextInst(msg,resp);
724  std::cout << "Upcoming Instruction: " << resp.instruction[nextInstruction] << std::endl;
725 
726  //store the response and compare with the new one, if it is equal dont show it
727  //com o indice ir ao vector da resposta e apresentar a instrução a realizar
728 
729  //Writes to DB
730  InsertGpsCoordRec(conn, msg); //ATENÇÂO ESTE conn pode nao funcionar pq nao foi declarado aqui !!!!
731  InsertClosestWaypointRec(conn, minIndex);
732  InsertNextInstructionRec(conn, resp, nextInstruction); //BETA
733 
734  static int sentinel = 0;
735  static double closeDist1;
736  static double closeDist2;
737  //std::pair<double, double> p = wrongDirection(msg,resp,minIndex);
738  if (sentinel == 0) {
739  std::pair<double, double> p = wrongDirection(msg,resp,minIndex);
740  closeDist1 = p.first; //Distance to closest waypoint
741  closeDist2 = p.second; //Distance to closest waypoint + 1
742  sentinel = 1 ;
743  }else if (sentinel == 1) {
744  if(closeDist1 !=0 && closeDist2 !=0){
745  std::pair<double, double> p2 = wrongDirection(msg,resp,minIndex);
746  double closeDist12 = p2.first; //Distance to closest waypoint, new check
747  double closeDist22= p2.second;
748 
749  //Check if the distance to the last check has increased, if "YES" then check if it is greater than 75m (100m = 0.1)
750  if((closeDist12 > closeDist1) && closeDist12 >= 0.075 && (closeDist22 > closeDist2) && closeDist22 >= 0.075)
751 
752  {
753  //Recalculate route
754  mission_planning::Path::Request req;
755 
756  req.destLat = resp.lat.back(); //last latitude element in vector ( previous destination )
757  req.destLon = resp.lon.back();
758 
759  //current position
760  req.gpsLat = msg->latitude;
761  req.gpsLon = msg->longitude;
762 
763  //Do a new request to the server
764  if(client.call(req,resp)){
765  hasData = true;
766  printf("Recalculating Route...");
767  }
768  //fazer a limpeza das bases de dados, porque é gerada uma nova rota !
770  InsertWaypointsRec(conn,resp); //Placed here because it should only write to this database when a new route is generated
771  }
772  }
773  sentinel = 0 ; //Reset static variable
774  }
775 
776 
777  /*
778  //NEEDS to be tested !
779  if(wrongDirection(msg,resp))
780  {
781  //Request class
782  mission_planning::Path::Request req;
783 
784  req.destLat = resp.lat.back(); //last latitude element in vector ( previous destination )
785  req.destLon = resp.lon.back();
786  req.gpsLat = msg->latitude;
787  req.gpsLon = msg->longitude;
788 
789  if(client.call(req,resp)){
790  hasData = true;
791  }
792  //fazer a limpeza das bases de dados, porque é gerada uma nova rota !
793  RemoveAllTablesRec(conn);
794  }
795 */
796  } //end void gpscallback
797 
798  //Able to process data
799  bool processData(const sensor_msgs::NavSatFixPtr &gps,const mission_planning::Path::Response& resp){
800 
801  //gps->latitude;
802  //gps->longitude;
803 
804  //std::cout<<"Processar a nova posição de gps, usando o que estiver em resp, já lá estão dados"<<std::endl;
805  //std::cout << resp.lat.size() << std::endl;
806  /*
807  for (int i = 0; i < resp.lat.size(); ++i) {
808  std::cout << resp.lat.at(i) << std::endl;
809 
810  }
811  */
812 
813  /*
814  for(std::vector<double>::iterator itDouble = resp.lat.begin(); itDouble != resp.lat.end(); itDouble++){
815  std::cout << *itDouble << std::endl;
816  }
817  */
818 
819  return true;
820  }
821 
822 
823 private:
824  // Nodehandle
825  ros::NodeHandle n;
826  //Response class
827  mission_planning::Path::Response resp;
828 
829  // Subscriber
830  ros::Subscriber gps_sub;
831  ros::ServiceClient client;
832  bool firstData;
833  bool hasData;
834 };
835 
836 /*
837 @brief
838 Main of the program.
839 Responsible to establish a connection to the database, clear all tables, initialize the node, the constructor and at the end close the connection with the database.
840 */
841 int main(int argc, char** argv)
842 {
843 
844  /*
845  * Make sure that you have followed the steps bellow, in case something goes wrong !
846  * first: roscore
847  * second: roslaunch novatel novatel_for_psr.launch (Make sure that the gps is powered on and connected to the USB port before launching this !!!)
848  * third: rosrun mission_planning mission_planning_client (Make sure that OSRM-backend is up and running !!! )
849  * forth: rosrun mission_planning mission_planning_node
850  */
851  /*
852  PGconn *conn = NULL;
853  conn = ConnectDB(); //connects to DB
854 */
856  RemoveAllTablesRec(conn); //Clean all tables
857  //InsertEmployeeRec(conn, -7.1312312414); // o max que da para colocar na table é 6 casas decimais
858  // InsertEmployeeRec(conn, 180.1712912454);
859  //FetchEmployeeRec(conn);
860  //RemoveAllEmployeeRec(conn);
861 
862  // Initializing the node for the GPS
863  ros::init(argc, argv, "gps_Subscriber"); //novo no para comunicação
864  ros::NodeHandle nh_;
865 
866 
867  GpsTest p(nh_); //inicialização do construtor
868  ros::spin(); // necessario para ler dados do topico mas não para pedir coisas ao servidor
869 
870  CloseConn(conn); //Disconnects from Database, is executed after the program is terminated
871  //PQfinish(PQconnectdb("user=ivan password=ivanferreira dbname=ivan hostaddr=127.0.0.1 port=5432"));
872  //PQfinish(PQconnectdb("user=atlas password=atlascar dbname=atlas_navigation hostaddr=127.0.0.1 port=5432"));
873  //CloseConn(PQconnectdb("user=ivan password=ivanferreira dbname=ivan hostaddr=127.0.0.1 port=5432"));
874  return 0;
875 
876 }
void InsertGpsCoordRec(PGconn *conn, const sensor_msgs::NavSatFixPtr &gps)
PGconn * conn
std::pair< double, double > wrongDirection(const sensor_msgs::NavSatFixPtr &gps, const mission_planning::Path::Response &resp, int minimumIndex)
void InsertWaypointsRec(PGconn *conn, const mission_planning::Path::Response &resp)
double nextInst(const sensor_msgs::NavSatFixPtr &gps, const mission_planning::Path::Response &resp)
int main(int argc, char **argv)
void InsertClosestWaypointRec(PGconn *conn, int closestwaypoint)
PGconn * ConnectDB()
ros::ServiceClient client
ros::Subscriber gps_sub
double haversine_km(double lat1, double lon1, double lat2, double lon2)
void RemoveAllTablesRec(PGconn *conn)
void CloseConn(PGconn *conn)
void RemoveAllEmployeeRec(PGconn *conn)
GpsTest(ros::NodeHandle nh_)
std::vector< std::string > FetchEmployeeRec(PGconn *conn)
void DBConnectionCheck(PGconn *conn)
void InsertNextInstructionRec(PGconn *conn, const mission_planning::Path::Response &resp, int nextinstruction)
void gpsCallback(const sensor_msgs::NavSatFixPtr &msg)
double shortestDistance(const sensor_msgs::NavSatFixPtr &gps, const mission_planning::Path::Response &resp)
ros::NodeHandle n
void InsertEmployeeRec(PGconn *conn, double fname)
mission_planning::Path::Response resp
bool processData(const sensor_msgs::NavSatFixPtr &gps, const mission_planning::Path::Response &resp)
#define d2r


mission_planning
Author(s): ivan
autogenerated on Thu Nov 12 2015 19:08:20