这个其实是各版本之间不停的改动导致的。
foxy:
That means replace the rclcpp::FutureReturnCode::SUCCESS
with rclcpp::executor::FutureReturnCode::SUCCESS
.
然后:
galactic:
rclcpp::FutureReturnCode::SUCCESS
humble:
rclcpp::FutureReturnCode::SUCCESS
那么针对如下出错信息:
修改对应源代码:
/home/ros/RobCode/mobot/src/mobot/src/send_client.cpp:38:13:
将:
if (rclcpp::spin_until_future_complete(node, result) ==
rclcpp::executor::FutureReturnCode::SUCCESS)
修改为:
if (rclcpp::spin_until_future_complete(node, result) ==
rclcpp::FutureReturnCode::SUCCESS)
然后就一切ok啦。
全部记录:
ros@ros:~/RobCode/mobot$ colcon build
Starting >>> teleop_tools_msgs
Starting >>> key_teleop
Starting >>> mobot
Starting >>> mobot_follow
Starting >>> mouse_teleop
Finished <<< key_teleop [2.30s]
Finished <<< mouse_teleop [2.36s]
Finished <<< teleop_tools_msgs [12.8s]
Starting >>> joy_teleop
Finished <<< joy_teleop [3.74s]
Starting >>> teleop_tools
Finished <<< teleop_tools [0.74s]
Finished <<< mobot_follow [19.8s]
--- stderr: mobot
/home/ros/RobCode/mobot/src/mobot/src/send_client.cpp: In function ‘int main(int, char**)’:
/home/ros/RobCode/mobot/src/mobot/src/send_client.cpp:38:13: error: ‘rclcpp::executor’ has not been declared
38 | rclcpp::executor::FutureReturnCode::SUCCESS)
| ^~~~~~~~
make[2]: *** [CMakeFiles/send_client.dir/build.make:63:CMakeFiles/send_client.dir/src/send_client.cpp.o] 错误 1
make[1]: *** [CMakeFiles/Makefile2:671:CMakeFiles/send_client.dir/all] 错误 2
make[1]: *** 正在等待未完成的任务....
make: *** [Makefile:141:all] 错误 2
---
Failed <<< mobot [25.3s, exited with code 2]
Summary: 6 packages finished [25.6s]
1 package failed: mobot
1 package had stderr output: mobot
ros@ros:~/RobCode/mobot$ colcon build
Starting >>> teleop_tools_msgs
Starting >>> key_teleop
Starting >>> mobot
Starting >>> mobot_follow
Starting >>> mouse_teleop
Finished <<< mobot_follow [0.90s]
Finished <<< teleop_tools_msgs [1.00s]
Starting >>> joy_teleop
Finished <<< key_teleop [1.99s]
Finished <<< mouse_teleop [2.07s]
Finished <<< joy_teleop [1.48s]
Starting >>> teleop_tools
Finished <<< teleop_tools [0.12s]
Finished <<< mobot [4.66s]
Summary: 7 packages finished [4.84s]
ros@ros:~/RobCode/mobot$
当节点使用服务进行通信时,发送数据请求的节点称为客户端节点,响应请求的节点称为服务节点。 请求和响应的结构由 .srv 文件确定。
When nodes communicate using services, the node that sends a request for data is called the client node, and the one that responds to the request is the service node. The structure of the request and response is determined by a .srv file.
这里使用的例子是一个简单的目标前进系统; 一个节点目标前进服务器,另一个客户端接收对应坐标。
到达目标点附近,任务完成。
这个比导航行动要简单,但是比速度控制反馈等要复杂一些。
给定目标点,到达目标点。
当然也可以用行动来完成,显示距离目标点完成的百分比。
服务器端:
#include <iostream>
#include <chrono>
#include <memory>
#include "rclcpp/rclcpp.hpp"
#include "mobot/srv/drivegoalsrv.hpp"
#include <geometry_msgs/msg/twist.hpp>
#include "nav_msgs/msg/odometry.hpp"
using namespace std::chrono_literals;
bool drive_flag=0;
float goal_x=0;
float goal_y=0;
float vel_x=0;
float vel_z=0;
float pid_z=2.0;
void get(const std::shared_ptr<mobot::srv::Drivegoalsrv::Request> request,
std::shared_ptr<mobot::srv::Drivegoalsrv::Response> response)
{
if(request->x>0.0)
{
drive_flag=1;
response->success=drive_flag;
goal_x=request->x;
goal_y=request->y;
RCLCPP_INFO(rclcpp::get_logger("service"), "Driving");
//RCLCPP_INFO(rclcpp::get_logger("service"), "Get Goal\nx: %lf" " y: %lf",
// request->x, request->y);
//RCLCPP_INFO(rclcpp::get_logger("service"), "Flag: [%d]", response->success);
}
else
{
drive_flag=0;
response->success=drive_flag;
goal_x=request->x;
goal_y=request->y;
//RCLCPP_INFO(rclcpp::get_logger("service"), "Error, x>0!!!\nx: %lf" " y: %lf",
// request->x, request->y);
//RCLCPP_INFO(rclcpp::get_logger("service"), "Flag: [%d]", response->success);
}
}
void odom_callback(const nav_msgs::msg::Odometry::SharedPtr msg)
{
if(drive_flag)
{
vel_x=goal_x-msg->pose.pose.position.x;
vel_z=pid_z*(goal_y-msg->pose.pose.position.y)*vel_x*vel_x;
if(vel_z>0.5)
{
vel_z=0.5;
}
if(vel_z<-0.5)
{
vel_z=-0.5;
}
if(vel_x>1.0)
{
vel_x=1.0;
}
if(vel_x<-1.0)
{
vel_x=-1.0;
}
if((vel_x<0.05)&&(vel_x>-0.05))
if((vel_z<0.05)&&(vel_z>-0.05))
{
RCLCPP_INFO(rclcpp::get_logger("service"), "Mission complete!");
RCLCPP_INFO(rclcpp::get_logger("service"), "Ready to get goal.");
drive_flag=0;
}
}
else
{
vel_x=0;
vel_z=0;
}
// RCLCPP_INFO(rclcpp::get_logger("odom_sub"), "I heard: mobot odom position(x,y)='%f','%f'", msg->pose.pose.position.x, msg->pose.pose.position.y);
}
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("get_goal_server");
rclcpp::Service<mobot::srv::Drivegoalsrv>::SharedPtr service =
node->create_service<mobot::srv::Drivegoalsrv>("get_goal", &get);
rclcpp::Publisher<geometry_msgs::msg::Twist>::SharedPtr vel_pub =
node->create_publisher<geometry_msgs::msg::Twist>("mobot/cmd_vel", 10);
geometry_msgs::msg::Twist mobot_vel;
rclcpp::Subscription<nav_msgs::msg::Odometry>::SharedPtr odom_sub =
node->create_subscription<nav_msgs::msg::Odometry>("/mobot/odom", 100, odom_callback);
RCLCPP_INFO(rclcpp::get_logger("service"), "Ready to get goal.");
rclcpp::WallRate loop_rate(100ms);
while (rclcpp::ok()) {
mobot_vel.linear.x = vel_x;
mobot_vel.angular.z = vel_z;
//RCLCPP_INFO(rclcpp::get_logger("vel_pub"), "Publishing mobot cmd_vel : linear='%f',angular='%f'", mobot_vel.linear.x, mobot_vel.angular.z);
vel_pub->publish(mobot_vel);
rclcpp::spin_some(node);
loop_rate.sleep();
}
rclcpp::shutdown();
return 0;
}
客户端:
#include "rclcpp/rclcpp.hpp"
#include "mobot/srv/drivegoalsrv.hpp"
#include <chrono>
#include <cstdlib>
#include <memory>
using namespace std::chrono_literals;
int main(int argc, char **argv)
{
rclcpp::init(argc, argv);
if (argc != 3) {
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "usage: send_goal_position_client X Y");
return 1;
}
std::shared_ptr<rclcpp::Node> node = rclcpp::Node::make_shared("send_goal_client");
rclcpp::Client<mobot::srv::Drivegoalsrv>::SharedPtr client =
node->create_client<mobot::srv::Drivegoalsrv>("get_goal");
auto request = std::make_shared<mobot::srv::Drivegoalsrv::Request>();
request->x = atoll(argv[1]);
request->y = atoll(argv[2]);
while (!client->wait_for_service(1s)) {
if (!rclcpp::ok()) {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Interrupted while waiting for the service. Exiting.");
return 0;
}
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "service not available, waiting again...");
}
auto result = client->async_send_request(request);
// Wait for the result.
if (rclcpp::spin_until_future_complete(node, result) ==
rclcpp::FutureReturnCode::SUCCESS)
{
RCLCPP_INFO(rclcpp::get_logger("rclcpp"), "Flag: %d", result.get()->success);
} else {
RCLCPP_ERROR(rclcpp::get_logger("rclcpp"), "Failed to call service get_goal");
}
rclcpp::shutdown();
return 0;
}