48小時 Hackathon 紀實:如何開發一款可實時視頻的智能小車

本文的三位作者正陽、海洋、阿力,是來自不同公司的工程師,將 Agora SDK 與智能小車結合,開發了一款可實時視頻遠程看房的創新性項目。本文將從方案設計到具體實現,詳實分享他們的開發經驗。三人也憑借該項目,在6月30日的Agora RTC Hack 上海站編程馬拉松獲得大獎。

創意構思

此前聽到多很多次“黑客馬拉松”這樣的活動,一群來自不同地方的人聚在一起,組隊、構思、開發,在48小時內做出產品雛形。我們三人抱著去聽聽別人的創意,重在參與的想法參加了這次比賽。對于想要做的東西,在比賽前也只是有一個大概的方向:

  1. 構思的方向依據我們擅長的部分來組合拼接,這就得說到我的兩位給力隊友海洋、阿力;海洋是嵌入式軟件工程師,汽車電子方向,寫個驅動做個小車手到擒來。阿力是后端工程師,具備處理服務器端和前端頁面的能力。
  2. 于是隊伍有了嵌入式和云端兩部分的能力,技術構思的方向是云端為嵌入式賦能。希望有一個小車,小車可以傳遞回視頻圖像,視頻圖像可以實時傳給多個用戶,用戶在得到授權之后,實現遠程對小車的操控。

方案設計與分工

出于這樣的構思,實現架構如上圖所示。現在有了一個基本架構,也清楚了我們要實現的功能,接下來就是分工了。考慮到我們各有所長,分工如下:

分工 人物 實現目標1 實現目標2
小車驅動與攝像頭端 海洋 使用 Android系統,完成攝像頭驅動 在 Android系統中加入驅動,解析運動控制信號,實現小車運動
車載APP與用戶APP 正陽 將攝像頭采集的視頻傳遞出去,解析服務器信令,給小車發送運動信號 用戶可以通過手機查看小車視頻,并控制小車
服務器端與web前端 阿力 將視頻傳輸服務器掛到公網上,用戶可以用輸入網址的方式查看小車視頻 提供web前端,用戶可以通過網頁控制小車

從硬件開發開始

小車采用了是4輪伺服電機驅動,搭配有視頻采集模塊、伺服電機驅動模塊、STM32控制模塊和攝像頭云臺模塊,安裝后整體效果圖如下:


用戶在遠程操控小車各種動作之前,需要小車通過wifi連接到互聯網。用戶可以通過上位機(Android APP 或網頁前端)控制小車前后左右移動或控制云臺調整攝像頭方向。

視頻采集模塊包含有wifi模塊,可以連接到wifi熱點為視頻傳輸提供網絡基礎。也提供HDMI接口與顯示器連接,方便用戶調試。攝像頭通過USB的方式與視頻采集模塊連接,我們采用免驅動的天敏6602型號攝像頭,分辨率可以達到640*480,并能夠自動調焦。

STM32控制模塊采用 Arduino 接口與伺服電機驅動模塊連接,STM32模塊負責控制電機、云臺信號的產生,并由伺服電機驅動模塊直接驅動電機工作。伺服電機輸入電壓為6~12V,直流驅動。

工作原理

小車上的視頻采集模塊采用了定制的 Android 系統,提供網絡連接、指令轉發和視頻流采集、傳輸功能。當上位機通過遠程服務連接到小車后,上位機可以請求到當前小車攝像頭上的視頻信息;同時,視頻采集模塊也將上位機上傳來的控制信號解析為指定格式和功能的協議數據,并通過串口發送到 STM32控制模塊。

小車上的STM32控制模塊在接收到相關控制信號后,調整輸出脈沖信號的占空比,由驅動板轉換輸出電平后直接控制伺服電機或云臺模塊做出相應的動作,從而完成上位機用戶想要的操控功能。

控制信號協議

對于只需要實現簡單的小車控制的話,我們只需要實現通過串口向 STM32控制模塊發送控制信號即可,簡單的控制信號協議如下:

命令類型 包頭 類型 命令 數據 包尾
停止 FF 00 00 00 FF
前進 FF 00 01 00 FF
后退 FF 00 02 00 FF
左轉 FF 00 03 00 FF
右轉 FF 00 04 00 FF
云臺上下 FF 01 01 角度值 FF
云臺左右 FF 01 02 角度值 FF

Android SDK定制

開發工具

為了實現我們想要的實時視頻與小車的遠程控制功能,我們需要采用聲網的視頻SDK,并運行在 Android 開發板上。開發板,我們選用了Firefly的RK3128平臺,采用Cortex-A7架構四核1.3GHz處理器、Mali-400MP2 GPU,板載千兆以太網口、2.4GHz Wi-Fi和藍牙4.0,支持Android與Ubuntu雙系統。

定制串口驅動

為了實現RK3128對小車的控制,我們需要實現 RK3128通過 USB 轉串口模塊與STM32控制模塊通信。因此我們首先要重新配置RK3128內核,使得RK3128支持 USB轉串口驅動程序。

首先下載完RK3128 Android SDK并先驗證文件MD5值:

md5sum /path/to/fireprime_android5.1_git_20180510.tar.gz
fce0e6d65549939167923260142b2c1e fireprime_android5.1_git_20180510.tar.gz

確認無誤后解壓:

mkdir -p ~/proj/fireprime
cd ~/proj/fireprime
tar xvf /path/to/fireprime_android5.1_git_20180510.tar.gz
git reset --hard
git remote add bitbucket https://bitbucket.org/T-Firefly/firenow-lollipop.git
git pull bitbucket fireprime:fireprime

配置并編譯內核:

cd ~/proj/fireprime/kernel
make rk3128-fireprime_defconfig
make menuconfig
make -j8 rk3128-fireprime.img

其中make menuconfig這一步需要勾選上Device Drivers ---> USB support ---> USB Serial Converyer support ---> USB Serial Console device support / USB Generic Serial Driver,并勾選上 CP210x / CH341 / FTDI / PL2303 等常用串口工具設備。

編譯Android系統:

cd ~/proj/fireprime
. build.sh
make -j8
./mkimage.sh

最后編譯完成后燒錄分區鏡像,并插入USB轉串口工具查看系統dmesg是否出現以下log信息:

[ 2213.003173] usb 1-1.3: new full-speed USB device number 6 using rockchip_ehct
[ 2213.113759] usb 1-1.3: New USB device found, idVendor=10c4, idProduct=ea60
[ 2213.113839] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumbe3
[ 2213.113883] usb 1-1.3: Product: CP2102 USB to UART Bridge Controller
[ 2213.113921] usb 1-1.3: Manufacturer: Silicon Labs
[ 2213.113956] usb 1-1.3: SerialNumber: 0001
[ 2213.120813] cp210x 1-1.3:1.0: cp210x converter detected
[ 2213.209852] usb 1-1.3: reset full-speed USB device number 6 using rockchip_et
[ 2213.320161] usb 1-1.3: cp210x converter now attached to ttyUSB0

出現串口設備附著到 ttyUSBx,即說明定制串口驅動成功。

以上為全編譯Android SDK的方法,需要編譯 Android 系統,相較于僅編譯內核而言比較費時。我們可以在上述make menuconfig時將需要的串口驅動程序勾選為M,通過make modules的方法,將驅動編譯成.ko文件,然后在 Android系統開機時自動加載驅動程序:

首先將.ko驅動程序文件復制到 Android 文件系統內

adb shell
su
mount -o remount ,rw /
mkdir /modules
chmod 777 /modules
chown -R nobody:nobody /modules
exit
exit
adb push ./xxxx.ko /modules

編寫啟動運行腳本/data/serial.sh

#!/system/bin/sh
insmod /modules/xxxx.ko
mknod /dev/ttyUSB c 240 0

修改init.rc并添加運行自己的腳本

service serial /system/bin/sh /data/serial.sh
    user root
    oneshot

在 App 端實現視頻傳輸

視頻傳輸和信令傳輸的部分,我們通過聲網 Agora SDK 來實現。由于涉及到與嵌入式開發板的結合,我們主要參考的是聲網在 Github 提供的各種案例中的抓娃娃機 demo。示例代碼中的結構圖如下:

示例代碼有視頻傳輸的部分,控制信令需要自己完成。

兩個APP 視頻 控制信號
小車端的 Android App 發送視頻信號 接受控制信號
用戶手機端 Android App 接受視頻信號 發送控制信號

聲網SDK簡要使用方法如下:

  1. 首先申請 AppID

AndroidAPP中在res/values/strings_config.xml加入如下內容,將agora_app_id進行配置

<resources>
   <string name="agora_app_id">1a486ee31a30xxxxxxxxxx</string>
</resources>
  1. 將.jar文件拷貝到libs/中
    因為用到信令和視頻傳輸兩部分,需要兩個.jar 文件分別為agora-rtc-sdk.jar和agora-sig-sdk.jar
  2. 在src/main/jniLibs加入armeabi-v7a與其中的.so文件


并在build.gradle中確定擁有如下描述:

dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.4.0'

}

就此,使用示例代碼可以順利開啟視頻傳輸功能。

用信令讓 App 控制小車

信令的具體使用方法見Agora 的參考,這里不進行詳盡描述。主要使用的函數如下:

// 初始化信令 SDK
m_agoraAPI = AgoraAPIOnlySignal.getInstance(context, appID);

// 登錄 Agora 信令系統
m_agoraAPI.login2(appId, account, token, uid, deviceID, retry_time_in_s, retry_count)

//////////////點對點測試/////////////
// 發送點對點消息
m_agoraAPI.messageInstantSend(account, uid, msg, msgID)

 // 設置對端收到消息回調(
 m_agoraAPI.onMessageInstantReceive(account, uid, msg){
      //code there
}
/////////////頻道測試///////////////
// 加入頻道
m_agoraAPI.channelJoin(channelName)

// 發送頻道消息
m_agoraAPI.messageChannelSend(channelName, msg, msgID)

// 設置對端接收到頻道消息回調
m_agoraAPI.onMessageChannelReceive(channelID, account, uid, msg) {
      // code there
}
//////////////////////////////////
// 退出 Agora 信令系統
m_agoraAPI.logout()

Android App 操作串口

對于小車端的 Android App 得到信令之后需要串口發送數據。因此如何實現 Android App 操作串口。這里簡述兩種方案:

  1. 采用 Android 系統給出的架構進行處理, Android 帶有串口demo代碼,名稱為 SerialPort。這里注意兩點,此處的代碼依賴于 JNI 工具和 NDK,如果沒有完整安裝在使用項目代碼的時候會出現問題。另外,串口操作不方便使用 Android 模擬器進行測試,對于沒有串口的設備,在開啟串口的動作時,會報錯并可能導致程序退出崩潰。
  2. 選擇使用 Android 代碼發送 shell 命令的方式,直接模擬linux的shell控制代碼,示例 echo ‘aa’ > /dev/ttyUSB0 將aa發送到串口ttyUSB0,這樣做的好處時代碼本身簡單,串口直接調用底層。

對于短時間實現功能來說,方案2是更容易實現的方法,這里需要非常注意的一點,需要重新編譯android的framework層給app賦予root權限
當信令解析完成,串口調試通過,就可以實現遠程控制小車的行進了。

最后:服務器端的部署

為了實現用戶可以方便通過手機或者電腦在線實時看房,我們需要通過web端連接小車的Android App端,獲取實時傳輸過來的視頻內容。在我們的設想中,用戶可以通過遠程控制小車,這樣可以方便用戶了解房屋各個方面的情況。綜上所述,我們需要實現如下兩個功能:

  • 具有視頻連接功能
  • 具有遠程遙控功能

幸運的是,通過聲網提供的服務,我們可以很便捷的搭建這兩個服務。
在本項目中,我們使用聲網的視頻SDK實現網頁端和小車APP端的視頻連接,通過信令SDK發送消息,去控制小車的前后左右行走和攝像頭上下左右擺動。

羅列一下我們使用到的工具:

  • 視頻通話的Web端SDK文檔,用來實現遠程的視頻交互功能;

  • 信令的SDK文檔,用來實現遠程遙控智能小車;

  • 服務器,用于部署靜態頁面;

實現視頻連接和發送消息

先在頁面上引入視頻和信令的 SDK。然后我們先來實現視頻連接。

// 創建 AgoraRTC 實例并加入頻道
const client = AgoraRTC.CreateClient({mode:"interop"}) 


client.init(appId, function () {
    console.log("AgoraRTC client initialized");
    client.join(channel_key, CHANNEL_NAME, null, function (uid) {
         console.log("User " + uid + " join channel successfully")
        console.log(new Date().toLocaleTimeString())
        
        // do something
    }
}

訂閱遠端的視頻流并播放。

let stream = AgoraRTC.creatStream(merge(defaultConfig.config))
localStream.init(() =>{
    client.on('stream-added', function (evt) {
        var stream = evt.stream;
        console.log("New stream added: " + stream.getId());
        console.log("Subscribe ", stream);
        client.subscribe(stream, function (err) {
            console.log("Subscribe stream failed", err);
        });
    });
    client.on('stream-subscribed', function (evt) {
        var stream = evt.stream;
        console.log("Subscribe remote stream successfully: " + stream.getId());
        if ($('div#video #agora_remote' + stream.getId()).length === 0) {
            $('div#video').append('<div id="agora_remote' + stream.getId() + '" style=" width:810px;height:607px;"></div>');
        }
        stream.play('agora_remote' + stream.getId());
    });

})

實現發送信息。

// 創建信令的對象
const signal = Signal(appId)

// 在實驗條件下,不設置token
const token = '_no_need_token'
// 登錄
const session = signal.login(account, token)

session.onLoginSuccess = (uid) => {
    //發送消息給指定的賬號
    signal.sendMessage(reciveAcount, message)
}

完成上述的步驟之后,與小車端設置相同的appId和token(如有必要),設定好對應的參數,我們就可以遠程控制小車并獲取視頻了。


現場演示

48小時改裝的小車

Hacker 們用實際行動,說明了 RTC 技術不僅僅可應用于娛樂、社交、教育等領域,還可以迸發出更多新的創意。就在近期,Agora RTC Hack 還在全球其它城市火熱進行中。有個人,也有來自創業公司的團隊參賽并獲獎。我們將邀請其中幾支來自世界各地的獲獎團隊參加到9月7日 - 8日舉行的 RTC 2018 實時互聯網大會。現場不僅有 Google WebRTC 產品經理、華為多媒體實驗室首席科學家、西北工業大學智能聲學與臨境通信中心首席科學家、Twitch 首席研發工程師、AVS 標準工作組組長等技術大咖們帶來的干貨,還將有這些飽含創意與開發熱情的小項目。想與他們聊一聊,交個朋友么?點擊這里報名,現場約起來吧!

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,030評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,310評論 3 415
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,951評論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,796評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,566評論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,055評論 1 322
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,142評論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,303評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,799評論 1 333
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,683評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,899評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,409評論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,135評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,520評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,757評論 1 282
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,528評論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,844評論 2 372

推薦閱讀更多精彩內容