В ROS есть готовое приложение для Android, которое позволяет использовать акселерометр вашего телефона в своих проектах - это Android Sensor Driver:
Чтобы сделать такое же управление, устанавливаем
- Запускаем в отдельном терминале roscore:
$ roscore
- Я прописал себе на компьютере статический IP адрес 192.168.0.10, чтобы каждый раз при пере подключениях компьютера не менять настройки в Android Sensor Driver. Запускаем его у себя на телефоне и указываем http://192.168.0.10:11311/ и нажимаем Ok.
- Проверим подключение - есть ли в списке нод /android_sensors_driver_imu:
$ rosnode list
Если не появилось, ищем где ошиблись.
-
# Проверяем соединение: $ rosnode ping android_sensors_driver_imu # Если пинг не идет, перезапустите приложение. (Мне потребовалось после смены IP) # Смотрим публикуемые топики, нужный нам /android/imu $ rostopic list # Кстати, топик /android/fix позволит нам общаться с GPS, но это нам пока не надо. # Можно посмотреть публикуемые сообщения $ rostopic echo /android/imu
В том же проекте katusha напишем Phyton-прослойку для приема сообщений от топика акселератора, преобразования их в команды перемещения и передачи нашему роботу katusha_accelerometr.py:
1 #!/usr/bin/env python 2 #coding=utf8 3 4 # Author: Stepan 5 # Howto use: http://robotlife.ru/upravlenie-akselerometrom/ 6 7 from turtlesim.msg import Velocity 8 from sensor_msgs.msg import Imu 9 from time import sleep 10 import serial 11 import rospy 12 13 # Data from accelerometers 14 acc_x = acc_y = acc_z = 0 15 16 def dec2hex(n): 17 """return the hexademical string in XXXX format""" 18 return ("%0.4X" % (n>=0 and n or n+256**2))[-4:] 19 # the mystery here n>=0 actually goes to n+256*2 and returns 10000 in hex. but it's cuted to 0000 by [-4:0] 20 21 def move(speed=255): 22 """move foreward, or backward if speed<0""" 23 ser.write('G'+dec2hex(speed)) 24 25 def rotate(speed=255): 26 """rotate clockwise if speed<0, or anti-clockwise if speed>0""" 27 ser.write('R'+dec2hex(speed)+'L'+dec2hex(-speed)) 28 29 def moveR(speed=255): 30 """Move right weels only. Forward if speed>0, backwards if speed<0""" 31 ser.write('R'+dec2hex(speed)) 32 33 def moveL(speed=255): 34 """Move left weels only. Forward if speed>0, backwards if speed<0""" 35 ser.write('L'+dec2hex(speed)) 36 37 def imucallback(msg): 38 """callback for 'android/imu' messages from turtlesim. Updateing current positoin of accelerometr""" 39 global acc_x, acc_y, acc_z 40 # rospy.loginfo(rospy.get_name() + ": I heard %s and %s and %s" % (msg.linear_acceleration.x, msg.linear_acceleration.y, msg.linear_acceleration.z)) 41 acc_x = msg.linear_acceleration.x 42 acc_y = -msg.linear_acceleration.y 43 acc_z = msg.linear_acceleration.z 44 45 def listener(): 46 """Main loop""" 47 rospy.init_node('katusha', anonymous=True) 48 rospy.Subscriber('android/imu', Imu, imucallback) 49 50 while not rospy.is_shutdown(): 51 # This way we prevent from sending values to motors which will not move the robot, but only make noise from motors. Also prevent acidental moving when phone in horiosntal position. 52 if (abs(acc_y+acc_x)>2) or (abs(acc_y-acc_x)>2): 53 moveR((acc_y+acc_x)*255/10) 54 moveL((acc_y-acc_x)*255/10) 55 else: 56 move(0) 57 print 'Y:%s' % acc_y 58 print 'X:%s' % acc_x 59 # read and print data from serial port (bluetooth) 60 data = ser.read(9999) 61 if len(data)>0: 62 print data 63 # Move with 64 # rospy.sleep(0.1) 65 66 if __name__ == '__main__': 67 # connect to bluetooth. Make sure you have connected robot with 68 # rfcomm connect 0 00:13:02:01:70:17 1 69 ser = serial.Serial('/dev/rfcomm0', 9600, timeout=0) 70 listener() 71 # stop motors before exit 72 move(0)
Запускаем каждую программу в новом терминале:
- $ roscore # Ядро ROS
- $ Приложение Android Sensor Driver на телефоне, указываем адрес ROSCore и подключаемся
- $ rfcomm connect 0 00:13:02:01:70:17 1 # Включаем bluetooth соединение с роботом - здесь 00:13:02:01:70:17 - MAC адрес bluetooth робота.
- $ rosrun katusha katusha_accelerometr.py # Наш модуль