navigation.cpp 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066
  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.8;
  626. double obs_h=1.5;
  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.5;
  634. obs_h=0.8;
  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. if(directY==false)
  835. SendMoveCmd(move_mode_, Monitor_emqx::eMPC, out[0], out[1]);
  836. else
  837. SendMoveCmd(move_mode_, Monitor_emqx::eHorizontal, out[0], out[1]);
  838. actionType_=eMPC;
  839. /*
  840. * 判断车辆是否在终点附近徘徊,无法到达终点
  841. */
  842. if (mpc_possible_to_end(target, target_diff,directY) == false) {
  843. printf(" --------------MPC imposible to target -----------------------\n");
  844. if(fabs(timedV_.Get())>0.1 || fabs(timedA_.Get())>5*M_PI/180.0)
  845. Stop();
  846. //调整到目标点
  847. stLimit limitv, limitR;
  848. limitv.min = 0.05;
  849. limitv.max = 0.1;
  850. limitR.min = 2 * M_PI / 180.0;
  851. limitR.max = 10 * M_PI / 180.0;
  852. Pose2d accuracy(target_diff.x(),target_diff.y(),M_PI*2);
  853. if (execute_adjust_action(target, accuracy, limitv, limitv, limitR,false))
  854. return true;
  855. else
  856. return false;
  857. }
  858. //std::this_thread::sleep_for(std::chrono::milliseconds (400));
  859. }
  860. return false;
  861. }
  862. bool Navigation::mpc_possible_to_end(const Pose2d& target,const Pose2d& target_diff,bool directY)
  863. {
  864. if(timedPose_.timeout()==false) {
  865. Pose2d current=timedPose_.Get();
  866. if(directY){
  867. float yaw=current.theta();
  868. yaw += M_PI / 2;
  869. if (yaw > M_PI)
  870. yaw -= 2 * M_PI;
  871. current.mutable_theta()=yaw;
  872. }
  873. Pose2d diff = Pose2d::relativePose(target, current);
  874. if (fabs(diff.y()) < target_diff.y() && fabs(diff.x()) < target_diff.x()) { //xy在精度内
  875. if (timedV_.timeout() == true)
  876. return false;
  877. /*if(fabs(timedV_.Get())<0.05 && fabs(diff.theta())>target_diff.theta())
  878. return false;*/
  879. return true;
  880. } else { //xy不在精度内
  881. if(directY==false) {
  882. if (fabs(diff.x()) < 1e-3)
  883. return false; //x已到达,Y未到达,则不可能到达目标点
  884. }
  885. double theta = fabs(atan(diff.y() / diff.x()));
  886. if (theta > 5 * M_PI / 180.0) {
  887. if (timedV_.timeout() == true)
  888. return false;
  889. if (fabs(timedV_.Get()) < 0.05)
  890. return false;
  891. else
  892. return true;
  893. } else {
  894. return true;
  895. }
  896. }
  897. }
  898. return false;
  899. }
  900. void Navigation::navigatting() {
  901. if (inited_ == false) {
  902. printf(" navigation has not inited\n");
  903. return;
  904. }
  905. pause_ = false;
  906. cancel_ = false;
  907. running_ = true;
  908. actionType_ = eReady;
  909. printf(" navigation beg...\n");
  910. while (newUnfinished_cations_.empty() == false && cancel_ == false) {
  911. std::cout << "unfinished size:" << newUnfinished_cations_.size() << std::endl;
  912. NavMessage::NewAction act = newUnfinished_cations_.front();
  913. if(act.type()==1){ //入库
  914. if(!execute_InOut_space(act)){
  915. printf(" In space failed\n");
  916. break;
  917. }
  918. }
  919. else if(act.type()==2){ //出库
  920. if(!execute_InOut_space(act)){
  921. printf(" out space failed\n");
  922. break;
  923. }
  924. }else if (act.type() == 3 || act.type() == 4) { //马路导航
  925. if (!execute_nodes(act))
  926. break;
  927. }else if(act.type()==5){
  928. printf(" 汽车模型导航....\n");
  929. }else if (act.type() == 6) {//夹持
  930. if (this->clamp_close() == false) {
  931. printf("夹持failed ...\n");
  932. break;
  933. }
  934. } else if (act.type() == 7) {
  935. if (this->clamp_open() == false) {
  936. printf("打开夹持 failed...\n");
  937. break;
  938. }
  939. } else if(act.type()==8){ //切换模式
  940. SwitchMode(Monitor_emqx::ActionMode(act.changedmode()),act.wheelbase());
  941. }else{
  942. printf(" action type invalid not handled !!\n");
  943. break;
  944. }
  945. newUnfinished_cations_.pop();
  946. }
  947. actionType_ = eReady;
  948. Stop();
  949. if (cancel_ == true) {
  950. printf(" navigation canceled\n");
  951. while (newUnfinished_cations_.empty() == false)
  952. newUnfinished_cations_.pop();
  953. } else {
  954. if (newUnfinished_cations_.empty())
  955. printf("navigation completed!!!\n");
  956. else {
  957. printf(" navigation Failed\n");
  958. while (newUnfinished_cations_.empty() == false)
  959. newUnfinished_cations_.pop();
  960. }
  961. }
  962. running_ = false;
  963. }
  964. void Navigation::SwitchMode(Monitor_emqx::ActionMode mode,float wheelBase){
  965. printf("Child AGV can not Switch Mode\n");
  966. }