navigation.cpp 12 KB

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