一起打造自己的自动驾驶小车mycar - 3.手机控制小车移动

news/2024/11/16 22:52:34/

Car Assembled

文章目录

  • 1. 功能
  • 2. 代码概述
    • 2.1 消息总线
    • 2.2 组件
    • 2.3 mycar代码目录结构
  • 3. 运动控制
    • 3.1 I2C、PWM与PCA9685
    • 3.2 PCA9685类
    • 3.3 PWMSteering和PWMThrottle类
  • 4. 摄像头
  • 5. 网页控制
  • 6. 配置文件
    • 6.1 subscription和publication属性
  • 7. 安装与运行
    • 7.1 clone代码
    • 7.2 安装依赖
    • 7.3 运行

小车组装好后,我们开始编写在小车上运行的python程序!

本次我们实现用手机来控制小车的移动。效果如下:
Remote Control on Phone

1. 功能

控制小车移动是通过一个网页实现的,这样通过手机或者电脑上的浏览器就能控制小车的移动。

网页上部是监控区域,可以看到小车摄像头的实时画面。

网页中部是控制区域,有两个摇杆,左摇杆控制小车左右转向,右摇杆控制小车前进和后退。

网页下部是功能选择,用于后面扩展功能,Autonomous Mode用于在手动驾驶和自动驾驶模式间切换,Record Video用于录制小车行进的视频,后面可以使用视频和控制输入来训练自动驾驶模型。

2. 代码概述

本次我们实现的功能虽然看起来不太复杂,但部分基础代码对以后的扩展是非常重要的,因此有必要设计一个良好的架构。

2.1 消息总线

在真实的汽车上有一个通信总线 - CAN,Controller Area Network,控制器局域网。汽车上需要通信、交换数据的部件都连接到该总线上。它可以实现点对点、一对多、广播的通信方式。CAN有行业的国际标准。

在我们的项目里用消息总线(message bus)模拟CAN,各组件通过发布/订阅(publish/subscribe)的方式进行通信。redis、kafka、rabbitmq、zeromq等都能实现所需功能,其中redis和zeromq比较轻量,在对比了redis和zeromq的性能后,我选择了zeromq作为mycar的消息中间件。

2.2 组件

组件是指小车上实现特定功能,可以独立运行的部件。mycar项目的组件可能有:运动控制、摄像头、蓝牙手柄、激光雷达、IMU等。

在这篇文章里,我们需要实现的功能模块是:

  • 运动控制,模块名:actuator
  • 摄像头,模块名:camera
  • 网页控制,模块名:web_controller

各具体组件的UML类图如下:
Class Diagram

  • Car
    代表一辆小车,是项目的主类,负责加载配置文件和启动各组件(Component)。
    创建该类需要传入配置文件和小车的运行时间。

  • Component
    是小车组件的抽象接口,组件主要的行为方法是runon_messagepublish_messagestartshutdown方法在小车启动和停止时会自动调用。on_messagepublish_message用来收发消息。run方法在start返回True时有作用,用于在单独线程执行组件长时间运行的业务逻辑,例子是摄像头不断产生图像数据。

  • CAN和ZmqCAN
    代表消息总线的抽象类和zeromq实现,它也是一种组件Component。主要方法是向指定的channel发送消息和订阅消息,分别是publish(channel, message)subscribe(channels, listener)

  • PWMSteering和PWMThrottle
    actuator模块,分别是控制小车方向和速度的类。依赖PCA9685类来发出PWM信号。

  • Camera
    是小车的摄像头类,用于产生实时图像。

  • WebController
    WebController组件用于接收页面输出,发送控制消息到消息总线。

2.3 mycar代码目录结构

├── bin
│   └── run.sh
├── config
│   └── web_drive.yml
├── README.md
├── requirements.txt
└── src├── car.py├── components│   ├── __init__.py│   ├── actuator.py│   ├── camera.py│   ├── can.py│   ├── component.py│   ├── templates│   │   └── index.html│   ├── web_controller.py│   └── zmq_can.py└── utils├── __init__.py├── map_range.py└── pca9685.py

下面分章节详细介绍一些重要的类和组件。

3. 运动控制

3.1 I2C、PWM与PCA9685

PWM,是指脉宽调制Pulse Width Modulation,遥控车一般使用PWM来控制转向和速度,所以2通道的遥控器一路输出到转向舵机,一路输出到电子调速器ESC。

I2C,IC间的通信协议,Inter-Integrated Circuit,包含一条双向串行数据线SDA,一条串行时钟线SCL。

PCA9685,是一个通用的16路舵机控制板,有16个输出端口,我们需要用到其中2个。

我们不需要了解如何产生I2C和PWM信号,在我们的项目里,由软件控制jetson nano的GPIO口产生I2C信号给PCA9685,PCA9685再生成PWM信号去驱动小车运动。

接线方式上一篇文章有讲到。

3.2 PCA9685类

这个类使用了adafruit公司的python包adafruit-circuitpython-servokit来控制舵机角度与ESC速度。它已经封装好了ServoKit这个类。

使用上一讲的接线方式,ServoKit的使用方法如下:

servokit = ServoKit(channels=16, address=0x40)
# 控制PCA9685第一个口的舵机的转动角度
servokit.servo[0].angle = 135  # 角度范围 0 ~ 180度
# 控制PCA9685第二个口的ESC的速度
servokit.continuous_servo[1].throttle = 0.3  # 速度的范围是 -1 ~ 1,大于0表示向前移动,如果输入负数代表后退,注意从前进切换到后退要输入两次同样的负数

3.3 PWMSteering和PWMThrottle类

这两个类实现了Component接口,调用PCA9685类来实现功能。

  • PWMSteering
    支持定义正前方的前进角度(straight_angle),以防小车有偏差;也支持自定义可转的角度范围(full_left_angle, full_right_angle)。默认的是小车舵机支持的90度的转向范围。

  • PWMThrottle
    支持自定义控制速度的范围(min_throttle, max_throttle),如(-0.3, 0.3),会把(-1, 1)的值映射到这个范围内,因为小车速度较快,调小点可以更方便控制小车,以防撞坏。

4. 摄像头

Camera这个类比较简单,它使用cv2.VideoCapture()来捕捉摄像头图像。

如果连接的是CSI摄像头,那么使用gstreamer pipline + Nvidia的nvarguscamerasrc,参数可以参考官方文档。

如果是在其他平台上做测试,可以使用cv2.VideoCapture(0)来使用默认的摄像头设备。

5. 网页控制

WebController类用Flask来启动了一个本地web server,端口为8080

实时图像展示部分使用的是返回帧图片的HTTP报文的方式,使用<img>HTML标签就可以让浏览器会不断加载新的帧。帧的格式为:

--frame
Content-Type: image/jpeg[图像字符串]

这种方式实现比较简单。

摇杆部分使用的是一个开源的js库做的,其实用一个摇杆就可以实现方向和速度的调节的,这里我选择分开来控制。

两个功能控制选项目前还没有用到,先忽略。

6. 配置文件

最后是小车运行的配置文件,用来配置小车需要加载的所有组件Component,一个例子如下:

components:zmq_can:  # 模块名server_mode: True  # 创建实例的参数actuator:  # 该模块有两个类PWMSteering:  # 第一个类subscription: ['web_steering']  # 接收来自这个channel的消息channel: 0PWMThrottle:  # 第二个类subscription: ['web_throttle']channel: 1min_throttle: -0.3max_throttle: 0.3camera:  #该模块只有一个类publication: ['cam/image']  # 把图像发送到这个channeldevice: '/device/video0'web_controller:subscription: ['cam/image']publication: ['web_steering', 'web_throttle', 'web_record', 'web_autonomous']  # 发送消息到多个channel
  • 顶层,使用components作为键,代表是小车的组件
  • 次层缩进,以组件的模块(文件)作为键,如果该模块只有一个类,那么第三层缩进可以直接写该类的创建时传入的参数,如camera
  • 最后层缩进,配置组件类创建时传入的参数

6.1 subscription和publication属性

这两个属性是每个Component都有的属性,默认为空([]),分别代表组件要订阅的消息和要发出的消息。

7. 安装与运行

介绍完项目的代码后,我们看看怎么跑起来。

7.1 clone代码

代码已开源到github,首先clone一下:

git clone https://github.com/evan-wu/mycar.git --branch blog-3 --single-branch

7.2 安装依赖

注意jetson nano的Jet Pack已经自带了python3和编译好的opencv,切勿自己手动安装opencv。安装以下4个依赖就可以了:

pip3 instal pyyaml adafruit-circuitpython-servokit flask pyzmq

7.3 运行

cd mycar
chmod +x bin/run.sh
bin/run.sh config/web_drive.yml 120

用浏览器(手机浏览器)访问: http://<jetson nano ip>:8080 就可以了。

欢迎github/blog点赞、留言、讨论!

后续预告:手柄控制小车移动,实现PID寻线小车算法…


http://www.ppmy.cn/news/724855.html

相关文章

手机控制汽车无钥匙进入一键启动方案设计

车辆手机控车解决方案&#xff0c;无钥匙进入&#xff0c;车辆一键启动系统方案。手机如何远程控制汽车&#xff0c;随着科技的不断发展&#xff0c;现在汽车加配一键启动无钥匙进入国&#xff0c;且手机也能操控汽车了&#xff0c;下面一起来看看吧&#xff01; 手机控制汽车远…

手机远程启动汽车,汽车远程启动还是手机控制好!有一种远程手机启动热车系统非常的不错是什么功能知道吗?

手机远程车控&#xff0c;可以通过手机APP进行远程操控&#xff0c;并且可以同时开启空调&#xff01; 逐渐进入冬季&#xff0c;气温也在走下坡趋势。对于许多拥有爱车的人来说&#xff0c;冬季驾驶时车内温度成为了他们最为担心的问题。只要进入车内&#xff0c;就会感觉到寒…

魔改车钥匙实现远程控车:(3)通过蓝牙与手机通信并持久化保存参数设置

前言 在前两篇文章中&#xff0c;我们已经完成了控制与距离感应&#xff0c;建议先看完前两篇文章再来看这篇文章&#xff0c;不然你会看的一头雾水的。 在今天这篇文章中&#xff0c;我们需要解决的是将某些参数设置持久化储存在 ESP32 的储存器中&#xff0c;并且在重新上电…

汽车PKE无钥匙入一键启动手机智能控车系统

汽车手机控制智能一键启动.智能无钥匙进入、一键启动、遥控启动、寻车功能、智能防盗系统,离车自锁、中控智能化&#xff0c;手机控车。可以无限距离手机APP界面操控。汽车无钥匙进入系统&#xff0c;简称PKE&#xff0c;该系统采用了RFID无线射频技术和车辆身份编码识别系统&a…

手机与汽车之间的控制方法

手机控车一键启动无钥匙进入 1.手机远程启动车辆&#xff1a;移动管家手机控车智能控车系统&#xff0c;在有手机信号的任何地方&#xff0c;使用车主加密绑定的手机发送指令到车辆&#xff0c;发动机自动启动并回复短信致车主手机提示车辆已经启动。&#xff08;车辆在启动状…

安卓手机控制小车(自己做成功了,有全套资料)

注:图片不知道怎么显示,可以去我空间的相册里查看图片。 小车分几部分组成:1、安卓手机控制软件:该软件可以通过蓝牙发送前进、后退、左转、右转指令(ASCII码)。2、蓝牙模块:通过与手机连接后,可以接收到手机发送的指令,采用HC_06模块。3、单片机最小系统:蓝牙模块将…

手机智能控制汽车系统作用详解

汽车手机启动&#xff0c;汽车远程启动是装置在智能汽车的一部分&#xff0c;是实现简远程遥控启动汽车的一个智能装置&#xff0c;同时也可以熄火。汽车手机启动可以在原车钥匙保留模式改装&#xff0c;也可以独立在汽车上改装。 目前很多汽车已经配有一键启动智能无钥匙进入…

uni-app获取节点的相关信息

获取单个节点&#xff1a; selectorQuery.select(selector) 在当前页面下选择第一个匹配选择器 selector 的节点&#xff0c;返回一个 NodesRef 对象实例&#xff0c;可以用于获取节点信息。 selector 说明&#xff1a; selector 类似于 CSS 的选择器&#xff0c;但仅支持下列…