LoginSignup
10
9

More than 5 years have passed since last update.

Arduinoを使いROSでサーボモータを動かす

Last updated at Posted at 2018-03-22

はじめに

ROSには,rosserial_arduinoというArduinoとシリアル通信をするためのパッケージが用意されている.
これを用いArduinoとROSを接続,ROS経由でArduinoを使用し,キーボード操作でサーボモータを動かそうと試みる.

環境

OS Ubuntu14.04
ROS indigo
ArduinoIDE 1.8.5
Arduino Arduino UNO

インストール

まずはROSにrosserialのパッケージをインストール.

バージョンindigoの場合
$ sudo apt-get install ros-indigo-rosserial-arduino
$ sudo apt-get install ros-indigo-rosserial

ArduinoIDEをインストールしていない場合は,これもインストールする.
下記サイトにてダウンロードして解凍する.
https://www.arduino.cc/en/main/software

任意のディレクトリ上で解凍

$ sudo tar Jxfv arduino-1.8.5-linux64.tar.xz

インストールしたIDEにros_libを追加する.

$ cd arduino-1.8.5/libraries/
$ rosrun rosserial_arduino make_libraries.py ./

デバイスファイルに権限を付与する

PCとArduinoをUSBで接続すると,/dev/ttyACM*が生成される.
しかし,のままではArduinoにコードの書き込みができないので,書き込み権限をつける.

ttyACM0の場合
sudo chmod 0666 /dev/ttyACM0

ノードの構成

今回は以下のようなノードの構成になる.

servo_test.png

  • keyboard_driverノードにてキーボード入力を受け取り,/Keysトピックにキー入力を配信する.
  • keys_to_servoノードにて特定のキーの場合,サーボの設定角度を/servoトピックに配信する.
  • serial_nodeノードにてサーボの設定角度をシリアル通信でArduinoへ転送する.

回路

サーボを動かすだけなので回路構成は単純.TinkerCADを使用して簡単な図を示した.

servo_test.png

使用コード

ArduinoにはIDEを使用して以下のコードを書き込む.

servo_test.ino
#if defined(ARDUINO) && ARDUINO >= 100
    #include "Arduino.h"
#else
    #include <WProgram.h>
#endif

#include <Servo.h>
#include <ros.h>
#include <std_msgs/UInt16.h>

ros::NodeHandle nh;

Servo servo;

void servo_cb(const std_msgs::UInt16& cmd_msg){

    servo.write(cmd_msg.data);
    digitalWrite(13, HIGH-digitalRead(13));

}

ros::Subscriber<std_msgs::UInt16> sub("servo", servo_cb);

void setup(){

    pinMode(13, OUTPUT);

    nh.initNode();
    nh.subscribe(sub);

    servo.attach(9);

}

void loop(){

    nh.spinOnce();
    delay(1);

}

keyboard_driverノードとkeys_to_servoノードは以下のコードを使う.

keyboard_driver.py
#!/usr/bin/env python
import sys, select, tty, termios
import rospy
from std_msgs.msg import String

if __name__ == '__main__':

  #KeysトピックにString型のメッセージを毎秒一回送る
  key_pub = rospy.Publisher('keys', String, queue_size=1)
  #keyboard_driverノード作成
  rospy.init_node("keyboard_driver")
  rate = rospy.Rate(100)

  old_attr = termios.tcgetattr(sys.stdin)
  tty.setcbreak(sys.stdin.fileno())

  print "Publishing [z], [x] or [a]. Press Ctrl-C to exit..."

  while not rospy.is_shutdown():

    if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:
      key_pub.publish(sys.stdin.read(1))
    rate.sleep()

  termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)
keys_to_servo.py
#!/usr/bin/env python
import rospy
from std_msgs.msg import String
from std_msgs.msg import UInt16

key_mapping = { 'z': 0, 'x': 90, 'a': 180 }

def keys_cb(msg, twist_pub):

  if len(msg.data) == 0 or not key_mapping.has_key(msg.data):
    return # unknown key.

  vels = key_mapping[msg.data]

  t = UInt16()
  t = vels
  publisher.publish(t)

if __name__ == '__main__':
  #keys_to_servoノード作成
  rospy.init_node('keys_to_servo')
  #servoトピックにUInt16型のメッセージを送る
  publisher = rospy.Publisher('servo', UInt16, queue_size=1)
  rospy.Subscriber('keys', String, keys_cb, publisher)
  rospy.spin()

実行

roscore,rosrunを個別のターミナルで実行.

ttyACM0の場合
$ roscore
$ rosrun rosserial_python serial_node.py /dev/ttyACM0
$ rosrun keyboard_driver keyboard_driver.py
$ rosrun keys_to_servo keys_to_servo.py

参考記事

ROSのrosserialを使ってArduinoでLチカをする
https://qiita.com/nnn112358/items/059487952eb3f9a5489b

ROS.org Servo Controller Example
http://wiki.ros.org/rosserial_arduino/Tutorials/Servo%20Controller

10
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
9