赞
踩
创新实验课程做的东西。
相机,托盘,光敏电阻开关懒得往上固定了,画在图上示意一下。
树莓派的引脚有不同的编码方式,由于我主要用的是C语言,所以用的wiringPi库,故应该使用WiringPi下的编码。
引脚约定:
树莓派引脚(WiringPi Pin) | 外设引脚 | 导线颜色 |
---|---|---|
22 | ULN2003_IN1 | 橙色 |
23 | ULN2003_IN2 | 黄色 |
24 | ULN2003_IN3 | 绿色 |
25 | ULN2003_IN4 | 蓝色 |
21 | 光敏模块的DO | 黄色 |
4 | HC-SR04_Trig | 黄色 |
5 | HC-SR04_Echo | 绿色 |
26 | 舵机的PWM输入 | 橙色 |
对应文件:
photosensitive_camera.cpp
和photosensitive_camera.h
功能:
实现原理:
/usr/bin/raspistill
(控制树莓派拍照的shell命令),后面加上合适的参数,这样就相当于在程序中执行shell命令,实现了拍照功能。对应文件:
step_motor.cpp
和step_motor.h
功能:
实现原理:
对应文件:
steering_engin.cpp
和steering_engin.h
功能:
实现原理:
对应文件:
ultrasonic_ranging.cpp
和ultrasonic_ranging.h
功能:
实现原理:
对应文件:
waste_sorting.cpp
和waste_sorting.h
When it comes to 图像识别,首先想到的肯定是深度学习,但是我并不会,只懂个其中的皮毛,所以采用了一种更为简单的解决方案:使用BaiduAI开放平台提供的图像识别接口同时配合天行数据提供的垃圾分类查询接口实现图像识别并分类。因此这部分的功能就是读入一张垃圾的图片,输出它属于什么垃圾(用一个整数表示)。
代码实现在waste_sorting.cpp
文件中,下面结合头文件waste_sorting.h
中的函数声明简单说明其原理:
#ifndef __WASTE_SORTING_H__ #define __WASTE_SORTING_H__ #include <vector> #include <string> #include <iostream> /* 获取垃圾类型的函数:传入识别出来的物体种类(包含所有可能结果的string数组),返回其中最有可能所属的垃圾类型,约定垃圾类型如下: 0-可回收 1-有害 2-厨余(湿) 3-其他(干) -1表示出错,并打印到stderr中 */ int getGarbageCategoryByNames(std::vector<std::string>* objectNames); int getGarbageNamesByImage(const char* fileName, std::vector<std::string>* objectNames); #endif
函数getGarbageNamesByImage
的第一个参数fileName
是图片的文件名,这个函数会调用BaiduAI的图像识别SDK中的aip::Imageclassify
类下的advanced_general
方法来获取图像中的物体类型,返回结果是一个JSON对象,格式如下(我输入了一张蓄电池的图片):
{ "error_code" : null, "log_id" : 1376707039807406080, "result" : [ { "keyword" : "蓄电池", "root" : "商品-电子原器件", "score" : 0.82018500000000005 }, { "keyword" : "车载电源", "root" : "商品-机器设备", "score" : 0.58906800000000004 }, { "keyword" : "包装袋/盒", "root" : "非自然图像-图像素材", "score" : 0.38386300000000001 }, { "keyword" : "冷冻油", "root" : "商品-原材料", "score" : 0.2089 }, { "keyword" : "电能表", "root" : "商品-仪表", "score" : 0.039449999999999999 } ], "result_num" : 5 }
相关字段含义应该很清楚,可参阅api文档。
接下来解析这个JSON对象,拿到所有的"keyword"(实验中发现"score"最高结果的也可能是错的,出于容错性的考虑,所有的"keyword"都带走),存到第二个参数objectNames
指向的一个字符串数组中去(传出参数)。这样函数调用者就能拿到图片中物体的所有可能类型了。
接下来将objectNames
传给函数getGarbageCategoryByNames
,它会将其中的每个字符串一一取出,写到post请求的参数中去,然后逐一向天行数据api发送HTTPpost请求查询这个物体的垃圾类型,一旦查询成功,就break,返回垃圾类型。四种垃圾类型用四个整数表示,映射关系在上面的注释里。
aip-cpp-sdk-version.zip
解压,其中文件为包含实现代码的头文件。如果库的安装或使用有错误,直接给树莓派重装系统吧。
这是一个可以发送很多网络请求的C库,利用它可以发送http请求,模拟浏览器的行为;
安装方法:
首先到官网下载源码包:https://curl.haxx.se/download.html
解压、进入主目录进行安装(经典三部曲):
tar -zxvf curl-7.51.0.tar.gz
sudo ./configure
sudo make
sudo make install
头文件目录:
动态库目录:
关于如何使用curl库,这里有详细的视频教程:https://www.bilibili.com/video/BV1o7411w75c
这是用C++编写的json库,可以用它来解析json字符串,操纵json对象等;
安装方法:直接命令sudo apt-get install libjsoncpp-dev
头文件目录:
动态库目录:
有一说一,他这个BaiduAI提供的SDK中json头文件引用的目录是错的,他直接#include<json/json.h>
,少了一层jsoncpp,在前面都加上就好了。顺便记录一下gcc的头文件搜索顺序:
/usr/include
/usr/local/include
/usr/lib/gcc-lib/i386-linux/2.95.2/include
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g++-3
/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include
负责https的吧,跟安全有关;
安装方法:
sudo apt-get install openssl
sudo apt-get install libssl-dev
头文件目录:
这部分不是跑在树莓派上的,是跑在本地机器,或者正儿八经服务器上的(简单考虑只在局域网内模拟),TCPServer和WebServer这两个服务程序相配合:TCPServer接收来自树莓派端封装了垃圾桶最新使用余量状态信息(usage)的报文,启动一个线程,将其解析为JSON对象,并写入到allTrashesInfo.json
文件中去。
WebServer在前端js脚本调用百度地图api,负责向用户在地图上展示垃圾桶的位置和usage以及是否已满,后端基于NodeJS实现,很简单。
这个文件存储了一个json数组(对象),里面的每个对象都包装了一个垃圾桶的信息,格式是这样的:
{
"id" : 0,
"location" : [ 120.3502, 30.3202 ],
"recyleBitMap" : 1,
"usage" : [ 0.2999, 0.5, 0.1000, 0.9000 ]
}
各个键值对儿的解读:
make.sh是一个编译TCPServer.cpp的一个shell脚本,懒得写makefile了,里面就一行编译命令。
TCPServer是编译出来的elf可执行文件。
TCPServer.cpp是TCP服务器源码,这个TCP服务器的作用是接受来自垃圾桶(树莓派)发过来的一段TCP报文,里面的信息是上面json文件中的那个对象,它包含了这个垃圾桶最新的状态。服务器收到这个报文后,按照其中的内容更新allTrashesInfo.json文件(读入-修改-写回)。服务器程序是多线程的,每当有一个树莓派建立连接都会pthread_create一个子线程去接收报文更新文件。由于各个线程共享打开的文件,文件属于临界资源,出于线程安全的考虑,应用锁的机制对线程访问文件时上锁,保证每个线程有序更改文件,原理示例如下:
/*进入临界区,加锁*/
pthread_mutex_lock(&mutex);
/*临界区:操作文件*/
pthread_mutex_unlock(&mutex);
/*退出临界区,解锁*/
剩下的两个wrap文件是把用于网络通信的系统调用函数进行了错误处理封装,提供给服务器程序使用,不赘述。
StressTest.sh是测试TCPServer程序用的,测试时在一两秒内迭代了请求512次,还挺快的。
这是一个提供给管理者(环卫部门)或者用户的Web服务器,用于在地图上展示垃圾桶的使用情况,效果如下:
界面很丑不要在意,毕竟直男审美。
这部分比较简单:
https://gitee.com/daniel187/InnovationLab/tree/cpp/Servers
主机系统是Ubuntu18.04;
树莓派跑的官方的是Debian系统;
一般用VSCode通过ssh连接到树莓派上编辑(VSCode天下第一);
https://gitee.com/daniel187/InnovationLab
你要用的话需要自己去百度AI开放平台和天行数据注册用户获取用户信息和密码等,写成一个json文件存入树莓派的进程工作目录,文件名叫personal_secret.json
,程序会读取相关信息的,格式如下:
{
"app_id_": "********",
"api_key_": "********",
"secret_key_": "********",
"tian_key_": "********"
}
最后感谢zl同学的collaboration!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。