navigation.cpp 16 KB

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