navigation.cpp 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077
  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(brotherEmqx_)
  13. delete brotherEmqx_;
  14. if(monitor_)
  15. delete monitor_;
  16. if(thread_!= nullptr)
  17. {
  18. if(thread_->joinable())
  19. thread_->join();
  20. delete thread_;
  21. }
  22. if(pubthread_!= nullptr)
  23. {
  24. if(pubthread_->joinable())
  25. pubthread_->join();
  26. delete pubthread_;
  27. }
  28. }
  29. /*
  30. * 高斯函数压缩,x=3
  31. */
  32. double limit_gause(double x,double min,double max){
  33. double r=x>=0?1.0:-1.0;
  34. double delta=max/1.0;
  35. return (max-(max-min)*exp(-x*x/(delta*delta)))*r;
  36. }
  37. double limit(double x,double min,double max){
  38. double ret=x;
  39. if(x>=0){
  40. if(x>max) ret=max;
  41. if(x<min) ret=min;
  42. }else{
  43. if(x<-max) ret=-max;
  44. if(x>-min) ret=-min;
  45. }
  46. return ret;
  47. }
  48. double next_speed(double speed,double target_speed,double acc,double dt=0.1)
  49. {
  50. if(fabs(target_speed-speed)/dt<acc)
  51. {
  52. return target_speed;
  53. }
  54. else
  55. {
  56. double r=target_speed-speed>=0.?1.0:-1.0;
  57. return speed+r*acc*dt;
  58. }
  59. }
  60. bool Navigation::PoseTimeout(){
  61. if(timedPose_.timeout()== false && timedBrotherPose_.timeout()==false){
  62. return false;
  63. }else{
  64. if(timedPose_.timeout()){
  65. printf(" current pose is timeout \n");
  66. }
  67. if(timedBrotherPose_.timeout()){
  68. printf(" brother pose is timeout \n");
  69. }
  70. return true;
  71. }
  72. }
  73. bool Navigation::Init(const NavParameter::Navigation_parameter& parameter)
  74. {
  75. parameter_=parameter;
  76. NavParameter::AgvEmqx_parameter agv_p=parameter.agv_emqx();
  77. if(monitor_== nullptr) {
  78. monitor_ = new Monitor_emqx(agv_p.nodeid());
  79. if(monitor_->Connect(agv_p.ip(),agv_p.port())==false)
  80. {
  81. printf(" agv emqx connected failed\n");
  82. return false;
  83. }
  84. monitor_->set_speedcmd_topic(agv_p.pubspeedtopic());
  85. monitor_->AddCallback(agv_p.subposetopic(),Navigation::RobotPoseCallback,this);
  86. monitor_->AddCallback(agv_p.subspeedtopic(),Navigation::RobotSpeedCallback,this);
  87. }
  88. NavParameter::Emqx_parameter terminal_p=parameter.terminal_emqx();
  89. if(terminator_== nullptr) {
  90. terminator_ = new Terminator_emqx(terminal_p.nodeid());
  91. if(terminator_->Connect(terminal_p.ip(),terminal_p.port())==false)
  92. {
  93. printf(" terminator emqx connected failed\n");
  94. return false;
  95. }
  96. terminator_->AddCallback(terminal_p.subnavcmdtopic(),Navigation::NavCmdCallback,this);
  97. }
  98. if(parameter.has_brother_emqx()) {
  99. NavParameter::BrotherEmqx brotherEmqx = parameter.brother_emqx();
  100. if (brotherEmqx_ == nullptr) {
  101. brotherEmqx_ = new Terminator_emqx(brotherEmqx.nodeid());
  102. if (brotherEmqx_->Connect(brotherEmqx.ip(), brotherEmqx.port()) == true) {
  103. brotherEmqx_->AddCallback(brotherEmqx.subbrotherstatutopic(), Navigation::BrotherAgvStatuCallback, this);
  104. }else{
  105. printf(" brother emqx connected failed\n");
  106. // return false;
  107. }
  108. }
  109. }
  110. inited_=true;
  111. if(pubthread_!= nullptr)
  112. {
  113. exit_=true;
  114. if(pubthread_->joinable())
  115. pubthread_->join();
  116. delete pubthread_;
  117. }
  118. exit_=false;
  119. pubthread_=new std::thread(&Navigation::pubStatuThreadFuc,this);
  120. return true;
  121. }
  122. void Navigation::RobotPoseCallback(const MqttMsg& msg,void* context)
  123. {
  124. Navigation* navigator=(Navigation*)context;
  125. NavMessage::LidarOdomStatu statu;
  126. if(msg.toProtoMessage(statu))
  127. {
  128. navigator->ResetPose(Pose2d(statu.x(),statu.y(),statu.theta()));
  129. }
  130. }
  131. void Navigation::HandleAgvStatu(const MqttMsg& msg)
  132. {
  133. NavMessage::AgvStatu speed;
  134. if(msg.toProtoMessage(speed))
  135. {
  136. ResetStatu(speed.v(),speed.w());
  137. ResetClamp((ClampStatu)speed.clamp());
  138. }
  139. }
  140. void Navigation::RobotSpeedCallback(const MqttMsg& msg,void* context)
  141. {
  142. Navigation* navigator=(Navigation*)context;
  143. navigator->HandleAgvStatu(msg);
  144. }
  145. void Navigation::pubStatuThreadFuc(void* p) {
  146. Navigation *navogator = (Navigation *) p;
  147. if (navogator) {
  148. while (navogator->exit_ == false) {
  149. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  150. NavMessage::NavStatu statu;
  151. statu.set_main_agv(false);
  152. navogator->publish_statu(statu);
  153. }
  154. }
  155. }
  156. void Navigation::publish_statu(NavMessage::NavStatu& statu) {
  157. //发布nav状态
  158. statu.set_statu(actionType_); //
  159. //printf(" statu:%d\n",actionType_);
  160. statu.set_move_mode(move_mode_);
  161. if (running_)
  162. {
  163. statu.set_key(global_navCmd_.key());
  164. }
  165. //发布MPC信息
  166. //发布mpc 预选点
  167. if (selected_traj_.timeout() == false) {
  168. for (int i = 0; i < selected_traj_.Get().size(); ++i) {
  169. Pose2d pt = selected_traj_.Get()[i];
  170. NavMessage::Pose2d *pose = statu.mutable_selected_traj()->add_poses();
  171. pose->set_x(pt.x());
  172. pose->set_y(pt.y());
  173. pose->set_theta(pt.theta());
  174. }
  175. }
  176. //发布 mpc 预测点
  177. if (predict_traj_.timeout() == false) {
  178. for (int i = 0; i < predict_traj_.Get().size(); ++i) {
  179. Pose2d pt = predict_traj_.Get()[i];
  180. NavMessage::Pose2d *pose = statu.mutable_predict_traj()->add_poses();
  181. pose->set_x(pt.x());
  182. pose->set_y(pt.y());
  183. pose->set_theta(pt.theta());
  184. }
  185. }
  186. //std::cout<<"nav statu:"<<statu.DebugString()<<std::endl;
  187. MqttMsg msg;
  188. msg.fromProtoMessage(statu);
  189. if(terminator_)
  190. terminator_->Publish(parameter_.terminal_emqx().pubnavstatutopic(),msg);
  191. //发布位姿 ------robot状态--------------------------
  192. NavMessage::RobotStatu robot;
  193. if(CreateRobotStatuMsg(robot)) {
  194. if (terminator_) {
  195. MqttMsg msg;
  196. msg.fromProtoMessage(robot);
  197. terminator_->Publish(parameter_.terminal_emqx().pubstatutopic(), msg);
  198. }
  199. }
  200. }
  201. bool Navigation::CreateRobotStatuMsg(NavMessage::RobotStatu& robotStatu)
  202. {
  203. //printf(" %d %d %d \n",timedPose_.timeout(),timedV_.timeout(),timedA_.timeout());
  204. if (timedPose_.timeout() == false) {
  205. Pose2d pose = timedPose_.Get();
  206. robotStatu.set_x(pose.x());
  207. robotStatu.set_y(pose.y());
  208. robotStatu.set_theta(pose.theta());
  209. if((timedV_.timeout() == false && timedA_.timeout() == false)) {
  210. NavMessage::AgvStatu plc;
  211. plc.set_v(timedV_.Get());
  212. plc.set_w(timedA_.Get());
  213. plc.set_clamp(timed_clamp_.Get());
  214. //printf(" timed_clamp_:%d\n ",timed_clamp_.Get());
  215. robotStatu.mutable_agvstatu()->CopyFrom(plc);
  216. }
  217. return true;
  218. }
  219. return false;
  220. }
  221. void Navigation::ResetStatu(double v,double a)
  222. {
  223. timedV_.reset(v,0.5);
  224. timedA_.reset(a,0.5);
  225. }
  226. void Navigation::ResetClamp(ClampStatu statu){
  227. timed_clamp_.reset(statu,1);
  228. }
  229. void Navigation::ResetPose(const Pose2d& pose)
  230. {
  231. timedPose_.reset(pose,1.0);
  232. }
  233. bool Navigation::Start(const NavMessage::NavCmd& cmd)
  234. {
  235. if(newUnfinished_cations_.empty()==false) //正在运行中,上一次指令未完成
  236. {
  237. if(pause_)
  238. {
  239. pause_=false;
  240. return true;
  241. }
  242. printf(" navigation is running pls cancel before\n");
  243. return false;
  244. }
  245. if(thread_!= nullptr)
  246. {
  247. if(thread_->joinable())
  248. thread_->join();
  249. delete thread_;
  250. }
  251. //add 先检查当前点与起点的距离
  252. global_navCmd_=cmd;
  253. for (int i = 0; i < cmd.newactions_size(); ++i)
  254. newUnfinished_cations_.push(cmd.newactions(i));
  255. thread_=new std::thread(&Navigation::navigatting,this);
  256. return true;
  257. }
  258. void Navigation::Cancel()
  259. {
  260. cancel_=true;
  261. }
  262. bool Navigation::Stop() {
  263. if(monitor_)
  264. {
  265. monitor_->stop();
  266. while(cancel_==false)
  267. {
  268. if(timedV_.timeout()==false && timedA_.timeout()==false)
  269. {
  270. if(fabs(timedV_.Get())<1e-6 && fabs(timedA_.Get())<1e-6)
  271. return true;
  272. else
  273. monitor_->stop();
  274. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  275. }else{
  276. printf("Stop failed V/A timeout\n");
  277. return false;
  278. }
  279. }
  280. }
  281. return false;
  282. }
  283. void Navigation::Pause()
  284. {
  285. if(Stop())
  286. pause_=true;
  287. }
  288. Navigation::Navigation()
  289. {
  290. move_mode_=Monitor_emqx::eSingle;
  291. thread_= nullptr;
  292. monitor_= nullptr;
  293. terminator_= nullptr;
  294. timedBrotherPose_.reset(Pose2d(-100,0,0),0.1);
  295. }
  296. void Navigation::BrotherAgvStatuCallback(const MqttMsg& msg,void* context)
  297. {
  298. Navigation* navigator=(Navigation*)context;
  299. NavMessage::LidarOdomStatu brother_statu;
  300. if(msg.toProtoMessage(brother_statu)==false) {
  301. std::cout<<" msg transform to AGVStatu failed,msg:"<<msg.data()<<std::endl;
  302. return;
  303. }
  304. //std::cout<<brother_nav.DebugString()<<std::endl<<std::endl;
  305. Pose2d pose(brother_statu.x(),brother_statu.y(),brother_statu.theta());
  306. navigator->timedBrotherPose_.reset(pose,1);
  307. navigator->timedBrotherV_.reset(brother_statu.v(),1);
  308. navigator->timedBrotherA_.reset(brother_statu.vth(),1);
  309. }
  310. void Navigation::HandleNavCmd(const NavMessage::NavCmd& cmd)
  311. {
  312. if(cmd.action()==3)
  313. {
  314. printf(" Nav cancel\n");
  315. Cancel();
  316. return ;
  317. }
  318. if(cmd.action()==2) {
  319. printf(" Nav continue\n");
  320. pause_=false;
  321. return ;
  322. }
  323. if(cmd.action()==1) {
  324. printf(" Nav pause\n");
  325. Pause();
  326. return ;
  327. }
  328. if(cmd.action()==0||cmd.action()==6)
  329. {
  330. Start(cmd);
  331. }
  332. else
  333. printf(" Invalid action ,action:%d\n",cmd.action());
  334. }
  335. void Navigation::NavCmdCallback(const MqttMsg& msg,void* context)
  336. {
  337. NavMessage::NavCmd cmd;
  338. if(msg.toProtoMessage(cmd)==false) {
  339. printf(" msg transform to NavCmd failed ..!!\n");
  340. return;
  341. }
  342. Navigation* navigator=(Navigation*)context;
  343. navigator->HandleNavCmd(cmd);
  344. }
  345. bool Navigation::execute_adjust_action(const Pose2d& target,const Pose2d& target_diff,stLimit limit_v,
  346. stLimit limit_h,stLimit limit_rotate,bool anyDitect)
  347. {
  348. std::cout<<" adjust target:"<<target<<" target diff:"<<target_diff<<std::endl;
  349. if(inited_==false) {
  350. printf(" navigation has not inited\n");
  351. return false;
  352. }
  353. Pose2d accuracy=target_diff;
  354. Pose2d thresh=Pose2d::abs(accuracy);
  355. int action=0; //1 原地旋转,2横移,3前进
  356. while(cancel_==false) {
  357. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  358. if (pause_ == true) {
  359. //发送暂停消息
  360. continue;
  361. }
  362. if (PoseTimeout() || timedV_.timeout() || timedA_.timeout()) {
  363. printf(" navigation Error:Pose/v/a is timeout \n");
  364. break;
  365. }
  366. //判断是否到达目标点
  367. int direct=0;
  368. if(anyDitect) direct=2;
  369. if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, accuracy,direct)) {
  370. if(Stop()) {
  371. printf("adjust completed anyDitect :%d\n",anyDitect);
  372. return true;
  373. }
  374. return false;
  375. }
  376. //计算目标点在当前pose下的pose
  377. Pose2d diff = Pose2d::relativePose(target, timedPose_.Get());
  378. //停止状态
  379. if (action == 0) {
  380. //
  381. if (Pose2d::abs(diff).x() > thresh.x()) {
  382. //前进
  383. action = 3;
  384. }else if (Pose2d::abs(diff).y() > thresh.y()) {
  385. //横移
  386. action = 2;
  387. }
  388. else if (Pose2d::abs(diff).theta() > thresh.theta()) {
  389. action = 1; //原地旋转
  390. }
  391. }
  392. else
  393. {
  394. double acc_v=0.6;
  395. double acc_angular=10.0*M_PI/180.0;
  396. double dt=0.1;
  397. if (action == 1) {
  398. float minYawDiff=diff.theta();
  399. if(anyDitect){
  400. Pose2d p0=timedPose_.Get();
  401. float yawdiff[4]={0};
  402. yawdiff[0]=diff.theta();
  403. yawdiff[1]=Pose2d::relativePose(target,p0-Pose2d(0,0,M_PI/2)).theta(); ////使用减法,保证角度在【-pi pi】
  404. yawdiff[2]=Pose2d::relativePose(target,p0-Pose2d(0,0,M_PI)).theta();
  405. yawdiff[3]=Pose2d::relativePose(target,p0-Pose2d(0,0,3*M_PI/2)).theta();
  406. for(int i=1;i<4;++i){
  407. if(fabs(yawdiff[i])<fabs(minYawDiff)){
  408. minYawDiff=yawdiff[i];
  409. }
  410. }
  411. }
  412. if (fabs(minYawDiff) > thresh.theta()) {
  413. double theta = limit_gause(minYawDiff,limit_rotate.min,limit_rotate.max);
  414. double angular=next_speed(timedA_.Get(),theta,acc_angular,dt);
  415. double limit_angular=limit(angular,limit_rotate.min,limit_rotate.max);
  416. SendMoveCmd(move_mode_,Monitor_emqx::eRotate, 0, limit_angular);
  417. actionType_=eRotation;
  418. printf(" Ratate | input anguar:%f,next angular:%f,down:%f diff:%f anyDitect:%d\n",
  419. timedA_.Get(),angular,limit_angular,minYawDiff,anyDitect);
  420. continue;
  421. }
  422. }
  423. if (action == 2) {
  424. if (Pose2d::abs(diff).y() > thresh.y()) {
  425. double hv=limit_gause(diff.y(),limit_h.min,limit_h.max);
  426. double velocity=limit(next_speed(timedV_.Get(),hv,acc_v,dt),limit_h.min,limit_h.max);
  427. SendMoveCmd(move_mode_,Monitor_emqx::eHorizontal,velocity , 0);
  428. actionType_=eHorizon;
  429. printf(" Horizontal input:%f out:%f\n",timedV_.Get(),velocity);
  430. continue;
  431. }
  432. }
  433. if (action == 3) {
  434. if (Pose2d::abs(diff).x() > thresh.x()) {
  435. double v=limit_gause(diff.x(),limit_v.min,limit_v.max);
  436. double velocity=limit(next_speed(timedV_.Get(),v,acc_v,dt),limit_v.min,limit_v.max);
  437. SendMoveCmd(move_mode_,Monitor_emqx::eMPC, velocity, 0);
  438. actionType_=eVertical;
  439. printf(" Vrtical input:%f,out:%f\n",timedV_.Get(),velocity);
  440. continue;
  441. }
  442. }
  443. if(Stop()) {
  444. printf(" monitor type :%d completed!!! reset action type!!!\n", action);
  445. action = 0;
  446. }
  447. }
  448. }
  449. return false;
  450. }
  451. bool Navigation::execute_nodes(NavMessage::NewAction action)
  452. {
  453. if(action.type()==3 || action.type()==4) //最优动作导航 or 导航中保证朝向严格一致
  454. {
  455. if(!action.has_nodevelocitylimit() || !action.has_nodeangularlimit()||
  456. !action.has_adjustvelocitylimit()|| !action.has_adjusthorizonlimit()
  457. || action.pathnodes_size()==0) {
  458. std::cout << "execute pathNodes failed ,Action invalid:" << action.DebugString() << std::endl;
  459. return false;
  460. }
  461. bool anyDirect=(action.type()==3);
  462. // if (move_mode_==Monitor_emqx::eMain) //双车模式静止自由方向做MPC
  463. // anyDirect=false;
  464. //原地调整起点
  465. NavMessage::PathNode first=action.pathnodes(0);
  466. //速度限制
  467. stLimit adjust_x={ action.adjustvelocitylimit().min(),action.adjustvelocitylimit().max() };
  468. stLimit adjust_h={ action.adjusthorizonlimit().min(),action.adjusthorizonlimit().max() };
  469. stLimit adjust_angular={ action.nodeangularlimit().min(),action.nodeangularlimit().max() };
  470. stLimit mpc_velocity={ action.nodevelocitylimit().min(),action.nodevelocitylimit().max() };
  471. //目标,精度
  472. double first_yaw=timedPose_.Get().theta();
  473. if(1<action.pathnodes_size()){
  474. NavMessage::PathNode next=action.pathnodes(1);
  475. first_yaw=Pose2d::vector2yaw(next.pose().x()-first.pose().x(),next.pose().y()-first.pose().y());
  476. }
  477. Pose2d first_target(first.pose().x(),first.pose().y(),first_yaw);
  478. Pose2d first_accuracy(first.accuracy().x(),first.accuracy().y(),first.accuracy().theta());
  479. execute_adjust_action(first_target,first_accuracy,adjust_x,adjust_h,adjust_angular,anyDirect);
  480. Pose2d last_node=first_target;
  481. for(int i=1;i< action.pathnodes_size();++i)
  482. {
  483. NavMessage::PathNode node = action.pathnodes(i);
  484. /// 巡线到目标点,判断巡线方向
  485. Pose2d target(node.pose().x(), node.pose().y(), node.pose().theta());
  486. Pose2d accuracy(node.accuracy().x(), node.accuracy().y(), node.accuracy().theta());
  487. if (execute_along_action(last_node, target, accuracy, mpc_velocity, anyDirect) == false)
  488. return false;
  489. //不是最后一个点,则原地当前点朝向
  490. if(i!=action.pathnodes_size()-1)
  491. {
  492. //目标,精度
  493. double adjust_yaw=timedPose_.Get().theta();
  494. NavMessage::PathNode next=action.pathnodes(i+1);
  495. adjust_yaw=Pose2d::vector2yaw(next.pose().x()-node.pose().x(),next.pose().y()-node.pose().y());
  496. Pose2d adjust_target(node.pose().x(),node.pose().y(),adjust_yaw);
  497. Pose2d adjust_accuracy(node.accuracy().x(),node.accuracy().y(),node.accuracy().theta());
  498. execute_adjust_action(adjust_target,adjust_accuracy,adjust_x,adjust_h,adjust_angular,anyDirect);
  499. last_node=adjust_target;
  500. }
  501. }
  502. return true;
  503. }
  504. printf("execute PathNode failed ,action type is not 3/4 :%d\n",action.type());
  505. return false;
  506. }
  507. bool Navigation::execute_vehicle_mode(NavMessage::NewAction action){
  508. if(action.type()==5 ) //最优动作导航 or 导航中保证朝向严格一致
  509. {
  510. if (!action.has_nodevelocitylimit() || !action.has_nodeangularlimit() ||
  511. !action.has_adjustvelocitylimit() || !action.has_adjusthorizonlimit()
  512. || action.pathnodes_size() == 0) {
  513. std::cout << "execute pathNodes failed ,Action invalid:" << action.DebugString() << std::endl;
  514. return false;
  515. //原地调整起点
  516. NavMessage::PathNode first=action.pathnodes(0);
  517. //速度限制
  518. stLimit adjust_x={ action.adjustvelocitylimit().min(),action.adjustvelocitylimit().max() };
  519. stLimit adjust_h={ action.adjusthorizonlimit().min(),action.adjusthorizonlimit().max() };
  520. stLimit adjust_angular={ action.nodeangularlimit().min(),action.nodeangularlimit().max() };
  521. stLimit mpc_velocity={ action.nodevelocitylimit().min(),action.nodevelocitylimit().max() };
  522. //目标,精度
  523. double first_yaw=timedPose_.Get().theta();
  524. if(1<action.pathnodes_size()){
  525. NavMessage::PathNode next=action.pathnodes(1);
  526. first_yaw=Pose2d::vector2yaw(next.pose().x()-first.pose().x(),next.pose().y()-first.pose().y());
  527. }
  528. Pose2d first_target(first.pose().x(),first.pose().y(),first_yaw);
  529. Pose2d first_accuracy(first.accuracy().x(),first.accuracy().y(),first.accuracy().theta());
  530. //execute_adjust_action(first_target,first_accuracy,adjust_x,adjust_h,adjust_angular,anyDirect);
  531. return false;
  532. }
  533. }else{
  534. return false;
  535. }
  536. }
  537. bool Navigation::execute_InOut_space(NavMessage::NewAction action) {
  538. if (action.type() != 1 && action.type() != 2) {
  539. printf(" Inout_space failed : msg action type must ==1\n ");
  540. return false;
  541. }
  542. if (!action.has_inoutvlimit() || !action.has_spacenode() ||
  543. !action.has_streetnode()) {
  544. std::cout << "execute enter_space failed ,Action miss some infos:" << action.DebugString() << std::endl;
  545. return false;
  546. }
  547. if (PoseTimeout() == true) {
  548. printf(" inout_space failed type:%d : current pose is timeout\n", action.type());
  549. return false;
  550. }
  551. Pose2d begin, target, begin_accuracy, target_accuracy;
  552. //入库,起点为streetNode
  553. begin = Pose2d(action.streetnode().pose().x(), action.streetnode().pose().y(), action.streetnode().pose().theta());
  554. begin_accuracy = Pose2d(action.streetnode().accuracy().x(),
  555. action.streetnode().accuracy().y(),
  556. action.streetnode().accuracy().theta());
  557. target = Pose2d(action.spacenode().pose().x(), action.spacenode().pose().y(), action.spacenode().pose().theta());
  558. //目标点精度
  559. target_accuracy = Pose2d(action.spacenode().accuracy().x()*2,
  560. action.spacenode().accuracy().y()*2,
  561. action.spacenode().accuracy().theta()*2);
  562. double yaw = Pose2d::vector2yaw(target.x() - begin.x(), target.y() - begin.y());
  563. if (action.type() == 2) { //出库起点终点对调
  564. Pose2d mid = target;
  565. Pose2d mid_accuracy = target_accuracy;
  566. target = begin;
  567. target_accuracy = begin_accuracy;
  568. begin = mid;
  569. begin_accuracy = mid_accuracy;
  570. yaw = Pose2d::vector2yaw(begin.x() - target.x(), begin.y() - target.y());
  571. }
  572. //给起点赋予朝向,保证agv以正对车位的方向行进
  573. begin.mutable_theta() = yaw;
  574. //严格调整到起点
  575. stLimit adjust_x = {0.05, 0.2};
  576. stLimit adjust_h = {0.05, 0.2};
  577. stLimit adjust_angular = {2 * M_PI / 180.0, 20 * M_PI / 180.0};
  578. stLimit mpc_velocity = {0.05, 0.3};
  579. //判断当前点与起点的距离
  580. Pose2d distance(1, 1, M_PI * 2);
  581. if (action.type() == 2) { //出库要求起点距离当前点非常近
  582. distance = Pose2d(1, 0.1, 3 * M_PI);
  583. adjust_x = {0.03, 0.1};
  584. adjust_h = {0.03, 0.1};
  585. adjust_angular = {2 * M_PI / 180.0, 5 * M_PI / 180.0};
  586. }
  587. Pose2d relativeDiff=Pose2d::relativePose(begin,timedPose_.Get());
  588. if (!(Pose2d::abs(relativeDiff) < distance)) {
  589. printf(" Inout space failed type:%d: current pose too far from begin node\n", action.type());
  590. std::cout << " begin:" << begin << " current:" << timedPose_.Get()<<" relative:"<<relativeDiff << std::endl;
  591. return false;
  592. }
  593. if (action.type() == 1) //1,进库,先调整到库位前方(起点)
  594. if (execute_adjust_action(begin, begin_accuracy, adjust_x, adjust_h, adjust_angular, true) == false)
  595. return false;
  596. if (execute_along_action(begin, target, target_accuracy, mpc_velocity, true) == false)
  597. return false;
  598. return true;
  599. }
  600. bool Navigation::mpc_once(Trajectory traj,stLimit limit_v,std::vector<double>& out,bool directY) {
  601. if (PoseTimeout() == true) {
  602. printf(" MPC once Error:Pose is timeout \n");
  603. return false;
  604. }
  605. if(timedV_.timeout() == true || timedA_.timeout() == true){
  606. printf(" MPC once Error:V/A is timeout \n");
  607. return false;
  608. }
  609. if (traj.size() == 0) {
  610. printf("traj size ==0\n");
  611. return false;
  612. }
  613. Pose2d pose = timedPose_.Get();
  614. double velocity = timedV_.Get(); //从plc获取状态
  615. double angular = timedA_.Get();
  616. Eigen::VectorXd statu = Eigen::VectorXd::Zero(5);//agv状态
  617. statu[0] = pose.x();
  618. statu[1] = pose.y();
  619. statu[2] = pose.theta();
  620. statu[3] = velocity;
  621. statu[4] = angular;
  622. Trajectory optimize_trajectory;
  623. Trajectory selected_trajectory;
  624. NavParameter::MPC_parameter mpc_parameter=parameter_.x_mpc_parameter();
  625. double obs_w=0.85;
  626. double obs_h=1.45;
  627. if (directY == true) {
  628. //将车身朝向旋转90°,车身朝向在(-pi,pi]
  629. statu[2] += M_PI / 2;
  630. if (statu[2] > M_PI)
  631. statu[2] -= 2 * M_PI;
  632. mpc_parameter=parameter_.y_mpc_parameter();
  633. obs_w=1.45;
  634. obs_h=0.85;
  635. }
  636. Pose2d brother = timedBrotherPose_.Get();
  637. Pose2d relative = Pose2d::relativePose(brother, pose);
  638. if(directY)
  639. relative = Pose2d::relativePose(brother.rotate(brother.x(),brother.y(),M_PI/2), pose.rotate(pose.x(),pose.y(),M_PI/2));//计算另一节在当前小车坐标系下的坐标
  640. std::cout<<"pose:"<<pose<<", brother:"<<brother<<", relative:"<<relative<<std::endl;
  641. if (move_mode_ == Monitor_emqx::ActionMode::eMain)
  642. relative = Pose2d(-1e8, -1e8, 0);
  643. MpcError ret = failed;
  644. LoadedMPC MPC(relative, obs_w,obs_h,limit_v.min, limit_v.max);
  645. LoadedMPC::MPC_parameter parameter={mpc_parameter.shortest_radius(),mpc_parameter.dt(),
  646. mpc_parameter.acc_velocity(),mpc_parameter.acc_angular()};
  647. //printf(" r:%f dt:%f acc:%f acc_a:%f\n",mpc_parameter.shortest_radius(),
  648. // mpc_parameter.dt(),mpc_parameter.acc_velocity(),mpc_parameter.acc_angular());
  649. ret = MPC.solve(traj, traj[traj.size() - 1], statu,parameter,
  650. out, selected_trajectory, optimize_trajectory);
  651. //std::cout<<" traj size %d %d -------- "<<selected_trajectory.size()<<","<<optimize_trajectory.size()<<std::endl;
  652. if(ret==no_solution) {
  653. printf(" mpc solve no solution set v/w = 0\n");
  654. out.clear();
  655. out.push_back(0);
  656. out.push_back(0);
  657. }
  658. predict_traj_.reset(optimize_trajectory, 1);
  659. selected_traj_.reset(selected_trajectory, 1);
  660. return ret==success || ret==no_solution;
  661. }
  662. bool Navigation::IsArrived(const Pose2d& cur,double velocity,double angular,
  663. const Pose2d& target,const Pose2d& diff,int direct)
  664. {
  665. //std::cout<<cur<<","<<target<<","<<nearest_yaw<<",v"<<velocity<<"a:"<<angular<<"diff:"<<diff<<std::endl;
  666. Pose2d distance=Pose2d::relativePose(target,cur);
  667. Pose2d absDiff=Pose2d::abs(distance);
  668. //std::cout<<" arrive distanc:"<<distance<<",direct:"<<direct<<std::endl;
  669. if(direct==1){ //纵向MPC
  670. if(absDiff.x()<diff.x() && absDiff.y()<diff.y())
  671. {
  672. float diffYaw=absDiff.theta(); //[0-pi)
  673. float diffYaw2=absDiff.theta()-M_PI;
  674. bool yawArrived=( fabs(diffYaw)<diff.theta() || fabs(diffYaw2)<diff.theta() );
  675. if(yawArrived && fabs(velocity) < 0.06 && fabs(angular) < 5 * M_PI / 180.0)
  676. return true;
  677. }
  678. }else if(direct==2){ //横向MPC
  679. if(absDiff.x()<diff.x() && absDiff.y()<diff.y())
  680. {
  681. float diffYaw=absDiff.theta(); //[0-pi)
  682. float diffYaw1=absDiff.theta()-M_PI/2;
  683. float diffYaw2=absDiff.theta()-M_PI;
  684. float diffYaw3=absDiff.theta()-3*M_PI/2;
  685. printf(" diff 123 :%f %f %f %f\n",diffYaw,diffYaw1,diffYaw2,diffYaw3);
  686. bool yawArrived=( fabs(diffYaw)<diff.theta() || fabs(diffYaw1)<diff.theta()
  687. || fabs(diffYaw2)<diff.theta() ||fabs(diffYaw3)<diff.theta() );
  688. if(yawArrived && fabs(velocity) < 0.06 && fabs(angular) < 5 * M_PI / 180.0)
  689. return true;
  690. }
  691. }else{ //原地调整
  692. if (absDiff < diff) {
  693. if (fabs(velocity) < 0.03 && fabs(angular) < 5 * M_PI / 180.0)
  694. return true;
  695. }
  696. }
  697. //std::cout<<"distance:"<<distance<<" diff:"<<diff<<" v:"<<velocity<<" a:"<<angular<<std::endl;
  698. return false;
  699. }
  700. void Navigation::SendMoveCmd(Monitor_emqx::ActionMode mode,Monitor_emqx::ActionType type,
  701. double v,double angular){
  702. if(monitor_) {
  703. monitor_->set_speed(mode, type, v, angular);
  704. }
  705. }
  706. bool Navigation::clamp_close()
  707. {
  708. if(monitor_) {
  709. printf("Clamp closing...\n");
  710. monitor_->clamp_close(move_mode_);
  711. actionType_=eClampClose;
  712. while (cancel_ == false) {
  713. if (timed_clamp_.timeout()) {
  714. printf("timed clamp is timeout\n");
  715. return false;
  716. }
  717. if (timed_clamp_.Get() == eClosed)
  718. return true;
  719. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  720. monitor_->clamp_close(move_mode_);
  721. actionType_=eClampClose;
  722. }
  723. return false;
  724. }
  725. return false;
  726. }
  727. bool Navigation::clamp_open() {
  728. if(monitor_) {
  729. printf("Clamp openning...\n");
  730. monitor_->clamp_open(move_mode_);
  731. actionType_=eClampOpen;
  732. while(cancel_==false)
  733. {
  734. if(timed_clamp_.timeout())
  735. {
  736. printf("timed clamp is timeout\n");
  737. return false;
  738. }
  739. if(timed_clamp_.Get()==eOpened)
  740. return true;
  741. std::this_thread::sleep_for(std::chrono::milliseconds(100));
  742. monitor_->clamp_open(move_mode_);
  743. actionType_=eClampOpen;
  744. }
  745. return false;
  746. }
  747. return false;
  748. }
  749. bool Navigation::execute_along_action(const Pose2d& begin,const Pose2d& target,const Pose2d& target_diff,
  750. stLimit limit_v,bool autoDirect) {
  751. if (inited_ == false) {
  752. printf(" navigation has not inited\n");
  753. return false;
  754. }
  755. if (PoseTimeout()) {
  756. printf(" navigation Error:Pose is timeout \n");
  757. return false;
  758. }
  759. //生成轨迹
  760. Trajectory traj = Trajectory::create_line_trajectory(begin, target);
  761. if (traj.size() == 0)
  762. return true;
  763. //判断 巡线方向
  764. bool directY=false;
  765. if(autoDirect){
  766. Pose2d target_relative=Pose2d::relativePose(target,timedPose_.Get());
  767. if( fabs(target_relative.y())>fabs(target_relative.x())) { //目标轨迹点在当前点Y轴上
  768. std::cout<<" MPC Y axis target_relative:"<<target_relative<<std::endl;
  769. directY = true;
  770. }else{
  771. std::cout<<" MPC X axis target_relative:"<<target_relative<<std::endl;
  772. }
  773. }
  774. printf(" exec along autoDirect:%d\n",autoDirect);
  775. while (cancel_ == false) {
  776. std::this_thread::sleep_for(std::chrono::milliseconds(50));
  777. if (pause_ == true) {
  778. //发送暂停消息
  779. continue;
  780. }
  781. if (PoseTimeout()) {
  782. printf(" navigation Error:Pose is timeout \n");
  783. return false;
  784. }
  785. if(timedV_.timeout() || timedA_.timeout()){
  786. printf(" navigation Error:v/a is timeout \n");
  787. return false;
  788. }
  789. //判断是否到达终点
  790. /*int direct=1;
  791. if(directY) direct=2;*/
  792. if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff,2)) {
  793. if (Stop()) {
  794. printf(" exec along completed !!!\n");
  795. return true;
  796. }
  797. }
  798. /*
  799. * 判断周边是否有障碍物,半径r,当障碍物进入r内,停下等待,当障碍物远离 1.2*r,恢复
  800. *
  801. if(move_mode_==Monitor_emqx::eSingle) {
  802. double r = 2.4;
  803. static bool obs_stoped = false;
  804. Pose2d obs_relative = Pose2d::relativePose(timedBrotherPose_.Get(), timedPose_.Get());
  805. double distance = sqrt(obs_relative.x() * obs_relative.x() + obs_relative.y() * obs_relative.y());
  806. if (obs_stoped == false) {
  807. if (distance < r && fabs(obs_relative.x()) > 0.2) {
  808. std::cout << "find obs stop to wait...." << std::endl;
  809. Stop();
  810. obs_stoped = true;
  811. continue;
  812. }
  813. } else {
  814. //障碍解除
  815. if (distance > 1.2 * r) {
  816. std::cout << "obs release continue MPC" << std::endl;
  817. obs_stoped = false;
  818. } else {
  819. continue;
  820. }
  821. }
  822. }
  823. */
  824. //一次变速
  825. std::vector<double> out;
  826. bool ret;
  827. TimerRecord::Execute([&, this]() {
  828. ret = mpc_once(traj, limit_v, out,directY);
  829. }, "mpc_once");
  830. if (ret == false) {
  831. Stop();
  832. return false;
  833. }
  834. /*
  835. * AGV 在终点附近低速巡航时,设置最小速度0.05
  836. */
  837. Pose2d target_in_agv=Pose2d::relativePose(target,timedPose_.Get());
  838. if(Pose2d::abs(target_in_agv)<Pose2d(0.2,0.2,M_PI*2)) {
  839. if (out[0] >= 0 && out[0] < limit_v.min)
  840. out[0] = limit_v.min;
  841. if (out[0] < 0 && out[0] > -limit_v.min)
  842. out[0] = -limit_v.min;
  843. }
  844. //下发速度
  845. if(directY==false)
  846. SendMoveCmd(move_mode_, Monitor_emqx::eMPC, out[0], out[1]);
  847. else
  848. SendMoveCmd(move_mode_, Monitor_emqx::eHorizontal, out[0], out[1]);
  849. actionType_=eMPC;
  850. /*
  851. * 判断车辆是否在终点附近徘徊,无法到达终点
  852. */
  853. if (mpc_possible_to_end(target, target_diff,directY) == false) {
  854. printf(" --------------MPC imposible to target -----------------------\n");
  855. if(fabs(timedV_.Get())>0.1 || fabs(timedA_.Get())>5*M_PI/180.0)
  856. Stop();
  857. //调整到目标点
  858. stLimit limitv, limitR;
  859. limitv.min = 0.05;
  860. limitv.max = 0.1;
  861. limitR.min = 2 * M_PI / 180.0;
  862. limitR.max = 10 * M_PI / 180.0;
  863. Pose2d accuracy(target_diff.x(),target_diff.y(),M_PI*2);
  864. if (execute_adjust_action(target, accuracy, limitv, limitv, limitR,false))
  865. return true;
  866. else
  867. return false;
  868. }
  869. //std::this_thread::sleep_for(std::chrono::milliseconds (400));
  870. }
  871. return false;
  872. }
  873. bool Navigation::mpc_possible_to_end(const Pose2d& target,const Pose2d& target_diff,bool directY)
  874. {
  875. if(timedPose_.timeout()==false) {
  876. Pose2d current=timedPose_.Get();
  877. if(directY){
  878. float yaw=current.theta();
  879. yaw += M_PI / 2;
  880. if (yaw > M_PI)
  881. yaw -= 2 * M_PI;
  882. current.mutable_theta()=yaw;
  883. }
  884. Pose2d diff = Pose2d::relativePose(target, current);
  885. if (fabs(diff.y()) < target_diff.y() && fabs(diff.x()) < target_diff.x()) { //xy在精度内
  886. if (timedV_.timeout() == true)
  887. return false;
  888. /*if(fabs(timedV_.Get())<0.05 && fabs(diff.theta())>target_diff.theta())
  889. return false;*/
  890. return true;
  891. } else { //xy不在精度内
  892. if(directY==false) {
  893. if (fabs(diff.x()) < 1e-3)
  894. return false; //x已到达,Y未到达,则不可能到达目标点
  895. }
  896. double theta = fabs(atan(diff.y() / diff.x()));
  897. if (theta > 5 * M_PI / 180.0) {
  898. if (timedV_.timeout() == true)
  899. return false;
  900. if (fabs(timedV_.Get()) < 0.05)
  901. return false;
  902. else
  903. return true;
  904. } else {
  905. return true;
  906. }
  907. }
  908. }
  909. return false;
  910. }
  911. void Navigation::navigatting() {
  912. if (inited_ == false) {
  913. printf(" navigation has not inited\n");
  914. return;
  915. }
  916. pause_ = false;
  917. cancel_ = false;
  918. running_ = true;
  919. actionType_ = eReady;
  920. printf(" navigation beg...\n");
  921. while (newUnfinished_cations_.empty() == false && cancel_ == false) {
  922. std::cout << "unfinished size:" << newUnfinished_cations_.size() << std::endl;
  923. NavMessage::NewAction act = newUnfinished_cations_.front();
  924. if(act.type()==1){ //入库
  925. if(!execute_InOut_space(act)){
  926. printf(" In space failed\n");
  927. break;
  928. }
  929. }
  930. else if(act.type()==2){ //出库
  931. if(!execute_InOut_space(act)){
  932. printf(" out space failed\n");
  933. break;
  934. }
  935. }else if (act.type() == 3 || act.type() == 4) { //马路导航
  936. if (!execute_nodes(act))
  937. break;
  938. }else if(act.type()==5){
  939. printf(" 汽车模型导航....\n");
  940. }else if (act.type() == 6) {//夹持
  941. if (this->clamp_close() == false) {
  942. printf("夹持failed ...\n");
  943. break;
  944. }
  945. } else if (act.type() == 7) {
  946. if (this->clamp_open() == false) {
  947. printf("打开夹持 failed...\n");
  948. break;
  949. }
  950. } else if(act.type()==8){ //切换模式
  951. SwitchMode(Monitor_emqx::ActionMode(act.changedmode()),act.wheelbase());
  952. }else{
  953. printf(" action type invalid not handled !!\n");
  954. break;
  955. }
  956. newUnfinished_cations_.pop();
  957. }
  958. actionType_ = eReady;
  959. Stop();
  960. if (cancel_ == true) {
  961. printf(" navigation canceled\n");
  962. while (newUnfinished_cations_.empty() == false)
  963. newUnfinished_cations_.pop();
  964. } else {
  965. if (newUnfinished_cations_.empty())
  966. printf("navigation completed!!!\n");
  967. else {
  968. printf(" navigation Failed\n");
  969. while (newUnfinished_cations_.empty() == false)
  970. newUnfinished_cations_.pop();
  971. }
  972. }
  973. running_ = false;
  974. }
  975. void Navigation::SwitchMode(Monitor_emqx::ActionMode mode,float wheelBase){
  976. printf("Child AGV can not Switch Mode\n");
  977. }