使用 python GUI(tkinter) 和 ROS的消息传
2019-03-22 本文已影响100人
DIO哒
简单的例子:
- 用两个按钮控制气泵 开启,关闭
- 用一个滑块控制舵机旋转角度
接线部分:
![](https://img.haomeiwen.com/i8555575/94f3189a505c21e6.png)
![](https://img.haomeiwen.com/i8555575/02c42b713ca6477d.jpg)
Arduino部分的代码
#include <ros.h>
#include <std_msgs/String.h>
#include <std_msgs/UInt16.h>
#include <Servo.h>
ros::NodeHandle nh;
int PumpPin = 4;
Servo servo;
void pump_cb(const std_msgs::String& cmd_msg) {
if (strcmp(cmd_msg.data,"begin")==0) {
//如果接收到的String为begin,则开启气泵
digitalWrite(PumpPin, HIGH);
//如果接收到的String为stop,则关闭气泵
}
if (strcmp(cmd_msg.data,"stop")==0) {
digitalWrite(PumpPin, LOW);
}
}
void servo_cb(const std_msgs::UInt16& cmd_msg){
servo.write(cmd_msg.data);
}
ros::Subscriber<std_msgs::String> sub("pump", pump_cb);
//订阅pump这个topic,调用pump_cb这个回调函数
ros::Subscriber<std_msgs::UInt16> sub2("servo", servo_cb);
//订阅servo这个topic,调用servo_cb这个回调函数
void setup() {
// put your setup code here, to run once:
pinMode(PumpPin, OUTPUT);
servo.attach(8);
nh.initNode();
nh.subscribe(sub);
nh.subscribe(sub2);
}
void loop() {
nh.spinOnce();
delay(1);
}
将代码上传Arduino后,启动rosserial。
![](https://img.haomeiwen.com/i8555575/3ea7b8d932d5b5d9.png)
开启另一个终端,查看所有topic,里面已经有pump和servo这两个topic了。
![](https://img.haomeiwen.com/i8555575/6e91bcbb3a24e93c.png)
此时直接使用rostopic pub发布相应的message给这两个topic,就能操纵气泵开启关闭,以及控制舵机旋转角度了。
![](https://img.haomeiwen.com/i8555575/dd2373f0cb093512.png)
Python部分
tkinter是Python自带的GUI库,使用起来非常简单,在这一部分需要点下按钮向之前的那两个topic发送相应的信息。
import rospy
import tkinter as tk
from std_msgs.msg import String
from std_msgs.msg import UInt16
pub = rospy.Publisher('pump', String, queue_size=10)
servo_pub = rospy.Publisher('servo', UInt16, queue_size=10)
//创建两个publisher,分别往之前的那两个topic发送不同数据类型的消息
def start():
pub.publish("begin")
def stop():
pub.publish("stop")
def talker():
rospy.init_node('pump_controller', anonymous=True)
rate = rospy.Rate(10)
def servo_publisher(v):
servo_pub.publish(int(v))//因为传过来的v是char,所以publish之前要先转换成int
root = tk.Tk()//root窗口
btnPumpStart = tk.Button(root, text="pump start", command=start)
btnPumpStop = tk.Button(root, text="pump stop", command=stop)
btnPumpStart.pack()
btnPumpStop.pack()
servoScale = tk.Scale(root, label='servo', from_=0, to='180', orient=tk.HORIZONTAL, length=400, showvalue=1,
tickinterval=20, resolution=1, command=servo_publisher)
servoScale.pack()
if __name__ == '__main__':
try:
talker()
root.mainloop()
except rospy.ROSInterruptException:
pass
![](https://img.haomeiwen.com/i8555575/3c13331efd0ba3e4.png)
![](https://img.haomeiwen.com/i8555575/9319439df5ab18ad.png)
点击按钮可以控制气泵开启关闭(也就是控制那个继电器),滑动滑块可以控制舵机旋转角度,非常直观,也没什么延迟。