ROS學習總結2-實時監聽鍵盤輸入(python)

在使用ROS開發移動機器人時,發現teleop_twist_keyboard這個包很好用,可以通過監聽鍵盤輸入來控制機器人的移動,具有很好的實時性。這個包用一個程序實現了'監聽鍵盤輸入'和'鍵盤輸入轉twist消息'兩個部分的內容,實際使用中,可能第一部分的使用需求更大一些,因此根據github上的源碼提取了其中'監聽鍵盤輸入'的部分。

#!/usr/bin/env python
import rospy
import sys, select, tty, termios
from std_msgs.msg import String
if __name__ == '__main__':
	rospy.init_node('keyboard')
	pub = rospy.Publisher('keys',String,queue_size = 1)
	rate = rospy.Rate(100)     #設置發佈頻率
	old_attr = termios.tcgetattr(sys.stdin)     #備份終端屬性
	tty.setcbreak(sys.stdin.fileno())     #設置屬性
	print('Please input keys, press Ctrl + C to quit')
	while not rospy.is_shutdown():
		if select.select([sys.stdin], [], [], 0)[0] == [sys.stdin]:     #設置超時參數爲0,防止阻塞
			pub.publish(sys.stdin.read(1))
		rate.sleep()     #使用sleep()函數消耗剩餘時間
	termios.tcsetattr(sys.stdin, termios.TCSADRAIN, old_attr)     #設置爲原先的標準模式

這個程序用了一些沒有學過的東西,本着探索學習的精神,下面對其中的一些模塊進行分析。

termios模塊中的函數採用文件描述符fd作爲它們的第一個傳入參數,可能是一個整數文件描述符,如sys.stdin.fileno(),或者是一個文件對象,如sys.stdin。這裏我們主要用到兩個函數:termios.tcgetattr()和termios.tcsetattr()。

termios.tcgetattr(fd)返回文件描述符的tty屬性的列表。

termios.tcsetattr(fd,when,attributes)根據傳入的attributes參數設置文件描述符的tty屬性,attributes參數可以由tcgetattr()函數得到返回值,根據傳入的when參數設置tty屬性的生效時間:TCSANOW(立即生效),TCSADRAIN(傳輸完所有排隊的輸出後生效),TCSAFLUSH(傳輸完所有排隊的輸出並丟棄所有排隊的輸入)。

Set the tty attributes for file descriptor fd from the attributes, which is a list like the one returned by tcgetattr(). The when argument determines when the attributes are changed: TCSANOW to change immediately, TCSADRAIN to change after transmitting all queued output, or TCSAFLUSH to change after transmitting all queued output and discarding all queued input.

tty模塊調用了tty.setcbreak(fd[,when])函數,這個函數將文件描述符的模式從fd變更爲cbreak,when參數的缺省值爲termios.TCSAFLUSH並傳遞給termios.tcsetattr()函數。調用cbreak函數後,除了"Del"和"Ctrl"鍵外,接受其他所有字符輸入。

select.select(rlist,wlist,xlist[,timeout])函數的官方解釋可以參考這個鏈接,使用可以參考這篇文章,這裏我們不希望程序阻塞在標準輸入上,因此設置超時參數爲0,即進行無休止的輪詢。在輪詢的過程中,函數的返回值是rlist,wlist和xlist的子集,如果達到超時參數且沒有可讀的內容,將會返回三個空列表,此時if的條件不滿足,將跳過if成立時執行的內容,進行下一次的輪詢。如果存在可讀的內容,則if條件滿足,執行sys.stdin.read()函數。

採用rospy.Rate.sleep()消耗剩餘的時間,防止程序佔用過多的內存。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章