navigation.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458
  1. //
  2. // Created by zx on 22-12-2.
  3. //
  4. #include "navigation.h"
  5. #include "loaded_mpc.h"
  6. #include "../define/TimerRecord.h"
  7. Navigation::~Navigation()
  8. {
  9. if(terminator_)
  10. delete terminator_;
  11. if(monitor_)
  12. delete monitor_;
  13. if(thread_!= nullptr)
  14. {
  15. if(thread_->joinable())
  16. thread_->join();
  17. delete thread_;
  18. }
  19. }
  20. bool Navigation::Init(const Navigation_parameter& parameter)
  21. {
  22. Emqx_parameter agv_p=parameter.agv_emqx();
  23. if(monitor_== nullptr) {
  24. monitor_ = new Monitor_emqx(agv_p.nodeid(), agv_p.pubtopic(), agv_p.subtopic());
  25. monitor_->set_statu_arrived_callback(Navigation::RobotStatuCallback, this);
  26. if(monitor_->Connect(agv_p.ip(),agv_p.port())==false)
  27. {
  28. printf(" agv emqx connected failed\n");
  29. return false;
  30. }
  31. }
  32. Emqx_parameter terminal_p=parameter.terminal_emqx();
  33. if(terminator_== nullptr) {
  34. terminator_ = new Terminator_emqx(terminal_p.nodeid(), terminal_p.pubtopic(), terminal_p.subtopic());
  35. terminator_->set_cmd_arrived(Navigation::NavCmdCallback,this);
  36. if(terminator_->Connect(terminal_p.ip(),terminal_p.port())==false)
  37. {
  38. printf(" terminator emqx connected failed\n");
  39. return false;
  40. }
  41. }
  42. inited_=true;
  43. return true;
  44. }
  45. void Navigation::publish_statu(ActionType type,float velocity,float angular)
  46. {
  47. NavStatu statu;
  48. if(running_)
  49. {
  50. statu.set_action_type(type);
  51. statu.set_isrunning(running_);
  52. std::queue<Trajectory> trajectorys_=global_trajectorys_;
  53. while(trajectorys_.empty()==false)
  54. {
  55. Trajectory traj=trajectorys_.front();
  56. TrajectoryMsg* trajMsg=statu.add_trajs();
  57. for(int i=0;i<traj.size();++i)
  58. {
  59. Pose2dMsg* pose=trajMsg->add_points();
  60. pose->set_x(traj[i].x());
  61. pose->set_y(traj[i].y());
  62. pose->set_theta(traj[i].theta());
  63. }
  64. trajectorys_.pop();
  65. }
  66. statu.set_velocity(velocity);
  67. statu.set_angular(angular);
  68. if(type==eMPC)
  69. {
  70. //发布mpc 预选点
  71. if(selected_traj_.timeout()==false) {
  72. for (int i = 0; i < selected_traj_.Get().size(); ++i){
  73. Pose2d pt=selected_traj_.Get()[i];
  74. Pose2dMsg* pose=statu.mutable_select_traj()->add_points();
  75. pose->set_x(pt.x());
  76. pose->set_y(pt.y());
  77. pose->set_theta(pt.theta());
  78. }
  79. }
  80. //发布 mpc 预测点
  81. if(predict_traj_.timeout()==false) {
  82. for (int i = 0; i < predict_traj_.Get().size(); ++i){
  83. Pose2d pt=predict_traj_.Get()[i];
  84. Pose2dMsg* pose=statu.mutable_predict_traj()->add_points();
  85. pose->set_x(pt.x());
  86. pose->set_y(pt.y());
  87. pose->set_theta(pt.theta());
  88. }
  89. }
  90. }
  91. }
  92. terminator_->publish_nav_statu(statu);
  93. }
  94. void Navigation::ResetStatu(double v,double a)
  95. {
  96. timedV_.reset(v,0.5);
  97. timedA_.reset(a,0.5);
  98. }
  99. void Navigation::ResetPose(const Pose2d& pose)
  100. {
  101. timedPose_.reset(pose,0.5);
  102. }
  103. bool Navigation::Start(std::queue<Trajectory> global_trajectorys)
  104. {
  105. if(running_==true)
  106. {
  107. if(pause_)
  108. {
  109. pause_=false;
  110. return true;
  111. }
  112. printf(" navigation is running pls cancel before\n");
  113. return false;
  114. }
  115. if(thread_!= nullptr)
  116. {
  117. if(thread_->joinable())
  118. thread_->join();
  119. delete thread_;
  120. }
  121. //add 先检查当前点与起点的距离
  122. global_trajectorys_=global_trajectorys;
  123. thread_=new std::thread(&Navigation::navigatting,this);
  124. return true;
  125. }
  126. void Navigation::Cancel()
  127. {
  128. cancel_=true;
  129. }
  130. void Navigation::Pause()
  131. {
  132. monitor_->stop();
  133. pause_=true;
  134. }
  135. Navigation::Navigation()
  136. {
  137. thread_= nullptr;
  138. monitor_= nullptr;
  139. terminator_= nullptr;
  140. }
  141. void Navigation::NavCmdCallback(const NavCmd& cmd,void* context)
  142. {
  143. Navigation* navigator=(Navigation*)context;
  144. if(cmd.action()==3)
  145. {
  146. navigator->Cancel();
  147. return ;
  148. }
  149. if(cmd.action()==2) {
  150. navigator->pause_=false;
  151. return ;
  152. }
  153. if(cmd.action()==1) {
  154. navigator->Pause();
  155. return ;
  156. }
  157. std::queue<Trajectory> trajs;
  158. for(int i=0;i<cmd.trajs_size();++i)
  159. {
  160. Trajectory traj;
  161. for(int j=0;j<cmd.trajs(i).points_size();++j)
  162. {
  163. Pose2dMsg pt_msg=cmd.trajs(i).points(j);
  164. Pose2d pt2d(pt_msg.x(),pt_msg.y(),pt_msg.theta());
  165. traj.push_point(pt2d);
  166. }
  167. trajs.push(traj);
  168. }
  169. navigator->Start(trajs);
  170. }
  171. void Navigation::RobotStatuCallback(double x,double y,double theta,double v,double vth,void* context)
  172. {
  173. Navigation* navigator=(Navigation*)context;
  174. navigator->ResetPose(Pose2d(x,y,theta));
  175. navigator->ResetStatu(v,vth);
  176. }
  177. bool Navigation::moveToPoint(const Pose2d& pose,const Pose2d& distance)
  178. {
  179. if(inited_==false) {
  180. printf(" navigation has not inited\n");
  181. return false;
  182. }
  183. Pose2d thresh=Pose2d::abs(distance);
  184. bool yCompleted=false;
  185. bool xCompleted=false;
  186. bool aCompleted=false;
  187. while(cancel_==false)
  188. {
  189. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  190. if (pause_ == true)
  191. {
  192. //发送暂停消息
  193. continue;
  194. }
  195. if (timedPose_.timeout() == true)
  196. {
  197. printf(" navigation Error:Pose is timeout \n");
  198. break;
  199. }
  200. //计算目标pose在当前pose下的pose
  201. Pose2d diff = Pose2d::PoseByPose(pose,timedPose_.Get());
  202. if (Pose2d::abs(diff).y() < thresh.y())
  203. yCompleted=true;
  204. else if(Pose2d::abs(diff).y()>2.0*thresh.y())
  205. yCompleted=false;
  206. if (Pose2d::abs(diff).x() < thresh.x())
  207. xCompleted=true;
  208. else if(Pose2d::abs(diff).x() >2.0* thresh.x())
  209. xCompleted=false;
  210. if (Pose2d::abs(diff).theta() < thresh.theta())
  211. aCompleted=true;
  212. else
  213. aCompleted=false;
  214. if(yCompleted&&xCompleted&&aCompleted)
  215. {
  216. monitor_->stop();
  217. return true;
  218. }
  219. //先旋转使得Y=0摆直,再移动x,再X最后旋转
  220. if(yCompleted==false)
  221. {
  222. double theta=atan(diff.y()/diff.x());
  223. double maxtheta=20.*M_PI/180.0;
  224. double mintheta=5.*M_PI/180.0;
  225. if(abs(theta)<mintheta)
  226. {
  227. theta=(theta>0)?mintheta:-mintheta;
  228. }
  229. if(abs(theta)>maxtheta)
  230. {
  231. theta=(theta>0)?maxtheta:-maxtheta;
  232. }
  233. publish_statu(eRotate,0,theta);
  234. monitor_->rotate(theta);
  235. printf("旋转 diff.y:%.5f\n",diff.y());
  236. continue;
  237. }
  238. if(xCompleted==false){
  239. double v=diff.x()/10.0;
  240. double maxv=1.9;
  241. double minv=0.1;
  242. if(abs(v)<minv)
  243. {
  244. v=(v>0)?minv:-minv;
  245. }
  246. if(abs(v)>maxv)
  247. {
  248. v=(v>0)?maxv:-maxv;
  249. }
  250. publish_statu(eLine,v,0);
  251. monitor_->set_speed(v,0);
  252. printf("x移动 diff.x():%.5f\n",diff.x());
  253. continue;
  254. }
  255. if(aCompleted==false){
  256. double theta=diff.theta()/5.0;
  257. if(std::abs(diff.theta())>M_PI)
  258. theta=-theta;
  259. double maxtheta=20.*M_PI/180.0;
  260. double mintheta=5.*M_PI/180.0;
  261. if(abs(theta)<mintheta)
  262. {
  263. theta=(theta>0)?mintheta:-mintheta;
  264. }
  265. if(abs(theta)>maxtheta)
  266. {
  267. theta=(theta>0)?maxtheta:-maxtheta;
  268. }
  269. publish_statu(eRotate,0,theta);
  270. monitor_->rotate(theta);
  271. printf("旋转angular:%.5f diff.theta():%.5f\n",theta,diff.theta());
  272. }
  273. }
  274. if(cancel_==true)
  275. return false;
  276. return true;
  277. }
  278. bool Navigation::mpc_once(const Trajectory& traj,std::vector<double>& out)
  279. {
  280. if(timedPose_.timeout()==true && timedV_.timeout()==false && timedA_.timeout()==false)
  281. {
  282. printf(" MPC once Error:Pose/V/A is timeout \n");
  283. return false;
  284. }
  285. if(traj.size()==0)
  286. {
  287. printf("traj size ==0\n");
  288. return false;
  289. }
  290. Pose2d pose=timedPose_.Get();
  291. double velocity=timedV_.Get(); //从plc获取状态
  292. double angular=timedA_.Get();
  293. LoadedMPC MPC(2.7);
  294. Eigen::VectorXd statu=Eigen::VectorXd::Zero(5);//agv状态
  295. statu[0]=pose.x();
  296. statu[1]=pose.y();
  297. statu[2]=pose.theta();
  298. statu[3]=velocity;
  299. statu[4]=angular;
  300. Trajectory optimize_trajectory;
  301. Trajectory selected_trajectory;
  302. bool ret= MPC.solve(traj,traj[traj.size()-1],statu,out,selected_trajectory,optimize_trajectory);
  303. predict_traj_.reset(optimize_trajectory,1);
  304. selected_traj_.reset(selected_trajectory,1);
  305. return ret;
  306. }
  307. bool Navigation::IsArrived(const Pose2d& cur,double speed,const Pose2d& target,const Pose2d& diff)
  308. {
  309. if(Pose2d::abs(cur-target)<diff)
  310. {
  311. if(fabs(speed)<0.1)
  312. return true;
  313. }
  314. return false;
  315. }
  316. bool Navigation::execute_edge(const Trajectory& child,const Pose2d& head_diff,const Pose2d& target_diff)
  317. {
  318. if(inited_==false) {
  319. printf(" navigation has not inited\n");
  320. return false;
  321. }
  322. if(child.size()==0)
  323. return true;
  324. Pose2d head=child[0];
  325. Pose2d tail=child[child.size()-1];
  326. Trajectory traj=child;
  327. bool init_start_pose=false;
  328. while(cancel_==false)
  329. {
  330. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  331. if(pause_==true)
  332. {
  333. //发送暂停消息
  334. continue;
  335. }
  336. if(timedPose_.timeout()==true)
  337. {
  338. printf(" navigation Error:Pose is timeout \n");
  339. break;
  340. }
  341. //判断是否到达终点
  342. Pose2d diff=Pose2d::abs(timedPose_.Get()-tail);
  343. if(IsArrived(timedPose_.Get(),timedV_.Get(),tail,target_diff))
  344. {
  345. monitor_->stop();
  346. printf(" edge navigation completed !!!\n");
  347. return true;
  348. }else if(diff.x()<target_diff.x() && diff.y()<target_diff.y()){
  349. monitor_->stop();
  350. moveToPoint(tail,target_diff);
  351. }
  352. //std::cout<<"diff:"<<Pose2d::abs(timedPose_.Get()-tail)<<std::endl;
  353. //如果与起点差距过大先运动到起点
  354. if(false==init_start_pose)
  355. {
  356. init_start_pose= moveToPoint(head, head_diff);
  357. continue;
  358. }
  359. else{
  360. //一次变速
  361. std::vector<double> out;
  362. bool ret;
  363. TimerRecord::Execute([&,this](){
  364. ret=mpc_once(traj,out);
  365. },"mpc_once");
  366. if(ret==false)
  367. {
  368. monitor_->stop();
  369. return false;
  370. }
  371. publish_statu(eMPC,out[0],out[1]);
  372. monitor_->set_speed(out[0],out[1]);
  373. }
  374. }
  375. return false;
  376. }
  377. void Navigation::navigatting()
  378. {
  379. if(inited_==false) {
  380. printf(" navigation has not inited\n");
  381. return ;
  382. }
  383. pause_=false;
  384. cancel_=false;
  385. running_=true;
  386. printf(" navigation beg...\n");
  387. #if 0
  388. Trajectory gtraj;
  389. while(global_trajectorys_.empty()==false)
  390. {
  391. gtraj=gtraj+global_trajectorys_.front();
  392. global_trajectorys_.pop();
  393. }
  394. execute_edge(gtraj);
  395. #else
  396. double v=0,a=0;
  397. Pose2d head_diff(0.1,0.1,3/180.0*M_PI);
  398. Pose2d target_diff(0.03,0.05,0.5/180.0*M_PI);
  399. while(global_trajectorys_.empty()==false && cancel_==false)
  400. {
  401. Trajectory traj=global_trajectorys_.front();
  402. if(execute_edge(traj,head_diff,target_diff))
  403. {
  404. global_trajectorys_.pop();
  405. }
  406. else
  407. {
  408. break;
  409. }
  410. }
  411. #endif
  412. monitor_->stop();
  413. if(cancel_==true)
  414. printf(" navigation canceled\n");
  415. printf(" navigation end...\n");
  416. if(global_trajectorys_.size()==0)
  417. printf("navigation completed!!!\n");
  418. running_=false;
  419. }