前言:

利用APP inventor构建一个APP作为客户端程序,利用Flask框架结合树莓派构建一个服务器端程序,两者间通信,制作出一个木质外壳结构、带有摄像头和机械臂,同时具备人脸检测和红外目标搜索功能的救援机器人。

材料准备:

横截面为边长1.5cm正方形的木条若干米、树莓派4B、BST-4WD拓展板、金属TT电机X4、金属舵机及必要配件X6、12.6V动力锂电池、3D打印齿轮X8、PCA9685舵机驱动板、人体热释红外传感器、手机X2、杜邦线若干条、废弃瓶盖若干

硬件结构:

软件原理:

实物图:





实现功能:

1.通过点击APP上的方向按钮和速度调节滑动条来操纵机器人前、后、左、右、转向的运动以及速度调节。
2.通过点击APP的上摄像头云台控制按钮实现对摄像头方向的水平和垂直调节,并通过APP图像显示区域实时显示opencv采集并处理过的视频流,如果检测到人脸则对人脸进行矩形框标记,从而实现对环境和人脸的感知。
3.通过点击人脸检测按钮,opencv采集单张图像,然后调用百度人脸检测接口进行人脸检测,将返回的数据处理后发送到手机,最终实现在信息显示框查看年龄、性别、表情、是否佩戴口罩、配戴眼镜类型等检测数据,APP调用百度语音合成接口朗读以上数据的效果。
4.点击红外目标搜索按钮,开始进行生命体搜索,如果搜索到红外目标则APP语音合成提示信息。
5.通过点击机械臂控制按钮实现对4自由度机械臂的控制,从而达到机械臂抓取物体并放置到车体上带回的目的。

程序实现:

树莓派Python代码:

# main.py
from flask import Flask, render_template, Response,request
from camera import VideoCamera
from urllib.parse import urlencode
import urllib
import RPi.GPIO as GPIO
import Adafruit_PCA9685
import requests
import base64#引脚定义
left_moto1=20
left_moto2=21
left_pwm=16right_moto1=19
right_moto2=26
right_pwm=13hongwai_pin=22#变量定义
speed=0pwm_left=None
pwm_right=Noneservo_min = 150
servo_max = 600  pwm_servo=Noneface_check_flag='0'#图片存储路径
pic_path='/home/pi/wifi_car/test.jpg'
#百度AI appkey secretkey
ak="qTKX7mY59YeZ1GfiW0HYv1mK"
sk="UHu5yYuQahn7L4DGxPYhi1WL6v5tjnXm"
data_str='收到此检测消息表明人脸检测功能正常,请正式开始使用!'#初始化函数
def init():GPIO.setmode(GPIO.BCM)GPIO.setwarnings(False)GPIO.setup(left_pwm,GPIO.OUT,initial=GPIO.HIGH)GPIO.setup(left_moto1,GPIO.OUT,initial=GPIO.LOW)GPIO.setup(left_moto2,GPIO.OUT,initial=GPIO.LOW)GPIO.setup(right_pwm,GPIO.OUT,initial=GPIO.HIGH)GPIO.setup(right_moto1,GPIO.OUT,initial=GPIO.LOW)GPIO.setup(right_moto2,GPIO.OUT,initial=GPIO.LOW)GPIO.setup(hongwai_pin,GPIO.IN)global pwm_leftglobal pwm_rightpwm_left = GPIO.PWM(left_pwm, 2000)pwm_right = GPIO.PWM(right_pwm, 2000)global pwm_servopwm_servo = Adafruit_PCA9685.PCA9685()pwm_servo.set_pwm_freq(60)#前进函数
def car_forward():GPIO.output(left_moto1,GPIO.HIGH)GPIO.output(left_moto2,GPIO.LOW)GPIO.output(right_moto1,GPIO.HIGH)GPIO.output(right_moto2,GPIO.LOW)pwm_left.start(speed)pwm_right.start(speed)#后退函数
def car_back():GPIO.output(left_moto1,GPIO.LOW)GPIO.output(left_moto2,GPIO.HIGH)GPIO.output(right_moto1,GPIO.LOW)GPIO.output(right_moto2,GPIO.HIGH)pwm_left.start(speed)pwm_right.start(speed)#左转函数
def car_left():GPIO.output(left_moto1,GPIO.LOW)GPIO.output(left_moto2,GPIO.HIGH)GPIO.output(right_moto1,GPIO.HIGH)GPIO.output(right_moto2,GPIO.LOW)pwm_left.start(speed)pwm_right.start(speed)#右转函数
def car_right():GPIO.output(left_moto1,GPIO.HIGH)GPIO.output(left_moto2,GPIO.LOW)GPIO.output(right_moto1,GPIO.LOW)GPIO.output(right_moto2,GPIO.HIGH)pwm_left.start(speed)pwm_right.start(speed)#停止函数
def car_stop():GPIO.output(left_moto1,GPIO.LOW)GPIO.output(left_moto2,GPIO.LOW)GPIO.output(right_moto1,GPIO.LOW)GPIO.output(right_moto2,GPIO.LOW)#获取百度AI access_token
def getAccess_token(AK,SK):host = "https://aip.baidubce.com/oauth/2.0/token?grant_type=client_credentials&client_id="+AK+"&client_secret="+SKresponse = requests.get(host)access_token=''if response:dict=response.json()access_token=dict.get("access_token","none")#print(dict.get("access_token","none"))return access_token#图片进行base64编码函数
def Base64(img_path):with open(img_path, 'rb') as f:image_data = f.read()base64_data = base64.b64encode(image_data)  # base64编码string=str(base64_data,"utf-8")# print(string)return string#请求数据函数
def request_post(base64_code,access_token):request_url = "https://aip.baidubce.com/rest/2.0/face/v3/detect"#请求参数 年龄 性别 表情 口罩 眼镜params={'image':''+base64_code+'','image_type':'BASE64','face_field':'age,gender,expression,mask,glasses'}params=urlencode(params)request_url = request_url + "?access_token=" + access_tokenrequest = urllib.request.Request(url=request_url,data=params.encode("utf-8"))request.add_header('Content-Type', 'application/json')response = urllib.request.urlopen(request)content = response.read()return content#返回数据处理
def baidu_api(path,ak,sk):global data_strbase64_code = Base64(path)token=getAccess_token(ak,sk)data_set=request_post(base64_code,token)print('**********************')print(data_set)print('**********************')string=bytes.decode(data_set)#print(string)dict_data=eval(string)dict_data2=dict_data.get("result","none")dict_data3=dict_data2.get("face_list","none")dict_data4=dict_data3[0]age=dict_data4.get("age","none")age_str="年龄:"+str(age)+","print(age_str)# beauty=dict_data4.get("beauty","none")# beauty_str="beauty:"+str(beauty)# print(beauty_str)gender=dict_data4.get("gender","none").get("type","none")gender_str="性别:"+str(gender)+","print(gender_str)glasses=dict_data4.get("glasses","none").get("type","none")glasses_str="眼镜类型:"+str(glasses)+","print(glasses_str)mask=dict_data4.get("mask","none").get("type","none")mask_str="是否佩戴口罩:"+str(mask)print(mask_str)expression=dict_data4.get("expression","none").get("type","none")expression_str="表情:"+str(expression)+","print(expression_str)data_str=age_str+gender_str+glasses_str+expression_str+mask_str#flask
app = Flask(__name__)#默认路由
@app.route('/')
def index():return render_template('index.html')def gen(camera):global face_check_flagwhile True:if face_check_flag=='1':camera.save_pic()#保存图像print("save pic OK")baidu_api(pic_path,ak,sk)face_check_flag='0'frame = camera.get_frame()yield (b'--frame\r\n'b'Content-Type: image/jpeg\r\n\r\n' + frame + b'\r\n\r\n')#获取视频流路由
@app.route('/video_feed')
def video_feed():return Response(gen(VideoCamera()),mimetype='multipart/x-mixed-replace; boundary=frame')#人脸检测路由
@app.route('/face_check',methods=['GET'])
def face_check():global face_check_flagdata=request.args.get('data')print('The data is :',data)#print("Type is :",type(data))face_check_flag=datareturn data_str#运动控制路由
@app.route('/sport',methods=['GET'])
def sport():data=request.args.get('data')if data=='forward':     car_forward()if data=='back':car_back() if data=='left':car_left()if data=='right':car_right()if data=='stop':car_stop()print("the data is :",data)#print(type(data))return 'Sport OK'#速度调节路由
@app.route('/speed',methods=['GET'])
def getSpeed():data=request.args.get('data')global speedspeed=float(data)return 'Speed OK'#舵机1控制路由
@app.route('/servo1',methods=['GET'])
def getServo1():data=request.args.get('data')angle=int(data)servo_val=int(450/270*angle)+150 pwm_servo.set_pwm(1,0,servo_val)return 'Servo1 OK'#舵机2控制路由
@app.route('/servo2',methods=['GET'])
def getServo2():data=request.args.get('data')angle=int(data)servo_val=int(450/270*angle)+150 pwm_servo.set_pwm(2,0,servo_val)return 'Servo2 OK'#舵机3控制路由
@app.route('/servo3',methods=['GET'])
def getServo3():data=request.args.get('data')angle=int(data)servo_val=int(450/270*angle)+150 pwm_servo.set_pwm(3,0,servo_val)return 'Servo3 OK'#舵机4控制路由
@app.route('/servo4',methods=['GET'])
def getServo4():data=request.args.get('data')angle=int(data)servo_val=int((servo_max-servo_min)/270*angle)+150 pwm_servo.set_pwm(4,0,servo_val)return 'Servo4 OK'#摄像头云台水平调节路由
@app.route('/camera_horizon',methods=['GET'])
def get_cam_horizon():data=request.args.get('data')angle=int(data)servo_val=int(450/270*angle)+150 pwm_servo.set_pwm(5,0,servo_val)return 'camera_horizon OK'#摄像头云台垂直调节路由
@app.route('/camera_vertical',methods=['GET'])
def get_cam_vertical():data=request.args.get('data')angle=int(data)servo_val=int(450/270*angle)+150 pwm_servo.set_pwm(6,0,servo_val)return 'camera_vertical OK'#红外检测路由
@app.route('/hongwai',methods=['GET'])
def hongwai():if GPIO.input(hongwai_pin)==True:print("hongwai_OK")return "hongwaiok"else:print("hongwai_ERROR")return "hongwaierror"if __name__ == '__main__':#初始化函数调用init()#flask运行app.run(host='192.168.43.180' ,port=8123, debug=True)
# camera.py
import cv2 as cv#IP摄像头地址
camera_url='http://admin:admin@192.168.43.73:8081'class VideoCamera(object):#实例视频流获取对象def __init__(self):self.video = cv.VideoCapture(camera_url)def __del__(self):self.video.release()#图像保存函数   def save_pic(self):ret, image = self.video.read()cv.imwrite('/home/pi/wifi_car/test.jpg',image)#获取视频流帧 处理def get_frame(self):success, frame = self.video.read()gray=cv.cvtColor(frame,cv.COLOR_BGR2GRAY)#opencv级联分类器检测face_cascade = cv.CascadeClassifier("data/haarcascade_frontalface_alt.xml")faces=face_cascade.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=4,flags=cv.CASCADE_SCALE_IMAGE,minSize=(100, 100),maxSize=(250,250))# print(faces)#矩形框标记人脸for (x,y,w,h) in faces:frame= cv.rectangle(frame,(x,y),(x+w,y+h),(255,255,0),2)ret, jpeg = cv.imencode('.jpg', frame)return jpeg.tobytes()
<!--index.html 视频显示页面-->
<html><head><title>Video Streaming Demonstration</title></head><body><img src="{{ url_for('video_feed') }}" width="100%" height="120%"></body>
</html>

APP inventor代码块(部分):



结束语:

受树莓派引脚和拓展板的限制,加装更多的传感器很不方便,在Arduino上安装传感器,利用串口将数据发送给树莓派理论上应当可行,但是在实际的编程中要将读取功能放在Flask里面,这却未能达到理想效果,因此这是一个待改进的地方。

树莓派救援机器人制作相关推荐

  1. python程序语言和机器人控制-利用树莓派+Python语言制作一部机器人就是如此简单!...

    前段时间,接触了一款在开源硬件界被称为是"人气之王"的树莓派(Raspberry Pi)袖珍计算机,功能强大的她拥有一颗SOC,集CPU.GPU.DSP和SDRAM为一体,以SD卡 ...

  2. 在西电四年的小结和对小型机器人制作的总结(上)

    一. 前言 在德国这里好山好水好无聊,何况又是个死宅,总感觉要做点啥.根据之前国创的小车和毕设双足机器人的经验和教训,并且打算在master阶段学工业机器人和机器学习方向.所以我打算做一款新式机器人. ...

  3. 擦地机器人毕业设计_救援机器人毕业设计

    论文(设计)题目 一.选题目的和意义 在 21 世纪的今天, 随着自然灾害. 恐怖活动和各种突然事故发生的越来越多, 在灾难 救援中,救援人员用较短的时间在废墟中寻找幸存者的几率比较小,在这种紧急而危 ...

  4. 写字机器人制作教程2.0

    写字机器人制作教程2.0 在一年前发布了写字机器人1.0,做的比较low,疫情期间在家重新建模,升级了2.0 点击前往写字机器人1.0 文件下载请前往文章末尾. 效果图如下: 视频教程 0基础制作写字 ...

  5. 仿生蠕虫机器人制作步骤_SAW 仿生机器人:跟蠕虫一样的运动方式,单靠一个马达就能完成!...

    近年来,救援机器人开始了开挂模式,发展极其迅速.以色列班古里安大学 David Zarrouk 博士带领的研究团队正在研发的 Single Actuator Wave-likeRobot(单独制动器波 ...

  6. 重装上阵怎么造简便机器人_重装上阵机器人怎么制作 机器人制作方法详解

    重装上阵机器人怎么制作?机器人制作需要注意哪些?很多的小伙伴能都不知道怎么制作机器人,所以小编今天带来的就是重装上阵机器人的制作方法,还不知道的小伙伴们快来看看吧! 机器人怎么制作: 1.机器人的制作 ...

  7. 被活捉!6条腿4个轮子2只机械手,半人马救援机器人傲娇登场了

    作者|震霆            出品|遇见人工智能        公众号|GOwithAI 救援机器人也是时候来了解一下了. 只因它的功力如同波士顿动力一样,已经让人一惊. 比如,先接一招: 在我们 ...

  8. 山区灭火机器人_5分钟灭掉4个“房间”的火丨东北林大研发的这个灭火救援机器人获得全国一等奖...

    灭火救援.高铁游中国.擂台对抗.智能搬运--日前,东北林业大学机械创新实验室的同学们带着他们的机器人去"2019中国教育机器人大赛"上打擂台,获得一等奖2项.二等奖6项,三等奖2项 ...

  9. 双足机器人重心在头部_双足机器人制作及其步态运行

    双足机器人制作及其步态运行 一. 实验目的 1 . 掌握实验室设备使用方法 2 . 学会 AutoCAD 知识并运用以及学习 arduino 单片机的基本开发 3 . 了解双足机器人平衡控制方法. 二 ...

最新文章

  1. python-docx 使用教程_python docx 中文字体设置的操作方法
  2. YSlow简介与使用(转)
  3. 基于 Bitbucket Pipeline + Amazon S3 的自动化运维体系
  4. [ Linux ] 釋放記憶體指令(cache) - 轉載
  5. Java多线程:线程属性
  6. php无法下单功能,PHP如何解决并发下单问题?(不一定是下单,举个例)
  7. axios队列 vue_vue axios全攻略
  8. Spring源码解析——如何阅读源码
  9. gridview排序加箭头(二)
  10. nginx支持php解析,upstream模块
  11. Swift中文教程(二十三) 高级运算符
  12. Ubuntu16.04上安装SU(Seismic Unix)的基本步骤
  13. 电竞大数据平台 FunData 的系统架构演进
  14. 区块链开发人员短缺?各大公司献上连环招
  15. 数据分析师如何正确地提意见?
  16. linux下批量查找文件内容
  17. php爬取ins图片_python爬取【追新番】日剧资源
  18. Ubuntu+Tesla M40上OpenCL问题解决过程
  19. C++产生随机数,随机序列和随机分布
  20. 自媒体、短视频博主都在用这5个免费视频网站

热门文章

  1. Selenium IDE的介绍
  2. 机器学习 数据预处理之数据打标签
  3. Java环境配置与eclipse安装破解与汉化
  4. 影响因子真的那么可靠吗?
  5. 多图理解MySQL事务的隔离等级,脏读,不可重复读,幻读的几大概念
  6. HTML5+CSS3笔记
  7. 青春痘的日常治疗方法
  8. 火狐浏览器手动安装插件“组件未验证无法安装”问题解决
  9. [echarts] 图表自适应宽高大小
  10. 限制输入长度,输入数字的大小和禁止输入e