目录
本文档是furyTerminal系统总体和各部分说明, 主要面向电气组开发人员, 其他组成员不应需要阅读 本文档, 系统实现的应当是十分友好 (傻瓜式) 的交互😁
2019-02-01
- 传感器调试, 安全回路状态界面
- 油门深度 (单色直柱)
- 刹车深度 (单色直柱)
- 安全电路状态图与flag数值的对应
- 车手界面电控报警信息提示 alert (可考虑通过浏览器级刷新页面来消除alert)
- 电池箱温度热力图
- G加速度圆
- 数据传输延迟. 可能是将是从CAN里读取数据更新到state中因为刷新率不同有延迟, 可能是将state里数据传输到后端的socket的缓冲区设置不合理有延迟, 另外前端页面刷新数据有几十毫秒的延迟. 也可能是其他原因.
- 开机后Plymouth结束到开始加载桌面不知为何有大约8s的黑屏. 尽量缩短界面加载时间.
- 为每个车手建立账号分别记录数据
- 将每次跑动的时间, 速率, 方向, 油门, 刹车, 电量等关联起来, 达到还原整次跑动的效果, 方便实时/后期的分析
- 语音提示, 蓝牙连接车手耳麦
命名为furyTerminal是因为本系统的目标是做出一个 友好, 直观, 健壮 的赛车 终端:
- 让操作方式足够友好, 车队队员们能通过简单操作来获取数据或者更改参数
- 数据呈现方式, 交互方式足够直观, 速度, 油门, 时间等车手常用数据明显, 故障原因提示内容足够直观, 分析用数据以图表形式呈现
- 系统足够健壮, 能够应对绝大多数故障情况, 比如掉电数据储存等.
至于什么是终端 (Terminal), 参见 🔗 这里
python
version: Python 3.7.3 (default, Apr 3 2019, 05:39:12) [GCC 8.2.0] on linux
💡 当前系统默认python为 3.7.3, 若想将系统默认python切换回python2, 运行以下命令然后跟随指导操作.
sudo update-alternatives --config python
pip -V
来查看pip版本和位置
django
version: 2.2.7
📑 7寸触摸屏说明书
位于/test
文件夹下的为各部分测试程序
TODO
之所以选择做网站是因为网站是最容易实现的GUI, 也能很轻松地接入大量库, 轻松实现远程访问等功能.
只要开机自启浏览器全屏模式, 用代码避免误触露出端倪, 根本看不出是网页!🎉
防止误触露出端倪具体来说指隐藏鼠标图标, 禁用右键菜单, 禁止选中等
🔗 防止误触相关代码
本网站基于 Django 框架和MySQL数据库.
.
├── config 用于快速部署环境的配置文件.
├── doc 项目相关的文档
├── furyCAN CAN总线数据读取模块
├── furyTerminal django网站基础目录
├── log 网站运行日志
├── oncar 网站oncar段后端
├── scripts 几个相关脚本
├── static 网站用到的静态文件
├── templates 网站静态页面模板
└── test 几个测试用脚本
/
(Home Page)/oncar
/
(车手页面)/devices
(赛前设备状态检查页)/refresh
(不是访问页面, 是给车手页面刷新数据的)
/remote
目前项目的难点在于如何实时从CAN总线传输数据到前端, 也就是数据流的方案.
💡 目前项目有4个分支: master
, sqlite_ver
, mysql_ver
, databaseless
. 其中master
分支暂时停留在某一版本的mysql_ver
提交, 待确定数据传输方案再合并到master
.
👇数据流方案示意图
其中彩色线部分是可能产生延迟的地方. 红色部分经实验目前的数据规模下几乎无延迟. 绿色和黄色部分因为是以一定频率发生, 怀疑因为缓冲区大小设置不合理因此存在延迟. 蓝色部分经试验会产生大致30ms延迟 (可能是django架构拖了后腿).
sqlite_ver
是以sqlite作为数据库, 储存数据的版本. 原本利用SQLite3数据库传输数据, 问题在于sqlite是个轻量级数据库, 无法支持高并发, 当有多于一个终端访问网站时向数据库写入新数据的程序会遭遇进程锁而结束. 这个问题以数据库只用来储存数据, 不被前端实时访问而解决. 在这个版本中后端直接调用furyCAN模块获取数据.mysql_ver
是在遇到上述问题后尝试的解决方式之一, 以MySQL数据库记录, 传输数据. MySQL的强大性能使得高并发导致程序终止问题不复存在, 但MySQL的事务隔离等级的选择值得再研究一下. 这可能是最后会使用的方案.databaseless
是不断从CAN总线读取数据并通过socket与后端通信的解决方案. ❗️实际上我没能理清这样的方式传递到前端的数据流是否还是按照正确的时间先后顺序排列的. 我想这种方案应当被放弃, 因为它似乎并没有什么好处. 💡 后续工作可以是用ROS的通信系统代替手搓socket, 数据流会健壮许多.
🚩 总而言之, 为了储存数据一个数据库是必要的. (存入简单的文件比如csv文件并不会是一个好选择, 以数据库的形式更便于管理数据, 与django协作更方便) 但使用数据库的方式需要进一步探索: 是单纯储存实时性没那么强的数据以供平时分析? 还是近乎实时记录数据 (经测试即便数据记录频率很高数据库体积相对于SD卡空间也很小), 利用数据库在Python文件间传递数据?
- 是一个python框架, 数据处理很方便, 容易接入ROS
- 容易上手. 个人认为结合了前后端, 更偏向后端, 但前端能很容易的结合前端
速度不算快
- SQLite3是一个轻量级数据库, 是Django默认使用的数据库, 不需要什么额外操作竟可以轻松部署一个SQLite3数据库, 很方便移植.
- 对SQLite3数据库操作也很简单, 几乎全部操作都可以用django提供的api命令完成. 学习起来也相对简单, 因为本身就没那么多高级功能.
- SQLite3数据库就是一个在指定目录的
.sqlite3
结尾的文件, 很方便管理
- 它的缺点同样很明显, 轻量级使SQLite3不支持高并发, 如果高并发就会产生进程锁.
一开始使用的是SQLite, 但是SQLite不支持高并发访问, 因此改用MySQL.
支持高并发, 有更丰富的功能
- 部署起来要麻烦一些, 需要单独创建这个数据库
- 操作复杂一点. 可设置参数更多实际上对不了解的人来说很不友好, 会让人迷茫该选哪个.
💡 root用户初始密码为空, 只能su
到root用户进入mysql
命令行进入mysql mysql -u fury -p
新建数据库 create database furyTerminal character set utf8;
删除数据库 drop database furyTerminal;
查看数据库中的数据表 use furyTerminal; show tables;
新建用户 create user fury identified by 'fury';
给予用户权限 grant all privileges on furyTerminal.* to fury;
查看用户权限 show grants for fury;
查看所有用户 select user, host from mysql.user;
👇一些推荐的学习资料
🔗 HTML教程
🔗 CSS教程
🔗 Bootstrap教程
🔗 Bootstrap官方文档
🔗 JavaScript教程
🔗 Django官方文档中文版 (翻译不全)
🔗 Django2.2文档个人中文翻译
🔗 Django MySQL数据库文档
管理员账号: leo
密码: leo
💡 添加管理员 python manage.py createsuperuser
💡 对于SQLite3数据库来说, 如果把数据库文件 (sqlite3
结尾的文件) 删掉了的话原本的管理员信息同时也被删掉了.
在 furyTerminal/furyTerminal/settings.py
中 ALLOWED_HOSTS一项设置了允许访问
网站的地址, 设为 '*'
则是允许所有地址访问.
在对应的父类为 admin.ModelAdmin 的类下重写 get_readonly_fields
方法如下:
def get_readonly_fields(self, request, obj=None):
if obj: # obj is not None, so this is an edit
return ['[readonly_fields]'] # Return a list or tuple of readonly fields' names
else: # This is an addition
return []
🔗 参考链接:
🔗 参考
💡 因为我记性很差, 将常用命令集成到了根目录下的python脚本fury
python furyTerminal/manage.py runserver 0:8000
python manage.py makemigrations
python manage.py migrate
我们使用这个命令而不是简单的使用 "Python" 是因为 manage.py 会设置 DJANGO_SETTINGS_MODULE 环境变量,这个变量会让 Django 根据 mysite/settings.py 文件来设置 Python 包的导入路径。
python manage.py shell
💡如果想通过脚本调用 database API, 需要在脚本开头加上以下语句:
from furyTerminal import settings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'furyTerminal.settings')
django.setup()
具体例子参见oncar应用的Speed部分的测试
举例: 向 oncar 应用的 Speed 模型添加记录
1.首先当然是引用它
from oncar.models import Speed
2.有两种添加方法:
-
先实例化然后保存 🔗save()
speeed = Speed(speed_value='123') speeed.save()
-
直接创建 🔗creat()
Speed.objects.create(speed_value='123')
- path()函数的参数
route
不会匹配 GET 和 POST 参数或域名。例如,URLconf 在处理请求 https://www.example.com/myapp/ 时,它会尝试匹配 myapp/ 。处理请求 https://www.example.com/myapp/?page=3 时,也只会尝试匹配 myapp/。 - 🔗django模型中auto_now和auto_now_add的区别
最开始自己手搓的仪表盘显得有些卡顿, 能达到0.5秒级刷新, 再快很容易让chrome崩溃. 这个刷新率听起来不低, 0.5s的延迟在汽车上不算高, 但呈现出来的变化过程不够平滑, 给人一种卡顿感.
🔗 这个是一个最简陋的有平滑移动的仪表盘的教程
🔗 这个是一个用树莓派读取传感器参数并显示在网页仪表盘的实例
🔗 这个是Google Charts的朴素派仪表 (效果如下图)
🔗 这个是目前找到最符合赛车样式的仪表 (好吧梁师傅说没有科技感), 由canvas绘制. 刷新值代码:
document.gauges[0].value = current_speed;
🔗 这个是科技简约风的, 由svg绘制, 刷新值代码:
speedGauge.setValue(10)