Spezifische Anwendung des ROS Service Service-Kommunikationsmechanismus in unbemannten Fahrzeugen

1. Einleitung

Im Kommunikationsmechanismus haben wir diesen Service- Dienst bereits eingeführt: Die Anwendung des Dienstes (Service) des ROS-Kommunikationsmechanismus
ist in einigen Szenarien, in denen die Kommunikationsverarbeitung relativ einfach ist, im Allgemeinen besser geeignet. Hier werden wir tatsächlich einige sehr häufige verwenden Das unbemannte Fahrzeug. Dienstleistungen: Veröffentlichen Sie Spannungsdaten, schalten Sie LED-Leuchten ein und aus, schalten Sie Summer ein und aus und steuern Sie die Geschwindigkeit des linken und rechten Motors.

Server: Der Knoten, der Dienste bereitstellt, definiert eine Rückruffunktion zur Verarbeitung von Anforderungen.
Client: Der Knoten, der Anforderungen bearbeitet, ruft den Dienst über einen lokalen Proxy auf.

Der Erstellungsprozess von Arbeitsbereichen und Paketen wurde ignoriert. Interessierte können sich Folgendes ansehen: ROS-Kompilierungspraxis für neue Arbeitsbereiche (Arbeitsbereich) und Pakete (Pakete) (C++-Beispiel)

2. Anwendungen für autonome Fahrzeuge

2.1. Verzeichnis

Lassen Sie uns zunächst verstehen, was Nachrichten, Dienste und Knotendateien sind:

cd ~/workspace/catkin_ws/src
ls jetbotmini_msgs/msg
ls jetbotmini_msgs/srv
ls jetbot_ros/scripts

Screenshot unten:

2.2. Starten Sie den Knoten

Dann öffnen wir direkt ROSMASTER , starten den Knoten des unbemannten Fahrzeugs und veröffentlichen dann den Hauptcode, um ein klareres Verständnis des Servicekommunikationsmechanismus des unbemannten Fahrzeugs zu erhalten.

roscore
rosrun jetbot_ros jetbotmini_driver.py

Okay, jetzt können wir mit dem autonomen Fahrzeug kommunizieren

2.3. Themen anzeigen

Werfen wir zunächst einen Blick auf die Themen: Rostopische Liste

/rosout
/rosout_agg
/spannung

Wie Sie hier sehen können, gibt es ein  Thema Spannung 


2.4. Dienste anzeigen

Konzentrieren wir uns als Nächstes auf die Liste der bereitgestellten Dienste: Rosservice-Liste

/Buzzer
/LEDBLUE
/LEDGREE
/Motor
/Servo
/driver_node/get_loggers
/driver_node/set_logger_level
/rosout/get_loggers
/rosout/set_logger_level 

Die Dienstliste umfasst Dienste wie Summer, LED-Leuchten, Motoren und Lenkgetriebe. Als Nächstes bedienen wir diese Dienste über die Befehlszeile, um mit dem autonomen Fahrzeug zu kommunizieren.
Die Definition von Service ist sehr einfach, schauen wir uns das genauer an

2.5. Summer

Geben Sie den Befehl ein: rossrv show Buzzer

Der Eingabetyp und der Ausgabetyp werden durch drei kleine horizontale Linien getrennt --- 

[jetbotmini_msgs/Buzzer]:
int32 Buzzer
---
Bool-Ergebnis

Schalten Sie den Summer ein: rosservice call /Buzzer „buzzer: 1“
Ergebnis: True #Dies ist der Rückgabewert
. Schalten Sie den Summer aus: rosservice call /Buzzer „buzzer: 0“
Ergebnis: True 

2.6. Lenkgetriebe

Geben Sie den Befehl ein: rossrv show Servo 

[jetbotmini_msgs/Servo]:
int32 servoid
int32 angle
---
boolisches Ergebnis

Mein unbemanntes Fahrzeug verfügt über zwei Servoschnittstellen S1 und S2, wie unten gezeigt:

Servo 1 Winkel 90: Rosservice-Aufruf /Servo 1 90
Ergebnis: True
Servo 2 Winkel 90: Rosservice-Aufruf /Servo 2 90
Ergebnis: True 

Überprüfen Sie die Servoparameter: rosservice args Servo-
Servoidwinkel

Servo 1 dreht sich um 30 Grad: Rosservice-Aufruf /Servo 1 30

Wenn mehrere Parameter vorhanden sind, können Sie natürlich auch die Schreibmethode für Parameternamen angeben und zum Ausführen die Wörterbuchform verwenden, was intuitiver ist:
Rosservice-Aufruf /Servo "{'servoid': 1, 'angle': 30}" 

2.7. LED-Leuchten

Schalten Sie das blaue LEB-Licht ein: rosservice call /LEDBLUE 1
Ergebnis: True
, wie unten gezeigt:

Schalten Sie das grüne LED-Licht ein: Rosservice-Aufruf /LEDGREE 1
Ergebnis: True
, wie unten gezeigt: 

Gemeinsam leuchten: 

2.8. Motor (Motor) 

Sehen Sie sich die Datentypstruktur von Motor an : rossrv show Motor

[jetbotmini_msgs/Motor]:
float32 rightspeed
float32 leftspeed
---
boolisches Ergebnis 

Sehen Sie sich die Parameter des Motormotors an : rosservice args Motor

Rechtsgeschwindigkeit, Linksgeschwindigkeit

[rightspeed]: [-1, 1], die rechte Motorgeschwindigkeit, kleiner als 0 für Rückwärtsdrehung und größer als 0 für Vorwärtsdrehung.
[leftspeed]: [-1, 1], linke Motorgeschwindigkeit, kleiner als 0 für Rückwärtsdrehung und größer als 0 für Vorwärtsdrehung.

Linker Motor (Motorrad) 50 % Geschwindigkeit, rechter Motor 80 % Geschwindigkeit: Rosservice-Anruf /Motor 0,5 0,8 

Sehen Sie, welche Themen verfügbar sind: Rostopische Liste 

/rosout
/rosout_agg
/spannung 

Themenmeldungen visuell anzeigen: rosrun rqt_topic rqt_topic
ist wie unten dargestellt. Klicken Sie auf das Kontrollkästchen des Spannungsthemas , um Folgendes zu überprüfen: 

Auf diese Weise können Sie intuitiv erkennen, dass die Spannung 10,67 V und die Frequenz 0,03 Hz beträgt (aktualisiert alle 30 Sekunden). 

3、jetbotmini_driver.py

Konzentrieren wir uns auf den Code dieses Knotens, der die verschiedenen oben definierten Dienste enthält, also importieren wir die Nachrichten und Dienste:

from jetbotmini_msgs.msg import *
from jetbotmini_msgs.srv import *

jetbotmini_msgs.msg und jetbotmini_msgs.srv werden automatisch generiert. Die Definition von Nachrichten wurde ebenfalls früher vorgestellt. Wenn Sie interessiert sind, können Sie Folgendes überprüfen: Die Veröffentlichung und das Abonnement von Themen (Topics) des ROS-Kommunikationsmechanismus und die Implementierung benutzerdefinierter Nachrichten
werden durchgeführt Basierend auf Ihrem Python Die Version wird am entsprechenden Speicherort generiert. Ich befinde mich beispielsweise im folgenden Verzeichnis
~/workspace/catkin_ws/devel/lib/python2.7/dist-packages/jetbotmini_msgs,
in dem msg und srv generiert werden Ordner.
Screenshot unten:


Gehen Sie dann zurück zur Datei jetbotmini_driver.py . Der Quellcode lautet wie folgt: 

#!/usr/bin/env python3
# encoding: utf-8
import rospy
import random
import threading
from time import sleep
from jetbotmini_msgs.msg import *
from jetbotmini_msgs.srv import *
import RPi.GPIO as GPIO # Raspberry Pi 的GPIO库
import smbus

bus = smbus.SMBus(1) # 使用编号为1的总线,用于I2C通信
ADDRESS = 0x1B
Led_G_pin = 24 # 引脚编号
Led_B_pin = 23
Key1_pin = 8
GPIO.setmode(GPIO.BCM) # BCM模式是指使用Broadcom SOC通道编号的方式
GPIO.setup(Led_G_pin, GPIO.OUT, initial=GPIO.HIGH) # 引脚设置为输出模式,初始化为高电平
GPIO.setup(Led_B_pin, GPIO.OUT, initial=GPIO.HIGH)
GPIO.setup(Key1_pin, GPIO.IN) #输入模式,可以读取引脚的状态

print("Starting now!")

class transbot_driver:
    def __init__(self):
        rospy.on_shutdown(self.cancel)
        self.srv_Buzzer = rospy.Service("/Buzzer", Buzzer, self.Buzzercallback)
        self.srv_Servo = rospy.Service("/Servo", Servo, self.Servocallback)
        self.srv_LEDBLUE = rospy.Service("/LEDBLUE", LEDBLUE, self.LEDBLUEcallback)
        self.srv_LEDGREE = rospy.Service("/LEDGREE", LEDGREE, self.LEDGREEcallback)
        self.srv_Motor = rospy.Service("/Motor", Motor, self.Motorcallback)
        self.volPublisher = rospy.Publisher("/voltage", Battery, queue_size=10)

    def cancel(self):
        self.srv_Buzzer.shutdown()
        self.srv_Servo.shutdown()
        self.srv_LEDBLUE.shutdown()
        self.srv_LEDGREE.shutdown()
        self.srv_Motor.shutdown()
        self.volPublisher.unregister()
        GPIO.cleanup()
        rospy.loginfo("Close the robot...")
        rospy.sleep(1)

    def pub_data(self):
        # 发布电池电压
        while not rospy.is_shutdown():
            sleep(30)
            AD_value = bus.read_i2c_block_data(ADDRESS,0x00,2)
            voltage = ((AD_value[0] << 8) + AD_value[1]) * 13.3 / 1023.0
            battery = Battery()
            battery.Voltage = voltage
            self.volPublisher.publish(battery)

    def Buzzercallback(self, request):
        #蜂鸣器控制,服务器回调函数
        if not isinstance(request, BuzzerRequest): return
        bus.write_byte_data(ADDRESS,0x06,request.buzzer)
        sleep(0.01)
        bus.write_byte_data(ADDRESS,0x06,request.buzzer)
        response = BuzzerResponse()
        response.result = True
        return response

    def Servocallback(self, request):
        # 控制舵机
        if not isinstance(request, ServoRequest): return
        bus.write_i2c_block_data(ADDRESS,3,[request.servoid,request.angle])
        sleep(0.01)
        bus.write_i2c_block_data(ADDRESS,3,[request.servoid,request.angle])
        response = ServoResponse()
        response.result = True
        return response

    def LEDBLUEcallback(self, request):
        # 控制蓝色LED
        if not isinstance(request, LEDBLUERequest): return
        if request.ledblue == 1:
            GPIO.output(Led_B_pin, GPIO.LOW)
        elif request.ledblue == 0:
            GPIO.output(Led_B_pin, GPIO.HIGH)
        response = LEDBLUEResponse()
        response.result = True
        return response

    def LEDGREEcallback(self, request):
        # 控制绿色LED
        if not isinstance(request, LEDGREERequest): return
        if request.ledgree == 1:
            GPIO.output(Led_G_pin, GPIO.LOW)
        elif request.ledgree == 0:
            GPIO.output(Led_G_pin, GPIO.HIGH)
        response = LEDGREEResponse()
        response.result = True
        return response

    def Motorcallback(self, request):
        # 控制马达,速度小于0就反方向
        if not isinstance(request, MotorRequest): return
        if request.leftspeed < 0:
            request.leftspeed = -request.leftspeed
            leftdir = 0
        else:
            leftdir = 1
        if request.rightspeed < 0:
            request.rightspeed = -request.rightspeed
            rightdir = 0
        else:
            rightdir = 1
        bus.write_i2c_block_data(ADDRESS,0x01,[leftdir,int(request.leftspeed*255),rightdir,int(request.rightspeed*255)])
        sleep(0.01)
        bus.write_i2c_block_data(ADDRESS,0x01,[leftdir,int(request.leftspeed*255),rightdir,int(request.rightspeed*255)])
        response = MotorResponse()
        response.result = True
        return response

if __name__ == '__main__':
    rospy.init_node("driver_node", anonymous=False)
    try:
        driver = transbot_driver()
        driver.pub_data()
        rospy.spin()
    except:
        rospy.loginfo("Final!!!")

Initialisieren Sie zunächst einige verwandte Vorgänge, stellen Sie den GPIO auf den BCM- Modus ein und initialisieren Sie ihn dann entsprechend der Pin-Nummer auf einen hohen Pegel . Der Modus ist Ausgabemodus , sodass Sie das LED-Licht entsprechend dem hohen und niedrigen Pegel steuern können. Wenn Sie Wenn Sie die Helligkeit steuern möchten, müssen Sie das Pulsweitenmodulationsverfahren „PWM“ . Es ist zu beachten, dass GPIO.cleanup() in der Abbruchfunktion die Pins in ihren ursprünglichen Zustand zurückversetzt und alle Pins freigibt, sodass sie keinen Ausgang mehr haben, wodurch elektrische Schäden und Brände vermieden werden. Der Rest sind einige Rückruffunktionen, hauptsächlich einige Schreib- und Beurteilungsvorgänge. Über diese Rückruffunktionen können die entsprechenden Komponenten bedient werden.

In diesem Abschnitt geht es hauptsächlich um die praktische Bedienung des Dienstes , die Konsolidierung seiner Verwendung als einer der Kommunikationsmechanismen und seine spezifische Anwendung in der Praxis.
Der Code enthält einige Wissenspunkte zur allgemeinen Ein- und Ausgabe von GPIO. Wenn Sie interessiert sind, können Sie Folgendes überprüfen:
Physikalisches Diagramm und Funktionseinführung der RPi.GPIO-Schnittstelle des JetsonNano-Boards

Supongo que te gusta

Origin blog.csdn.net/weixin_41896770/article/details/134264461
Recomendado
Clasificación