【ROS-Stage】Stage機器人仿真實驗(一)

環(huán)境:64位 ubuntu16.04,代碼見:https://github.com/cr19941016/ROS_stage_test

  1. 安裝ROS
    更換軟件源(設置 --> Software & Update),會下載的更快。
    stage_ros仿真包是ros自帶的,安裝完之后就有了。
  2. 按照教程,創(chuàng)建一個工作空間
    記得添加 source:
echo "source ~/catkin_ws/devel/setup.bash" >> ~/.bashrc
source ~/.bashrc 
  1. 按照教程,創(chuàng)建ROS程序包
  2. 下載 turtlebot_simulator,將里面的 /turtlebot_stage/maps/ 復制出來,放在新建的程序包文件夾中(beginner_tutorials)。
  3. 共享內存用于ROS節(jié)點和非ROS進程之間的通信。
    創(chuàng)建共享內存區(qū)的數據結構,存放在 sharemem.h中。
#ifndef SHAREMEM_H
#define SHAREMEM_H
struct ShareMem
{
  double x; //  x方向的速度(前后)
  double y; //  y方向的速度(左右)
  double z; //  旋轉
};
#endif
  1. 新建talker節(jié)點。
    創(chuàng)建共享內存、監(jiān)聽共享內存區(qū)域的速度變化和發(fā)布速度話題。
/****************************************
*文件名: talker.cpp            *
*簡介: 鏈接非ROS進程和ROS節(jié)點的ROS節(jié)點   *
*BY: CR (qq: 414481619)         *
*創(chuàng)建時間: 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;
  // 創(chuàng)建共享內存 ,相當于打開文件,文件不存在則創(chuàng)建
  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. 創(chuàng)建launch文件
    新建launch文件夾,創(chuàng)建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. 創(chuàng)建速度控制父類
    便于其他速度控制類的編寫,其他速度控制類只需要繼承父類的框架,完成自己的mainloop()就好。
/****************************************
*文件名: VelControl.h          *
*簡介: 速度控制父類         *
*BY: CR (qq: 414481619)         *
*創(chuàng)建時間: 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)         *
*創(chuàng)建時間: 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和其他相關節(jié)點:
roslaunch beginner_tutorials stage_test.launch 

另一個終端輸入:

./keyboard_not_ros
  1. 結果輸出


    最后的運行結果

備注:但是stage不通過ROS也能使用,具體看下一篇文章。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容