Ich habe eine Matrix-LED (64 x 64) von Shigezone in Akihabara gekauft, aber ich habe beschlossen, sie auf ROS zu betreiben. In diesem Artikel erstellen wir einen "ROS-Knoten, der das Bildthema abonniert und das Bild auf der Matrix-LED anzeigt".
Dieses Mal werden wir Raspberry Pi 3 mit Ubuntu verwenden, um ROS zu handhaben. Flashen Sie das Image von hier auf die SD-Karte und installieren Sie ROS. Ich habe Ubuntu 18.04.3. Von arm64 installiert. ROS installierte ros-melodic-desktop unter Bezugnahme auf diese Site.
Um diese Software als Treiber für MatrixLED zu verwenden, haben wir eine entsprechende Treiberplatine vorbereitet. Das Board wurde von Electrodragon (https://www.electrodragon.com/product/rgb-matrix-panel-drive-board-raspberry-pi/) bezogen, aber Sie können es selbst vorbereiten. Die von Ihnen gekaufte Karte verfügt über einen eingebauten Pegelwandler von 3,3 V auf 5 V, sodass Sie einen stabilen Betrieb erwarten können. Da die verwendete Matrix-LED 64 x 64 groß ist und Adressleitungen von A nach E hat, muss die Treiberplattenseite an einer Stelle verlötet werden, um "E" anzuschließen. Für das Matrix-LED-Panel, das ich dieses Mal gekauft habe, habe ich einen Jumper gesetzt, um Pin8 mit E zu verbinden. Es ist notwendig, 5 V (ich denke, es sind mindestens 3 A) separat an das LED-Panel-Gehäuse zu liefern.
Um festzustellen, ob die Hardware ordnungsgemäß funktioniert, klonen Sie aus dem Repository und kompilieren Sie das Beispielprogramm.
rpi-rgb-led-matrix$ make -C examples-api-use
rpi-rgb-led-matrix$ sudo examples-api-use/demo -D0 --led-rows=64 --led-cols=64 --led-panel-type=FM6126A
Die bunten Würfel sollten sich drehen. Abhängig vom Typ des Matrix-LED-Panels kann FM6126A als Chip montiert werden. In diesem Fall muss eine Option angegeben werden, da das für die Initialisierung erforderliche Signal unterschiedlich ist.
Wenn dies funktioniert, installieren Sie die Bibliothek für Python gemäß den Prozeduren desselben Repositorys. Ich werde.
$ sudo apt-get update && sudo apt-get install python2.7-dev python-pillow -y
rpi-rgb-led-matrix/bindings/python$ make build-python
rpi-rgb-led-matrix/bindings/python$ sudo make install-python
An diesem Punkt können Sie "aus rgbmatrix RGBMatrix, RGBMatrixOptions importieren".
Die diesmal verwendete Matrix LED-Treibersoftware muss von sudo ausgeführt werden. Mit der Kombination von Ubuntu18.04 + Raspberry pi3 konnte ich nicht auf die Hardwareressourcen (GPIO usw.) zugreifen, die von allgemeinen Benutzern benötigt werden, und entschied mich daher, die ROS-Seite mit sudo auszuführen. (Ich denke, es sollte so eingestellt werden, dass allgemeine Benutzer auf die erforderlichen Hardwareressourcen zugreifen können.)
Im Allgemeinen funktioniert ROS nicht gut, da Umgebungsvariablen gelöscht werden, wenn sudo ausgeführt wird. Also habe ich beschlossen, die Einstellungen zur sudoers-Datei hinzuzufügen.
Defaults env_keep += "PATH PKG_CONFIG_PATH PYTHONPATH ROS_ROOT ROS_ETC_DIR ROS_MASTER_URI ROS_VERSION ROS_PYTHON_VERSION ROS_PACKAGE_PATH ROS_DISTRO CMAKE_PREFIX_PATH LD_LIBRARY_PATH"
Durch Hinzufügen dieser einen Zeile mit dem Befehl "sudo visudo" werden die für ROS erforderlichen Umgebungsvariablen bei der Ausführung von sudo vererbt. LD_LIBRARY_PATH wird jedoch nicht von den Spezifikationen geerbt.
Daher habe ich beschlossen, die erforderlichen Pfade in "/etc/ld.so.conf.d/ros.conf" zu verknüpfen. Im Fall von ROS Merodic sieht es so aus.
/home/user/catkin_ws/devel/lib
/opt/ros/melodic/lib
Führen Sie nach Abschluss der Einstellungen "sudo ld config" aus.
Legen Sie außerdem Berechtigungen fest, damit Daemon-Benutzer auf /home/user/.ros/log zugreifen können. Ohne dies wird es mit einem Berechtigungsfehler beendet, wenn ein ROS-Knoten ausgeführt wird. (Wenn Sie einen ROS-Knoten mit sudo ausführen, scheint die Protokolldatei als Daemon-Benutzer generiert zu werden.) An diesem Punkt können Sie meiner Meinung nach auch mit sudo auf ROS-Ressourcen zugreifen.
Erstellen Sie zunächst ein ROS-Paket.
~/catkin_ws/src$ catkin_create_pkg matrix_led_ros roscpp rospy std_msgs
~/catkin_ws$ catkin_make
Von hier aus implementieren wir das Skript unter dem erstellten Paket matrix_led_ros.
Um das als nächstes zu erstellende Programm zu testen, habe ich einen Knoten implementiert, der GIF liest und als Image-Thema veröffentlicht.
#!/usr/bin/env python
from __future__ import print_function
import roslib
import sys
import rospy
import cv2
from std_msgs.msg import String
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
import argparse
FILE_NAME = "test.gif"
REFRESH_RATE = 1
parser = argparse.ArgumentParser(
prog='gif-publisher.py',
usage='python gif-publisher --filename inputfilename',
description='publish Image message from gif file',
epilog='end',
add_help=True,
)
parser.add_argument('-f', '--filename', help='input file name',
required=True)
parser.add_argument('-r', '--rate', help='refresh rate',type=int)
args = parser.parse_args()
if args.filename:
FILE_NAME = args.filename
if args.rate:
REFRESH_RATE = args.rate
class image_publisher:
def __init__(self):
self.image_pub = rospy.Publisher("/imagetopic",Image)
self.bridge = CvBridge()
def readGif(self, filename, hz=1):
gif = cv2.VideoCapture(filename)
r = rospy.Rate(hz)
while not rospy.is_shutdown():
try:
stat, frame = gif.read()
if not stat:
gif = cv2.VideoCapture(filename)
else:
try:
self.image_pub.publish(self.bridge.cv2_to_imgmsg(frame, "bgr8"))
r.sleep()
except CvBridgeError as e:
print(e)
except KeyboardInterrupt:
break
def main(args):
ip = image_publisher()
rospy.init_node('gif_image_publisher', anonymous=True)
ip.readGif(FILE_NAME, REFRESH_RATE)
try:
rospy.spin()
except KeyboardInterrupt:
print("Shutting down")
if __name__ == '__main__':
main(sys.argv)
Verwenden Sie es wie "python gif-publisher.py -f test.gif -r 10". In diesem Beispiel wird test.gif mit 10 fps mit dem Namen / imagetopic veröffentlicht. Wenn nichts angegeben ist, wird der Frame mit explosiver Geschwindigkeit veröffentlicht, daher setze ich die Framerate mit "r = rospy.Rate (hz)" und "r.sleep ()". Im Fall von Raspberry Pi funktionierte es bis zu weniger als 30 fps.
Es ist endlich das Hauptthema. Ein Skript, das / imagetopic abonniert und auf dem Matrix-LED-Bedienfeld anzeigt.
#!/usr/bin/env python
from __future__ import print_function
import roslib
import sys, time
import rospy
import cv2
from std_msgs.msg import String
from sensor_msgs.msg import Image
from cv_bridge import CvBridge, CvBridgeError
from rgbmatrix import RGBMatrix, RGBMatrixOptions
from PIL import Image as pilI
BRIGHTNESS = 0.5
class image_viewer:
def __init__(self):
self.bridge = CvBridge()
self.image_sub = rospy.Subscriber("imagetopic",Image,self.callback)
# Configuration for the matrix
self.options = RGBMatrixOptions()
self.options.rows = 64
self.options.cols = 64
self.options.chain_length = 1
self.options.parallel = 1
self.options.hardware_mapping = 'regular'
self.matrix = RGBMatrix(options = self.options)
self.max_brightness = self.matrix.brightness
self.matrix.brightness = self.max_brightness * BRIGHTNESS
self.double_buffer = self.matrix.CreateFrameCanvas()
def toSquare(self, img):
w, h =img.size
if w == h:
return img
elif w > h:
result = pilI.new(img.mode, (w, w), (0,0,0))
result.paste(img, (0, (w - h) // 2))
return result
else:
result = pilI.new(img.mode, (h, h), (0,0,0))
result.paste(img, ((h - w) // 2, 0))
return result
def callback(self,data):
try:
cv_image = self.bridge.imgmsg_to_cv2(data, "bgr8")
except CvBridgeError as e:
print(e)
pilImage = cv2.cvtColor(cv_image, cv2.COLOR_BGR2RGB)
pilImage = pilI.fromarray(pilImage)
pilImage.thumbnail((self.matrix.width, self.matrix.height), pilI.ANTIALIAS)
offset = (int)(self.matrix.height - pilImage.height)/2
self.double_buffer.SetImage(self.toSquare(pilImage), 0)
self.double_buffer = self.matrix.SwapOnVSync(self.double_buffer)
def main(args):
iv = image_viewer()
rospy.init_node('image_viewer')
try:
rospy.spin()
except KeyboardInterrupt:
print("Shutting down")
if __name__ == '__main__':
main(sys.argv)
Starten Sie es wie "sudo python image-viewer-ros.py". Dieses Skript funktioniert nur dann gut, wenn Sie über Root-Rechte verfügen. Sie können es jedoch mit ROS in sudo verwenden, indem Sie den Inhalt unter "So verwenden Sie ROS mit sudo" verwenden. Es sieht so aus, wenn es sich bewegt. Ich habe [diese GIF-Animation] ausgeliehen (https://gifmagazine.net/post_images/3976039).
Im Teil "self.matrix = RGBMatrix (options = self.options)" können Sie die Optionen angeben, die an die Matrix-LED übergeben werden sollen. Bei Bildern größer als 64 x 64 wurden die langen Seiten auf 64 Pixel reduziert und die Ränder mit Schwarz gefüllt.
Was haben Sie gedacht. In dieser Implementierung gibt es einen Teil, in dem das Flimmern etwas besorgniserregend ist, sodass Raum für Verbesserungen zu bestehen scheint. Wenn ich eine Chance habe, werde ich auch die in C ++ implementierte auflisten. Darüber hinaus kann die diesmal verwendete Treiberplatine 3 Kanäle gleichzeitig verwenden. Als Matrix-LED kann sie durch Verbinden von Perlen erweitert werden. Wenn Sie also mehrere LED-Panels erhalten, möchte ich eine höhere Auflösung ausprobieren.
Recommended Posts