|
@@ -389,7 +389,7 @@ void Navigation::NavCmdCallback(const MqttMsg& msg,void* context)
|
|
|
|
|
|
|
|
|
|
bool Navigation::execute_adjust_action(const Pose2d& target,const Pose2d& target_diff,
|
|
bool Navigation::execute_adjust_action(const Pose2d& target,const Pose2d& target_diff,
|
|
- stLimit limit_v,stLimit limit_h,stLimit limit_rotate)
|
|
|
|
|
|
+ stLimit limit_v,stLimit limit_h,stLimit limit_rotate,bool nearest_yaw)
|
|
{
|
|
{
|
|
std::cout<<" adjust tarhet:"<<target<<" diff:"<<target_diff<<std::endl;
|
|
std::cout<<" adjust tarhet:"<<target<<" diff:"<<target_diff<<std::endl;
|
|
if(inited_==false) {
|
|
if(inited_==false) {
|
|
@@ -411,9 +411,9 @@ bool Navigation::execute_adjust_action(const Pose2d& target,const Pose2d& target
|
|
break;
|
|
break;
|
|
}
|
|
}
|
|
//判断是否到达目标点
|
|
//判断是否到达目标点
|
|
- if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff)) {
|
|
|
|
|
|
+ if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff,nearest_yaw)) {
|
|
if(Stop()) {
|
|
if(Stop()) {
|
|
- printf("adjust completed\n");
|
|
|
|
|
|
+ printf("adjust completed nearest yaw:%d\n",nearest_yaw);
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
return false;
|
|
@@ -443,13 +443,28 @@ bool Navigation::execute_adjust_action(const Pose2d& target,const Pose2d& target
|
|
double dt=0.1;
|
|
double dt=0.1;
|
|
if (action == 1) {
|
|
if (action == 1) {
|
|
if (Pose2d::abs(diff).theta() > thresh.theta()) {
|
|
if (Pose2d::abs(diff).theta() > thresh.theta()) {
|
|
- double theta = limit_gause(diff.theta(),limit_rotate.min*M_PI/180.0,limit_rotate.max*M_PI/180.0);
|
|
|
|
|
|
+ float diff_yaw=diff.theta();
|
|
|
|
+ if(nearest_yaw==true)
|
|
|
|
+ {
|
|
|
|
+ int n=int(diff_yaw/(M_PI/4.0));
|
|
|
|
+ if (n%2==1)
|
|
|
|
+ {
|
|
|
|
+ if(n>0)
|
|
|
|
+ diff_yaw=diff_yaw-float((n+1)/2)*M_PI/2.0;
|
|
|
|
+ else
|
|
|
|
+ diff_yaw=diff_yaw-float((n-1)/2)*M_PI/2.0;
|
|
|
|
+ }else{
|
|
|
|
+ diff_yaw=diff_yaw-float(n/2)*M_PI/2.0;
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ double theta = limit_gause(diff_yaw,limit_rotate.min*M_PI/180.0,limit_rotate.max*M_PI/180.0);
|
|
double angular=next_speed(timedA_.Get(),theta,acc_angular,dt);
|
|
double angular=next_speed(timedA_.Get(),theta,acc_angular,dt);
|
|
double limit_angular=limit(angular,limit_rotate.min*M_PI/180.0,limit_rotate.max*M_PI/180.0);
|
|
double limit_angular=limit(angular,limit_rotate.min*M_PI/180.0,limit_rotate.max*M_PI/180.0);
|
|
|
|
|
|
SendMoveCmd(move_mode_,Monitor_emqx::eRotate, 0, limit_angular);
|
|
SendMoveCmd(move_mode_,Monitor_emqx::eRotate, 0, limit_angular);
|
|
actionType_=eRotation;
|
|
actionType_=eRotation;
|
|
- printf(" Ratate | input anguar:%f,next angular:%f,down:%f diff:%f\n",timedA_.Get(),angular,limit_angular,theta);
|
|
|
|
|
|
+ printf(" Ratate | input anguar:%f,next angular:%f,down:%f diff:%f NearestYaw:%d\n",
|
|
|
|
+ timedA_.Get(),angular,limit_angular,theta,nearest_yaw);
|
|
continue;
|
|
continue;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -483,7 +498,50 @@ bool Navigation::execute_adjust_action(const Pose2d& target,const Pose2d& target
|
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
-bool Navigation::mpc_once(const Trajectory& traj,stLimit limit_v,std::vector<double>& out)
|
|
|
|
|
|
+
|
|
|
|
+bool Navigation::execute_nodes(NavMessage::NewAction action)
|
|
|
|
+{
|
|
|
|
+ if(action.type()==3 || action.type()==4) //最优动作导航 or 导航中保证朝向严格一致
|
|
|
|
+ {
|
|
|
|
+ if(!action.has_nodevelocitylimit() || !action.has_nodeangularlimit()||
|
|
|
|
+ !action.has_adjustvelocitylimit()|| !action.has_adjusthorizonlimit()
|
|
|
|
+ || action.pathnodes_size()==0) {
|
|
|
|
+ std::cout << "execute pathNodes failed ,Action invalid:" << action.DebugString() << std::endl;
|
|
|
|
+ return false;
|
|
|
|
+ }
|
|
|
|
+ bool autoDirect=(action.type()==3);
|
|
|
|
+ //原地调整
|
|
|
|
+ NavMessage::PathNode first=action.pathnodes(0);
|
|
|
|
+ //速度限制
|
|
|
|
+ stLimit adjust_x={ action.adjustvelocitylimit().min(),action.adjustvelocitylimit().max() };
|
|
|
|
+ stLimit adjust_h={ action.adjusthorizonlimit().min(),action.adjusthorizonlimit().max() };
|
|
|
|
+ stLimit adjust_angular={ action.nodeangularlimit().min(),action.nodeangularlimit().max() };
|
|
|
|
+ stLimit mpc_velocity={ action.nodevelocitylimit().min(),action.nodevelocitylimit().max() };
|
|
|
|
+ //目标,精度
|
|
|
|
+ Pose2d target(first.pose().x(),first.pose().y(),first.pose().theta());
|
|
|
|
+ Pose2d accuracy(first.accuracy().x(),first.accuracy().y(),first.accuracy().theta());
|
|
|
|
+ execute_adjust_action(target,accuracy,adjust_x,adjust_h,adjust_angular,autoDirect);
|
|
|
|
+ NavMessage::PathNode last_node=first;
|
|
|
|
+
|
|
|
|
+ for(int i=1;i< action.pathnodes_size();++i)
|
|
|
|
+ {
|
|
|
|
+ NavMessage::PathNode node=action.pathnodes(i);
|
|
|
|
+ /// 巡线到目标点,判断巡线方向
|
|
|
|
+ Pose2d begin(last_node.pose().x(),last_node.pose().y(),last_node.pose().theta());
|
|
|
|
+ Pose2d target(node.pose().x(),node.pose().y(),node.pose().theta());
|
|
|
|
+ Pose2d accuracy(node.accuracy().x(),node.accuracy().y(),node.accuracy().theta());
|
|
|
|
+
|
|
|
|
+ if(execute_along_action(begin,target,accuracy,mpc_velocity,autoDirect)==false)
|
|
|
|
+ return false;
|
|
|
|
+ last_node=node;
|
|
|
|
+ }
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ printf("execute PathNode failed ,action type is not 3/4 :%d\n",action.type());
|
|
|
|
+ return false;
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+bool Navigation::mpc_once(Trajectory traj,stLimit limit_v,std::vector<double>& out,bool directY)
|
|
{
|
|
{
|
|
if(timedPose_.timeout()==true && timedV_.timeout()==false && timedA_.timeout()==false)
|
|
if(timedPose_.timeout()==true && timedV_.timeout()==false && timedA_.timeout()==false)
|
|
{
|
|
{
|
|
@@ -504,7 +562,7 @@ bool Navigation::mpc_once(const Trajectory& traj,stLimit limit_v,std::vector<dou
|
|
Pose2d relative=Pose2d::relativePose(brother,pose);//计算另一节在当前小车坐标系下的坐标
|
|
Pose2d relative=Pose2d::relativePose(brother,pose);//计算另一节在当前小车坐标系下的坐标
|
|
if(move_mode_==Monitor_emqx::ActionMode::eMain)
|
|
if(move_mode_==Monitor_emqx::ActionMode::eMain)
|
|
relative=Pose2d(-1e8,-1e8,0);
|
|
relative=Pose2d(-1e8,-1e8,0);
|
|
- LoadedMPC MPC(relative,limit_v.min, limit_v.max);
|
|
|
|
|
|
+
|
|
Eigen::VectorXd statu=Eigen::VectorXd::Zero(5);//agv状态
|
|
Eigen::VectorXd statu=Eigen::VectorXd::Zero(5);//agv状态
|
|
|
|
|
|
statu[0]=pose.x();
|
|
statu[0]=pose.x();
|
|
@@ -515,21 +573,47 @@ bool Navigation::mpc_once(const Trajectory& traj,stLimit limit_v,std::vector<dou
|
|
|
|
|
|
Trajectory optimize_trajectory;
|
|
Trajectory optimize_trajectory;
|
|
Trajectory selected_trajectory;
|
|
Trajectory selected_trajectory;
|
|
- bool ret= MPC.solve(traj,traj[traj.size()-1],statu,out,selected_trajectory,optimize_trajectory);
|
|
|
|
|
|
+
|
|
|
|
+ bool ret=false;
|
|
|
|
+ if(directY==false) {
|
|
|
|
+ LoadedMPC MPC(relative, limit_v.min, limit_v.max);
|
|
|
|
+ ret = MPC.solve(traj, traj[traj.size() - 1], statu, out, selected_trajectory, optimize_trajectory);
|
|
|
|
+ }else{
|
|
|
|
+ MPC_Y MPC(relative, limit_v.min, limit_v.max);
|
|
|
|
+ ret = MPC.solve(traj, traj[traj.size() - 1], statu, out, selected_trajectory, optimize_trajectory);
|
|
|
|
+ }
|
|
predict_traj_.reset(optimize_trajectory,1);
|
|
predict_traj_.reset(optimize_trajectory,1);
|
|
selected_traj_.reset(selected_trajectory,1);
|
|
selected_traj_.reset(selected_trajectory,1);
|
|
return ret;
|
|
return ret;
|
|
}
|
|
}
|
|
|
|
|
|
bool Navigation::IsArrived(const Pose2d& cur,double velocity,double angular,
|
|
bool Navigation::IsArrived(const Pose2d& cur,double velocity,double angular,
|
|
- const Pose2d& target,const Pose2d& diff)
|
|
|
|
|
|
+ const Pose2d& target,const Pose2d& diff,bool nearest_yaw)
|
|
{
|
|
{
|
|
Pose2d distance=Pose2d::relativePose(target,cur);
|
|
Pose2d distance=Pose2d::relativePose(target,cur);
|
|
- if(Pose2d::abs(distance)<diff)
|
|
|
|
|
|
+ Pose2d absDiff=Pose2d::abs(distance);
|
|
|
|
+ if(nearest_yaw==false) {
|
|
|
|
+ if (absDiff < diff) {
|
|
|
|
+ if (fabs(velocity) < 0.05 && fabs(angular) < 10 * M_PI / 180.0)
|
|
|
|
+ return true;
|
|
|
|
+ }
|
|
|
|
+ }else{
|
|
|
|
+ if(absDiff.x()<diff.x() && absDiff.y()<diff.x())
|
|
{
|
|
{
|
|
- if(fabs(velocity)<0.05 && fabs(angular)< 10*M_PI/180.0)
|
|
|
|
- return true;
|
|
|
|
|
|
+ double theta=absDiff.theta();
|
|
|
|
+ int n=int(theta/(M_PI/4.0));
|
|
|
|
+ if (n%2==1)
|
|
|
|
+ {
|
|
|
|
+ theta=float((n+1)/2)*M_PI/2.0-theta;
|
|
|
|
+ }else{
|
|
|
|
+ theta=theta-float(n/2)*M_PI/2.0;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(theta<diff.theta() && fabs(velocity) < 0.05 && fabs(angular) < 10 * M_PI / 180.0)
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ }
|
|
//std::cout<<"distance:"<<distance<<" diff:"<<diff<<" v:"<<velocity<<" a:"<<angular<<std::endl;
|
|
//std::cout<<"distance:"<<distance<<" diff:"<<diff<<" v:"<<velocity<<" a:"<<angular<<std::endl;
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -583,7 +667,8 @@ bool Navigation::clamp_open() {
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
-bool Navigation::execute_along_action(const Pose2d& begin,const Pose2d& target,const Pose2d& target_diff,stLimit limit_v) {
|
|
|
|
|
|
+bool Navigation::execute_along_action(const Pose2d& begin,const Pose2d& target,const Pose2d& target_diff,
|
|
|
|
+ stLimit limit_v,bool autoDirect) {
|
|
if (inited_ == false) {
|
|
if (inited_ == false) {
|
|
printf(" navigation has not inited\n");
|
|
printf(" navigation has not inited\n");
|
|
return false;
|
|
return false;
|
|
@@ -596,6 +681,13 @@ bool Navigation::execute_along_action(const Pose2d& begin,const Pose2d& target,c
|
|
Trajectory traj = Trajectory::create_line_trajectory(begin, target);
|
|
Trajectory traj = Trajectory::create_line_trajectory(begin, target);
|
|
if (traj.size() == 0)
|
|
if (traj.size() == 0)
|
|
return true;
|
|
return true;
|
|
|
|
+ //判断 巡线方向
|
|
|
|
+ bool directY=false;
|
|
|
|
+ if(autoDirect){
|
|
|
|
+ Pose2d target_relative=Pose2d::relativePose(target,timedPose_.Get());
|
|
|
|
+ if( fabs(target_relative.y()>fabs(target_relative.x()))) //目标轨迹点在当前点Y轴上
|
|
|
|
+ directY=true;
|
|
|
|
+ }
|
|
|
|
|
|
while (cancel_ == false) {
|
|
while (cancel_ == false) {
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
std::this_thread::sleep_for(std::chrono::milliseconds(50));
|
|
@@ -608,7 +700,7 @@ bool Navigation::execute_along_action(const Pose2d& begin,const Pose2d& target,c
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
//判断是否到达终点
|
|
//判断是否到达终点
|
|
- if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff)) {
|
|
|
|
|
|
+ if (IsArrived(timedPose_.Get(), timedV_.Get(), timedA_.Get(), target, target_diff,directY)) {
|
|
if (Stop()) {
|
|
if (Stop()) {
|
|
printf(" exec along completed !!!\n");
|
|
printf(" exec along completed !!!\n");
|
|
return true;
|
|
return true;
|
|
@@ -645,7 +737,7 @@ bool Navigation::execute_along_action(const Pose2d& begin,const Pose2d& target,c
|
|
std::vector<double> out;
|
|
std::vector<double> out;
|
|
bool ret;
|
|
bool ret;
|
|
TimerRecord::Execute([&, this]() {
|
|
TimerRecord::Execute([&, this]() {
|
|
- ret = mpc_once(traj, limit_v, out);
|
|
|
|
|
|
+ ret = mpc_once(traj, limit_v, out,directY);
|
|
}, "mpc_once");
|
|
}, "mpc_once");
|
|
if (ret == false) {
|
|
if (ret == false) {
|
|
Stop();
|
|
Stop();
|