我制作了一个简单的 ROS2 节点来移动机器人。
#include<unistd.h>
#include "rclcpp/rclcpp.hpp"
#include "geometry_msgs/msg/twist.hpp"
#include"SDL.h"
void cleanUp() {
SDL_Quit();
rclcpp::shutdown();
}
int main(int argc, char** argv) {
rclcpp::init(argc,argv);
auto node_ = rclcpp::Node::make_shared("keyboard_teleop");
node_->declare_parameter("vx", 1.0);
node_->declare_parameter("vtheta", 1.0);
node_->declare_parameter("twist_topic", rclcpp::ParameterValue("/cmd_vel"));
std::string twist_topic;
node_->get_parameter("twist_topic", twist_topic);
auto pub_ = node_->create_publisher<geometry_msgs::msg::Twist>(twist_topic, 10);
double vx;
double vtheta;
node_->get_parameter("vx", vx);
node_->get_parameter("vtheta", vtheta);
geometry_msgs::msg::Twist robot_vel;
SDL_Event event;
if (SDL_Init(SDL_INIT_EVENTS) < 0)
{
fprintf(stderr, "Could not initialise SDL: %s\n", SDL_GetError());
cleanUp();
return 0;
}
if (SDL_Init(SDL_INIT_VIDEO) < 0)
{
fprintf(stderr, "Could not initialise SDL: %s\n", SDL_GetError());
cleanUp();
return 0;
}
SDL_Window* window = SDL_CreateWindow(
"ROS Teleop", // window title
SDL_WINDOWPOS_UNDEFINED, // initial x position
SDL_WINDOWPOS_UNDEFINED, // initial y position
100, // width, in pixels
100, // height, in pixels
SDL_WINDOW_OPENGL // flags
);
if(window == nullptr)
{
fprintf(stderr, "Could not create SDL window: %s\n", SDL_GetError());
cleanUp();
return 0;
}
bool is_running{true};
while (rclcpp::ok())
{
while(SDL_PollEvent(&event))
{
switch(event.type)
{
// check if even is keyup or keydown
case SDL_KEYDOWN:
// check which key was pressed
switch(event.key.keysym.sym)
{
case SDLK_w:
robot_vel.linear.x = vx;
break;
case SDLK_a:
robot_vel.angular.z = vtheta;
break;
case SDLK_s:
robot_vel.linear.x = -vx;
break;
case SDLK_d:
robot_vel.angular.z = -vtheta;
break;
default:
break;
}
break;
case SDL_KEYUP:
// check which key was released
switch(event.key.keysym.sym)
{
case SDLK_w:
if(robot_vel.linear.x > 0.0)
robot_vel.linear.x = 0.0;
break;
case SDLK_a:
if(robot_vel.angular.z > 0.0)
robot_vel.angular.z = 0.0;
break;
case SDLK_s:
if(robot_vel.linear.x < 0.0)
robot_vel.linear.x = 0.0;
break;
case SDLK_d:
if(robot_vel.angular.z < 0.0)
robot_vel.angular.z = 0.0;
break;
default:
break;
}
break;
case SDL_QUIT:
is_running = false;
break;
default:
break;
}
if (!is_running)
{
break;
}
pub_->publish(robot_vel);
usleep(10000); // 100Hz
}
if (!is_running)
{
break;
}
}
SDL_DestroyWindow(window);
cleanUp();
return 0;
}
运行此代码将弹出一个黑色小窗口,您可以在其中使用 wasd 键来控制机器人。
问题是当我按右上角的 x 按钮时,窗口没有关闭。我读到按 x 键会发出
SDL_QUIT
事件,因此我编写了 case 语句来检测它并退出 while 循环,但它不起作用。
当我按 x 键时没有任何反应。我尝试将 print 语句放入
SDL_QUIT
的 case 语句中,但没有打印任何内容,这意味着永远不会发出 SDL_QUIT
信号。
这段代码有什么问题?
我怀疑问题可能是由于程序中未使用 OpenGL 时使用
SDL_WINDOW_OPENGL
标志引起的。将其替换为 SDL_WINDOW_SHOWN
或 0
并查看是否有效。