24 #include <QtGui/QApplication>
33 #include "ros/package.h"
35 #include "cgr_localization/DisplayMsg.h"
36 #include "cgr_localization/LocalizationInterfaceSrv.h"
37 #include "cgr_localization/LocalizationMsg.h"
38 #include "sensor_msgs/LaserScan.h"
47 using namespace cgr_localization;
52 bool testMode =
false;
53 bool saveLocs =
false;
54 bool saveOrientations =
false;
55 bool liveView =
false;
56 bool persistentDisplay =
true;
60 ros::ServiceClient client;
61 ros::ServiceClient localizationClient;
66 static const bool debug =
false;
67 static FILE* fid=NULL;
68 if(saveLocs && fid==NULL)
69 fid = fopen(
"savedLocs.txt",
"aw");
72 fprintf(fid,
"%f,%f,%f\n",V2COMP(loc),(loc2-loc).angle());
73 printf(
"Saved location: %f,%f,%f\n",V2COMP(loc),(loc2-loc).angle());
75 fprintf(fid,
"%f,%f,%f,%f\n",V2COMP(loc),V2COMP(loc2));
76 printf(
"Saved location: %f,%f,%f,%f\n",V2COMP(loc),V2COMP(loc2));
80 LocalizationInterfaceSrv srv;
81 srv.request.loc_x = loc.x;
82 srv.request.loc_y = loc.y;
83 srv.request.orientation = orientation;
84 srv.request.map = map_name;
88 if(debug) printf(
"SetPosition: %7.3f,%7.3f %6.1f\u00b0\n",V2COMP(loc),DEG(orientation));
89 client = localizationClient;
93 if(debug) printf(
"SetTarget: %7.3f,%7.3f %6.1f\u00b0\n",V2COMP(loc),DEG(orientation));
97 if(type==2 || type==3){
101 printf(
"Failed to send command!\n");
111 vector<vector2d> pathPlan;
114 sensor_msgs::LaserScan laserScanMsg;
115 vector<DisplayMsg> displayMsgs;
116 vector<string> displayProviders;
117 double tPathPlan, tDisplay, tLaser;
119 vector<line2f> lines;
120 vector<vector2f> points;
121 vector<vector2f> circles;
122 vector<VectorDisplay::Color> circleColors;
123 vector<VectorDisplay::Color> lineColors;
124 vector<VectorDisplay::Color> pointColors;
127 void drawMap(vector<line2f> &lines, vector<VectorDisplay::Color> &lineColors)
129 int numLines = vectorMap.lines.size();
130 for(
int i=0; i<numLines; i++){
131 lines.push_back(
line2f(vectorMap.lines[i].P0().x,vectorMap.lines[i].P0().y,
132 vectorMap.lines[i].P1().x,vectorMap.lines[i].P1().y));
137 void localizationCallback(
const LocalizationMsg& msg)
139 static const bool debug =
false;
140 if(debug) printf(
"Localization update: %f,%f, %f\u00b0, %s\n",msg.x,msg.y,DEG(msg.angle),msg.map.c_str());
142 robotAngle = msg.angle;
143 snprintf(map_name, 4095,
"%s",msg.map.c_str());
144 if(msg.map.compare(vectorMap.mapName)!=0){
145 vectorMap.
loadMap(msg.map.c_str(),
false);
149 void laserCallback(
const sensor_msgs::LaserScan& msg)
152 tLaser = GetTimeSec();
155 void statusCallback(
const ros::MessageEvent<DisplayMsg const>& msgEvent)
157 static const bool debug =
false;
158 const DisplayMsgConstPtr &msg = msgEvent.getConstMessage();
159 bool duplicate =
false;
161 for(;i<displayProviders.size() && !duplicate; i++){
162 if(displayProviders[i].compare(msgEvent.getPublisherName())==0)
167 displayMsgs[i] = *msg;
168 if(debug) printf(
"Duplicate message from %s\n",displayProviders[i].c_str());
170 displayMsgs.push_back(*msg);
171 displayProviders.push_back(msgEvent.getPublisherName());
172 if(debug) printf(
"New message from %s\n",displayProviders[i].c_str());
176 void compileDisplay()
178 static double tLast = 0.0;
179 static const double MessageTimeout = 1.0;
180 static const int LidarPointColor = 0xF0761F;
181 static const bool debug =
false;
182 if(debug) printf(
"GUI updated!\n");
184 if(GetTimeSec()-tLast<0.016)
186 tLast = GetTimeSec();
191 circleColors.clear();
195 drawMap(lines, lineColors);
196 for(
unsigned int j=0; j<displayMsgs.size(); j++){
197 DisplayMsg displayMsg = displayMsgs[j];
198 if(GetTimeSec()-tDisplay<MessageTimeout || persistentDisplay){
199 unsigned int numLines = min(min((
int)displayMsg.lines_p1x.size(),(int)displayMsg.lines_p1y.size()),min((
int)displayMsg.lines_p2x.size(),(int)displayMsg.lines_p2y.size()));
200 for(
unsigned int i=0; i<numLines; i++){
201 lines.push_back(
line2f(displayMsg.lines_p1x[i],displayMsg.lines_p1y[i],displayMsg.lines_p2x[i],displayMsg.lines_p2y[i]));
202 if(i<displayMsg.lines_col.size())
203 lineColors.push_back(displayMsg.lines_col[i]);
205 unsigned int numPoints = min(displayMsg.points_x.size(),displayMsg.points_y.size());
206 for(
unsigned int i=0; i<numPoints; i++){
207 points.push_back(
vector2f(displayMsg.points_x[i],displayMsg.points_y[i]));
208 if(i<displayMsg.points_col.size())
211 unsigned int numCircles = min(displayMsg.circles_x.size(),displayMsg.circles_y.size());
212 for(
unsigned int i=0; i<numCircles; i++){
213 circles.push_back(
vector2f(displayMsg.circles_x[i],displayMsg.circles_y[i]));
214 if(i<displayMsg.circles_col.size())
220 printf(
"lines: %d points: %d circles: %d\n",
int(lines.size()),
int(points.size()),
int(circles.size()));
225 if((GetTimeSec()-tLaser<MessageTimeout || persistentDisplay) && liveView){
228 vector2f laserLoc(0.145,0.0), p(0.0,0.0);
229 laserLoc =
vector2f(V2COMP(robotLoc)) + laserLoc.
rotate(robotAngle);
230 for(i=0, a = robotAngle + laserScanMsg.angle_min; i<laserScanMsg.ranges.size(); i++, a+=laserScanMsg.angle_increment){
231 if(laserScanMsg.ranges[i]<=laserScanMsg.range_min || laserScanMsg.ranges[i]>=laserScanMsg.range_max)
234 p = p*laserScanMsg.ranges[i]+laserLoc;
236 pointColors.push_back(LidarPointColor);
240 if(GetTimeSec()-tPathPlan<MessageTimeout || persistentDisplay){
241 if(pathPlan.size()>0){
242 lines.push_back(
line2f(pathPlan[0].x, pathPlan[0].y, robotLoc.x, robotLoc.y));
243 lineColors.push_back(0x00FF00);
244 points.push_back(
vector2f(V2COMP(pathPlan[0])));
245 pointColors.push_back(0xFF0000);
247 for(
int i=0; i<int(pathPlan.size())-1; i++){
248 lines.push_back(
line2f(pathPlan[i].x, pathPlan[i].y, pathPlan[i+1].x, pathPlan[i+1].y));
249 lineColors.push_back(0x00FF00);
250 points.push_back(
vector2f(V2COMP(pathPlan[i])));
251 points.push_back(
vector2f(V2COMP(pathPlan[i+1])));
252 pointColors.push_back(0xFF0000);
253 pointColors.push_back(0xFF0000);
257 display->updateDisplay(robotLoc,robotAngle, 100.0, lines, points, circles, lineColors, pointColors, circleColors);
263 static const bool debug =
false;
266 while(runApp && ros::ok()){
270 vector<line2f> lines;
271 vector<vector2f> points;
272 double dTheta = 2.0*M_PI/double(numLines);
275 double omega = RAD(30.0);
276 for(
int i=0; i<numLines; i++){
278 p1 = p.
rotate(theta+omega*GetTimeSec());
279 p2 = p.
rotate(theta+dTheta+omega*GetTimeSec());
282 lines.push_back(
line2f(p1.x,p1.y,p2.x,p2.y));
285 dTheta = 2.0*M_PI/double(numPoints);
287 for(
int i=0;i<numPoints;i++){
289 p = p*max(0.0,1.1+sin(sin(2.0*theta)*M_PI))/2.0;
290 p = p.
rotate(theta+omega*GetTimeSec())+offset;
292 points.push_back(
vector2f(p.x,p.y));
295 display->updateLines(lines);
296 display->updatePoints(points);
299 if(debug) printf(
"Terminating testMode thread. runApp:%d ok():%d\n",runApp?1:0,ros::ok()?1:0);
302 vectorMap =
VectorMap(map_name,mapsFolder.c_str(),
false);
304 ros::Subscriber guiSub;
305 ros::Subscriber statusSub;
306 ros::Subscriber laserSub;
307 ros::Subscriber localizationSub;
309 laserSub = n->subscribe(
"laser", 1, &MyThread::laserCallback,
this);
310 localizationSub = n->subscribe(
"localization", 1, &MyThread::localizationCallback,
this);
311 guiSub = n->subscribe(
"localization_gui", 1, &MyThread::statusCallback,
this);
313 drawMap(lines, lineColors);
314 display->updateLines(lines, lineColors);
316 while(runApp && ros::ok()){
321 if(debug) printf(
"Terminating thread. runApp:%d ok():%d\n",runApp?1:0,ros::ok()?1:0);
326 MyThread(
const char* _mapsFolder, QObject* parent = 0) : vectorMap(_mapsFolder)
328 mapsFolder = string(_mapsFolder);
335 int main(
int argc,
char *argv[])
337 static const bool debug =
false;
338 ColourTerminal(TerminalUtils::TERMINAL_COL_GREEN,TerminalUtils::TERMINAL_COL_BLACK,TerminalUtils::TERMINAL_ATTR_BRIGHT);
339 printf(
"\nVector LIDAR Localization GUI\n\n");
342 if(debug) printf(
"Starting up...\n");
344 ros::init(argc, argv,
"vector_LIDAR_GUI");
345 map_name = (
char*) malloc(4096);
346 snprintf(map_name, 4095,
"GHC7");
348 static struct poptOption options[] = {
349 {
"test-mode",
't', POPT_ARG_NONE , &testMode, 0,
"Test Drawing Capabilities",
"NONE"},
350 {
"map-name",
'm', POPT_ARG_STRING , &map_name, 0,
"Map name",
"STRING"},
351 {
"save-locs",
's', POPT_ARG_NONE, &saveLocs, 0,
"Save Locations",
"NONE"},
352 {
"live-view",
'l', POPT_ARG_NONE, &liveView, 0,
"Live View of Robot",
"NONE"},
353 {
"persistent-display",
'p', POPT_ARG_NONE, &persistentDisplay, 0,
"Persistent Display",
"NONE"},
354 {
"save-orientation",
'S', POPT_ARG_NONE, &saveOrientations, 0,
"Save Orientations",
"NONE"},
357 { NULL, 0, 0, NULL, 0, NULL, NULL }
360 POpt popt(NULL,argc,(
const char**)argv,options,0);
362 while((c = popt.getNextOpt()) >= 0){
367 app =
new QApplication(argc, argv);
372 n =
new ros::NodeHandle();
373 localizationClient = n->serviceClient<LocalizationInterfaceSrv>(
"localization_interface");
375 InitHandleStop(&runApp);
377 MyThread thread(ros::package::getPath(
"cgr_localization").append(
"/maps/").c_str());
379 int retVal = app->exec();
381 if(debug) printf(
"Waiting for thread termination... ");
383 if(debug) printf(
"Done. Bye Bye!\n");
Subroutines to spice up stdout.
A GUI for Vector Localization; C++ Interface: VectorDisplay.
C++ Interfaces: VectorMap, LineSection.
void setCallback(void(*_ptrCallback)(vector2d, vector2d, double, int))
vector2d< num > rotate(const double a) const MustUseResult
return vector rotated by angle a
bool loadMap(const char *name, bool usePreRender)
Load map by name.
void heading(num angle)
make a unit vector at given angle