状态机的编写(使用C++)

这几天写了一些无人车的状态机的程序,其实就是从python上面翻译过来的,忽然发现python写东西很方便,不需要考虑数据类型什么的,而且python有一个smach的语句,C++没有,状态机需要自己手动实现,做起来细节很多,主要是语法方面不熟导致了很多错误

ROS里面不要用sleep和usleep函数,如果需要等待,请使用ros::Rate

此外,还有一个地方搞不懂的就是,我一开始写的时候是初始化和执行放在两个不同的函数当中,但是在两个函数里面声明的变量其实不是同一个变量,他们的成员变量并不是同一个,即使在声明变量的时候放在加上static可不行,可能static只初始化一次这个操作需要在同一函数的的当中,这样我只能把这来那个个函数合并起来了,但是如果真的需要分开,那该怎么写呢?

附上代码供以后参阅:

#include <string>
#include <unistd.h>
#include <csignal>
#include "std_msgs/String.h"
#include "ros/ros.h"  

using std::__cxx11::string;

void exit(int signum)
{
    printf("You choose to stop me.");
    exit(0);
}

string state;
class Idle
{

    private:
    ros::NodeHandle n;
    string goal;
    ros::Subscriber sub_;
    public:

     void callback(const std_msgs::String::ConstPtr& msg)
    {

        if (state=="IDLE")
        {
            goal=msg->data;
        }

    }
    public:
    void init(const ros::NodeHandle  &n1)
    {   

        n=n1;
        sub_=n.subscribe("Idle/goal", 1000, &Idle::callback,this);

    }
    string execute()
    {

        state="IDLE";
        ros::Rate loop_rate(5);

        while (true)
        {

            ros::spinOnce();
            loop_rate.sleep();
            if (goal=="a")
            {
                ROS_INFO("Having a new goal %s",goal.c_str()); 
                goal="";
                return "got_goal";
            }
            std::cout << "goal=" << goal << std::endl;
            ROS_INFO("In state Idle : %s",goal.c_str());

        }

        return "" ;
    }
};


class Planner
{
    private:
    string global_plan;
    ros::NodeHandle n;
    ros::Subscriber sub_;
    public:

     void callback(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="PLANNER")
        {
            global_plan=msg->data;
        }
    }
    void init(const ros::NodeHandle  &n1)
    {
        n=n1;
        sub_=n.subscribe("/Planner/global_plan", 1000, &Planner::callback,this);
    }
    string execute()
    {
        state="PLANNER";
        ros::Rate loop_rate(5);
        while (true)
        {
            ros::spinOnce();
            loop_rate.sleep();
            if (global_plan=="a")
            {
                ROS_INFO("Having a new topological plan");
                global_plan="";
                return "got_plan";
            }
            ROS_INFO("In state Planner: %s",global_plan.c_str());

        }
    }   
};

class Approach_start
{
    private:
    ros::NodeHandle n;
    ros::Subscriber sub_;
    public:
     string succeeded_flag;

     void callback(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="APPROACH_START")
        {
            succeeded_flag=msg->data;
        }
    }
    void init(const ros::NodeHandle  &n1)
    {
        n=n1;
        sub_=n.subscribe("/Approach_to_startnode/succeeded", 1000, &Approach_start::callback,this);
    }
    string execute()
    {
        state="APPROACH_START";
        ros::Rate loop_rate(5);
        while (true)
        {
            ros::spinOnce();
            loop_rate.sleep();
            if (succeeded_flag=="a")
            {
                ROS_INFO("Arrived starting node");
                succeeded_flag="";
                return "succeeded";
            }
                ROS_INFO("In state Approach_to_startnode");

        }
    }   
};

class Approach_end
{
    private:
        ros::NodeHandle n;
        ros::Subscriber sub_;
    public :
     string succeeded_flag;
     void callback(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="APPROACH_END")
        {
            succeeded_flag=msg->data;
        }
    }
    void init(const ros::NodeHandle  &n1)
    {
        n=n1;
        sub_=n.subscribe("/Approach_to_endnode/succeeded", 1000, &Approach_end::callback,this);
    }
    string execute()
    {
        state="APPROACH_END";
        ros::Rate loop_rate(5);
        while (true)
        {

            ros::spinOnce();
            loop_rate.sleep();
            if (succeeded_flag=="a")
            {
                ROS_INFO("Arrived ending node");
                succeeded_flag="";
                return "reach_goal";
            }
            ROS_INFO("In state Approach_to_endnode");

        }
    }   
};

class Repeat
{
    private:
        ros::NodeHandle n;
        ros::Subscriber sub_;
    public :
    string succeeded_flag;
    void callback(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="REPEAT")
        {
            succeeded_flag=msg->data;
        }
    }
    void init(const ros::NodeHandle  &n1)
    {
        n=n1;
        sub_=n.subscribe("/Repeat/succeeded", 1000 , &Repeat::callback,this);
    }
    string execute()
    {
        state="REPEAT";
        ros::Rate loop_rate(5);
        while (true)
        {
            ros::spinOnce();
            loop_rate.sleep();
            if (succeeded_flag=="a")
            {
                ROS_INFO("Repeat the taught content");
                succeeded_flag="";
                return "succeeded";
            }
            ROS_INFO("In state Repeat");

        }
    }   
};

class Obstacle
{
    private:
        ros::NodeHandle n;
        ros::Subscriber sub_;
    public:
    string cleared_flag;
    void callback(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="OBSTACLE_AVOID")
        {
            cleared_flag==msg->data;        
        }
    }
    void init(const ros::NodeHandle  &n1)
    {
        n=n1;
        sub_=n.subscribe("/Obstacle/cleared", 1000, &Obstacle::callback,this);
    }
    string execute()
    {
        state="OBSTACLE_AVOID";
        ros::Rate loop_rate(5);
        while (true)
        {
            ros::spinOnce();
            loop_rate.sleep();
            if (cleared_flag=="a")
            {
                ROS_INFO("Now free to go");
                cleared_flag="";
                return "cleared";
            }
            ROS_INFO("In state Obstacle");

        }
    }
    void run(){
    }
};

class Resume
{
    private:
        ros::NodeHandle n;
        ros::Subscriber sub_;
    public:
     string resumed_flag;
     void callback(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="RESUME")
        {
            resumed_flag=msg->data; 
        }
    }
    void init(const ros::NodeHandle  &n1)
    {
        n=n1;
        sub_=n.subscribe("/Resume/resume_goal", 1000, &Resume::callback,this);
    }
    string execute()
    {
        state="APPROACH_START";
        ros::Rate loop_rate(5);
        while (true)
        {
            ros::spinOnce();
            loop_rate.sleep();
            if (resumed_flag=="a")
            {
                ROS_INFO("Now resume to new goal");
                resumed_flag="";
                return "resume_goal";
            }
            ROS_INFO("In state Resume");

        }
    }   
};



void work(const ros::NodeHandle &n)
{
    static Idle tmp_idle;
    tmp_idle.init(n);

    static Planner tmp_planner;
    tmp_planner.init(n);

    static Approach_start tmp_approach_start;
    tmp_approach_start.init(n);

    static Approach_end tmp_approach_end;
    tmp_approach_end.init(n);

    static Repeat tmp_repeat;
    tmp_repeat.init(n);

    static Obstacle tmp_obstacle;
    tmp_obstacle.init(n);

    static Resume tmp_resume;   
    tmp_resume.init(n);
    while (true)
    {

        string res;
        if (state=="IDLE")
        {
            res=tmp_idle.execute();
            if (res=="got_goal") state="PLANNER";
        }
        else
        if (state=="PLANNER")
        {
            res=tmp_planner.execute();
            if (res=="got_goal") state="PLANNER";
        }
        else
        if (state=="APPROACH_START")
        {
            res=tmp_approach_start.execute();
            if (res=="succeeded") state="REPEAT";
            else
            if (res=="detect_obstacle") state="detect_obstacle";
        }
        else
        if (state=="REPEAT")
        {
            res=tmp_repeat.execute();
            if (res=="succeeded") state="APPROACH_END";
            else
            if (res=="detect_obstacle") state="detect_obstacle";
        }
        else
        if (state=="APPROACH_END")
        {
            res=tmp_approach_end.execute();
            if (res=="reach_goal") state="reach_goal";
            else 
            if (res=="detect_obstacle") state="detect_obstacle";
        }
        else
        if (state=="EXECUTE")
        {
            //res=???.execute();
            if (res=="reach_goal") state="IDLE";
            else
            if (res=="detect_obstacle") state="OBSTACLE_AVOID";
        }
        else
        if (state=="OBSTACLE_AVOID")
        {
            res=tmp_obstacle.execute();
            if (res=="cleared") state="RESUME";
            else 
            if (res=="stuck") state="stuck";
        }
        else
        if (state=="RESUME")
        {
            res=tmp_resume.execute();
            if (res=="resume_goal") state="PLANNER";
        }
    }
}

std::string goal;
void callback_Idle(const std_msgs::String::ConstPtr& msg)
    {
        if (state=="IDLE")
        {
            goal=msg->data;
        }

    }
int main(int argc, char **argv)
{
    signal(SIGINT, exit);
    signal(SIGTERM, exit);  

    ros::init(argc, argv, "test_smach2_node");  
    ros::NodeHandle n;

    state="IDLE";
    work(n);

    return 0;
}

  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值