123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529 |
- //
- // Created by zx on 22-12-2.
- //
- #include "navigation.h"
- #include "loaded_mpc.h"
- #include "../define/TimerRecord.h"
- Navigation::~Navigation()
- {
- exit_=true;
- if(terminator_)
- delete terminator_;
- if(monitor_)
- delete monitor_;
- if(thread_!= nullptr)
- {
- if(thread_->joinable())
- thread_->join();
- delete thread_;
- }
- if(pubthread_!= nullptr)
- {
- if(pubthread_->joinable())
- pubthread_->join();
- delete pubthread_;
- }
- }
- /*
- * 高斯函数压缩,x=3
- */
- double limit(double x,double min,double max){
- double r=x>=0?1.0:-1.0;
- double delta=max/3.0;
- return (max-(max-min)*exp(-x*x/(delta*delta)))*r;
- }
- bool Navigation::Init(const Navigation_parameter& parameter)
- {
- parameter_=parameter;
- AgvEmqx_parameter agv_p=parameter.agv_emqx();
- if(monitor_== nullptr) {
- monitor_ = new Monitor_emqx(agv_p.nodeid());
- if(monitor_->Connect(agv_p.ip(),agv_p.port())==false)
- {
- printf(" agv emqx connected failed\n");
- return false;
- }
- monitor_->AddCallback(agv_p.subposetopic(),Navigation::RobotPoseCallback,this);
- monitor_->AddCallback(agv_p.subspeedtopic(),Navigation::RobotSpeedCallback,this);
- }
- Emqx_parameter terminal_p=parameter.terminal_emqx();
- if(terminator_== nullptr) {
- terminator_ = new Terminator_emqx(terminal_p.nodeid());
- if(terminator_->Connect(terminal_p.ip(),terminal_p.port())==false)
- {
- printf(" terminator emqx connected failed\n");
- return false;
- }
- terminator_->AddCallback(terminal_p.subnavcmdtopic(),Navigation::NavCmdCallback,this);
- terminator_->AddCallback(terminal_p.subbrotherstatutopic(),Navigation::BrotherAgvStatuCallback,this);
- }
- inited_=true;
- if(pubthread_!= nullptr)
- {
- exit_=true;
- if(pubthread_->joinable())
- pubthread_->join();
- delete pubthread_;
- }
- exit_=false;
- pubthread_=new std::thread(&Navigation::publish_statu,this);
- return true;
- }
- void Navigation::RobotPoseCallback(const MqttMsg& msg,void* context)
- {
- Navigation* navigator=(Navigation*)context;
- NavMessage::AGVStatu statu;
- if(msg.toProtoMessage(statu))
- {
- navigator->ResetPose(Pose2d(statu.x(),statu.y(),statu.theta()));
- }
- }
- void Navigation::RobotSpeedCallback(const MqttMsg& msg,void* context)
- {
- Navigation* navigator=(Navigation*)context;
- NavMessage::AGVSpeed speed;
- if(msg.toProtoMessage(speed))
- {
- navigator->ResetStatu(speed.v(),speed.w());
- }
- }
- void Navigation::publish_statu() {
- while (exit_ == false)
- {
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
- //发布nav状态
- NavMessage::NavStatu statu;
- statu.set_statu(eReady); //默认ready
- NavMessage::Action *current_action = nullptr;
- if (running_)
- {
- statu.set_statu(eRunning);
- statu.set_key(global_navCmd_.key());
- std::queue<NavMessage::Action> actios = unfinished_cations_;
- while (actios.empty() == false) {
- //保存当前动作
- NavMessage::Action *act = statu.add_unfinished_actions();
- current_action = new NavMessage::Action(*act);
- act->CopyFrom(actios.front());
- actios.pop();
- }
- }
- //发布MPC信息
- if (current_action != nullptr) {
- delete current_action;
- //发布mpc 预选点
- if (selected_traj_.timeout() == false) {
- for (int i = 0; i < selected_traj_.Get().size(); ++i) {
- Pose2d pt = selected_traj_.Get()[i];
- NavMessage::Pose2d *pose = statu.mutable_selected_traj()->add_poses();
- pose->set_x(pt.x());
- pose->set_y(pt.y());
- pose->set_theta(pt.theta());
- }
- }
- //发布 mpc 预测点
- if (predict_traj_.timeout() == false) {
- for (int i = 0; i < predict_traj_.Get().size(); ++i) {
- Pose2d pt = predict_traj_.Get()[i];
- NavMessage::Pose2d *pose = statu.mutable_predict_traj()->add_poses();
- pose->set_x(pt.x());
- pose->set_y(pt.y());
- pose->set_theta(pt.theta());
- }
- }
- }
- MqttMsg msg;
- msg.fromProtoMessage(statu);
- if(terminator_)
- terminator_->Publish(parameter_.terminal_emqx().pubnavstatutopic(),msg);
- //发布位姿 --------------------------------
- if (timedPose_.timeout() == false&&
- timedV_.timeout() == false && timedA_.timeout() == false) {
- NavMessage::AGVStatu agvStatu;
- Pose2d pose = timedPose_.Get();
- agvStatu.set_x(pose.x());
- agvStatu.set_y(pose.y());
- agvStatu.set_theta(pose.theta());
- agvStatu.set_v(timedV_.Get());
- agvStatu.set_vth(timedA_.Get());
- if(terminator_) {
- MqttMsg msg;
- msg.fromProtoMessage(agvStatu);
- terminator_->Publish(parameter_.terminal_emqx().pubstatutopic(), msg);
- }
- }
- }
- }
- void Navigation::ResetStatu(double v,double a)
- {
- timedV_.reset(v,0.5);
- timedA_.reset(a,0.5);
- }
- void Navigation::ResetPose(const Pose2d& pose)
- {
- timedPose_.reset(pose,0.5);
- }
- bool Navigation::Start(const NavMessage::NavCmd& cmd)
- {
- if(unfinished_cations_.empty()==false) //正在运行中,上一次指令未完成
- {
- if(pause_)
- {
- pause_=false;
- return true;
- }
- printf(" navigation is running pls cancel before\n");
- return false;
- }
- if(thread_!= nullptr)
- {
- if(thread_->joinable())
- thread_->join();
- delete thread_;
- }
- //add 先检查当前点与起点的距离
- global_navCmd_=cmd;
- for(int i=0;i<cmd.actions_size();++i)
- unfinished_cations_.push(cmd.actions(i));
- thread_=new std::thread(&Navigation::navigatting,this);
- return true;
- }
- void Navigation::Cancel()
- {
- cancel_=true;
- }
- void Navigation::Pause()
- {
- monitor_->stop();
- pause_=true;
- }
- Navigation::Navigation()
- {
- thread_= nullptr;
- monitor_= nullptr;
- terminator_= nullptr;
- timedBrotherPose_.reset(Pose2d(-100,0,0),0.1);
- }
- void Navigation::BrotherAgvStatuCallback(const MqttMsg& msg,void* context)
- {
- Navigation* navigator=(Navigation*)context;
- NavMessage::AGVStatu brother_statu;
- if(msg.toProtoMessage(brother_statu)==false) {
- printf(" msg transform to AGVStatu failed ..!!\n");
- return;
- }
- //std::cout<<brother_nav.DebugString()<<std::endl<<std::endl;
- Pose2d pose(brother_statu.x(),brother_statu.y(),brother_statu.theta());
- navigator->timedBrotherPose_.reset(pose,1);
- navigator->timedBrotherV_.reset(brother_statu.v(),1);
- navigator->timedBrotherA_.reset(brother_statu.vth(),1);
- }
- void Navigation::NavCmdCallback(const MqttMsg& msg,void* context)
- {
- Navigation* navigator=(Navigation*)context;
- NavMessage::NavCmd cmd;
- if(msg.toProtoMessage(cmd)==false) {
- printf(" msg transform to NavCmd failed ..!!\n");
- return;
- }
- if(cmd.action()==3)
- {
- navigator->Cancel();
- return ;
- }
- if(cmd.action()==2) {
- navigator->pause_=false;
- return ;
- }
- if(cmd.action()==1) {
- navigator->Pause();
- return ;
- }
- navigator->Start(cmd);
- }
- bool Navigation::exec_adjust_action(const Pose2d& target,const Pose2d& target_diff,
- stLimit limit_v,stLimit limit_h,stLimit limit_rotate)
- {
- if(inited_==false) {
- printf(" navigation has not inited\n");
- return false;
- }
- Pose2d thresh=Pose2d::abs(target_diff);
- int action=0; //1 原地旋转,2横移,3前进
- while(cancel_==false) {
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
- if (pause_ == true) {
- //发送暂停消息
- continue;
- }
- if (timedPose_.timeout() || timedV_.timeout() || timedA_.timeout()) {
- printf(" navigation Error:Pose/v/a is timeout \n");
- break;
- }
- //判断是否到达目标点
- if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff)) {
- monitor_->stop();
- printf("adjust completed\n");
- return true;
- }
- //计算目标点在当前pose下的pose
- Pose2d diff = Pose2d::relativePose(target, timedPose_.Get());
- //停止状态
- if (action == 0) {
- //优先进入旋转
- if (Pose2d::abs(diff).theta() > thresh.theta()) {
- action = 1; //原地旋转
- } else if (Pose2d::abs(diff).x() > thresh.x()) {
- //前进
- action = 3;
- }else if (Pose2d::abs(diff).y() > thresh.y()) {
- //横移
- action = 2;
- }
- }
- else
- {
- if (action == 1) {
- if (Pose2d::abs(diff).theta() > thresh.theta()) {
- double theta = limit(diff.theta(),limit_rotate.min*M_PI/180.0,limit_rotate.max*M_PI/180.0);
- monitor_->set_speed(Monitor_emqx::eRotate, 0, theta);
- printf(" Ratate :%f\n",theta);
- continue;
- }
- }
- if (action == 2) {
- if (Pose2d::abs(diff).y() > thresh.y()) {
- monitor_->set_speed(Monitor_emqx::eHorizontal, limit(diff.y(),limit_h.min,limit_h.max), 0);
- printf(" Horizontal :%f\n",limit(diff.y(),limit_h.min,limit_h.max));
- continue;
- }
- }
- if (action == 3) {
- if (Pose2d::abs(diff).x() > thresh.x()) {
- monitor_->set_speed(Monitor_emqx::eMPC, limit(diff.x(),limit_v.min,limit_v.max), 0);
- printf(" Vrtical :%f\n",limit(diff.x(),limit_v.min,limit_v.max));
- continue;
- }
- }
- monitor_->stop();
- printf(" monitor type :%d completed!!! reset action type!!!\n", action);
- action = 0;
- }
- }
- return false;
- }
- bool Navigation::mpc_once(const Trajectory& traj,stLimit limit_v,std::vector<double>& out)
- {
- if(timedPose_.timeout()==true && timedV_.timeout()==false && timedA_.timeout()==false)
- {
- printf(" MPC once Error:Pose/V/A is timeout \n");
- return false;
- }
- if(traj.size()==0)
- {
- printf("traj size ==0\n");
- return false;
- }
- Pose2d pose=timedPose_.Get();
- double velocity=timedV_.Get(); //从plc获取状态
- double angular=timedA_.Get();
- Pose2d brother=timedBrotherPose_.Get();
- Pose2d relative=Pose2d::relativePose(brother,pose);//计算另一节在当前小车坐标系下的坐标
- LoadedMPC MPC(relative,limit_v.min, limit_v.max);
- Eigen::VectorXd statu=Eigen::VectorXd::Zero(5);//agv状态
- statu[0]=pose.x();
- statu[1]=pose.y();
- statu[2]=pose.theta();
- statu[3]=velocity;
- statu[4]=angular;
- Trajectory optimize_trajectory;
- Trajectory selected_trajectory;
- bool ret= MPC.solve(traj,traj[traj.size()-1],statu,out,selected_trajectory,optimize_trajectory);
- predict_traj_.reset(optimize_trajectory,1);
- selected_traj_.reset(selected_trajectory,1);
- return ret;
- }
- bool Navigation::IsArrived(const Pose2d& cur,double velocity,double angular,
- const Pose2d& target,const Pose2d& diff)
- {
- Pose2d distance=Pose2d::relativePose(target,cur);
- if(Pose2d::abs(distance)<diff)
- {
- if(fabs(velocity)<0.1 && fabs(angular)< 10*M_PI/180.0)
- return true;
- }
- return false;
- }
- bool Navigation::execute_along_action(const Pose2d& target,const Pose2d& target_diff,stLimit limit_v)
- {
- if(inited_==false) {
- printf(" navigation has not inited\n");
- return false;
- }
- if (timedPose_.timeout() ) {
- printf(" navigation Error:Pose is timeout \n");
- return false;
- }
- //生成轨迹
- Trajectory traj=Trajectory::create_line_trajectory(timedPose_.Get(),target);
- if(traj.size()==0)
- return true;
- while(cancel_==false)
- {
- std::this_thread::sleep_for(std::chrono::milliseconds(50));
- if(pause_==true)
- {
- //发送暂停消息
- continue;
- }
- if (timedPose_.timeout() || timedV_.timeout() || timedA_.timeout()) {
- printf(" navigation Error:Pose/v/a is timeout \n");
- return false;
- }
- //判断是否到达终点
- if(IsArrived(timedPose_.Get(),timedV_.Get(),timedA_.Get(),target,target_diff))
- {
- monitor_->stop();
- printf(" exec along completed !!!\n");
- return true;
- }
- //一次变速
- std::vector<double> out;
- bool ret;
- TimerRecord::Execute([&,this](){
- ret=mpc_once(traj,limit_v,out);
- },"mpc_once");
- if(ret==false)
- {
- monitor_->stop();
- return false;
- }
- monitor_->set_speed(Monitor_emqx::eMPC,out[0],out[1]);
- //std::this_thread::sleep_for(std::chrono::milliseconds (400));
- }
- return false;
- }
- void Navigation::navigatting()
- {
- if(inited_==false) {
- printf(" navigation has not inited\n");
- return ;
- }
- pause_=false;
- cancel_=false;
- running_=true;
- printf(" navigation beg...\n");
- while(unfinished_cations_.empty()==false && cancel_==false)
- {
- NavMessage::Action act=unfinished_cations_.front();
- Pose2d target(act.target().x(),act.target().y(),act.target().theta());
- Pose2d target_diff(act.target_diff().x(),act.target_diff().y(),act.target_diff().theta());
- if(act.type()==1)
- {
- printf(" adjust to (%.3f %.3f %.3f) diff:(%.3f,%.3f,%.3f)\n",
- act.target().x(),act.target().y(),act.target().theta(),
- act.target_diff().x(),act.target_diff().y(),act.target_diff().theta());
- stLimit limit_angular,limit_velocity,limint_horize;
- limit_velocity.min=act.velocity_limit().min();
- limit_velocity.max=act.velocity_limit().max();
- limit_angular.min=act.angular_limit().min();
- limit_angular.max=act.angular_limit().max();
- limint_horize.min=act.horize_limit().min();
- limint_horize.max=act.horize_limit().max();
- if(exec_adjust_action(target,target_diff,limit_velocity,limint_horize,limit_angular)==false)
- {
- printf("execute adjust action failed\n");
- break;
- }
- }
- else if(act.type()==2)
- {
- stLimit limit_velocity;
- limit_velocity.min=act.velocity_limit().min();
- limit_velocity.max=act.velocity_limit().max();
- printf(" MPC to (%.3f %.3f %.3f) diff:(%.3f,%.3f,%.3f)\n",
- act.target().x(),act.target().y(),act.target().theta(),
- act.target_diff().x(),act.target_diff().y(),act.target_diff().theta());
- if(execute_along_action(target,target_diff,limit_velocity)==false) {
- printf("execute along action failed\n");
- break;
- }
- }
- else
- {
- printf(" unknow action type:%d\n",act.type());
- break;
- }
- unfinished_cations_.pop();
- }
- monitor_->stop();
- if(cancel_==true) {
- printf(" navigation canceled\n");
- while(unfinished_cations_.empty()==false)
- unfinished_cations_.pop();
- }else {
- if (unfinished_cations_.empty())
- printf("navigation completed!!!\n");
- else{
- printf(" navigation Failed\n");
- while(unfinished_cations_.empty()==false)
- unfinished_cations_.pop();
- }
- }
- running_=false;
- }
|