1. 程式人生 > 其它 >Ubuntu16.04 ROS 話題 服務 動作 訊息

Ubuntu16.04 ROS 話題 服務 動作 訊息

技術標籤:ROSUbuntuc++linuxubuntu

Ubuntu16.04 Ros 話題 服務 動作 訊息

一、新增話題服務檔案

1、找包

find_package(catkin REQUIRED COMPONENTS
  roscpp
  rospy
  std_msgs
  message_generation
  actionlib_msgs 
  actionlib
)

2、找檔案

add_message_files(
    FILES
    Person.msg
#   Message1.msg
#   Message2.msg
 )



## Generate services in the 'srv'
folder # add_service_files( # FILES # Service1.srv # Service2.srv # ) add_service_files(FILES AddTwoInts.srv) ## Generate actions in the 'action' folder add_action_files( FILES DoDishes.action # Action1.action # Action2.action )

3、產生訊息

Generate_messages(DEPENDENCIES std_msgs actionlib_msgs)

4、配置package包

  <buildtool_depend>catkin</buildtool_depend>
  <build_depend>roscpp</build_depend>
  <build_depend>rospy</build_depend>
  <build_depend>std_msgs</build_depend>
  <build_depend>message_generation</build_depend>
  <build_depend>
actionlib</build_depend> <build_depend>actionlib_msgs</build_depend> <build_export_depend>roscpp</build_export_depend> <build_export_depend>rospy</build_export_depend> <build_export_depend>std_msgs</build_export_depend> <exec_depend>roscpp</exec_depend> <exec_depend>rospy</exec_depend> <exec_depend>std_msgs</exec_depend> <exec_depend>message_runtime</exec_depend> <exec_depend>actionlib</exec_depend> <exec_depend>actionlib_msgs</exec_depend>

二、如何產生可執行檔案

1、希望生成一個可執行檔案

add_executable(talker可執行檔名  src/talker.cpp生成可執行檔案的原始檔)
add_executable(talker src/talker.cpp 1.cpp 2.cpp)

2、設定連結第三方庫,這裡沒有連結庫,所以連結catkin_LIBRARIES,如果需要連結第三方庫,就把catkin_LIBRARIES改為第三方庫的名子

target_link_libraries(talker ${catkin_LIBRARIES})

3、設定所需要的依賴

add_dependencies(server ${PROJECT_NAME}_gencpp)

4、整體

add_executable(talker src/talker.cpp)
target_link_libraries(talker ${catkin_LIBRARIES})
 #target_link_libraries(${PROJECT_NAME}_node
 #  ${catkin_LIBRARIES}
# )

# add_dependencies(talker ${PROJECT_NAME}_generate_messages_cpp)
add_executable(listener src/listener.cpp)
target_link_libraries(listener ${catkin_LIBRARIES})
# target_link_libraries(${PROJECT_NAME}_node
 #  ${catkin_LIBRARIES}
# )

add_executable(server src/server.cpp)
target_link_libraries(server ${catkin_LIBRARIES})
add_dependencies(server ${PROJECT_NAME}_gencpp)

add_executable(client src/client.cpp)
target_link_libraries(client ${catkin_LIBRARIES})
add_dependencies(client ${PROJECT_NAME}_gencpp)


add_executable(DoDishes_client src/DoDishes_client.cpp)
target_link_libraries( DoDishes_client ${catkin_LIBRARIES})
add_dependencies(DoDishes_client ${${PROJECT_NAME}_EXPORTED_TARGETS})

add_executable(DoDishes_server src/DoDishes_server.cpp)
target_link_libraries( DoDishes_server ${catkin_LIBRARIES})
add_dependencies(DoDishes_server ${${PROJECT_NAME}_EXPORTED_TARGETS})

三、話題:

某一個功能包節點只管自己釋出訊息,以一定的迴圈頻率釋出,
另一個功能包需要是即訂閱,兩者可以不同步,

ros::Publisher chatter_pub = n.advertise<std_msgs::String>("chatter", 1000);

這裡的1000的意思是資料結構的佇列結構,如果記憶體過大,就先進先出,使此功能包所佔用的系統記憶體不超過1000,保證記憶體資源的不浪費。

四、訊息型別

自己定義,也可引用系統訊息型別,注意配置格式
用於功能包直接的通訊的資訊服務非常方便也非常必須。

在這裡插入圖片描述

五、服務

服務的核心在於服務服務方,裡面包括若干處理資訊,把客戶發來的資料進行處理,把處理結果返回給客戶端。
而客戶端主要是傳送請求資料,然後從服務方就收結果,客戶自己不關心處理過程,只關心處理結果。客戶端的請求服務程式碼為

client.call(srv)

六、動作

1、動作服務端

#include <ros/ros.h>
#include <actionlib/server/simple_action_server.h>
#include "linlinshi/DoDishesAction.h"

typedef actionlib::SimpleActionServer<linlinshi::DoDishesAction> Server;

// 收到action的goal後呼叫該回調函式
void execute(const linlinshi::DoDishesGoalConstPtr& goal, Server* as)
{
    ros::Rate r(1);
    linlinshi::DoDishesFeedback feedback;

    ROS_INFO("Dishwasher %d is working.", goal->dishwasher_id);

    // 假設洗盤子的進度,並且按照1hz的頻率釋出進度feedback
    for(int i=1; i<=10; i++)
    {
        feedback.percent_complete = i * 10;
        as->publishFeedback(feedback);
        r.sleep();
    }

    // 當action完成後,向客戶端返回結果
    ROS_INFO("Dishwasher %d finish working.", goal->dishwasher_id);
    as->setSucceeded();
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "do_dishes_server");
    ros::NodeHandle n;

    // 定義一個伺服器
    Server server(n, "do_dishes", boost::bind(&execute, _1, &server), false);
    
    // 伺服器開始執行
    server.start();

    ros::spin();

    return 0;
}

2、動作客戶端

#include <actionlib/client/simple_action_client.h>
#include "linlinshi/DoDishesAction.h"

typedef actionlib::SimpleActionClient<linlinshi::DoDishesAction> Client;

// 當action完成後會呼叫該回調函式一次
void doneCb(const actionlib::SimpleClientGoalState& state,
        const linlinshi::DoDishesResultConstPtr& result)
{
    ROS_INFO("Yay! The dishes are now clean");
    ros::shutdown();
}

// 當action啟用後會呼叫該回調函式一次
void activeCb()
{
    ROS_INFO("Goal just went active");
}

// 收到feedback後呼叫該回調函式
void feedbackCb(const linlinshi::DoDishesFeedbackConstPtr& feedback)
{
    ROS_INFO(" percent_complete : %f ", feedback->percent_complete);
}

int main(int argc, char** argv)
{
    ros::init(argc, argv, "do_dishes_client");

    // 定義一個客戶端
    Client client("do_dishes", true);

    // 等待伺服器端
    ROS_INFO("Waiting for action server to start.");
    client.waitForServer();
    ROS_INFO("Action server started, sending goal.");

    // 建立一個action的goal
    linlinshi::DoDishesGoal goal;
    goal.dishwasher_id = 1;

    // 傳送action的goal給伺服器端,並且設定回撥函式
    client.sendGoal(goal,  &doneCb, &activeCb, &feedbackCb);

    ros::spin();

    return 0;
}