在驾驶过程中,车辆定位的准确程度直接影响决策系统输出结果。在真实驾驶环境中,我们一般使用 GPS 与地图进行车辆定位,但是在模型车辆加载高精度 GPS 会造成车重增加以及耗能增加的问题。因此,我们采用二维码,将车辆位置信息写入二维码(QR code)中,并结合摄像头的车道线识别识别算法进行车辆定位,并指导车辆在双车道上进行变道操作。
二维码在日常生活中非常常见,它是一种特殊类型的条形码,可以将数字与文本信息进行二进制编码与解码,无需考虑方向,角度与透视畸变,并通过冗余纠错进行信息校验保证非常高的准确性。如果我们把位置信息与操作指令编写到二维码中,车辆在对应位置可以毫秒级读取对应信息,并进行对应操作。
例如,在 DeepRacer offroad sample project 中,我们看到如下代码范例:
import qrcode
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_H,
box_size=200,
border=1,
)
qr.add_data('DR: {"wp": 1, "p": "l"}')
img = qr.make_image(fill_color="black", back_color="white")
img.save("deepracer_offroad_qr_images/left_wp1.png")
在这段代码中,我们把'DR: {"wp": 1, "p": "l"}'
写入二维码中,表示含义为:这个二维码所在位置是第一个 waypoint, 二维码 position 是 left,这两个值都是位置信息,因此可以实现不借助视觉识别,仅计算到二维码的相对位置就可以限定小车的运行方向(https://github.com/aws-deepracer/aws-deepracer-offroad-sample-project/blob/main/getting-started.md)。如果这时我们再加入一个字段:"action": "left"
,定义为在看到二维码后车辆应该延着左侧车道行驶,我们就可以控制车辆接下来的变道动作。如果再加一个字段:"RGB": (10000000, 0, 0)
“RGB”: (10,就可以控制尾灯的颜色为红。
在本次比赛中,我们预期车辆识别二维码后行驶路线是这样:
那么我们就需要在 0 和 1 号二维码处标识 action 为左侧道路,2 和 3 号二维码处标识 action 为右侧道路,这种组合车辆在每一处二维码都需要进行变道。
Topic 初始化:
def Pub_init(self):
self.pub = self.create_publisher(
ServoCtrlMsg,
'/ctrl_pkg/servo_msg', #对应topic
3
)
self.cli = self.create_client(SetLedCtrlSrv, 'servo_pkg/set_led_state')
while not self.cli.wait_for_service():
print('service not available, waiting again...')
self.req = SetLedCtrlSrv.Request()
识别 QR code:
def QR_detect_thread(self, img):
self.QR_DETECTING = True
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
result = self.QR_detector.detect(gray)
if len(result) == 0:
pass
else:
self.qrcode = result[0].tag_id
self.req.red = int(self.LED_status[self.qrcode, 0])
self.req.green = int(self.LED_status[self.qrcode, 1])
self.req.blue = int(self.LED_status[self.qrcode, 2])
self.cli.call_async(self.req)
self.QR_DETECTING = False
对应控制逻辑:
M = cv2.moments(img_erode)
if M['m00'] > 0: #识别到二维码
cx = int(M['m10']/M['m00']) #二维码中心x坐标
if self.qrcode == -1:
self.err = -cx+self.IMG_WIDTH/2 - 15 #计算x偏差
elif ...
self.ang = 0.026*self.err + \
0.02 * (self.err-self.last_err)
self.ang = np.clip(self.ang, -0.9, 0.9)
self.speed = 0.45-abs(self.ang)*0.06
self.speed = np.clip(self.speed, 0.385, 0.41) #计算速度+角度
if self.qrcode == -1:
self.speed = 0.39
elif ...
else: #没有识别二维码
if self.qrcode == -1:
self.speed = 0.35
self.ang = 0.9
elif ...
self.control.throttle = self.speed
self.control.angle = self.ang + 0.25 #下发control message矫正
if not self.QR_DETECTING and self.sample % 2 == 0:
threading_QR_LED = Thread(
target=self.QR_detect_thread, args=(img_ori[:, 100:, :],))
threading_QR_LED.start() #LED尾灯控制
else:
self.control.throttle = 0.0
self.control.angle = 0.0
self.pub.publish(self.control) #下发message
此外,在实际指令下发中,需要考虑处理器延迟以及环境噪声,进行实际场景中的调试。在下一篇 blog 中,我们将会讨论基于- Intel Neural Compute Stick 2 与 openvino 的对象识别算法加速场景与实现流程。
本篇作者