navigation.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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. exit_=true;
  10. if(terminator_)
  11. delete terminator_;
  12. if(monitor_)
  13. delete monitor_;
  14. if(thread_!= nullptr)
  15. {
  16. if(thread_->joinable())
  17. thread_->join();
  18. delete thread_;
  19. }
  20. if(pubthread_!= nullptr)
  21. {
  22. if(pubthread_->joinable())
  23. pubthread_->join();
  24. delete pubthread_;
  25. }
  26. }
  27. /*
  28. * 高斯函数压缩,x=3
  29. */
  30. double limit(double x,double min,double max){
  31. double r=x>=0?1.0:-1.0;
  32. double delta=max/3.0;
  33. return (max-(max-min)*exp(-x*x/(delta*delta)))*r;
  34. }
  35. bool Navigation::Init(const Navigation_parameter& parameter)
  36. {
  37. parameter_=parameter;
  38. AgvEmqx_parameter agv_p=parameter.agv_emqx();
  39. if(monitor_== nullptr) {
  40. monitor_ = new Monitor_emqx(agv_p.nodeid());
  41. if(monitor_->Connect(agv_p.ip(),agv_p.port())==false)
  42. {
  43. printf(" agv emqx connected failed\n");
  44. return false;
  45. }
  46. monitor_->AddCallback(agv_p.subposetopic(),Navigation::RobotPoseCallback,this);
  47. monitor_->AddCallback(agv_p.subspeedtopic(),Navigation::RobotSpeedCallback,this);
  48. }
  49. Emqx_parameter terminal_p=parameter.terminal_emqx();
  50. if(terminator_== nullptr) {
  51. terminator_ = new Terminator_emqx(terminal_p.nodeid());
  52. if(terminator_->Connect(terminal_p.ip(),terminal_p.port())==false)
  53. {
  54. printf(" terminator emqx connected failed\n");
  55. return false;
  56. }
  57. terminator_->AddCallback(terminal_p.subnavcmdtopic(),Navigation::NavCmdCallback,this);
  58. terminator_->AddCallback(terminal_p.subbrotherstatutopic(),Navigation::BrotherAgvStatuCallback,this);
  59. }
  60. inited_=true;
  61. if(pubthread_!= nullptr)
  62. {
  63. exit_=true;
  64. if(pubthread_->joinable())
  65. pubthread_->join();
  66. delete pubthread_;
  67. }
  68. exit_=false;
  69. pubthread_=new std::thread(&Navigation::publish_statu,this);
  70. return true;
  71. }
  72. void Navigation::RobotPoseCallback(const MqttMsg& msg,void* context)
  73. {
  74. Navigation* navigator=(Navigation*)context;
  75. NavMessage::AGVStatu statu;
  76. if(msg.toProtoMessage(statu))
  77. {
  78. navigator->ResetPose(Pose2d(statu.x(),statu.y(),statu.theta()));
  79. }
  80. }
  81. void Navigation::RobotSpeedCallback(const MqttMsg& msg,void* context)
  82. {
  83. Navigation* navigator=(Navigation*)context;
  84. NavMessage::AGVSpeed speed;
  85. if(msg.toProtoMessage(speed))
  86. {
  87. navigator->ResetStatu(speed.v(),speed.w());
  88. }
  89. }
  90. void Navigation::publish_statu() {
  91. while (exit_ == false)
  92. {
  93. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  94. //发布nav状态
  95. NavMessage::NavStatu statu;
  96. statu.set_statu(eReady); //默认ready
  97. NavMessage::Action *current_action = nullptr;
  98. if (running_)
  99. {
  100. statu.set_statu(eRunning);
  101. statu.set_key(global_navCmd_.key());
  102. std::queue<NavMessage::Action> actios = unfinished_cations_;
  103. while (actios.empty() == false) {
  104. //保存当前动作
  105. NavMessage::Action *act = statu.add_unfinished_actions();
  106. current_action = new NavMessage::Action(*act);
  107. act->CopyFrom(actios.front());
  108. actios.pop();
  109. }
  110. }
  111. //发布MPC信息
  112. if (current_action != nullptr) {
  113. delete current_action;
  114. //发布mpc 预选点
  115. if (selected_traj_.timeout() == false) {
  116. for (int i = 0; i < selected_traj_.Get().size(); ++i) {
  117. Pose2d pt = selected_traj_.Get()[i];
  118. NavMessage::Pose2d *pose = statu.mutable_selected_traj()->add_poses();
  119. pose->set_x(pt.x());
  120. pose->set_y(pt.y());
  121. pose->set_theta(pt.theta());
  122. }
  123. }
  124. //发布 mpc 预测点
  125. if (predict_traj_.timeout() == false) {
  126. for (int i = 0; i < predict_traj_.Get().size(); ++i) {
  127. Pose2d pt = predict_traj_.Get()[i];
  128. NavMessage::Pose2d *pose = statu.mutable_predict_traj()->add_poses();
  129. pose->set_x(pt.x());
  130. pose->set_y(pt.y());
  131. pose->set_theta(pt.theta());
  132. }
  133. }
  134. }
  135. MqttMsg msg;
  136. msg.fromProtoMessage(statu);
  137. if(terminator_)
  138. terminator_->Publish(parameter_.terminal_emqx().pubnavstatutopic(),msg);
  139. //发布位姿 --------------------------------
  140. if (timedPose_.timeout() == false&&
  141. timedV_.timeout() == false && timedA_.timeout() == false) {
  142. NavMessage::AGVStatu agvStatu;
  143. Pose2d pose = timedPose_.Get();
  144. agvStatu.set_x(pose.x());
  145. agvStatu.set_y(pose.y());
  146. agvStatu.set_theta(pose.theta());
  147. agvStatu.set_v(timedV_.Get());
  148. agvStatu.set_vth(timedA_.Get());
  149. if(terminator_) {
  150. MqttMsg msg;
  151. msg.fromProtoMessage(agvStatu);
  152. terminator_->Publish(parameter_.terminal_emqx().pubstatutopic(), msg);
  153. }
  154. }
  155. }
  156. }
  157. void Navigation::ResetStatu(double v,double a)
  158. {
  159. timedV_.reset(v,0.5);
  160. timedA_.reset(a,0.5);
  161. }
  162. void Navigation::ResetPose(const Pose2d& pose)
  163. {
  164. timedPose_.reset(pose,0.5);
  165. }
  166. bool Navigation::Start(const NavMessage::NavCmd& cmd)
  167. {
  168. if(unfinished_cations_.empty()==false) //正在运行中,上一次指令未完成
  169. {
  170. if(pause_)
  171. {
  172. pause_=false;
  173. return true;
  174. }
  175. printf(" navigation is running pls cancel before\n");
  176. return false;
  177. }
  178. if(thread_!= nullptr)
  179. {
  180. if(thread_->joinable())
  181. thread_->join();
  182. delete thread_;
  183. }
  184. //add 先检查当前点与起点的距离
  185. global_navCmd_=cmd;
  186. for(int i=0;i<cmd.actions_size();++i)
  187. unfinished_cations_.push(cmd.actions(i));
  188. thread_=new std::thread(&Navigation::navigatting,this);
  189. return true;
  190. }
  191. void Navigation::Cancel()
  192. {
  193. cancel_=true;
  194. }
  195. void Navigation::Pause()
  196. {
  197. monitor_->stop();
  198. pause_=true;
  199. }
  200. Navigation::Navigation()
  201. {
  202. thread_= nullptr;
  203. monitor_= nullptr;
  204. terminator_= nullptr;
  205. timedBrotherPose_.reset(Pose2d(-100,0,0),0.1);
  206. }
  207. void Navigation::BrotherAgvStatuCallback(const MqttMsg& msg,void* context)
  208. {
  209. Navigation* navigator=(Navigation*)context;
  210. NavMessage::AGVStatu brother_statu;
  211. if(msg.toProtoMessage(brother_statu)==false) {
  212. printf(" msg transform to AGVStatu failed ..!!\n");
  213. return;
  214. }
  215. //std::cout<<brother_nav.DebugString()<<std::endl<<std::endl;
  216. Pose2d pose(brother_statu.x(),brother_statu.y(),brother_statu.theta());
  217. navigator->timedBrotherPose_.reset(pose,1);
  218. navigator->timedBrotherV_.reset(brother_statu.v(),1);
  219. navigator->timedBrotherA_.reset(brother_statu.vth(),1);
  220. }
  221. void Navigation::NavCmdCallback(const MqttMsg& msg,void* context)
  222. {
  223. Navigation* navigator=(Navigation*)context;
  224. NavMessage::NavCmd cmd;
  225. if(msg.toProtoMessage(cmd)==false) {
  226. printf(" msg transform to NavCmd failed ..!!\n");
  227. return;
  228. }
  229. if(cmd.action()==3)
  230. {
  231. navigator->Cancel();
  232. return ;
  233. }
  234. if(cmd.action()==2) {
  235. navigator->pause_=false;
  236. return ;
  237. }
  238. if(cmd.action()==1) {
  239. navigator->Pause();
  240. return ;
  241. }
  242. navigator->Start(cmd);
  243. }
  244. bool Navigation::exec_adjust_action(const Pose2d& target,const Pose2d& target_diff,
  245. stLimit limit_v,stLimit limit_h,stLimit limit_rotate)
  246. {
  247. if(inited_==false) {
  248. printf(" navigation has not inited\n");
  249. return false;
  250. }
  251. Pose2d thresh=Pose2d::abs(target_diff);
  252. int action=0; //1 原地旋转,2横移,3前进
  253. while(cancel_==false) {
  254. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  255. if (pause_ == true) {
  256. //发送暂停消息
  257. continue;
  258. }
  259. if (timedPose_.timeout() || timedV_.timeout() || timedA_.timeout()) {
  260. printf(" navigation Error:Pose/v/a is timeout \n");
  261. break;
  262. }
  263. //判断是否到达目标点
  264. if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff)) {
  265. monitor_->stop();
  266. printf("adjust completed\n");
  267. return true;
  268. }
  269. //计算目标点在当前pose下的pose
  270. Pose2d diff = Pose2d::relativePose(target, timedPose_.Get());
  271. //停止状态
  272. if (action == 0) {
  273. //优先进入旋转
  274. if (Pose2d::abs(diff).theta() > thresh.theta()) {
  275. action = 1; //原地旋转
  276. } else if (Pose2d::abs(diff).x() > thresh.x()) {
  277. //前进
  278. action = 3;
  279. }else if (Pose2d::abs(diff).y() > thresh.y()) {
  280. //横移
  281. action = 2;
  282. }
  283. }
  284. else
  285. {
  286. if (action == 1) {
  287. if (Pose2d::abs(diff).theta() > thresh.theta()) {
  288. double theta = limit(diff.theta(),limit_rotate.min*M_PI/180.0,limit_rotate.max*M_PI/180.0);
  289. monitor_->set_speed(Monitor_emqx::eRotate, 0, theta);
  290. printf(" Ratate :%f\n",theta);
  291. continue;
  292. }
  293. }
  294. if (action == 2) {
  295. if (Pose2d::abs(diff).y() > thresh.y()) {
  296. monitor_->set_speed(Monitor_emqx::eHorizontal, limit(diff.y(),limit_h.min,limit_h.max), 0);
  297. printf(" Horizontal :%f\n",limit(diff.y(),limit_h.min,limit_h.max));
  298. continue;
  299. }
  300. }
  301. if (action == 3) {
  302. if (Pose2d::abs(diff).x() > thresh.x()) {
  303. monitor_->set_speed(Monitor_emqx::eMPC, limit(diff.x(),limit_v.min,limit_v.max), 0);
  304. printf(" Vrtical :%f\n",limit(diff.x(),limit_v.min,limit_v.max));
  305. continue;
  306. }
  307. }
  308. monitor_->stop();
  309. printf(" monitor type :%d completed!!! reset action type!!!\n", action);
  310. action = 0;
  311. }
  312. }
  313. return false;
  314. }
  315. bool Navigation::mpc_once(const Trajectory& traj,stLimit limit_v,std::vector<double>& out)
  316. {
  317. if(timedPose_.timeout()==true && timedV_.timeout()==false && timedA_.timeout()==false)
  318. {
  319. printf(" MPC once Error:Pose/V/A is timeout \n");
  320. return false;
  321. }
  322. if(traj.size()==0)
  323. {
  324. printf("traj size ==0\n");
  325. return false;
  326. }
  327. Pose2d pose=timedPose_.Get();
  328. double velocity=timedV_.Get(); //从plc获取状态
  329. double angular=timedA_.Get();
  330. Pose2d brother=timedBrotherPose_.Get();
  331. Pose2d relative=Pose2d::relativePose(brother,pose);//计算另一节在当前小车坐标系下的坐标
  332. LoadedMPC MPC(relative,limit_v.min, limit_v.max);
  333. Eigen::VectorXd statu=Eigen::VectorXd::Zero(5);//agv状态
  334. statu[0]=pose.x();
  335. statu[1]=pose.y();
  336. statu[2]=pose.theta();
  337. statu[3]=velocity;
  338. statu[4]=angular;
  339. Trajectory optimize_trajectory;
  340. Trajectory selected_trajectory;
  341. bool ret= MPC.solve(traj,traj[traj.size()-1],statu,out,selected_trajectory,optimize_trajectory);
  342. predict_traj_.reset(optimize_trajectory,1);
  343. selected_traj_.reset(selected_trajectory,1);
  344. return ret;
  345. }
  346. bool Navigation::IsArrived(const Pose2d& cur,double velocity,double angular,
  347. const Pose2d& target,const Pose2d& diff)
  348. {
  349. Pose2d distance=Pose2d::relativePose(target,cur);
  350. if(Pose2d::abs(distance)<diff)
  351. {
  352. if(fabs(velocity)<0.1 && fabs(angular)< 10*M_PI/180.0)
  353. return true;
  354. }
  355. return false;
  356. }
  357. bool Navigation::execute_along_action(const Pose2d& target,const Pose2d& target_diff,stLimit limit_v)
  358. {
  359. if(inited_==false) {
  360. printf(" navigation has not inited\n");
  361. return false;
  362. }
  363. if (timedPose_.timeout() ) {
  364. printf(" navigation Error:Pose is timeout \n");
  365. return false;
  366. }
  367. //生成轨迹
  368. Trajectory traj=Trajectory::create_line_trajectory(timedPose_.Get(),target);
  369. if(traj.size()==0)
  370. return true;
  371. while(cancel_==false)
  372. {
  373. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  374. if(pause_==true)
  375. {
  376. //发送暂停消息
  377. continue;
  378. }
  379. if (timedPose_.timeout() || timedV_.timeout() || timedA_.timeout()) {
  380. printf(" navigation Error:Pose/v/a is timeout \n");
  381. return false;
  382. }
  383. //判断是否到达终点
  384. if(IsArrived(timedPose_.Get(),timedV_.Get(),timedA_.Get(),target,target_diff))
  385. {
  386. monitor_->stop();
  387. printf(" exec along completed !!!\n");
  388. return true;
  389. }
  390. //一次变速
  391. std::vector<double> out;
  392. bool ret;
  393. TimerRecord::Execute([&,this](){
  394. ret=mpc_once(traj,limit_v,out);
  395. },"mpc_once");
  396. if(ret==false)
  397. {
  398. monitor_->stop();
  399. return false;
  400. }
  401. monitor_->set_speed(Monitor_emqx::eMPC,out[0],out[1]);
  402. //std::this_thread::sleep_for(std::chrono::milliseconds (400));
  403. }
  404. return false;
  405. }
  406. void Navigation::navigatting()
  407. {
  408. if(inited_==false) {
  409. printf(" navigation has not inited\n");
  410. return ;
  411. }
  412. pause_=false;
  413. cancel_=false;
  414. running_=true;
  415. printf(" navigation beg...\n");
  416. while(unfinished_cations_.empty()==false && cancel_==false)
  417. {
  418. NavMessage::Action act=unfinished_cations_.front();
  419. Pose2d target(act.target().x(),act.target().y(),act.target().theta());
  420. Pose2d target_diff(act.target_diff().x(),act.target_diff().y(),act.target_diff().theta());
  421. if(act.type()==1)
  422. {
  423. printf(" adjust to (%.3f %.3f %.3f) diff:(%.3f,%.3f,%.3f)\n",
  424. act.target().x(),act.target().y(),act.target().theta(),
  425. act.target_diff().x(),act.target_diff().y(),act.target_diff().theta());
  426. stLimit limit_angular,limit_velocity,limint_horize;
  427. limit_velocity.min=act.velocity_limit().min();
  428. limit_velocity.max=act.velocity_limit().max();
  429. limit_angular.min=act.angular_limit().min();
  430. limit_angular.max=act.angular_limit().max();
  431. limint_horize.min=act.horize_limit().min();
  432. limint_horize.max=act.horize_limit().max();
  433. if(exec_adjust_action(target,target_diff,limit_velocity,limint_horize,limit_angular)==false)
  434. {
  435. printf("execute adjust action failed\n");
  436. break;
  437. }
  438. }
  439. else if(act.type()==2)
  440. {
  441. stLimit limit_velocity;
  442. limit_velocity.min=act.velocity_limit().min();
  443. limit_velocity.max=act.velocity_limit().max();
  444. printf(" MPC to (%.3f %.3f %.3f) diff:(%.3f,%.3f,%.3f)\n",
  445. act.target().x(),act.target().y(),act.target().theta(),
  446. act.target_diff().x(),act.target_diff().y(),act.target_diff().theta());
  447. if(execute_along_action(target,target_diff,limit_velocity)==false) {
  448. printf("execute along action failed\n");
  449. break;
  450. }
  451. }
  452. else
  453. {
  454. printf(" unknow action type:%d\n",act.type());
  455. break;
  456. }
  457. unfinished_cations_.pop();
  458. }
  459. monitor_->stop();
  460. if(cancel_==true) {
  461. printf(" navigation canceled\n");
  462. while(unfinished_cations_.empty()==false)
  463. unfinished_cations_.pop();
  464. }else {
  465. if (unfinished_cations_.empty())
  466. printf("navigation completed!!!\n");
  467. else{
  468. printf(" navigation Failed\n");
  469. while(unfinished_cations_.empty()==false)
  470. unfinished_cations_.pop();
  471. }
  472. }
  473. running_=false;
  474. }