本文的三位作者正阳、海洋、阿力,是来自不同公司的工程师,将 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.shuser rootoneshot

在 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

  1. 在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(如有必要),设定好对应的参数,我们就可以远程控制小车并获取视频了。


Hacker 们用实际行动,说明了 RTC 技术不仅仅可应用于娱乐、社交、教育等领域,还可以迸发出更多新的创意。就在近期,Agora RTC Hack 还在全球其它城市火热进行中。有个人,也有来自创业公司的团队参赛并获奖。我们将邀请其中几支来自世界各地的获奖团队参加到9月7日 - 8日举行的 RTC 2018 实时互联网大会。现场不仅有 Google WebRTC 产品经理、华为多媒体实验室首席科学家、西北工业大学智能声学与临境通信中心首席科学家、Twitch 首席研发工程师、AVS 标准工作组组长等技术大咖们带来的干货,还将有这些饱含创意与开发热情的小项目。想与他们聊一聊,交个朋友么?点击这里报名,现场约起来吧!

48小时开发实践:如何开发一款可实时视频的智能小车相关推荐

  1. MIL开发实践(1)——开发环境的设置

    目录 前言 软件安装 注意事项 MIL图像库函数说明 关于[MIL+QT实践教程](https://www.zhihu.com/column/c_1124353074277572608)的总结 MIL ...

  2. Android实践:做一个可视频交互的智能小车

    本文的三位作者正阳.海洋.阿力,是来自不同公司的工程师,在Agora RTC Hack 上海站编程马拉松上,开发了一款可实时视频远程看房的智能小车.本文将从方案设计.硬件开发.Android 端开发. ...

  3. 开发实践 | Android开发Zegbee 温度、气体采集系统(代码类)

    博主github:https://github.com/MichaelBeechan 博主CSDN:https://blog.csdn.net/u011344545 package com.socke ...

  4. Flutter开发之《马蜂窝的跨平台开发实践》笔记(53)

    摘自:Flutter 实现原理及在马蜂窝的跨平台开发实践 跨平台开发,针对 Android 与 iOS 的风格设计了两套设计语言的控件实现(Material & Cupertino).这样不但 ...

  5. MIL开发实践(2)——MIL实时采图

    前言 前言 效果图 正文 初始化 实时采图 总结 前言 网上找到的关于MIL实时采图的代码基本上都是只有很老的代码,但其实MIL是有自带的关于采图方面的QT的demo的.这里给出地址,应该比一些普通的 ...

  6. MIL开发实践(4)——E2v相机参数

    目录 前言 效果图 正文 连接串口 向串口写入命令 举例设置的参数 ComBox类型 Int类型 总结 前言 这篇文章的主要内容是完成对相机参数这部分的配置.因为这个相机参数这个接口的特殊原因,只能采 ...

  7. Blockathon(北京):48小时极客开发,区块松11个现场交付项目创意公开

    5月25日-27日,全球首届Blockathon(区块松)在北京中关村e世界联合创业办公社举办,来自新加坡.澳大利亚.韩国.日本等国家以及杭州.深圳.西安.内蒙.上海.北京等城市的100名开发者在48 ...

  8. 使用Unity引擎打造赛博朋克之城!CIGA Game Jam 2019 48小时独立游戏开发挑战

    一年一度的CIGA Game Jam 48小时极限开发挑战赛结束了,作为开发独立游戏的爱好者和玩家的我们在这次活动中纷纷展现出了自己独特的才华.同样作为开发者中的一员,我们团队参与了这次比赛,而这次, ...

  9. 48小时极限游戏开发比赛介绍以及Global Game Jam 历年主题和CiGA Game Jam 多年主题

    首先介绍一下48小时极限游戏开发,顾名思义就是在48小时里开发出一款游戏demo,通常我们在题目发布前到达开发场地,找到志同道合的小伙伴,等到活动开始就可以进行开发讨论了.这个活动在国内一般有两个,是 ...

最新文章

  1. Gnu/Linux 链接XServer方法
  2. 使用 NuGet 管理我们的程序集 - 预发行版
  3. python操作docx学习资料
  4. 怎么改vue项目的标题_如何动态修改Vue项目中的页面title
  5. 解决mysql报错Can’t connect to local MySQL server through socket ‘/var/lib/mysql/mysql.sock
  6. java 命令读取参数_如何读取/处理命令行参数?
  7. LeetCode 2182. 构造限制重复的字符串(贪心、map)
  8. Aptana studio 3汉化教程
  9. java面向对象笔试_Java面向对象笔试题.doc
  10. android 多个模块,Android Studio:多个模块的多个APK
  11. javascript option 菜单图标_善用 CSS,不用 JavaScript 也能写出这些元素
  12. MVC之使用Nhibernate
  13. myeclipse2015添加tomcat
  14. 为什么不使用ipv6计算机网络,ipv6无网络访问权限解决教程
  15. python进行文本分类_python实现文本分类
  16. 关于身份证加密展示处理以及update table set cou=(select from ..)
  17. EXSI6怎么设置虚拟机从光驱启动
  18. 解决vue项目在浏览器中打开后,#后面的链接被截取的问题
  19. 雷迪9000使用说明_标准版DM雷迪操作及维护手册 精品
  20. java sign函数_C / C ++中是否有标准的符号函数(signum,sgn)?

热门文章

  1. 分布式块设备DRBD9基础用法(快速上手教程)
  2. 部署Vista – 第1部分:理解Windows AIK
  3. 网易大数据平台HDFS性能优化实践
  4. 黄东旭: 关于基础软件产品价值的思考
  5. Node-RED通过npm安装的方式对应卸载
  6. 工业交换机在轨道交通自动售检票系统(AFC)解决方案
  7. SQL Server 2012 管理工具
  8. 通用程序测试软件,得实打印机通用驱动程序系列1
  9. JS高级(含ES6)
  10. 城际铁路列车控制系统