PageRenderTime 43ms CodeModel.GetById 13ms RepoModel.GetById 1ms app.codeStats 0ms

/brown-ros-pkg-read-only/experimental/ardrone_nav/ardrone_planner/src/ardrone_planner.cpp

https://github.com/dutchcheesehead/ROSMAV
C++ | 517 lines | 320 code | 96 blank | 101 comment | 21 complexity | aff2e318893c4d3be1678538b15f90f1 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. #include <iostream>
  2. #include <vector>
  3. #include <queue>
  4. #include <costmap_2d/costmap_2d.h>
  5. #include <navfn/navfn.h>
  6. #include <nav_msgs/Path.h>
  7. #include <ros/ros.h>
  8. #include <geometry_msgs/PoseStamped.h>
  9. #include <nav_msgs/OccupancyGrid.h>
  10. #include <move_base_msgs/MoveBaseGoal.h>
  11. #include "ardrone_lclzr/ardrone_mean_state.h"
  12. using namespace std;
  13. using namespace costmap_2d;
  14. using namespace navfn;
  15. //subscriber to move_base_msgs/MoveBaseGoal
  16. //ros::Subscriber movebasegoal_sub;
  17. //ros::Subscriber mapserver_sub;
  18. //#define _ARDRONE_STARTX_ 12.55
  19. //#define _ARDRONE_STARTY_ 41.88
  20. #define _ARDRONE_STARTX_ 14.75
  21. #define _ARDRONE_STARTY_ 41.88
  22. //Butterworth low pass filter coefficients
  23. /*
  24. //fs=5Hz
  25. //fc=0.75Hz
  26. #define B1 0.1311
  27. #define B2 0.2622
  28. #define B3 0.1311
  29. #define A1 1.0
  30. #define A2 -0.7478
  31. #define A3 0.2722
  32. */
  33. /*
  34. //fs=40Hz
  35. //fc=0.1Hz
  36. #define B1 0.000061
  37. #define B2 0.000122
  38. #define B3 0.000061
  39. #define A1 1.0
  40. #define A2 -1.9778
  41. #define A3 0.9780
  42. */
  43. /*
  44. //fs=5Hz
  45. //fc=0.75Hz
  46. #define B1 0.3375
  47. #define B2 0.3375
  48. #define A1 1.0
  49. #define A2 -0.3249
  50. */
  51. //fs=40Hz
  52. //fc=0.2Hz
  53. #define B1 0.0155
  54. #define B2 0.0155
  55. #define A1 1.0
  56. #define A2 -0.9691
  57. /*
  58. //fs=40Hz
  59. //fc=0.1Hz
  60. #define B1 0.0078
  61. #define B2 0.0078
  62. #define A1 1.0
  63. #define A2 -0.9844
  64. */
  65. //#define _ARDRONE_STARTX_ 8.21
  66. //#define _ARDRONE_STARTY_ 41.885
  67. //#define _ARDRONE_STARTX_ 6.85
  68. //#define _ARDRONE_STARTY_ 43.05
  69. ros::Publisher path_pub;
  70. class ardrone_planner
  71. {
  72. public:
  73. //costmap_2d
  74. //a costmap instance subscribes to map_server
  75. Costmap2D *cmobj;
  76. //navfn
  77. NavFn *navfnobj;
  78. //costmap initialized?
  79. bool cm_initialized;
  80. //navfn initialized?
  81. bool navfn_initialized;
  82. //costmap parameters
  83. unsigned int map_width;
  84. unsigned int map_height;
  85. double map_resolution;
  86. vector<unsigned char> map_data;
  87. double map_originx;
  88. double map_originy;
  89. double inradius;
  90. double circumradius;
  91. double inflationradius;
  92. double costscaling;
  93. double obstacle_range;
  94. double raytrace_range;
  95. double max_obstacle_height;
  96. int lethal_threshold;
  97. bool track_unknown_space;
  98. int unknown_cost_value;
  99. //NavFn parameters
  100. bool allow_unknown;
  101. double planner_window_x;
  102. double planner_window_y;
  103. double goal_tolerance;
  104. //create an instance of navfn
  105. ardrone_planner()
  106. :cmobj(NULL),navfnobj(NULL)
  107. {
  108. cm_initialized=false;
  109. navfn_initialized=false;
  110. //costmap parameters
  111. /*
  112. inradius=0.66; //for ardrone
  113. circumradius=0.66; //for ardrone
  114. inflationradius=0.60;
  115. */
  116. inradius=0.66; //for ardrone
  117. circumradius=0.7; //for ardrone
  118. inflationradius=0.75;
  119. costscaling=1.0;
  120. obstacle_range=2.5;
  121. raytrace_range=3.0;
  122. max_obstacle_height=2.0;
  123. lethal_threshold=100;
  124. track_unknown_space=false;
  125. unknown_cost_value=100;
  126. //NavFn parameters
  127. allow_unknown=true;
  128. planner_window_x=0.0;
  129. planner_window_y=0.0;
  130. goal_tolerance=0.0;
  131. }
  132. ~ardrone_planner()
  133. {
  134. if(cmobj)
  135. delete cmobj;
  136. if(navfnobj)
  137. delete navfnobj;
  138. }
  139. };
  140. ardrone_planner planner2d;
  141. //queue<geometry_msgs::PoseStamped> ardrone_lclzr_poses;
  142. double ardrone_lclzrx;
  143. double ardrone_lclzry;
  144. void initialize_navfn();
  145. void mapserver_callback(const nav_msgs::OccupancyGridConstPtr& new_map)
  146. {
  147. cout << "Inside mapserver_callback.\n";
  148. cout << "new_map->info.resolution: " << new_map->info.resolution << "\n";
  149. cout << "new_map->info.width: " << new_map->info.width << "\n";
  150. cout << "new_map->info.height: " << new_map->info.height << "\n";
  151. cout << "new_map->info.origin.position: (" << new_map->info.origin.position.x << ","
  152. << new_map->info.origin.position.y << ","
  153. << new_map->info.origin.position.z << ")\n";
  154. cout << "new_map->info.origin.orientation: (" << new_map->info.origin.orientation.x
  155. << "," << new_map->info.origin.orientation.y << ","
  156. << new_map->info.origin.orientation.z << ","
  157. << new_map->info.origin.orientation.w << ")\n";
  158. planner2d.map_width = new_map->info.width;
  159. planner2d.map_height = new_map->info.height;
  160. planner2d.map_resolution = new_map->info.resolution;
  161. planner2d.map_originx = new_map->info.origin.position.x;
  162. planner2d.map_originy = new_map->info.origin.position.y;
  163. unsigned int map_cellcount = planner2d.map_width * planner2d.map_height;
  164. planner2d.map_data.reserve(map_cellcount);
  165. for(unsigned int i=0; i<map_cellcount; i++)
  166. planner2d.map_data.push_back((unsigned char)new_map->data[i]);
  167. planner2d.cmobj = new Costmap2D(planner2d.map_width,planner2d.map_height, \
  168. planner2d.map_resolution,planner2d.map_originx, \
  169. planner2d.map_originy,planner2d.inradius, \
  170. planner2d.circumradius,planner2d.inflationradius, \
  171. planner2d.obstacle_range,planner2d.max_obstacle_height, \
  172. planner2d.raytrace_range,planner2d.costscaling, \
  173. planner2d.map_data,planner2d.lethal_threshold, \
  174. planner2d.track_unknown_space, \
  175. planner2d.unknown_cost_value);
  176. cout << "Completed costmap initialization.\n";
  177. cout << "costmap size in meters(x): " << planner2d.cmobj->getSizeInMetersX()
  178. << "\n";
  179. cout << "costmap size in meters(y): " << planner2d.cmobj->getSizeInMetersY()
  180. << "\n\n";
  181. cout << "costmap size in cells/pixels(x): " << planner2d.cmobj->getSizeInCellsX()
  182. << "\n";
  183. cout << "costmap size in cells/pixels(y): " << planner2d.cmobj->getSizeInCellsY()
  184. << "\n";
  185. planner2d.cm_initialized=true;
  186. initialize_navfn();
  187. }
  188. void initialize_navfn()
  189. {
  190. //Initialize the navfn
  191. if(!planner2d.navfn_initialized && planner2d.cm_initialized)
  192. {
  193. planner2d.navfnobj = new NavFn(planner2d.cmobj->getSizeInCellsX(), \
  194. planner2d.cmobj->getSizeInCellsY());
  195. planner2d.navfnobj->setCostmap(planner2d.cmobj->getCharMap(),true, \
  196. planner2d.allow_unknown);
  197. planner2d.navfn_initialized=true;
  198. }
  199. }
  200. //start and goal positions should be in the world frame
  201. int makePlanDijkstra(double startx, double starty, double goalx, double goaly, vector<geometry_msgs::PoseStamped> &plan)
  202. {
  203. if(!(planner2d.cm_initialized && planner2d.navfn_initialized))
  204. {
  205. cout << "costmap or planner have not been initialized. unable to plan.\n";
  206. return -1;
  207. }
  208. plan.clear();
  209. unsigned int mstartx, mstarty;
  210. if(!planner2d.cmobj->worldToMap(startx,starty,mstartx,mstarty))
  211. {
  212. cout << "robot start position is outside map area.\n";
  213. cout << "(startx,starty): (" << startx << "," << starty << ")\n";
  214. cout << "map coordinates of startx,starty: " << mstartx << "," << mstarty << "\n";
  215. return -1;
  216. }
  217. unsigned int mgoalx, mgoaly;
  218. if(!planner2d.cmobj->worldToMap(goalx,goaly,mgoalx,mgoaly))
  219. {
  220. cout << "robot goal position is outside map area.\n";
  221. cout << "(goalx,goaly): (" << goalx << "," << goaly << ")\n";
  222. cout << "map coordinates of goalx,goaly: " << mgoalx << "," << mgoaly << "\n";
  223. return -1;
  224. }
  225. int map_start[2];
  226. map_start[0]=mstartx;
  227. map_start[1]=mstarty;
  228. int map_goal[2];
  229. map_goal[0]=mgoalx;
  230. map_goal[1]=mgoaly;
  231. planner2d.navfnobj->setStart(map_start);
  232. planner2d.navfnobj->setGoal(map_goal);
  233. //compute the potential inplace in the costmap
  234. bool atStart=true;
  235. planner2d.navfnobj->calcNavFnDijkstra(atStart);
  236. //get plan from potential
  237. planner2d.navfnobj->setStart(map_start);
  238. planner2d.navfnobj->calcPath(planner2d.cmobj->getSizeInCellsX() * 4);
  239. //extract the plan
  240. float *x = planner2d.navfnobj->getPathX();
  241. float *y = planner2d.navfnobj->getPathY();
  242. int len = planner2d.navfnobj->getPathLen();
  243. float xfilt[len];
  244. float yfilt[len];
  245. for(int i=0; i<len; i++)
  246. {
  247. xfilt[i]=x[i];
  248. yfilt[i]=y[i];
  249. }
  250. /*
  251. //Second order Butterworth filter
  252. if(len>2)
  253. {
  254. for(int i=2; i<len; i++)
  255. {
  256. xfilt[i]=(B1*x[i]+B2*x[(i-1)]+B3*x[(i-2)]-A2*xfilt[(i-1)]-A3*xfilt[(i-2)]);
  257. yfilt[i]=(B1*y[i]+B2*y[(i-1)]+B3*y[(i-2)]-A2*yfilt[(i-1)]-A3*yfilt[(i-2)]);
  258. }
  259. }
  260. */
  261. //First order Butterworth filter
  262. if(len>1)
  263. {
  264. for(int i=1; i<len; i++)
  265. {
  266. xfilt[i]=(B1*x[i]+B2*x[(i-1)]-A2*xfilt[(i-1)]);
  267. yfilt[i]=(B1*y[i]+B2*y[(i-1)]-A2*yfilt[(i-1)]);
  268. }
  269. }
  270. ros::Time plan_time = ros::Time::now();
  271. double worldx, worldy;
  272. for(int i=0; i<len; i++)
  273. {
  274. worldx = planner2d.cmobj->getOriginX() + xfilt[i] * planner2d.cmobj->getResolution();
  275. worldy = planner2d.cmobj->getOriginY() + yfilt[i] * planner2d.cmobj->getResolution();
  276. geometry_msgs::PoseStamped pose;
  277. pose.header.stamp = plan_time;
  278. pose.header.frame_id = "/map";
  279. pose.pose.position.x = worldx;
  280. pose.pose.position.y = worldy;
  281. pose.pose.position.z = 0.0;
  282. pose.pose.orientation.x = 0.0;
  283. pose.pose.orientation.y = 0.0;
  284. pose.pose.orientation.z = 0.0;
  285. pose.pose.orientation.w = 1.0;
  286. plan.push_back(pose);
  287. }
  288. //publish plan for visualization
  289. nav_msgs::Path drone_path;
  290. drone_path.poses.resize(plan.size());
  291. drone_path.header.frame_id = plan[0].header.frame_id;
  292. drone_path.header.stamp = plan[0].header.stamp;
  293. for(unsigned int i=0; i < plan.size(); i++){
  294. drone_path.poses[i] = plan[i];
  295. }
  296. path_pub.publish(drone_path);
  297. return 1;
  298. }
  299. int makePlanAstar(double startx, double starty, double goalx, double goaly, vector<geometry_msgs::PoseStamped> &plan)
  300. {
  301. if(!(planner2d.cm_initialized && planner2d.navfn_initialized))
  302. {
  303. cout << "costmap or planner have not been initialized. unable to plan.\n";
  304. return -1;
  305. }
  306. plan.clear();
  307. unsigned int mstartx, mstarty;
  308. if(!planner2d.cmobj->worldToMap(startx,starty,mstartx,mstarty))
  309. {
  310. cout << "robot start position is outside map area.\n";
  311. cout << "(startx,starty): (" << startx << "," << starty << ")\n";
  312. cout << "map coordinates of startx,starty: " << mstartx << "," << mstarty << "\n";
  313. return -1;
  314. }
  315. unsigned int mgoalx, mgoaly;
  316. if(!planner2d.cmobj->worldToMap(goalx,goaly,mgoalx,mgoaly))
  317. {
  318. cout << "robot goal position is outside map area.\n";
  319. cout << "(goalx,goaly): (" << goalx << "," << goaly << ")\n";
  320. cout << "map coordinates of goalx,goaly: " << mgoalx << "," << mgoaly << "\n";
  321. return -1;
  322. }
  323. int map_start[2];
  324. map_start[0]=mstartx;
  325. map_start[1]=mstarty;
  326. int map_goal[2];
  327. map_goal[0]=mgoalx;
  328. map_goal[1]=mgoaly;
  329. planner2d.navfnobj->setStart(map_start);
  330. planner2d.navfnobj->setGoal(map_goal);
  331. //compute the potential inplace in the costmap
  332. //bool atStart=true;
  333. //planner2d.navfnobj->calcNavFnDijkstra(atStart);
  334. planner2d.navfnobj->calcNavFnAstar();
  335. //get plan from potential
  336. planner2d.navfnobj->setStart(map_start);
  337. planner2d.navfnobj->calcPath(planner2d.cmobj->getSizeInCellsX() * 4);
  338. //extract the plan
  339. float *x = planner2d.navfnobj->getPathX();
  340. float *y = planner2d.navfnobj->getPathY();
  341. int len = planner2d.navfnobj->getPathLen();
  342. ros::Time plan_time = ros::Time::now();
  343. double worldx, worldy;
  344. for(int i=0; i<len; i++)
  345. {
  346. worldx = planner2d.cmobj->getOriginX() + x[i] * planner2d.cmobj->getResolution();
  347. worldy = planner2d.cmobj->getOriginY() + y[i] * planner2d.cmobj->getResolution();
  348. geometry_msgs::PoseStamped pose;
  349. pose.header.stamp = plan_time;
  350. pose.header.frame_id = "/map";
  351. pose.pose.position.x = worldx;
  352. pose.pose.position.y = worldy;
  353. pose.pose.position.z = 0.0;
  354. pose.pose.orientation.x = 0.0;
  355. pose.pose.orientation.y = 0.0;
  356. pose.pose.orientation.z = 0.0;
  357. pose.pose.orientation.w = 1.0;
  358. plan.push_back(pose);
  359. }
  360. //publish plan for visualization
  361. nav_msgs::Path drone_path;
  362. drone_path.poses.resize(plan.size());
  363. drone_path.header.frame_id = plan[0].header.frame_id;
  364. drone_path.header.stamp = plan[0].header.stamp;
  365. for(unsigned int i=0; i < plan.size(); i++){
  366. drone_path.poses[i] = plan[i];
  367. }
  368. path_pub.publish(drone_path);
  369. return 1;
  370. }
  371. void moveBaseCallback(const geometry_msgs::PoseStampedConstPtr& goalpose)
  372. {
  373. double startx;
  374. double starty;
  375. double goalx;
  376. double goaly;
  377. vector<geometry_msgs::PoseStamped> plan;
  378. startx = ardrone_lclzrx;
  379. starty = ardrone_lclzry;
  380. goalx = goalpose->pose.position.x;
  381. goaly = goalpose->pose.position.y;
  382. cout << "\nInside movebaseCallback.\n";
  383. cout << "(goalx,goaly): " << goalx << "," << goaly << "\n";
  384. //makePlan(startx, starty, goalx, goaly, plan);
  385. //makePlanAstar(startx, starty, goalx, goaly, plan);
  386. makePlanDijkstra(startx, starty, goalx, goaly, plan);
  387. }
  388. void ardrone_lclzr_callback(const ardrone_lclzr::ardrone_mean_state& drone_pose)
  389. {
  390. //ardrone_lclzr_poses.push_back(drone_pose);
  391. ardrone_lclzrx=drone_pose.x;
  392. ardrone_lclzry=drone_pose.y;
  393. }
  394. int main(int argc, char **argv)
  395. {
  396. ros::init(argc, argv, "ardrone_planner");
  397. ros::NodeHandle n;
  398. //the coordinates correspond to the center of lab 121
  399. //ardrone_lclzrx=6.85;
  400. //ardrone_lclzry=43.05;
  401. ///ardrone_lclzrx=8.21;
  402. ///ardrone_lclzry=41.885;
  403. ardrone_lclzrx=_ARDRONE_STARTX_;
  404. ardrone_lclzry=_ARDRONE_STARTY_;
  405. //ardrone_lclzrx=0.0;
  406. //ardrone_lclzry=0.0;
  407. ros::Subscriber mapsub = n.subscribe("/map", 0, &mapserver_callback);
  408. ros::Subscriber lclzr_sub = n.subscribe("/ardrone_mean_state",0,&ardrone_lclzr_callback);
  409. ros::Subscriber moveBaseSub = n.subscribe("/move_base_simple/goal",0,&moveBaseCallback);
  410. path_pub = n.advertise<nav_msgs::Path>("plan",1);
  411. ros::Rate loop_rate(10);
  412. //int i=0;
  413. while (ros::ok())
  414. {
  415. //cout << "i: " << i << "\n";
  416. //i++;
  417. ros::spinOnce();
  418. loop_rate.sleep();
  419. }
  420. return 0;
  421. }