在 ROS 中订阅 Joy Topic
Subscriber to Joy Topic in ROS
我想将我的 XBOX 游戏手柄集成到 ROS 中。
我的想法是为主题“/joy”编写一个订阅者,并获取每个按钮和每个轴的数据,以便我可以使用它们来控制我的机器人。
我遵循了这个教程:“http://wiki.ros.org/joy/Tutorials/WritingTeleopNode”并且我想编辑它。但他们只从轴心国获取信息。我也想从按钮中获取。
此外,我不想将这些消息作为Twist Messages 发布到turtle 节点。我想将它们发送到一个新主题。
我能得到一些帮助吗?或者 link 可以打包已经解决此类问题的程序吗?
当您订阅 sensor_msgs/joy 消息时,您有一个 float32[] axes
和一个 int32[] buttons
。在节点中主题的回调中,您可以访问 msg 的成员。数组在 python 中是列表,在 C++ 中是向量。经典的两种范例是从回调中发布新消息,在回调中进行转换,and/or 将回调中的数据存储为全局变量,以用于另一个消息回调或 timer/periodic回调。
但是,您仍然需要弄清楚哪些按钮映射到数组中的哪个数字元素。请参阅 joy_node docs 或 jstest
/jstest-gtk
中的正常编号以获取帮助;将映射存储为相关位置的枚举。
最小示例:
// joy_to_something_node.cpp
// ROS
#include <ros/ros.h>
#include <sensor_msgs/Joy.h>
#include <std_msgs/Bool.h>
#include <geometry_msgs/Vector3Stamped.h>
// Std Libs
#include <vector>
#include <stdint.h>
// Subscribers
// joy_sub (sensor_msgs/Joy): "joy"
// Publishers
// estop_pub (std_msgs/Bool): "estop"
// btn_dir_pub (geometry_msgs/Vector3Stamped): "joy/btn_dir"
// Parameters
// frequency (double): 10 Hz
// lag (double): 0.25 %
// // could have the mappings as params
enum {
JOY_BTN_A = 0,
JOY_BTN_B = 1,
JOY_BTN_X = 2,
JOY_BTN_Y = 3,
JOY_BTN_LB = 4,
JOY_BTN_RB = 5,
};
// ROS Nodehandles and Publishers
ros::NodeHandle *nh;
ros::NodeHandle *pnh;
ros::Publisher estop_pub;
ros::Publisher btn_dir_pub;
// ROS Callbacks
void joy_cb(const sensor_msgs::Joy::ConstPtr& msg);
void timer_cb(const ros::TimerEvent&);
// ROS Params
double frequency = 10.0;
double lag = 0.25;
// Globals (ex)
std::vector<int32_t> btn_dir_data;
geometry_msgs::Vector3Stamped btn_dir_msg;
int main(int argc, char** argv){
// Init
ros::init(argc, argv, "joy_to_something_node");
nh = new ros::NodeHandle();
pnh = new ros::NodeHandle("~");
pnh->getParam("frequency", frequency);
pnh->getParam("lag", lag);
btn_dir_msg.header.frame_id = "base_link";
// Subs
ros::Subscriber joy_sub = nh->subscribe("joy", 1, joy_cb);
ros::Timer timer = nh->createTimer(ros::Duration(1.0/frequency), timer_cb);
// Pubs
estop_pub = nh->advertise<std_msgs::Bool>("estop", 1);
btn_dir_pub = nh->advertise<geometry_msgs::Vector3Stamped>("joy/btn_dir", 1);
// Exec
ros::spin();
return 0;
}
void joy_cb(const sensor_msgs::Joy::ConstPtr& msg){
std_msgs::Bool estop_msg;
estop_msg.data = msg->buttons[JOY_BTN_LB] > 0; // Should be 1 or zero
estop_pub.publish(estop_msg);
btn_dir_data = msg->buttons;
}
void timer_cb(const ros::TimerEvent&){
btn_dir_msg.header.seq++;
btn_dir_msg.header.stamp = ros::Time::now();
// X is fwd, Y is right
btn_dir_msg.vector.x *= lag;
btn_dir_msg.vector.x += (1.0 - lag) * (btn_dir_data[JOY_BTN_Y] - btn_dir_data[JOY_BTN_A]);
btn_dir_msg.vector.y *= lag;
btn_dir_msg.vector.y += (1.0 - lag) * (btn_dir_data[JOY_BTN_B] - btn_dir_data[JOY_BTN_X]);
btn_dir_pub.publish(btn_dir_msg);
}
我通常 CMakeLists.txt 有这些:
find_package(catkin REQUIRED
roscpp
cmake_modules
std_msgs
geometry_msgs
)
catkin_package(
INCLUDE_DIRS include
# LIBRARIES [custom libs]
CATKIN_DEPENDS
roscpp
std_msgs
nav_msgs
# DEPENDS [sys libs]
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_executable(my_node src/my_node.cpp)
target_link_libraries(my_node ${catkin_LIBRARIES})
set_target_properties(my_node PROPERTIES COMPILE_FLAGS "${CPP_DEVEL_FLAGS}")
同样,您的 package.xml 依赖可以只是您也放入 CMakeLists.txt 中的那些,如果您使用(现代)格式 =2,则不需要多次声明。
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>geometry_msgs</depend>
<depend>std_msgs</depend>
编辑:添加了说明和 cmake/package.xml.
我想将我的 XBOX 游戏手柄集成到 ROS 中。
我的想法是为主题“/joy”编写一个订阅者,并获取每个按钮和每个轴的数据,以便我可以使用它们来控制我的机器人。
我遵循了这个教程:“http://wiki.ros.org/joy/Tutorials/WritingTeleopNode”并且我想编辑它。但他们只从轴心国获取信息。我也想从按钮中获取。
此外,我不想将这些消息作为Twist Messages 发布到turtle 节点。我想将它们发送到一个新主题。
我能得到一些帮助吗?或者 link 可以打包已经解决此类问题的程序吗?
当您订阅 sensor_msgs/joy 消息时,您有一个 float32[] axes
和一个 int32[] buttons
。在节点中主题的回调中,您可以访问 msg 的成员。数组在 python 中是列表,在 C++ 中是向量。经典的两种范例是从回调中发布新消息,在回调中进行转换,and/or 将回调中的数据存储为全局变量,以用于另一个消息回调或 timer/periodic回调。
但是,您仍然需要弄清楚哪些按钮映射到数组中的哪个数字元素。请参阅 joy_node docs 或 jstest
/jstest-gtk
中的正常编号以获取帮助;将映射存储为相关位置的枚举。
最小示例:
// joy_to_something_node.cpp
// ROS
#include <ros/ros.h>
#include <sensor_msgs/Joy.h>
#include <std_msgs/Bool.h>
#include <geometry_msgs/Vector3Stamped.h>
// Std Libs
#include <vector>
#include <stdint.h>
// Subscribers
// joy_sub (sensor_msgs/Joy): "joy"
// Publishers
// estop_pub (std_msgs/Bool): "estop"
// btn_dir_pub (geometry_msgs/Vector3Stamped): "joy/btn_dir"
// Parameters
// frequency (double): 10 Hz
// lag (double): 0.25 %
// // could have the mappings as params
enum {
JOY_BTN_A = 0,
JOY_BTN_B = 1,
JOY_BTN_X = 2,
JOY_BTN_Y = 3,
JOY_BTN_LB = 4,
JOY_BTN_RB = 5,
};
// ROS Nodehandles and Publishers
ros::NodeHandle *nh;
ros::NodeHandle *pnh;
ros::Publisher estop_pub;
ros::Publisher btn_dir_pub;
// ROS Callbacks
void joy_cb(const sensor_msgs::Joy::ConstPtr& msg);
void timer_cb(const ros::TimerEvent&);
// ROS Params
double frequency = 10.0;
double lag = 0.25;
// Globals (ex)
std::vector<int32_t> btn_dir_data;
geometry_msgs::Vector3Stamped btn_dir_msg;
int main(int argc, char** argv){
// Init
ros::init(argc, argv, "joy_to_something_node");
nh = new ros::NodeHandle();
pnh = new ros::NodeHandle("~");
pnh->getParam("frequency", frequency);
pnh->getParam("lag", lag);
btn_dir_msg.header.frame_id = "base_link";
// Subs
ros::Subscriber joy_sub = nh->subscribe("joy", 1, joy_cb);
ros::Timer timer = nh->createTimer(ros::Duration(1.0/frequency), timer_cb);
// Pubs
estop_pub = nh->advertise<std_msgs::Bool>("estop", 1);
btn_dir_pub = nh->advertise<geometry_msgs::Vector3Stamped>("joy/btn_dir", 1);
// Exec
ros::spin();
return 0;
}
void joy_cb(const sensor_msgs::Joy::ConstPtr& msg){
std_msgs::Bool estop_msg;
estop_msg.data = msg->buttons[JOY_BTN_LB] > 0; // Should be 1 or zero
estop_pub.publish(estop_msg);
btn_dir_data = msg->buttons;
}
void timer_cb(const ros::TimerEvent&){
btn_dir_msg.header.seq++;
btn_dir_msg.header.stamp = ros::Time::now();
// X is fwd, Y is right
btn_dir_msg.vector.x *= lag;
btn_dir_msg.vector.x += (1.0 - lag) * (btn_dir_data[JOY_BTN_Y] - btn_dir_data[JOY_BTN_A]);
btn_dir_msg.vector.y *= lag;
btn_dir_msg.vector.y += (1.0 - lag) * (btn_dir_data[JOY_BTN_B] - btn_dir_data[JOY_BTN_X]);
btn_dir_pub.publish(btn_dir_msg);
}
我通常 CMakeLists.txt 有这些:
find_package(catkin REQUIRED
roscpp
cmake_modules
std_msgs
geometry_msgs
)
catkin_package(
INCLUDE_DIRS include
# LIBRARIES [custom libs]
CATKIN_DEPENDS
roscpp
std_msgs
nav_msgs
# DEPENDS [sys libs]
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
add_executable(my_node src/my_node.cpp)
target_link_libraries(my_node ${catkin_LIBRARIES})
set_target_properties(my_node PROPERTIES COMPILE_FLAGS "${CPP_DEVEL_FLAGS}")
同样,您的 package.xml 依赖可以只是您也放入 CMakeLists.txt 中的那些,如果您使用(现代)格式 =2,则不需要多次声明。
<buildtool_depend>catkin</buildtool_depend>
<depend>roscpp</depend>
<depend>geometry_msgs</depend>
<depend>std_msgs</depend>
编辑:添加了说明和 cmake/package.xml.