PiRex – 基于 Raspberry Pi 的遥控机器人





5.00/5 (20投票s)
本文描述了PiRex机器人,它可以通过Web浏览器或专用客户端应用程序使用REST API进行控制。

引言
去年我发布了cam2web开源项目,旨在通过HTTP将摄像头作为MJPEG流进行传输。尽管该项目旨在支持多种平台,但最初的目标是从树莓派传输摄像头流,以便可以远程观看。该项目本身可用于家庭安防、物联网设备等多种用途。然而,最初它是作为另一个项目——构建一个遥控机器人——的第一步。
我过去做过一些业余机器人项目。然而,这些项目都是基于一些专用控制器,这使得它们有点昂贵。这次的计划是使用或多或少的传统组件,这些组件可以从其他电子/机器人/物联网项目中重复使用,并降低总价。
我心中的想法很简单——建造一个带有摄像头的遥控机器人,这样就可以远程从“机器人的眼睛”看东西。显然,它应该能够四处移动,所以轮子和电机是必不可少的。此外,一些传感器也可能有用,例如超声波距离传感器。
另一个想法是开发一些可重用的软件,可以用来控制类似规格的机器人。它应该允许直接从网页浏览器进行一些简单的机器人控制,或者开发专门的客户端应用程序来提供更高级的控制和添加额外功能,例如计算机视觉。
因此,决定基于 Raspberry Pi 主板构建机器人。它的价格相对较低,并提供了足够的电力和连接性来处理将想法付诸行动所需的所有其他电子设备。
至于名字,它被称为 **PiRex**。这是在一次散步中与孩子们进行短暂头脑风暴的结果。为什么叫 PiRex?嗯,就像我最小的孩子说的——它是基于 Pi 的 Rex。不,它看起来一点也不像霸王龙那样可怕。但这个名字就这么定了。
快速预览
在深入探讨构建过程和所开发软件的细节之前,最好快速预览一下最终结果。下面是它最终的样子。

没什么特别花哨的——只是一个轮式机器人。是的,它确实不是霸王龙。更像是一个带轮子的饭盒,配备了摄像头、距离传感器、Wi-Fi 天线和一个电池模块。
此外,还有一个快速视频演示,展示了通过网页浏览器和专用 .NET 客户端应用程序控制 PiRex 机器人的过程。网页界面使一切变得简单——在 Raspberry Pi 上运行软件,机器人就可以通过您选择的网页浏览器进行控制。而客户端应用程序则允许通过游戏手柄等设备进行更灵活的控制,并集成不同的图像处理 SDK 来处理来自机器人的视频。
GitHub项目
所有已开发的软件都发布在 GitHub 上。因此,如果有人想重复构建步骤并开始玩机器人,所有内容都在那里,以便快速入门,为任何自定义提供基础。
硬件
在开始编写/编译任何代码之前,我们最好先构建机器人。为此,我们最好先获取所有零件,以便估算总成本并思考如何将它们组装在一起。当然,事情可以迭代地完成,随着项目的进展添加新组件。然而,这可能导致项目的完全重建,有时甚至不止一次,这既耗时又耗钱(或者只是钱2)。我们最好避免的问题是,从我们认为最关键的几个组件开始,用它们构建一些东西,然后意识到没有足够的空间来安装下一个组件,或者没有足够的电池电量来满足我们所需的所有电子设备,或者最终组装变得足够重,而所选电机根本无法发挥作用。
在我达到最终工作成果的过程中,发生了多少此类错误?两次。首先,无法将所有东西都放入最初计划的紧凑设计中。然后发现最初选择的电机太便宜了,没有足够的动力来驱动机器人。
物料清单
下面是用于构建PiRex机器人的组件清单及其价格估算(基于亚马逊或任何其他更合适的在线商店)
- 树莓派主板 - 32.00英镑。
- 树莓派摄像头模块 - 20.00英镑。
- 4个6V 60 RPM电机,DiddyBorg v1车轮和安装套件 - 60.00英镑。是的,看起来是一项投资。但这是一个简单的事实——好的电机不便宜;便宜的电机不好。避免任何用于Arduino项目的廉价塑料——它无法承受任何或多或少的严重负载。
- 带天线的USB Wi-Fi模块 - 10.00英镑。带天线的模块比不带天线的模块更受青睐,因为信号质量可能会导致讨厌的通信问题。
- 用于手机/平板电脑的便携式充电器,5V输出 - 仅用于为树莓派主板供电。我买的那个似乎已经不再有售了。所以,假设大约 20.00英镑。
- L293D 步进电机驱动器。通常5个一包,大约 2.00英镑。
- HC-SR04 超声波测距传感器 - 价格略有波动,我们假设 4.00英镑。
- 用于树莓派镜像的 8 GB micro SD 卡 - 大约 6.00英镑,具体取决于型号。
- 树莓派摄像头线缆 - 4.50英镑。这可能是一个可选组件,具体取决于构建方式。默认线缆对我的设置来说有点太短,所以需要一根更长的。
- 4节AA电池为电机供电。购买了可充电的金霸王电池,大约可能需要 8.00英镑。
- 4节AA 6V电池座。大约 1.00英镑 两件。
- 原型PCB电路板。20块一包大约 5.00英镑。
- 16引脚IC插座,在焊接时可以避免烧坏电机驱动芯片——5个一包不到 1.00英镑。
- USB Micro B 分线板,用于从电源获取5V并将其导向树莓派 - 大约 4.00英镑。您不太可能直接将树莓派连接到电源,因为它可能很好地隐藏在您的设置中。因此,在外部设置一个微型USB分线板可能会有很大帮助。此外,在电源和Pi之间设置一个开关按钮会更简洁——避免拉扯任何电缆来打开/关闭机器人。
- PCB安装螺丝接线端子 - 20个一包 1.50英镑。这是一个可选组件,但对于连接不同的组件非常方便。
- 一个午餐盒。是的,你没听错,我用一个午餐盒做机器人的主体。我没有3D打印机来制作定制的机身,所以选择了容易切割且不太重的东西。假设 2.00英镑。
- 最后,一些电线、电阻器、几个用于状态指示的LED、几个开关按钮用于打开和关闭设备,一些螺母和螺栓等。这些我从其他项目中都有足够多的,但我们再算上 10.00英镑(应该绰绰有余)。
总共是191.00英镑。为了安全起见,以防有什么遗漏或只是有一些备用预算,让我们为基于树莓派的机器人计划约200英镑。
这听起来可能不便宜。但要降低最终价格,能做的事情很少。最昂贵的组件是带轮子的电机。嗯,你必须接受这一点。试图在它们上面省钱并购买更便宜的东西,最终可能会导致价格上涨,当机器人无法真正移动时。在电子元件或电池上节省太多钱也可能很困难。
另一个选择是使用一些现成的机器人套件。这确实节省了时间。但对我来说,它也剥夺了乐趣和创造力。无论如何,许多套件实际上更贵,即使没有包含所有电子元件。
组装
一旦所有组件都到手,就可以将它们组装成一个工作的机器人了。为了控制电机,使用了一个简单的L293D芯片,它可以独立控制多达两个电机。芯片本身只能打开/关闭电机并控制其旋转方向。将其1,2EN和3,4EN引脚(引脚1和9,参见L293D数据手册)连接到脉冲调制模块(PWM)也可以控制电机速度。然而,树莓派只有一个硬件PWM,因此无法控制两个电机的速度(除非使用软件PWM,这将在后面提到)。
**注意**:要快速了解 L293D、其接线和简单控制,请参阅本教程:使用 Python 和 Raspberry Pi 控制直流电机。
为了方便连接,最好将较小的组件放在单独的电路板上。例如,如下图所示,我将L293D芯片放在自己的分线板上,该分线板具有用于连接电机、电源和树莓派引脚的独立端子块。这样,所有焊接都只集中在这些小板上,而其余连接则通过将电线拧入一侧的端子块并连接到另一侧的树莓派引脚来完成。

第二个分线板上装有2个LED(用于显示运行时和连接状态)以及一个用于连接两个开关按钮的端子块(计划用于与机器人进行一些交互)。所有必要的电阻器也都在那里;只缺少与树莓派和组件的连接。虽然LED和开关对于最终结果来说确实是可选的,但该板也用于连接HC-SR04超声波传感器(用于分压器的下两个电阻器和一个端子块)。
**注意**:有关 HC-SR04 传感器接线和使用的更多信息,请参阅本教程:HC-SR04 超声波传感器与 Raspberry Pi 接口。

有了上面两个分线板,现在是时候将它们与其他一些组件一起放入我们的饭盒中——这完成了机器人的第一层。一些接线端子已经连接到电机和开关,而另一些则等待添加装有树莓派的第二层。**注意**:还有两个额外的开关暂时松散放置。它们将用于打开/关闭机器人,并为电机供电(在大多数软件调试过程中,电机并不是真正需要的,所以让它们独立非常方便)。

组件的第二层装有树莓派和另一个小分线板,该分线板用于从微型USB插座获取电源并将其引导至电子元件(通过开关来控制所有设备的开/关)。最初计划使用相同的便携式充电器电池(提供两个输出)为树莓派和电机供电,因此分线板上有两个USB连接器。然而,后来决定使用一包AA电池单独为电机供电,因此分线板通过一个额外的接线端子得到了扩展。

现在,添加最终和主要的组件,树莓派,完成了大约99%的组装。如果我们打开PiRex的引擎盖,它看起来是这样的。

最后,添加电池和 Wi-Fi 模块,使其准备就绪。当然,前提是所有连接都正确,并且软件已就位。

连接组件
尽管使用哪个GPIO引脚连接不同组件到树莓派是完全自定义的(下面讨论的软件可以为此进行配置),但下面是我在构建PiRex机器人时使用的引脚分配。仅供参考。
| 2个开关按钮的电源 | 3.3伏 | 1 | 2 | 5伏 | HC-SR04电源(VCC) | 
| GPIO 2 | 3 | 4 | 5伏 | L293D芯片电源(VCC1,引脚16) | |
| GPIO 3 | 5 | 6 | GND | LED和开关按钮的地线 | |
| 运行时状态LED(运行软件) | GPIO 4 | 7 | 8 | GPIO 14 | |
| L293D 地线(引脚 4、5、12、13) | GND | 9 | 10 | GPIO 15 | |
| 连接状态LED | GPIO 17 | 11 | 12 | GPIO 18 | 启用左电机 (1,2EN, 引脚 1) | 
| 来自开关按钮 1 的信号 | GPIO 27 | 13 | 14 | GND | HC-SR04 接地 | 
| 来自开关按钮 2 的信号 | GPIO 22 | 15 | 16 | GPIO 23 | 左电机输入 1(引脚 2) | 
| 3.3伏 | 17 | 18 | GPIO 24 | 左电机输入 2(引脚 7) | |
| GPIO 10 | 19 | 20 | GND | ||
| GPIO 9 | 21 | 22 | GPIO 25 | HC-SR04 触发 | |
| GPIO 11 | 23 | 24 | GPIO 8 | ||
| GND | 25 | 26 | GPIO 7 | ||
| GPIO 0 | 27 | 28 | GPIO 1 | ||
| 右电机输入 1(引脚 15) | GPIO 5 | 29 | 30 | GND | |
| 右电机输入 2(引脚 10) | GPIO 6 | 31 | 32 | GPIO 12 | |
| 启用右电机 (3,4EN, 引脚 9) | GPIO 13 | 33 | 34 | GND | |
| GPIO 19 | 35 | 36 | GPIO 16 | ||
| HC-SR04 回波,通过分压器 | GPIO 26 | 37 | 38 | GPIO 20 | |
| GND | 39 | 40 | GPIO 21 | 
这就是关于机器人构建和不同组件连接的全部内容。通过 L293D 驱动芯片和 HC-SR04 超声波传感器的数据手册,并遵循一些教程,应该不难弄清楚哪些引脚连接到哪里,并首先在测试应用程序中使其工作。
软件
PiRex 机器人端的软件主要基于 cam2web 代码库。事实上,大约 95% 的代码都来自那里。原因在于 cam2web 提供了本项目所需的大部分基础设施——从摄像头获取图像、基于 mongoose 库的嵌入式 Web 服务器、将图像作为 MJPEG 流传输、允许通过 REST API 查询/配置对象的基础设施类等。
如果我们看一下 PiRex 代码的核心类图,就会发现项目中只增加了两个类(当然还有一些连接代码)。这解释了为什么 cam2web 确实是构建这个机器人项目的第一大步。

让我们快速回顾一下从 cam2web 项目中获得了什么。
XWebServer 类实现了一个基于 mongoose 库 API 的嵌入式 Web 服务器。它允许注册实现 IWebRequestHandler 接口的对象集合,这些对象为特定请求提供响应。例如,XVideoSourceToWeb 类接受任意视频源(实现 IVideoSource 接口并通过 IVideoSourceListener 回调接口生成新图像的类)并提供两个请求处理程序——一个将图像作为 MJPEG 流传输,另一个将图像作为单个 JPEG 快照提供。
XEmbeddedContentHandler 类允许从嵌入式资源中提供静态内容。cam2web 项目附带一个 **web2h** 工具,该工具允许将某些类型的文件(Web 资源)转换为 C 头文件。这样,所有必需的 Web 内容都可以直接嵌入到最终的可执行文件中,使其独立于任何外部文件。
最后,XObjectInformationRequestHandler 和 XObjectConfigurationRequestHandler 类提供通过 REST API 对实现 IObjectInformation 接口的对象进行只读访问,或对实现 IObjectConfiguration 接口的对象进行读写访问。例如,PiRex 版本和功能的信息通过只读接口提供,而摄像头的设置可以更改,并通过 IObjectConfiguration 接口公开。
为了演示上述类的使用,这里有一个小代码片段,它配置了一个Web服务器来流式传输树莓派的摄像头,允许通过REST API更改其设置,查询设备的一些信息,并提供一些静态嵌入内容。这一切都来自cam2web项目,并且使用起来非常简单。那么为什么不重用呢?
XWebServer               server;
XVideoSourceToWeb        video2web;
shared_ptr<XRaspiCamera> camera = XRaspiCamera::Create( );
// subscribe XVideoSourceToWeb object for video frame events
camera->SetListener( video2web.VideoSourceListener( ) );
// add JPEG and MJPEG handlers to the web server
server.AddHandler( video2web.CreateJpegHandler( "/camera/jpeg" ) ).
       AddHandler( video2web.CreateMjpegHandler( "/camera/mjpeg", 30 ) );
// allow changing camera's setting using REST
shared_ptr<IObjectConfigurator> cameraConfig = make_shared<xraspicameraconfig>( camera );
server.AddHandler( make_shared<XObjectConfigurationRequestHandler>(
                   "/camera/config", cameraConfig ) );
                   
// allow querying some read only information through REST
PropertyMap versionInfo;
versionInfo.insert( PropertyMap::value_type( "product", "pirexbot" ) );
versionInfo.insert( PropertyMap::value_type( "version", "1.0.0" ) );
versionInfo.insert( PropertyMap::value_type( "platform", "RaspberryPi" ) );
server.AddHandler( make_shared<XObjectInformationRequestHandler>(
                   "/version", make_shared<XObjectInformationMap>( versionInfo ) ) );
                   
// add some static embedded content
server.AddHandler( make_shared<XEmbeddedContentHandler>( "/", &web_index_html ) ).
       AddHandler( make_shared<XEmbeddedContentHandler>( "index.html", &web_index_html ) ).
       AddHandler( make_shared<XEmbeddedContentHandler>( "styles.css", &web_styles_css ) );
       // ...
       
// start the camera and the web server
camera->Start( );
server.Start( );       
</xraspicameraconfig>
上述代码并非cam2web功能的完整演示。例如,它没有展示如何配置访问权限——哪些请求处理程序可以被所有人访问,哪些只能被已知用户访问。这可以从描述cam2web项目的原始文章中找到,或者深入研究提供的源代码。
控制电机
使用L293D芯片控制电机非常容易,而且有大量关于这个主题的教程。其中大部分是基于Python的,但将其翻译成C代码非常简单。为了让电机移动,我们所需要做的就是将**使能**引脚设置为高电平,然后将**输入1**引脚设置为高电平,同时将**输入2**引脚设置为低电平。要改变旋转方向,需要交换输入引脚——将**输入1**引脚设置为低电平,同时将**输入2**引脚设置为高电平。如果我们想停止所有操作,只需将**使能**引脚重新设置为低电平即可。
为了在 C 应用程序中操作树莓派的引脚,可以使用 Wiring Pi 库。它随官方 Raspbian 镜像预装。下面是一个快速示例,说明如何让电机移动。
#include <wiringPi.h>
// configure pins
pinMode( BOT_PIN_MOTOR_LEFT_INPUT1, OUTPUT );
pinMode( BOT_PIN_MOTOR_LEFT_INPUT2, OUTPUT );
pinMode( BOT_PIN_MOTOR_LEFT_ENABLE, OUTPUT );
// move motors "forward"
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT1, HIGH );
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT2, LOW );
digitalWrite( BOT_PIN_MOTOR_LEFT_ENABLE, HIGH );
// move motors opposite direction
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT1, LOW );
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT2, HIGH );
digitalWrite( BOT_PIN_MOTOR_LEFT_ENABLE, HIGH );
// stop motors
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT1, LOW );
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT2, LOW );
digitalWrite( BOT_PIN_MOTOR_LEFT_ENABLE, LOW );
上面的代码允许控制电机的旋转方向,但不能控制速度。要实现速度控制,需要将**使能**引脚连接到树莓派上一个**PWM**使能的引脚。问题是树莓派只有一个硬件PWM,因此无法通过硬件支持来控制左右两个电机的速度。作为替代解决方案,可以使用软件PWM,它可以在树莓派的任何GPIO引脚上启用。下面的代码演示了基于软件PWM的速度控制。
// configure pins
pinMode( BOT_PIN_MOTOR_LEFT_INPUT1, OUTPUT );
pinMode( BOT_PIN_MOTOR_LEFT_INPUT2, OUTPUT );
softPwmCreate( BOT_PIN_MOTOR_LEFT_ENABLE, 0, 100 );
// rotate motor at half the speed
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT1, HIGH );
digitalWrite( BOT_PIN_MOTOR_LEFT_INPUT2, LOW );
softPwmWrite( BOT_PIN_MOTOR_LEFT_ENABLE, 50 );
// full speed
softPwmWrite( BOT_PIN_MOTOR_LEFT_ENABLE, 100 );
// stop the motor
softPwmWrite( BOT_PIN_MOTOR_LEFT_ENABLE, 0 );
虽然软件PWM确实允许控制电机速度,但它不如硬件PWM高效。Wiring Pi库为每个配置的软件PWM创建一个后台线程,该线程频繁更新所选GPIO引脚的状态。结果是它增加了CPU负载,进而更快地耗尽电池。然而,软件PWM不仅影响系统性能,还会受到系统性能的影响。如果由于处理其他计算而导致CPU负载很高,则软件PWM的线程可能无法在平滑速度控制所需的时间间隔内更新GPIO状态。由于这些问题,PiRex配置中默认禁用电机速度控制。
测量与障碍物的距离
使用 HC-SR04 超声波传感器测量距离也是一项非常简单的任务。作为一种极其流行的传感器,它在许多业余项目中被广泛使用,因此不难找到有关它的教程。传感器的原理非常简单。它发出超声波,超声波从障碍物反射回来,并返回到传感器。因此,只需测量发出声波和检测其返回之间的时间。由于声速已知,计算到障碍物的距离就变得微不足道了。
HC-SR04 不会持续发出声波。相反,它需要被告知何时发出声波,然后等待传感器接收反射。两个 GPIO 引脚用于与传感器交互。**触发**引脚用于告知传感器何时发送声波——它必须在短时间内设置为高电平,然后恢复为低电平。**回波**引脚随后用于检测声波何时发送以及何时返回。触发测量后,**回波**引脚在发送波时变为高电平,并在其返回时恢复为低电平。将所有这些放入代码中可能看起来像这样
uint32_t start, stop; // time in microseconds
// trigger measurement round
digitalWrite( BOT_PIN_ULTRASONIC_TRIGGER, HIGH );
delayMicroseconds( 10 );
digitalWrite( BOT_PIN_ULTRASONIC_TRIGGER, LOW );
// wait for the echo wave start
start = micros( );
while ( digitalRead( BOT_PIN_ULTRASONIC_ECHO ) == LOW )
{
    start = micros( );
}
// wait for the echo wave stop
stop = micros( );
while ( digitalRead( BOT_PIN_ULTRASONIC_ECHO ) == HIGH )
{
    stop = micros( );
}
// calculate the distance to an obstacle (cm)
float lastDistance = (float) ( stop - start ) / 58.2f;
上面的示例代码表示稍微简化过的版本,但它给出了想法。为了改进代码,需要处理可能出现的超时,即回波没有在预期的时间间隔内开始/停止。
配置 PiRex 软件
尽管上面提供了参考的 GPIO 布局(树莓派的引脚连接到哪里),但使用 PiRex 软件并非必须如此。最低要求是机器人拥有摄像头和基于 L293D 的电机驱动器。然而,它们的连接方式并不重要。相反,可以进行配置。超声波传感器也一样——它是一个可选组件,因此可能根本不连接。
为了定制构建,有`BotConfig.h`头文件。它包含许多`#define`指令,允许指定树莓派的哪些引脚用于哪些目的。只需更改以反映您的设置,即可开始使用。
构建和运行
构建PiRex代码就像运行`make`命令一样简单。唯一需要记住的是,发布版本将所有Web资源直接嵌入到可执行文件中,以便始终提供默认的Web UI,而无需依赖任何额外文件。这意味着必须首先构建`web2h`工具——该工具用于将一些常见的Web文件转换为头文件中定义的C结构。
从项目根文件夹运行以下命令,将在**build/release/bin**中生成所需的可执行文件。
pushd . cd src/tools/web2h/ make popd pushd . cd src/app/ make popd
**注意**:PiRex 构建成功需要安装 libjpeg 开发库(默认可能未安装)
sudo apt-get install libjpeg-dev
构建完成后,PiRex 软件即可运行。这意味着机器人已准备好投入使用,前提是硬件部分也已完成并且配置反映了实际的 GPIO 引脚连接。
注意:有许多命令行选项可用于更改默认摄像头分辨率、Web 侦听端口、身份验证设置等。所有这些都继承自 cam2web 项目。只需使用 -? 键运行应用程序即可查看可用配置选项列表。
Web 界面
正如前面提到的,PiRex 应用程序附带一个内置的 Web UI。这意味着一旦应用程序运行,您只需在您选择的 Web 浏览器中输入 IP 地址:端口即可连接并开始控制您的机器人。

默认视图仅显示机器人摄像头的当前视图。然而,“控制”选项卡允许控制机器人的移动和获取距离测量,而“摄像头”选项卡允许更改不同的摄像头设置。
GitHub 仓库提供了默认 Web UI 的源代码,因此如果需要更改任何内容,都在那里。只是不要忘记重新构建应用程序。另一种方法是将所有必需的 Web 内容放入一个单独的文件夹,然后告诉 PiRex 应用程序从那里提供静态 Web 内容(使用 **-web:folder_name** 选项)。这将使在将最终内容嵌入到可执行文件之前更快地调试 Web UI 部分。**注意**:在调试模式下构建会自动用 Web 内容填充该文件夹,并且应用程序从该文件夹提供内容。
.NET 客户端应用程序
虽然PiRex机器人可以直接通过网页浏览器控制,客户端无需额外软件,但在某些情况下,专用应用程序可能更适合任务。例如,我发现通过点击UI按钮操作机器人并不能提供最佳控制,因此无法轻松执行某些技巧。相反,使用游戏手柄设备并用独立轴控制左右电机,可以更好地控制机器人,从而更快地切换不同的移动模式。另一个例子是在来自机器人摄像头的视频上使用一些图像处理和/或计算机视觉算法。专用客户端应用程序可能更适合许多此类任务,而浏览器环境实现它们可能会复杂得多(如果可能的话)。

为了提供控制PiRex机器人额外的灵活性,还提供了一个.NET客户端应用程序,它允许查看机器人的摄像头并通过暴露的REST API操作机器人。为了演示另一种控制方式,它支持游戏手柄设备,这样机器人的操作变得更加敏捷。
将 .NET 客户端与任何可用的计算机视觉 SDK 结合使用,可以将机器人变成许多有趣应用程序的开发平台。它可以用于一些旨在在现实世界环境中寻找隐藏物品的趣味游戏,也可以用于一些检测任务,在这些任务中,较小的机器人更适合杂乱且移动空间有限的环境。
与其他应用程序的接口 - REST API
如上所述的应用程序所示,PiRex 机器人提供了与其他应用程序交互的 API,以便可以开发原生客户端并提供更高级的机器人控制或添加额外功能,例如计算机视觉。
第一件事是从机器人中获取视频流,它以MJPEG流的形式提供。它不提供最佳压缩——只是一串独立的JPEG。然而,它实现起来非常简单,因此受到各种应用程序的支持。访问MJPEG流的URL格式是
http://ip:port/camera/mjpeg
如果需要单个图像,下一个 URL 提供最新的摄像头快照
http://ip:port/camera/jpeg
所有其他 URL 提供机器人的信息(版本、状态、配置),通过 HTTP GET 请求以 JSON 格式提供,或者用于控制机器人——通过 JSON 格式的命令发送 HTTP PUT 请求。
获取版本信息
要获取 PiRex 机器人软件的版本信息,可以使用 **http://ip:port/version** URL,它以如下格式提供信息
{
  "status":"OK",
  "config":
  {
    "platform":"RaspberryPi",
    "product":"pirexbot",
    "version":"1.0.0"
  }
}
获取功能和标题
要查明 PiRex 机器人是否配备了距离测量传感器或是否允许控制电机速度,请使用 **http://ip:port/info** URL。它还会报告机器人的标题,该标题可以指定为支持的命令行选项之一。
{
  "status":"OK",
  "config":
  {
    "device":"PiRex Bot",
    "providesDistance":"true",
    "providesSpeedControl":"false",
    "title":"My Home Robot"
  }
}
距离测量
为了查询PiRex机器人执行的距离测量,使用 **http://ip:port/distance** URL。它提供最近一次的测量值(厘米),以及最近5次测量的中位数。
{
  "status":"OK",
  "config":
  {
    "lastDistance":"128.95",
    "medianDistance":"127.25"
  }
}
控制电机
对于电机控制,使用 **http://ip:port/motors/config** URL。如果发送 GET 请求,则回复只包含电机的当前状态。但这并没有多大用处,因为大多数时候电机都是静止的,除非被告知移动。
{
  "status":"OK",
  "config":
  {
    "leftPower":"0",
    "rightPower":"0"
  }
}
然而,发送PUT请求是告诉机器人移动所必需的。这是通过一个简单的JSON字符串完成的,该字符串表示两个电机的功率在[-100, 100]范围内。如果未启用速度控制,则只有三个可能的值:100 - 向前旋转,0 - 不移动,-100 - 向后旋转(尽管机器人也会接受中间值,但会进行阈值处理)。如果启用了速度控制,则速度值可以是上述范围内的任何值。
例如,下面的命令使机器人顺时针旋转(向右旋转)。
{
  "leftPower":"100",
  "rightPower":"-100"
}
相机配置
通过向 **http://ip:port/camera/config** URL 发送 GET 请求,可以检索 PiRex 机器人摄像头的当前配置,该 URL 列出了所有可用属性的当前值
{
  "status":"OK",
  "config":
  {
    "awb":"Auto",
    "brightness":"63",
    "contrast":"41",
    "effect":"None",
    "expmeteringmode":"Average",
    "expmode":"Night",
    "hflip":"1",
    "saturation":"16",
    "sharpness":"100",
    "vflip":"1",
    "videostabilisation":"0"
   }
}
同样,要更改任何属性,必须向同一 URL 发送 POST 请求,提供一个或多个要设置的配置值。例如,下面是更改亮度和对比度的命令
{
  "brightness":"50",
  "contrast":"15"
}
相机信息
要获取有关机器人摄像头的一些信息,例如其当前分辨率,可以使用 **http://ip:port/camera/info** URL。
{
  "status":"OK",
  "config":
  {
    "device":"RaspberryPi Camera",
    "height":"480",
    "title":"Front Camera",
    "width":"640"
  }
}
获取相机属性描述
最后,可以通过使用 **http://ip:port/camera/properties** URL 来查询所有支持的摄像头配置属性的描述。此 API 继承自 cam2web 项目,在该项目中这很有意义,因为该项目支持多种平台和摄像头 API。然而,对于 PiRex 来说,这用处不大——目前只支持一种摄像头类型。
结论
是时候总结一下了。回顾一下为了让 PiRex 运行所做的一切,我会说这是一个非常有趣的经历,无论是从软件开发还是硬件组装的角度来看。从焊接单个小组件到将所有组件组装在一起并确保它确实工作,整个构建过程都很有趣。是的,它被重建了几次——更换烧坏的电机驱动器,安装新的更强大的电机,查找松动的连接等等。但最终,看到它不断进步和改进真是太棒了。
目标达到了吗?当然达到了。机器人在合理预算内,用现成的通用电子元件搭建完成。由于它都是用较小的独立组件而不是一体化的专用机器人控制器构建的,因此更换/升级东西要容易得多。这在维修方面也很有用——如果电机驱动器烧坏了,我们只需要更换一个成本很低的小芯片,而不是更换整个机器人控制器。
至于开发的软件,运行得也相当不错。PiRex 机器人可以通过网页浏览器 UI 或通过调用暴露的 REST API 从专用应用程序进行控制。提供了参考 .NET 客户端应用程序,以演示如何与机器人交互以及如何在游戏手柄设备的帮助下实现更灵活的控制。
有什么事情可以做得不同吗?如果预算允许,可以使用更高级的电机驱动器,例如ThunderBorg,它开箱即用提供速度控制。或者,另一个替代方案是添加 Arduino Nano,它提供了足够的硬件 PWM 引脚来实现 L293D 电机驱动器的速度控制。这个选项听起来实际上更有趣,因为 Arduino 板不仅带来了额外的数字 IO 引脚,还有模拟输入引脚,这对于与各种传感器连接会非常有用。
无论如何,PiRex 软件目前的形式非常易于重用和扩展。所提供的嵌入式服务器和其余基础设施允许轻松插入新的 REST 处理程序,然后(如果需要)与附加硬件组件进行交互。
一个项目之后
接下来会是什么?嗯,一旦机器人建造完成并按预期运行,它就可以作为许多不同项目的平台。特别是当它与一些图像处理和计算机视觉应用程序结合时。下面是其中一个项目的快速演示——用 PiRex 机器人寻找字形。一组方形二进制字形隐藏在某个环境中,目标是通过远程控制机器人找到它们。我必须说,和孩子们一起玩这个游戏非常有趣!
嗯,我相信还有更多很棒的想法可以实现。只要有创意,坚持下去。玩得开心!

