ROS 通过节点控制Arduino实现舵机转动到相应角度(代码详解)

前言:

 本人大二,写的不对的地方请多包涵。最近在做一个项目(机械手的控制)同时也在自学ros,所以在想能不能用ros作为媒介来控制下位机arduino进而控制舵机使机械手完成相应的动作。在网上参考了一些博客后,开始着手写。


文章目录

  • 系列文章目录
  • 前言
  • 一、ros相较于串口通讯控制的好处
  • 二、实现步骤
    • 1.引入库
    • 2.编程实现
  • 总结

:用ros控制的好处在于,基于ros的通信机制,如话题,服务,行为等方式,只要用到rosserial库,需要安装rosserial_arduino。不需要知道串口之间的通信协议,直接发布和订阅来传递参数。相对于串口通讯而言,你就要查阅各种串口的开启、关闭的方法。尤其是那些有很多引脚和甚至共用功能的引脚,对新手很不友好。

:实现步骤:

1.在开工之前,确保你已经下好ros_lib库,这个库是专门用来和arduino之间做通讯的,具体的操作可以参考我的另一篇博客,这里就不在赘述。博客名字为 ROS与Arduino之间的串口通讯(详解)_Agno ni的博客-CSDN博客

在安装好环境之后,我这边就直接上代码了,里面有详细的解释。


#if (ARDUINO >= 100)
 #include 
#else
 #include 
#endif

#include  
#include   
#include   //包含节点头文件斜杠后面是数据类型无符号16位
#include   //同理字符型

#include  

ros::NodeHandle  nh;     //初始化节点句柄命名为nh
std_msgs::UInt16 cmd_msg; //声明将要使用的消息
std_msgs::String std_msg;
int angle,i;              //定义变量舵机旋转的角度
Servo servo[4];           //引入舵机库因为我的机械手是四个自由度的,有四个舵机所以定义长度为 
                            四的数组。

void servo_message( const std_msgs::UInt16& cmd_msg){       //定义节点发送函数消息内容为 
                                                             //cmd_msg
                                                              
  servo[0].write(cmd_msg.data);  //    set middle servo angle 90  设置舵机要输入的数据
  servo[1].write(cmd_msg.data+15);
  servo[2].write(cmd_msg.data+30);
  servo[3].write(cmd_msg.data+25);
  
}

ros::Subscriber servo_sender("servo_sender", servo_message);  //创建发布者sub is 
                                                                        subscriber
ros::Publisher servo_publisher("servo_publisher",&std_msg);  //创建订阅者

void setup(){           //初始化函数
  pinMode(13, OUTPUT);

  nh.initNode();
  nh.subscribe(servo_sender);
  nh.advertise(servo_publisher);
  servo[0].attach(11);
  servo[1].attach(10);
  servo[2].attach(9);
  servo[3].attach(5);
                     //servo.attach(9); //attach it to pin 9
}

void loop(){       
  for(i=0;i<4;i++){            //循环读取每个舵机的角度
    angle=servo[i].read();
    if(angle!=0){              //只要有角度数据就写入
      std_msg.data = "servo move to";
    }
  }
  servo_publisher.publish(&std_msg);
  nh.spinOnce();
  delay(100);
}

这边我要提一点小技巧,也不算是技巧只能算是格式吧。总结如下

1.ros::NodeHandle  nh; 初始化节点句柄在每个ros通讯中都要用到

2.#include 发布者为std_msgs斜杠后面的类型可以根据需要改比如Int8、Flout16......

3.void servo_message( const std_msgs::UInt16& cmd_msg)  里面的参数应该要与前面定义的消息对应也就是:std_msgs::UInt16 cmd_msg

4.ros::Subscriber sub("servo_sender", servo_message)括号里面的引号里的发布者名称一旦确定就不能更改,理论上可以随便取但最好有意义,servo_message为前面写的函数名。

5.ros::Publisher servo_publisher("servo_publisher",&std_msg);同理订阅者也一样

3.nh.initNode();  这句代码是固定不变的
  nh.subscribe(servo_sender);参数servo_sender为发布者名字
  nh.advertise(servo_publisher);参数servo_publisher为订阅者名字

效果呈现:

   ROS 通过节点控制Arduino实现舵机转动到相应角度(代码详解)_第1张图片

 


总结

     路漫漫其修远兮,吾将上下而求索

你可能感兴趣的:(ROS,arduino,arduino,linux,物联网)