解决方案:Simulink与自动驾驶(ADAS)算法的开发
优采云 发布时间: 2022-11-29 23:42解决方案:Simulink与自动驾驶(ADAS)算法的开发
点击上方蓝字,您的关注就是对我最大的鼓励!
美国大选已经落下帷幕。不知道白哥对我们Matlab/Simulink是什么态度,是继续禁,还是?其实我还是支持的,继续禁用。只有这样才能激发我们的自主创新能力,您怎么看?哈哈哈!
好久没更新了 一直忙这忙那,还没有静下心来总结这些东西。这次聊一个高端的话题---自动驾驶,闲聊,总结一下最近的一些学习工作,Simulink在自动驾驶的发展过程中是如何存在的?话不多说,开始说吧!自动驾驶软件开发的基本架构逃不开我们常说的三大法宝,感知---决策(规划)---执行(控制),这三个内容,软件开发的基本思路是不一样的,听听本的解说!
感知:雷达的感知大部分是通过傅里叶变换等算法对具有多普勒效应的脉冲波信号进行处理。目前主流是使用C作为代码。雷达有很多种。这个算法仅限于毫米波雷达,激光雷达不懂。
大多数相机对应的是图像处理。虽然Simulink目前已经收录
了相应的图像处理算法模型,但是这些算法模型只是对大家写论文有用,容易出结果,容易仿真!然而,大多数实际算法都是与 OpenCV 和 C++ 一起使用的。
惯性导航和 GPS 中的算法是另一类。Simulink 涉及的不多。轮速和车身姿态大多来源于ESC,EPS,这些对应的模块!
综上所述,Simulink在感知层面用的不多。Decision-making:L3以上的层级,由于有地图的参与,我们称之为规划,L3以下的层级大部分称为决策层,即融合多个目标源进行决策.
融合算法目前大部分在雷达和*敏*感*词*,但有走向独立和向域控制器靠拢的趋势,相当一部分算法软在里面。软件开发虽然说是用Simulink开发,但是很多都是用C和C++开发的,尤其是多维目标跟踪融合!执行(控制):执行分为横向控制域和纵向控制。横向控制主要是和EPS交互角度和力矩。纵控主要与动力总成和底盘进行交互,交互的核心是加速和制动的需求。
这些控制逻辑,通俗的说就是简单的门控逻辑,大部分是OR,AND,NOT的逻辑,这些都是Simulink的强项,所以相关逻辑的执行都是用Simulink开发,然后自动生成代码,终于软了!
综上所述,目前Simulink对自动驾驶的支持其实还不是很广泛。大多侧重于功能的控制,其他相关图像,以及雷达算法的应用。他们中的大多数还处于写论文的阶段。总结如下,呵呵!
" />
目前从事自动驾驶算法开发,Simulink中有很多对应的库文件和例子可以参考。下图所示的库文件可以直接使用。
还有对应的示例文件,点Help自己学习就好了,应该问题不大。
然后说说相应的算法生成和集成!至于所谓的可以做融合和感知算法的Simulink,我不能否认,但是实践是检验真理的唯一标准,现在在实际项目中还是很少用到!
但是,当你在开发某个功能时,如何进行前期验证呢?如何建立一个模拟感知算法,如何建立一个模拟融合算法,如何在前期验证你的功能算法,这就需要我们的大杀器出来了!这两个东西是ADAS系统开发的主角,因为真正的功能开发肯定没有发动机和变速箱那么复杂,但是ADAS系统的数据量和仿真要求远大于其他系统,因为这个东西不模拟,直接测试太贵了!
ADAS系统是一个非常复杂的东西。在开发初期,如果使用特定阶段或特定场景的验证,使用实车成本太高,不切实际!所以我们前期做场景验证的时候,如果后面问题重现,就需要我们的大杀器Simulink了!尤其是L3、L4级别的功能,必须要有这个大杀器才能完成百万公里的验证。ADAS系统仿真与验证 在Simulink环境中建立仿真环境,进行算法验证与开发。目前Simulink集成了Driving Scenario Designer的库。这个库可以完成场景的规划和定义,如下图:
场景建模完成后,Matab可以将其转换成Mat文件(类似自动代码生成的S-function格式),然后导入到Simulink环境中,添加相应的传感器模型,进行open-循环和闭环模拟!如下图开环仿真来验证对应的融合算法!
闭环仿真增加了车辆动力学和相应的路径设计。把它变成一个闭环来验证相应的功能算法,比如ACC、AEB、TJA等功能。这两个就是我们所说的SIL,软件在环仿真的学术定义!
当设计这些场景和算法时,需要对其进行测试。测试工具和方法与前面提到的代码自动生成测试方法相同。Simulink 的测试管理器可用于执行动态测试用例和静态代码。覆盖测试,如下图,和基本的测试方法是一样的!
以上都是形式化的算法验证流程,适用于基础功能开发,但目前大多用于面向应用的项目中。面向应用的项目主要测试工作是采集道路数据,然后进行验证,比较符合实际。它是可靠的,并且在建立仿真模型时也省去了很多工作。省钱又高效!哈哈哈。
" />
中国贴牌的传统做法。具体操作方法同上!通过导入场景数据,可以验证具体的传感器算法,通过导入目标列表数据,可以验证具体的功能算法,如下图!
设计、仿真、测试,这个闭环形成了ADSA算法的开发和验证,展示了Simulink软件的NB:
ADAS数据处理
在实际测试验证的过程中,会采集到大量的数据,比如*敏*感*词*图像数据、雷达数据、车道检测数据、激光雷达数据、惯性测量单元数据等,这些结果如何处理?如何标记真值?
Simulink中的ADST工具箱收录
了相应的函数,然后就可以说说相应的图像数据,分析后的目标列表,统一用一个图表来展示分析,进行我们所谓的真值标定,然后可视化,就是比我们的好 肉眼看,比NB还要多,请参考下图!
在做可视化时,Simulink可以在同一屏幕上转换车辆坐标系和图像坐标系,从而绘制出不同的点云数据,便于传感器信号的分析和验证。
小才小学,这些总结仅供朋友参考,启发大家,大家一起学习吧!ADSA系统的算法研究犹如星辰大海。只要抓住一颗闪亮的星星,你就可以在智慧的潮汐中屹立于桥上,成为潮汐中的潮人。一起学习,一起进步,一起征服灿烂的星海!
学无止境,深入浅出,细细研读,必成大器!分享给有志之士!
解决方案:使用树莓派3B+开发智能音乐播放器(续---加入自动唤醒功能)
下次预定。. .
上次讲到给智能音乐播放器增加语音唤醒功能。我google了一下相关资料。目前有百度AI、科大讯飞、谷歌、snowboy。最简单的大概就是snowboy了。去github下载源码,然后去官网查看相关说明。注意下载的源码中有四个demo。四个源码最好都看一遍,可以解决大部分应用问题。
我这里用demo.py这个框架就够了。其次最重要的是登录snowboy官网注册用户(需要用谷歌账号登录),然后录制自己的个性化唤醒词(例如:你好小爱),下载您记录的唤醒词文件 pmdl 作为程序运行的参数 (python3 demo.py XXX.pmdl)。
好了,我们直接上代码:
# -*- coding: utf-8 -*-
from aip import AipSpeech #百度语音识别库
import pyaudio #麦克风声音采集库
import wave
import requests,json #音乐搜索
import pygame #mp3播放
import snowboydecoder
import sys
import signal
import os
import time
import sys
interrupted = False
""" 我的 APPID AK SK """
APP_ID = 'xxxxxxxxx'
API_KEY = 'xxxxxxxxxxxxxx'
SECRET_KEY = 'xxxxxxxxxxxxxxxxxxxxxxxxxx'
#定义采集声音文件参数
CHUNK = 1024
FORMAT = pyaudio.paInt16 #16位采集
CHANNELS = 1 #单声道
RATE = 16000 #采样率
RECORD_SECONDS = 9 #采样时长 定义为9秒的录音
WAVE_OUTPUT_FILENAME = "./myvoice.pcm" #采集声音文件存储路径
def get_file_content(filePath):
with open(filePath, 'rb') as fp:
return fp.read()
#获取下载地址
def get_down_url(songid):
req=requests.get("http://tingapi.ting.baidu.com/v1/restserver/ting?method=baidu.ting.song.play&format=jsonp&callback=jQuery17206073972467458864_1511011710426&songid=%s&_=1511011713541" %songid)
req.encoding='utf-8'
#print(json.loads(req.text))
json1=json.loads(req.text.replace("jQuery17206073972467458864_1511011710426(","").replace(");",""))
print("下载地址:",json1["bitrate"]['show_link'])
return json1["bitrate"]['show_link']
#下载保存文件
def music_down(url,music_name,artistname):
f=open(music_name+'-'+artistname+'.mp3','wb')
req_mp3=requests.get(url)
f.write(req_mp3.content)
f.close()
#调用百度AI,将文字转化为声音输出,用于提示音
def word_to_voice(text):
result = client.synthesis(text, 'zh', 1, {
'vol': 5, 'spd': 3, 'per': 3})
if not isinstance(result, dict):
with open('./audio.mp3', 'wb') as f:
f.write(result)
f.close()
pygame.mixer.music.load('./audio.mp3')#text文字转化的语音文件
<p>
" />
pygame.mixer.music.play(loops=0)
while pygame.mixer.music.get_busy() == True:
print('waiting')
def word_to_voice1(text):
result = client.synthesis(text, 'zh', 1, {
'vol': 5, 'spd': 3, 'per': 3})
if not isinstance(result, dict):
with open('./audio1.mp3', 'wb') as f:
f.write(result)
f.close()
pygame.mixer.music.load('./audio1.mp3')
pygame.mixer.music.play(loops=0)
while pygame.mixer.music.get_busy() == True:
print('waiting')
#获得麦克风输入的声音文件,保存在myvoice.pcm
def get_mic_voice_file(p):
word_to_voice('请说出歌名')
stream = p.open(format=FORMAT,
channels=CHANNELS,
rate=RATE,
input=True,
frames_per_buffer=CHUNK)
print("* recording")
frames = []
for i in range(0, int(RATE / CHUNK * RECORD_SECONDS)):
data = stream.read(CHUNK)
frames.append(data)
print("* done recording")
stream.stop_stream()
stream.close()
#p.terminate()#这里先不使用p.terminate(),否则 p = pyaudio.PyAudio()将失效,还得重新初始化。
wf = wave.open(WAVE_OUTPUT_FILENAME, 'wb')
wf.setnchannels(CHANNELS)
wf.setsampwidth(p.get_sample_size(FORMAT))
wf.setframerate(RATE)
wf.writeframes(b''.join(frames))
wf.close()
print('recording finished')
#百度语音识别出歌名文字并返回
def baidu_get_song_name(client):
results = client.asr(get_file_content(WAVE_OUTPUT_FILENAME), 'pcm', 16000, { 'dev_pid': 1536, })
# print(results['result'])
song_name=results['result'][0]
print(song_name)
return song_name
#百度音乐下载歌曲
def download_music_file(song_name):
req_url = "http://sug.music.baidu.com/info/suggestion?format=json&word=%s&version=2&from=0&callback=window.baidu.sug&third_type=0&client_type=0&_=1511013032878" % song_name
req_so = requests.get(req_url)
data = json.loads(req_so.text.replace("window.baidu.sug(", "").replace(");", ""))
for i in data["data"]["song"]:
print("\tsongid:" + str(i["songid"]), "音乐名字:" + i["songname"], "\t歌手:" + i["artistname"])
input_songid = data["data"]["song"][0]["songid"] # input("请输入你要下载的songid:")
for i in data["data"]["song"]:
if input_songid == str(i["songid"]):
" />
url = get_down_url(i["songid"])
music_down(url, i["songname"], i["artistname"])
print("下载完成")
music_name = i['songname'] # 获取MP3文件中的歌曲名
artistname = i["artistname"] # 获取MP3文件中的歌手名
filename = './' + music_name + '-' + artistname + '.mp3'
print(filename)
word_to_voice1('请欣赏')
return filename
def play_mp3(music_file):
pygame.mixer.music.load(music_file)
'''while True:
# 检查音乐流播放,有返回True,没有返回False
# 如果一直有音乐流则选择播放
if pygame.mixer.music.get_busy() == False:
pygame.mixer.music.play()'''
pygame.mixer.music.play(loops=0) #该函数运行后立即返回,音乐一直在后台运行
def one_time_process(p,detector):#一次麦克采样+语音识别+音乐下载+自动播放
detector.terminate() #该条代码很重要,因为detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)已经在内部使用pyaudio库获取了MIC的权限,如果我们再次鲁莽的使用pyaudio,将造成程序出错
get_mic_voice_file(p)
play_mp3(download_music_file(baidu_get_song_name(client)))
#snowboy 相关代码
def signal_handler(signal, frame):#改变全局变量interrupted值
global interrupted
interrupted = True
def interrupt_callback():#键盘输入ctrl+c终端程序运行
global interrupted
return interrupted
if __name__=='__main__':
#麦克风采集初始化、百度语音识别初始化、mp3文件播放初始化
p = pyaudio.PyAudio()
client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
pygame.mixer.init()
model = sys.argv[1]
#
# capture SIGINT signal, e.g., Ctrl+C
signal.signal(signal.SIGINT, signal_handler)
detector = snowboydecoder.HotwordDetector(model, sensitivity=0.5)
print('Listening... Press Ctrl+C to exit')
# main loop
while 1:
detector.start(detected_callback=lambda: one_time_process(p,detector),interrupt_check=interrupt_callback,sleep_time=0.03)#detector作为回调函数的一个参数,目的是将MIC的权限进行释放
detector.terminate()
</p>