navigation.cpp 15 KB

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