b2b2c電商平臺開發(fā)長沙seo外包平臺
有了前面顏色識別跟蹤的基礎(chǔ)之后,我們就可以設(shè)定顏色路徑,讓無人車沿著指定線路做自動駕駛了,視頻:PID控制無人車自動駕駛
有了前幾章的知識鋪墊,就比較簡單了,也是屬于顏色識別的一種應(yīng)用,主要是掌握自動駕駛中的一些基礎(chǔ)知識,這樣就可以進一步去了解在無人駕駛當中遇到的各種問題
1、導(dǎo)入庫并初始化
from jetbotmini import Camera
from jetbotmini import bgr8_to_jpeg
from IPython.display import display
from jetbotmini import Robot
import numpy as np
import torch
import torchvision
import cv2
import traitlets
import ipywidgets.widgets as widgets
import numpy as np#初始化攝像頭
camera = Camera.instance(width=300, height=300)
#初始化機器人馬達
robot = Robot()#使用PID控制
import PIDturn_gain = 1.7
turn_gain_pid = PID.PositionalPID(0.15, 0, 0.05)
這部分很簡單,依然是初始化攝像頭用來顏色識別,機器人也叫馬達,用來驅(qū)動輪子的運動,加一個PID控制,讓無人車更加的平穩(wěn)。
2、顯示部件
# 紅色數(shù)組
color_lower=np.array([156,43,46])
color_upper = np.array([180, 255, 255])image_widget = widgets.Image(format='jpeg', width=300, height=300)
speed_widget = widgets.FloatSlider(value=0.4, min=0.0, max=1.0, description='speed')display(widgets.VBox([widgets.HBox([image_widget]),speed_widget,
]))width = int(image_widget.width)
height = int(image_widget.height)def execute(change):global turn_gaintarget_value_speed = 0#更新圖片值frame = camera.valueframe = cv2.resize(frame, (300, 300))frame = cv2.GaussianBlur(frame,(5,5),0) hsv =cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)mask=cv2.inRange(hsv,color_lower,color_upper) mask=cv2.erode(mask,None,iterations=2)mask=cv2.dilate(mask,None,iterations=2)mask=cv2.GaussianBlur(mask,(3,3),0) cnts=cv2.findContours(mask.copy(),cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)[-2] # 檢測到目標if len(cnts)>0:cnt = max (cnts,key=cv2.contourArea)(color_x,color_y),color_radius=cv2.minEnclosingCircle(cnt)if color_radius > 10:# 將檢測到的顏色標記出來cv2.circle(frame,(int(color_x),int(color_y)),int(color_radius),(255,0,255),2) # 中心偏移量center = (150 - color_x)/150#轉(zhuǎn)向增益PID調(diào)節(jié)turn_gain_pid.SystemOutput = centerturn_gain_pid.SetStepSignal(0)turn_gain_pid.SetInertiaTime(0.2, 0.1)#將轉(zhuǎn)向增益限制在有效范圍內(nèi)target_value_turn_gain = 0.15 + abs(turn_gain_pid.SystemOutput)if target_value_turn_gain < 0:target_value_turn_gain = 0elif target_value_turn_gain > 2:target_value_turn_gain = 2#將輸出電機速度保持在有效行駛范圍內(nèi)target_value_speedl = speed_widget.value - target_value_turn_gain * centertarget_value_speedr = speed_widget.value + target_value_turn_gain * centerif target_value_speedl<0.3:target_value_speedl=0elif target_value_speedl>1:target_value_speedl = 1if target_value_speedr<0.3:target_value_speedr=0elif target_value_speedr>1:target_value_speedr = 1#設(shè)置馬達速度robot.set_motors(target_value_speedl, target_value_speedr)# 沒有檢測到目標else:robot.stop()# 更新圖像顯示至小部件image_widget.value = bgr8_to_jpeg(frame)
這里是關(guān)鍵部分,檢測目標(這里是紅顏色),然后通過其檢測的位置來控制左右馬達的速度,驅(qū)動無人車的行駛與轉(zhuǎn)彎,后臺通過圖像部件來顯示無人車的跟蹤情況,方便看到無人車在整個行駛過程中的各種狀態(tài)。
3、調(diào)用并執(zhí)行
execute({'new': camera.value})
camera.unobserve_all()
camera.observe(execute, names='value')
這里就是前面介紹的,通過調(diào)用observer方法來更新攝像頭的數(shù)據(jù),使用的是一個上面定義的execute的一個回調(diào)方法。
4、停止無人車
import time
camera.unobserve_all()
time.sleep(1.0)
robot.stop()
5、倒車
前面介紹的是向前行駛和轉(zhuǎn)彎,還缺少一個能倒車的功能,恩,很簡單,調(diào)用backward函數(shù)即可
robot.backward(0.8)
time.sleep(0.5)
robot.stop()
6、調(diào)節(jié)顏色數(shù)組
我這里是用紅色的膠帶粘貼在地板上,所以使用的是紅色的數(shù)組,當然這里我們可以顯示mask來測試顏色數(shù)組是否設(shè)置的比較恰當,代碼如下
from matplotlib import pyplot as plt
%matplotlib inline
from IPython import displayfor i in range(10):frame = camera.valueframe = cv2.resize(frame, (300, 300))frame_=cv2.GaussianBlur(frame,(5,5),0) hsv=cv2.cvtColor(frame,cv2.COLOR_BGR2HSV)mask=cv2.inRange(hsv,color_lower,color_upper) # 顏色數(shù)組的取值范圍mask=cv2.erode(mask,None,iterations=2)mask=cv2.dilate(mask,None,iterations=2)mask=cv2.GaussianBlur(mask,(3,3),0) plt.imshow(mask)plt.show()#display.clear_output(wait=True)
這里我將display.clear_output(wait=True)注釋,將會連續(xù)生成10張圖片,全部在Jupyter中展示出來。我們也可以去掉注釋,這樣每次的生成將會清除上一次的圖片,這樣便于更好地觀察。10張連續(xù)圖片也做成了動圖便于大家了解:
?如果這里沒有出現(xiàn)mask或者比較少的情況,就需要調(diào)節(jié)顏色數(shù)組,讓其更好地匹配線路。
7、模擬方向盤
有些時候不想要自動駕駛來控制,而且很多場景更需要人來遠程控制,比如在礦山等危險地方,最好的方法就是能夠遠程去控制工程車去進行作業(yè)。
有了上面的向前向后和轉(zhuǎn)彎的了解后,我們就可以制作一個模擬方向盤來控制無人車了。
7.1、按鈕部件
# 創(chuàng)建按鈕
button_layout = widgets.Layout(width='100px', height='80px', align_self='center')
stop_button = widgets.Button(description='停止', button_style='danger', layout=button_layout)
forward_button = widgets.Button(description='向前', layout=button_layout)
backward_button = widgets.Button(description='向后', layout=button_layout)
left_button = widgets.Button(description='向左', layout=button_layout)
right_button = widgets.Button(description='向右', layout=button_layout)# 顯示按鈕
middle_box = widgets.HBox([left_button, stop_button, right_button], layout=widgets.Layout(align_self='center'))
controls_box = widgets.VBox([forward_button, middle_box, backward_button])
display(controls_box)
如圖:
方向盤的布局,通過widgets.Layout創(chuàng)建層,在這個上面通過widgets.Button創(chuàng)建按鈕,然后將按鈕通過widgets.HBox和widgets.VBox進行橫向和垂直的排版即可。Horizontal:水平的,橫向。Vertical:垂直的
7.2、方向控制方法
def stop(change):robot.stop()def step_forward(change):robot.forward(0.8)time.sleep(0.5)robot.stop()def step_backward(change):robot.backward(0.8)time.sleep(0.5)robot.stop()def step_left(change):robot.left(0.6)time.sleep(0.5)robot.stop()def step_right(change):robot.right(0.6)time.sleep(0.5)robot.stop()
前后左右加停止按鈕的方法,方法體很簡單,就是控制左右馬達的速度。
7.3、按鈕動作
定義好了各自方法之后,只需要將方法綁定到各自的按鈕就可以了。
stop_button.on_click(stop)
forward_button.on_click(step_forward)
backward_button.on_click(step_backward)
left_button.on_click(step_left)
right_button.on_click(step_right)
這樣就可以點擊按鈕,遠程控制無人車了。
8、心跳開關(guān)
最后就是介紹下心跳開關(guān),檢測無人車與瀏覽器的連接是否還存在的一種簡單方法??梢酝ㄟ^下面顯示的滑塊調(diào)整心跳周期(以秒為單位),如果兩次心跳之內(nèi)不能在瀏覽器之間往返通信的,那么心跳的status(狀態(tài))屬性值將會設(shè)置為dead,一旦連接恢復(fù)連接,status屬性將設(shè)置為alive
from jetbotmini import Heartbeatheartbeat = Heartbeat()# 這個函數(shù)將在心跳狀態(tài)改變時被調(diào)用
def handle_heartbeat_status(change):if change['new'] == Heartbeat.Status.dead:robot.stop()heartbeat.observe(handle_heartbeat_status, names='status')period_slider = widgets.FloatSlider(description='period', min=0.001, max=0.5, step=0.01, value=0.5)
traitlets.dlink((period_slider, 'value'), (heartbeat, 'period'))display(period_slider, heartbeat.pulseout)
?自動駕駛的相關(guān)知識點介紹完畢,有錯誤之處,請指正,一起學(xué)習(xí)與進步!