ros手柄控制机器人小车(二)

接着上一篇的文章.上一篇实现了可以用摇杆控制海龟的运动控制,但按键部分不行,仔细看了下rostopic echo /joy后,应该是关于axis的设置问题

 比较容易实现,直接在demo.launch文件里面添加关于按键的参数设置:

<launch>
    <node pkg="turtlesim" type="turtlesim_node" name="turtle1" output="screen" />
   
    <node pkg="ros_handle_control" type="teleop_turtle" name="teleop" output="screen" />

<!-- 方向按键控制 -->
    <param name="axis_linear" value="7" type="int" />
    <param name="axis_angular" value="6" type="int" />
<!-- 摇杆控制 -->
    <param name="sticks_left" value="1" type="int" />
    <param name="sticks_right" value="3" type="int" />

    <node respawn="true" pkg="joy" type="joy_node" name="joystick" />

</launch>

然后在源文件中修改一下,就可以了:

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/Joy.h>

class TeleopTurtle
{
public:
    TeleopTurtle();

private:
    // 处理手柄发送过来的信息
    void callback(const sensor_msgs::Joy::ConstPtr &joy);
    // 实例化ROS句柄
    ros::NodeHandle nh;
    // 定义订阅者对象,用来订阅手柄发送的数据
    ros::Subscriber sub;
    // 定义发布者对象,用来将手柄数据发布到乌龟控制话题上
    ros::Publisher pub;
    // 用来接收launch文件中设置的参数,绑定手柄摇杆、轴的映射
    int axis_linear, axis_angular;
    int sticks_left, sticks_right;
};

TeleopTurtle::TeleopTurtle()
{
    // 从参数服务器读取的参数
    // 按手柄摇杆分配
    nh.param<int>("sticks_left", sticks_left, 1);
    nh.param<int>("sticks_right", sticks_right, 3);
    // 按键分配
    nh.param<int>("axis_linear", axis_linear, 1);
    nh.param<int>("axis_angular", axis_angular, 2);
    // Axes:  0:     0  1:     0  2: 0   3:     0  4:     0  5: 0   6:     0  7:     0 
    // 对应:0: 左摇杆轴左右
    //    1: 左摇杆轴前后
    //    2: 默认全不开放
    //    3: 右摇杆轴左右
    //    4: 右摇杆轴前后
    //    5: 默认全不开放
    //    6: 方向按键左+右
    //    7: 方向按键前+后  
    pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);
    sub = nh.subscribe<sensor_msgs::Joy>("joy", 10, &TeleopTurtle::callback, this);
}

void TeleopTurtle::callback(const sensor_msgs::Joy::ConstPtr &joy)
{
    geometry_msgs::Twist vel;

    if(joy->axes[axis_linear] || joy->axes[axis_angular])
    {
        vel.linear.x = joy->axes[axis_linear];
        vel.angular.z = joy->axes[axis_angular];
    }
    else if(joy->axes[sticks_left] ||  joy->axes[sticks_right])
    {
        vel.linear.x = joy->axes[sticks_left];
        vel.angular.z = joy->axes[sticks_right];
    }
    // // 将手柄摇杆轴拨动时值的输出赋值给乌龟的线速度和角速度
    // vel.linear.x = joy->axes[axis_linear];
    // vel.angular.z = joy->axes[axis_angular];
    // // 按键按动时也可以输出乌龟的线速度和角速度
    // vel.linear.x = joy->axes[sticks_left];
    // vel.angular.z = joy->axes[sticks_right];
    ROS_INFO("当前线速度为:%.3lf ; 角速度为:%.3lf", vel.linear.x, vel.angular.z);
    pub.publish(vel);
}

int main(int argc, char **argv)
{
    // 设置编码
    setlocale(LC_ALL, "");
    // 初始化ROS节点
    ros::init(argc, argv, "teleop_turtle");
    TeleopTurtle teleopTurtle;
    ros::spin();
    return 0;
}

代码中的注释写的很清楚了,主要还是对于axis[]不同按键的设置问题,最开始设置好了发现只能在callback函数里面最前面的可以运行,后面就不行了,可能是因为每次只能接受最前面的按键指令?改了if-else if判断后就好很多了.

但现在还存在一个问题,就是它每回按键只能运行一下,就是当前设置的运动周期,一直按着也只能运行一个周期,必须有按键的改变才能继续运行.这应该是没有设置loop循环的原因,重新设置一下,具体实现参考了这篇文章

具体改变有两处:
1.添加了安全保护按钮,只有当L1按动的时候,控制按键才会启动

2.设置了按住不动的时候一直发送控制指令

具体代码实现如下:

#include <ros/ros.h>
#include <geometry_msgs/Twist.h>
#include <sensor_msgs/Joy.h>

void callback(const sensor_msgs::Joy::ConstPtr &joy);

int axis_linear, axis_angular;
int sticks_left, sticks_right;
int ton;
double vel_x, vel_z;

int main(int argc, char **argv)
{
    // 设置编码
    setlocale(LC_ALL, "");

    ros::init(argc, argv, "teleop_turtle");
    ros::NodeHandle nh;

    ros::Subscriber sub;
    ros::Publisher pub;

    ros::Rate r(20);


    nh.param<int>("ton", ton, 4);
    // 按手柄摇杆分配
    nh.param<int>("sticks_left", sticks_left, 7);
    nh.param<int>("sticks_right", sticks_right, 6);
    // 按键分配
    nh.param<int>("axis_linear", axis_linear, 1);
    nh.param<int>("axis_angular", axis_angular, 2);

    sub = nh.subscribe<sensor_msgs::Joy>("joy", 10, callback);
    // 如果想要换成机器人控制就把"/turtle1/cmd_vel"更换成要求的
    pub = nh.advertise<geometry_msgs::Twist>("/turtle1/cmd_vel", 10);

    while(nh.ok())
    {
        geometry_msgs::Twist v;
        v.linear.x = vel_x;
        v.angular.z = vel_z;
        if(v.linear.x != 0 || v.angular.z != 0)
        {
            pub.publish(v);
        }
        else
        {
            v.linear.x = 0;
            v.angular.z = 0;    
            pub.publish(v);
        }

        ros::spinOnce();
        r.sleep();
    }
    return 0;
}

void callback(const sensor_msgs::Joy::ConstPtr &joy)
{
    if(joy->buttons[ton])
    {
        if(joy->axes[axis_linear] || joy->axes[axis_angular])
        {
            vel_x = joy->axes[axis_linear];
            vel_z = joy->axes[axis_angular];
        }
        else if(joy->axes[sticks_left] ||  joy->axes[sticks_right])
        {
            vel_x = joy->axes[sticks_left];
            vel_z = joy->axes[sticks_right];
        }
        ROS_INFO("当前线速度为:%.3lf ; 角速度为:%.3lf", vel_x, vel_z);
    }
    else
    {
        vel_x = 0;
        vel_z = 0;
    }
}

还有cmakelists.txt和launch里面修改一下.

最开始写的时候发现按一下后,就会一直发送速度指令,与设想不符合,然后就加了一个判断当没有按键的时候就会发送速度为零,并且以L4为安全按键,当不按L4的时候,就会停止.

基本实现了海龟的控制,之后在移植机器人还要更改发布的topic和设置开机启动,就是之后的事了.

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值