美文网首页
【ROS-Stage】Stage机器人仿真实验(一)

【ROS-Stage】Stage机器人仿真实验(一)

作者: 十月石榴2013 | 来源:发表于2018-10-09 20:42 被阅读256次

    环境:64位 ubuntu16.04,代码见:https://github.com/cr19941016/ROS_stage_test

    1. 安装ROS
      更换软件源(设置 --> Software & Update),会下载的更快。
      stage_ros仿真包是ros自带的,安装完之后就有了。
    2. 按照教程,创建一个工作空间
      记得添加 source:
    echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
    source ~/.bashrc 
    
    1. 按照教程,创建ROS程序包
    2. 下载 turtlebot_simulator,将里面的 /turtlebot_stage/maps/ 复制出来,放在新建的程序包文件夹中(beginner_tutorials)。
    3. 共享内存用于ROS节点和非ROS进程之间的通信。
      创建共享内存区的数据结构,存放在 sharemem.h中。
    #ifndef SHAREMEM_H
    #define SHAREMEM_H
    struct ShareMem
    {
      double x; //  x方向的速度(前后)
      double y; //  y方向的速度(左右)
      double z; //  旋转
    };
    #endif
    
    1. 新建talker节点。
      创建共享内存、监听共享内存区域的速度变化和发布速度话题。
    /****************************************
    *文件名: talker.cpp            *
    *简介: 链接非ROS进程和ROS节点的ROS节点   *
    *BY: CR (qq: 414481619)         *
    *创建时间: 2018.10.09           *
    ****************************************/
    
    #include "ros/ros.h"
    #include <geometry_msgs/Twist.h>
    
    #include <iostream>
    #include <stdio.h>
    #include <sys/shm.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <pthread.h>
    
    #include "sharemem.h"
    
    using namespace std;
    
    
    int main(int argc, char **argv)
    {
    
      ros::init(argc, argv, "talker");
      ros::NodeHandle n;
      ros::Publisher chatter_pub = n.advertise<geometry_msgs::Twist>("cmd_vel", 1000);
    
      ros::Rate loop_rate(100); // 100Hz的定时器
    
      
      ShareMem _ShareMem;
      // 创建共享内存 ,相当于打开文件,文件不存在则创建
      int shmid = shmget((key_t)2333, sizeof(_ShareMem), 0666|IPC_CREAT);  
      if(shmid==-1)
      {
        perror("shmget err");
        return errno;
      }
      cout<<shmid<<endl; 
    
      // 将共享内存段连接到进程地址空间, 第二个参数shmaddr为NULL,核心自动选择一个地址
      ShareMem *shareMem = (ShareMem *)shmat(shmid, NULL, 0); 
      if (shareMem == (void *)-1 )
      {
        perror("shmat err");
        return errno;
      }
      
      shareMem->x = 0;  
      shareMem->y = 0; 
      shareMem->z = 0; 
    
      pthread_mutex_t mutex;  
      pthread_mutex_init(&mutex, NULL);
      while (ros::ok())
      {
        geometry_msgs::Twist cmdvel_msg; 
    
        pthread_mutex_lock(&mutex);
        cmdvel_msg.linear.x = shareMem->x;  
        cmdvel_msg.linear.y = shareMem->y; 
        cmdvel_msg.angular.z = shareMem->z; 
        pthread_mutex_unlock(&mutex);
        chatter_pub.publish(cmdvel_msg);
    
        ros::spinOnce();
    
        loop_rate.sleep();
      }
      pthread_mutex_destroy(&mutex);
      shmdt(shareMem);  //将共享内存段与当前进程脱离
      shmctl(shmid, IPC_RMID, NULL); //IPC_RMID为删除内存段
      return 0;
    }
    

    在beginner_tutorials 的 CMakeLists.txt 中添加:

    include_directories(include ${catkin_INCLUDE_DIRS})
    
    add_executable(talker src/talker.cpp)
    target_link_libraries(talker ${catkin_LIBRARIES})
    

    在终端中:

    cd ~/catkin_ws
    catkin_make
    
    1. 创建launch文件
      新建launch文件夹,创建stage_tast.launch文件
    <!--   
      stage_test 
      - stage_ros
      - talker
     -->
    <launch>  
      <arg name="world_file"     default=" $(find beginner_tutorials)/maps/stage/maze.world"/>  
    
      <node pkg="stage_ros" type="stageros" name="stageros" args="$(arg world_file)">  
        <param name="base_watchdog_timeout" value="0.5"/>  
        <remap from="odom" to="odom"/>  
        <remap from="base_pose_ground_truth" to="base_pose_ground_truth"/>  
        <remap from="cmd_vel" to="cmd_vel"/>  
      </node>  
    
      <node pkg="beginner_tutorials" type="talker" name="talker">
      </node>  
    
    </launch>  
    
    1. 创建速度控制父类
      便于其他速度控制类的编写,其他速度控制类只需要继承父类的框架,完成自己的mainloop()就好。
    /****************************************
    *文件名: VelControl.h          *
    *简介: 速度控制父类         *
    *BY: CR (qq: 414481619)         *
    *创建时间: 2018.10.09           *
    ****************************************/
    
    // this code ism't in ros system 
    
    #include <iostream>
    #include <stdio.h>
    #include <sys/shm.h>
    #include <errno.h>
    #include <sys/types.h>
    #include <stdlib.h>
    #include <pthread.h>
    #include <unistd.h>
    
    #include "sharemem.h"
    
    using namespace std;
    
    class VelControl
    {
    public:
        VelControl();
        ~VelControl();
        void mainloop();
    protected:
        ShareMem *shareMem;
        pthread_mutex_t mutex;  
        void writeVel(double x, double y, double z);
    };
    
    VelControl::VelControl()
    {
        pthread_mutex_init(&mutex, NULL);
    
        // 绑定共享内存
        int shmid = shmget((key_t)2333, 0, 0);  
        if(shmid != -1)
        {
            shareMem =(ShareMem *)shmat(shmid, NULL, 0);
            cout<<shmid<<endl;
        }
        else
        {
            cout<<"ERROR: stage_test haven't started"<<endl;
            exit(1);
        }
    }
    
    VelControl::~VelControl()
    {
        shmdt(shareMem);  //将共享内存段与当前进程脱离
        pthread_mutex_destroy(&mutex);
    }
    
    
    void VelControl::writeVel(double x, double y, double z)
    {
        pthread_mutex_lock(&mutex);
        shareMem->x = x;  
        shareMem->y = y; 
        shareMem->z = z;
        pthread_mutex_unlock(&mutex);
    }
    
    1. 这是一个键盘控制速度的例程(非常粗糙,仅供参考)
    /****************************************
    *文件名: keyboard_not_ros.cpp      *
    *简介: 速度控制例程         *
    *BY: CR (qq: 414481619)         *
    *创建时间: 2018.10.09           *
    ****************************************/
    
    // this code isn't in ros system 
    
    #include "VelControl.h"
    
    using namespace std;
    
    class keyboard_not_ros:VelControl
    {
    public:
        void mainloop();
    };
    
    void keyboard_not_ros::mainloop()
    {
        char c = 'a';
        while(c!='q')
        {
            cout<<"please input a letter"<<endl;
            c = getchar();
            getchar();
            double x,y,z;
            switch(c)
            {
                
                case 'W':
                case 'w':
                    x = 1;
                    y = 0;
                    z = 0;
                    break;
                case 'S':
                case 's':
                    x = -1;
                    y = 0;
                    z = 0;
                    break;
                case 'A':
                case 'a':
                    x = 0;
                    y = 0;
                    z = 1;
                    break;
                case 'D':
                case 'd':
                    x = 0;
                    y = 0;
                    z = -1;
                    break;
                default:;
            }
            writeVel(x, y, z);
            usleep(100*1000);
            writeVel(0,0,0);
        }
    }
    
    
    int main(int argc, char const *argv[])
    {
        keyboard_not_ros k;
        k.mainloop();
        return 0;
    }
    
    1. 编译程序
      在 ~/catkin_ws/src/beginner_tutorials/src/ 目录下,终端输入:
    g++ -o keyboard_not_ros keyboard_not_ros.cpp 
    
    1. 运行程序
      终端输入,启动ROS stage和其他相关节点:
    roslaunch beginner_tutorials stage_test.launch 
    

    另一个终端输入:

    ./keyboard_not_ros
    
    1. 结果输出


      最后的运行结果

    备注:但是stage不通过ROS也能使用,具体看下一篇文章。

    相关文章

      网友评论

          本文标题:【ROS-Stage】Stage机器人仿真实验(一)

          本文链接:https://www.haomeiwen.com/subject/elejaftx.html