ESP32遥控格斗机器人制作:从PS3手柄控制到坦克差速转向

ESP32遥控格斗机器人制作:从PS3手柄控制到坦克差速转向 1. 项目概述与核心思路几年前我在一个学校项目里需要做一个基于Arduino的东西。当时在网上逛看到有人做了个自主移动的小车再加上那阵子看了不少机器人格斗的视频一个念头就冒出来了我能不能也做一个不过不是那种全自动的而是用手柄遥控的带点“攻击性”的小机器人。这个想法让我兴奋了好一阵子。最终我选择了ESP32作为主控因为它自带蓝牙正好可以连上我手头闲置的一个PS3手柄DualShock 3。整个项目我把它叫做“Boxxer”一个用ESP32驱动的遥控格斗机器人。这个项目听起来复杂但拆解开来核心就是三件事控制、驱动和结构。控制端是PS3手柄通过蓝牙与ESP32通信驱动部分是用电机驱动模块控制四个轮子电机和一个武器电机结构部分则是用木板搭建一个结实的小车底盘。整个过程涉及嵌入式编程、基础电路焊接和简单的木工非常适合想从零开始体验机器人制作的朋友。无论你是电子爱好者、Arduino玩家还是对物联网和机器人控制感兴趣的学生跟着这篇指南你都能亲手打造出一个属于自己的、能跑能“打”的遥控小车。2. 核心组件选型与原理剖析做硬件项目选对零件就成功了一半。下面我详细拆解一下Boxxer用到的核心部件并解释为什么选它们以及背后的工作原理。2.1 主控芯片为什么是ESP32在众多微控制器里选择ESP32主要基于三个硬核理由集成双模无线ESP32最大的优势就是集成了Wi-Fi和蓝牙包括经典蓝牙和低功耗蓝牙。对于这个项目我们只需要它的经典蓝牙功能来连接PS3手柄。如果选用传统的Arduino Uno你需要额外添加一个蓝牙模块如HC-05/HC-06不仅增加成本接线和编程也更复杂。ESP32让无线连接变得像调用库函数一样简单。性能与资源ESP32是一颗双核处理器主频高达240MHz内存也足够大。虽然我们这个机器人控制代码并不需要这么强的算力但充裕的资源意味着你可以轻松添加更多功能比如通过Wi-Fi传输摄像头画面、加入更多传感器等为后续升级留足了空间。丰富的GPIO与PWM控制电机需要用到多个GPIO通用输入输出引脚来输出方向信号并且最好能支持PWM脉冲宽度调制来进行调速。ESP32提供了充足的GPIO并且大部分引脚都支持PWM输出完美契合了我们需要同时控制多个电机的需求。注意ESP32有多个不同的开发板型号如ESP32-DevKitC、NodeMCU-32S等它们引脚排列可能不同。在接线时务必以你手中实际板子的引脚标注为准。2.2 动力核心电机与驱动模块的搭配机器人的移动和攻击都依赖电机。我选择了最常见的两种直流电机移动底盘电机我用了4个“TT减速电机”DC Gearbox motors。这种电机内部集成了齿轮箱将高速低扭矩的电机输出转换为低速高扭矩非常适合直接驱动轮子。我选的减速比是120:1这意味着电机轴转120圈输出轴才转1圈扭矩大大增加能让小车有劲爬过一些小障碍。武器电机为了驱动前端的攻击武器比如一个旋转的滚筒或摆臂我使用了一个普通的6V直流电机。这种电机转速高但扭矩小通常需要额外的减速机构或直接用于驱动轻量化的攻击部件。光有电机不行微控制器的GPIO引脚输出电流太小通常只有几十毫安根本无法直接驱动电机。这就需要电机驱动模块。我选择了两个MX1508双路电机驱动模块。工作原理MX1508是一个H桥驱动芯片。简单理解H桥就像四个开关晶体管组成的一个“桥”电路通过控制这四个开关的不同通断组合可以改变电流流经电机的方向从而实现电机的正转和反转。同时通过PWM信号快速开关这些晶体管可以控制平均电压从而实现电机的调速。选型考量MX1508每个通道持续输出电流约为1.2A-1.5A。对于TT电机在空载或轻载下是足够的但在负载较重如爬坡、卡住时可能会接近或超过极限导致模块发热甚至保护。原文作者也提到“这不是最理想的选择但最终让它工作了”。这是一种在成本和性能间的权衡。如果预算允许选择持续电流更大的驱动模块如L298N、TB6612FNG会更稳妥。2.3 控制端破解DualShock 3的蓝牙连接用游戏手柄控制机器人体验感直接拉满。但PS3手柄DualShock 3的蓝牙连接并非标准的SPP串口协议它使用的是蓝牙HID人机接口设备协议的一种特定实现。幸运的是开源社区有现成的库帮我们解决了这个问题。我们使用的esp32-ps3库本质上是在ESP32上模拟了一个PS3主机让手柄认为它连接到了一台PS3上。这个过程的关键在于蓝牙MAC地址的配对。每个蓝牙设备都有一个唯一的MAC地址。手柄在初次连接时会寻找并绑定一个特定的主机MAC地址。我们的代码里需要预设一个MAC地址然后通过电脑上的工具Sixaxis Pair Tool将手柄的配对地址修改成这个预设地址两者才能成功握手连接。这是一个一次性的配置过程。2.4 供电系统设计机器人上有两种电压需求ESP32主控工作电压通常是3.3V一般通过USB口由电脑或移动电源供电。电机系统TT电机和武器电机的工作电压一般在3-6V但启动和堵转时需要较大电流。我的供电方案是双电源系统一个移动电源2000mAh通过USB线给ESP32供电。稳定可靠方便充电。一个4节AA电池盒6V给所有电机通过电机驱动模块供电。AA电池能提供比USB口更大的瞬间电流满足电机启动需求。实操心得双电源方案避免了电机大电流波动对ESP32造成的干扰或重启提高了系统稳定性。一个更集成的改进方案是使用一个大的电池组如2S锂电7.4V然后通过一个DC-DC降压模块如LM2596降压到5V给ESP32供电这样只需一块电池但需要小心处理电压匹配和稳压问题。3. 开发环境搭建与手柄配对工欲善其事必先利其器。第一步就是把编程环境准备好并让手柄和ESP32“认识”对方。3.1 配置Arduino IDE支持ESP32Arduino IDE默认不支持ESP32需要手动添加开发板支持。打开Arduino IDE进入文件-首选项。在“附加开发板管理器网址”一栏中填入ESP32的板支持包地址。你可以添加多个网址用逗号隔开。核心网址是https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json点击“确定”关闭首选项。进入工具-开发板-开发板管理器。在搜索框中输入“esp32”找到由“Espressif Systems”提供的“ESP32 Arduino”并点击安装。这个过程会下载一些必要的工具链和库需要一点时间。安装完成后用USB线连接ESP32到电脑。在工具-开发板菜单下就能选择对应的ESP32型号了例如“ESP32 Dev Module”。关键步骤给ESP32上传代码时有可能会失败。一个常见的解决方法是在上传代码的瞬间点击上传按钮后IDE开始编译时按下并按住ESP32板子上的“BOOT”按钮直到IDE提示“正在上传…”或进度条开始走动再松开按钮。这是因为ESP32需要进入下载模式才能接收新的程序。3.2 安装PS3手柄控制库并获取MAC地址在Arduino IDE中点击项目-加载库-管理库。在库管理器中搜索“PS3 Controller Host”找到由“jvpernis”开发的库并安装。安装后你可以在文件-示例中找到该库的示例代码参考。接下来是关键的配对步骤。我们需要一个固定的MAC地址供ESP32使用并让手柄记住它。在代码中设定MAC地址我们稍后写的代码里需要调用Ps3.begin(XX:XX:XX:XX:XX:XX);函数其中的字符串就是一个MAC地址。你可以任意设定一个只要格式正确6组十六进制数用冒号分隔例如44:d8:32:c8:8d:1a。注意为了避免与局域网内其他蓝牙设备冲突最好使用一个不太常见的地址。修改手柄的配对地址下载并安装“Sixaxis Pair Tool”这个软件可在开源社区找到。用USB线将PS3手柄连接到电脑。打开Sixaxis Pair Tool软件应该能识别到手柄。在相关字段中你将看到手柄当前的配对地址。将其修改为你在上一步代码中设定的那个MAC地址然后点击“Update”或“Write”按钮写入手柄。完成后断开手柄与电脑的USB连接。至此手柄就已经被“训练”为只寻找我们这个特定MAC地址的ESP32了。4. 控制逻辑与代码深度解析代码是机器人的大脑。下面我逐部分拆解控制程序并解释每一个关键决策背后的原因。4.1 代码结构与全局变量#include Ps3Controller.h // 引入PS3手柄库 // 定义手柄模拟量值变量 int leftVertical; int rightVertical; int ds3Triangle; // 三角按钮状态 // 定义右侧电机驱动引脚 (假设控制右侧两个电机) int pinIn1 27; // 电机A方向引脚1 int pinIn2 14; // 电机A方向引脚2 PWM // 定义左侧电机驱动引脚 int pinIn3 33; // 电机B方向引脚1 int pinIn4 32; // 电机B方向引脚2 PWM // 定义武器电机驱动引脚 int pinIn5 18; // 武器电机方向/PWM int pinIn6 19; // 武器电机方向 int deadZone 40; // 摇杆死区 int attackMotorEnabled 0; // 武器电机状态标志位引脚定义pinIn1到pinIn6对应连接电机驱动模块输入端的ESP32引脚。这里需要根据你实际的接线来修改我选择的引脚如27,14,33,32,18,19大多是ESP32上通用的GPIO且支持PWM输出。死区Dead ZonedeadZone 40是一个非常重要的参数。游戏手柄的模拟摇杆是物理器件在中心位置可能会有几毫伏的电压波动导致微小的数值输出比如-5到5。如果不处理机器人即使在你没碰摇杆时也会微微抖动。设置死区后只有当摇杆偏移量绝对值超过40时才认为是有意操作否则视为零输入。这个值可以根据手柄实际情况调整。状态标志位attackMotorEnabled用于记录武器电机的开关状态实现按一次开、再按一次关的“ toggle ”功能。4.2 核心控制函数notify()Ps3Controller库采用回调函数机制。当手柄有任何状态变化如摇杆移动、按钮按下时都会自动调用notify()函数。我们把所有控制逻辑都放在这里。void notify() { // 1. 获取手柄数据 leftVertical (Ps3.data.analog.stick.ly); rightVertical (Ps3.data.analog.stick.ry); ds3Triangle (Ps3.event.button_down.triangle); // 2. 映射摇杆值到PWM范围 int engineValueRight map(rightVertical, 0, 128, 0, 255); int engineValueLeft map(leftVertical, 0, 128, 0, 255); // 3. 武器电机控制点动开关 if (attackMotorEnabled 0 ds3Triangle 1) { analogWrite(pinIn5, 127); // 以50%占空比启动武器电机 digitalWrite(pinIn6, LOW); attackMotorEnabled 1; } else if (attackMotorEnabled 1 ds3Triangle 1) { analogWrite(pinIn5, 0); // 停止武器电机 digitalWrite(pinIn6, LOW); attackMotorEnabled 0; } // 4. 右侧电机控制基于右摇杆 if (rightVertical -deadZone) { // 摇杆向后拉 digitalWrite(pinIn1, LOW); analogWrite(pinIn2, abs(engineValueRight)); // 电机反转 } if (rightVertical deadZone) { // 摇杆向前推 analogWrite(pinIn1, abs(engineValueRight)); // 电机正转 digitalWrite(pinIn2, LOW); } if (abs(rightVertical) deadZone) { // 摇杆在死区内 analogWrite(pinIn1, 0); analogWrite(pinIn2, 0); // 电机停止 } // 5. 左侧电机控制基于左摇杆- 逻辑同右侧 if (leftVertical -deadZone) { digitalWrite(pinIn3, LOW); analogWrite(pinIn4, abs(engineValueLeft)); } if (leftVertical deadZone) { analogWrite(pinIn3, abs(engineValueLeft)); digitalWrite(pinIn4, LOW); } if (abs(leftVertical) deadZone) { analogWrite(pinIn3, 0); analogWrite(pinIn4, 0); } }关键逻辑解读数据映射map()函数将手柄摇杆的原始值0到128代表前半个行程实际读取的是-128到127我们取绝对值后处理线性映射到PWM的输出范围0到255。这样摇杆推得越猛电机转速越快。坦克式差速转向这是代码最精妙的地方。我们没有使用传统的“前轮转向”而是让左右两侧的轮子独立驱动。当左右摇杆输入相同时两侧轮子同速同向机器人直行。当左右摇杆输入不同时就产生了速度差从而实现转向。例如左摇杆向前推到底全速正转右摇杆向后拉到底全速反转左侧轮子向前右侧轮子向后机器人就会原地顺时针旋转。这种转向方式结构简单越障能力强。电机方向控制以右侧电机为例pinIn1和pinIn2接驱动模块的两个输入。通过设置其中一个为PWM输出另一个为固定的高或低电平来控制电机的方向和速度。这是一种常见的H桥控制方法。武器电机点动控制使用ds3Triangle按钮按下事件和attackMotorEnabled标志位组合实现了按一下三角键启动武器再按一下停止的功能。analogWrite(pinIn5, 127)表示以大约50%的功率驱动武器电机这个值可以调整。4.3 初始化与主循环void setup() { Ps3.attach(notify); // 设置回调函数 Ps3.begin(44:d8:32:c8:8d:1a); // 初始化PS3连接填入你的MAC地址 // 将所有控制引脚设置为输出模式 pinMode(pinIn1, OUTPUT); pinMode(pinIn2, OUTPUT); pinMode(pinIn3, OUTPUT); pinMode(pinIn4, OUTPUT); pinMode(pinIn5, OUTPUT); pinMode(pinIn6, OUTPUT); } void loop() { if (!Ps3.isConnected()) { // 检查手柄是否连接 return; // 未连接则直接返回不执行任何操作 } delay(2000); // 一个简单的延时防止loop()空转消耗资源 }setup()函数中Ps3.attach(notify)是关键它将手柄事件与我们的控制逻辑绑定。loop()函数极其简单因为主要工作都在回调函数notify()中完成了。这里只是检查连接状态并加了一个延时。一个常见的优化是可以在手柄断开连接时增加一个让所有电机停止的安全逻辑。5. 电路连接与焊接实战理论懂了接下来就是动手接线。强烈建议先在不焊接的情况下用面包板和杜邦线搭建整个电路进行测试确认所有功能正常后再进行焊接这样可以避免很多麻烦。5.1 电路原理图与接线表根据代码中的引脚定义我们可以整理出以下接线关系。这里假设使用两个MX1508双路驱动模块每个模块驱动两个电机。ESP32 GPIO 引脚连接到功能说明GND电机驱动模块1的GND 电机驱动模块2的GND 电池盒负极共地非常重要GPIO 27电机驱动模块1 - IN1控制右侧电机方向1GPIO 14电机驱动模块1 - IN2控制右侧电机PWM/方向2GPIO 33电机驱动模块2 - IN1控制左侧电机方向1GPIO 32电机驱动模块2 - IN2控制左侧电机PWM/方向2GPIO 18武器电机驱动端或第三个驱动模块IN1控制武器电机PWMGPIO 19武器电机驱动端或第三个驱动模块IN2控制武器电机方向Vin / 5V不连接ESP32由USB供电电机驱动模块1 VCC电池盒正极通过开关给右侧电机供电电机驱动模块1 GND电池盒负极电机驱动模块1 OUT1, OUT2右侧两个电机的线注意电机极性反了会反转电机驱动模块2 VCC电池盒正极通过开关给左侧电机供电电机驱动模块2 GND电池盒负极电机驱动模块2 OUT1, OUT2左侧两个电机的线注意电机极性电源部分电机电源4节AA电池盒约6V的正极接一个拨动开关开关另一端同时接到两个电机驱动模块的VCC输入。负极直接接到驱动模块的GND。ESP32电源通过Micro-USB线连接一个移动电源。重要提示务必确保ESP32的GND和电机电池的GND连接在一起共地。这是保证控制信号来自ESP32能够正确被电机驱动模块识别的关键否则控制可能失灵。5.2 焊接工艺与注意事项测试无误后就可以将临时连接转为永久性的焊接了。对于新手我有几个血泪教训准备工作准备好焊锡丝建议用含松香芯的、焊台可调温为佳、助焊剂、吸锡器、镊子和一个“第三只手”工具台。焊接MX1508这种小模块时“第三只手”能稳稳夹住板子解放你的双手。焊接顺序先焊电线到电机驱动模块的引脚上因为它的焊盘小。将杜邦线的公头剪下剥出约1cm的铜丝上锡预焊然后焊接在驱动模块对应的输入输出端子上。避免虚焊和桥接焊接时烙铁头要同时接触引脚和焊盘待两者都热了之后从另一侧送入焊锡丝。焊点应呈光滑的圆锥形。焊接密集引脚时如ESP32要特别小心焊锡不要连到相邻引脚上。线材管理用不同颜色的电线区分电源正极红色、负极黑色和信号线黄、绿等。焊接后用热缩管或电工胶带包裹裸露的焊点防止短路。安全第一焊接时保持通风避免吸入烟雾。烙铁温度很高用完务必放回烙铁架。6. 机械结构设计与组装机器人的“身体”决定了它的稳定性和耐用性。我用的是多层胶合板因为它容易加工且成本低。6.1 底盘设计与切割设计草图在纸上画出底盘草图。核心尺寸由你的电机和轮子决定。测量电机含轮子的宽度和长度预留出安装位置。底盘形状可以是长方形或更战斗感的异形。关键点一定要在轮子周围留出足够间隙我的初版就忽略了这点导致轮子摩擦侧板严重消耗动力。建议每边至少留出5-10mm的余量。切割材料用线锯或曲线锯沿着画好的线切割出底板。然后切割侧板。我的设计是“浴缸”式的即一个底板加上四周立起来的侧板最后加盖。侧板的高度要能容纳立放的电池盒、ESP32和驱动板。开孔在底板上钻出电机轴的孔。在侧板或底板上钻出电线穿出的孔。在顶板上开一个大的检修口方便后续更换电池和调试。6.2 组装与总装粘合主体使用强度足够的胶水如木工胶、环氧树脂或原文中的建筑胶将底板和侧板粘合。可以用夹子或重物固定等待胶水完全固化通常需要24小时。安装动力总成将四个TT电机用螺丝或强力胶如AB胶固定在底板预留的位置上。确保电机轴与底板垂直且所有轮子触地高度一致。安装武器电机将武器电机安装在机器人前部。可以考虑设计一个简单的支架或者直接粘在底板上。如果是旋转武器要确保其旋转范围不会打到自己的轮子或身体。内部设备布局与固定将电池盒、移动电源用双面胶或尼龙扎带固定在底板上。将焊接好的ESP32和驱动板也用尼龙扎带或螺丝固定在底板上最好垫上绝缘垫如一块塑料片。布线这是体现工艺的地方。用尼龙扎带将电线捆扎整齐沿着底盘边缘走线避免杂乱。长的线可以适当剪短再焊接减少杂乱。电源线电池到驱动板建议用粗一点的线如AWG22以减少压降。最终封闭将所有设备连接好打开开关进行最后一次通电测试。确认一切正常后用胶水将顶板粘合。我的做法是在顶板检修口上盖一张厚卡纸用胶带一边固定做成一个活页盖既方便检修又不影响外观。7. 系统调试与故障排除实录即使按照步骤来组装过程中也难免遇到问题。下面是我遇到的和可能遇到的典型问题及解决方法。问题现象可能原因排查步骤与解决方案手柄无法连接ESP321. MAC地址不匹配。2. ESP32蓝牙未启动或代码错误。3. 手柄未进入配对模式需先按PS键。1.首要检查用Sixaxis Pair Tool确认手柄内写入的MAC地址与代码中Ps3.begin()内的地址完全一致包括冒号和字母大小写。2. 检查代码是否包含了#include Ps3Controller.h和正确的setup()初始化。3. 给ESP32重新上电然后打开手柄电源按PS键观察ESP32串口输出需在代码中添加Serial打印连接状态或手柄指示灯是否常亮。上传代码到ESP32失败1. 驱动未安装CH340/CP2102。2. 开发板型号选错。3. 未进入下载模式。1. 检查设备管理器确认USB转串口驱动已安装端口号正确。2. 在Arduino IDE的工具-开发板中选择与你硬件匹配的ESP32型号。3.尝试按住BOOT键再点击上传待编译完成后出现“上传”提示时再松开。这是ESP32的常见操作。部分或全部电机不转1. 电源问题开关未开、电池没电、接触不良。2. 信号线连接错误或虚焊。3. 代码引脚定义与实际接线不符。4. 电机驱动模块损坏。1. 用万用表测量电池盒输出电压检查开关通断检查所有电源连接点是否焊牢。2.分段排查先断开电机用万用表电压档测量驱动模块输出端OUT1/OUT2在摇动手柄时观察是否有电压变化。如果有问题在电机或接线如果没有问题在ESP32信号或驱动模块输入端。3. 仔细核对代码中pinIn1等变量定义的引脚号是否与ESP32上实际插的线一致。4. 替换法用另一个好的驱动模块测试。电机转动方向错误电机线接反了。将接在同一个驱动通道如OUT1和OUT2上的两根电机线对调即可。这是最快最简单的解决方法。电机只能单向转1. 驱动模块的某个方向控制信号缺失。2. 代码中某个方向的控制逻辑未触发。1. 检查驱动模块对应方向的控制引脚IN1或IN2是否与ESP32连接良好。2. 在notify()函数中添加串口打印输出leftVertical和rightVertical的值确认手柄摇杆在两个方向都能产生正确一正一负的数值。检查if条件判断是否正确如rightVertical -deadZone和rightVertical deadZone。摇杆回中后电机仍缓慢转动抖动死区设置过小或手柄摇杆有物理漂移。增大deadZone变量的值例如从40调到50或60直到摇杆回中时电机完全停止。武器电机无法点动开关按钮状态检测逻辑或标志位逻辑有误。添加串口打印检查ds3Triangle在按钮按下时是否为1。检查attackMotorEnabled标志位在每次按下时是否正确翻转0变11变0。确保控制武器电机的analogWrite和digitalWrite语句写在了正确的分支里。机器人跑起来一瘸一拐1. 左右轮子电机转速不一致个体差异。2. 某侧轮子打滑或悬空。3. 底盘不水平。1. 这是常见现象。可以在代码中为左右侧的map函数设置不同的缩放系数进行微调例如int engineValueLeft map(leftVertical, 0, 128, 0, 250);让左侧电机最大速度稍慢。2. 检查所有轮子是否都牢固安装轮胎是否有足够抓地力。3. 将机器人放在平整桌面上检查底盘是否翘曲。调试心法遇到问题不要慌采用“分而治之”的策略。先确保电源畅通再确保信号畅通用LED或万用表测电压最后检查逻辑用串口打印调试信息。硬件项目就是不断假设、验证、排除的过程。8. 项目优化与扩展思路基础版本完成后你的Boxxer已经是一个能战斗的机器人了。但创客的乐趣在于不断改进。这里分享几个可以继续深化的方向动力系统升级电池将AA电池盒升级为7.4V的2S锂聚合物电池电量更足放电能力更强。务必配套使用平衡充电器并考虑添加锂电保护板电机驱动换用TB6612FNG或DRV8833等更强大、效率更高的驱动模块它们支持更大电流且发热更小。武器威力为武器电机增加减速齿轮组将高转速转换为高扭矩让攻击部件更有力。或者设计一个弹射、敲击机构。控制与感知增强低电量指示通过ESP32的ADC引脚读取电池电压当电压低于阈值时让ESP32板载LED闪烁报警。无线图传加装一个微型摄像头如ESP32-CAM和Wi-Fi图传模块实现第一人称视角FPV驾驶体验立刻升级。自动模式增加超声波或红外测距传感器编写简单的避障程序让Boxxer在遥控之外也具备一定的自主能力。结构与外观材料使用更轻更强的材料如碳纤维板、航空铝板或者用3D打印设计更复杂的定制化零件。防护为轮子、电机和电路板设计可拆卸的防护罩在格斗中保护核心部件。灯光效果在底盘四周加上LED灯带由ESP32控制不同状态如前进、后退、攻击显示不同灯光炫酷度满分。这个项目从想法到实物的过程让我深刻体会到嵌入式开发的魅力——将代码逻辑转化为物理世界的动作。最大的收获不是做出了一个会动的小车而是在解决一个个具体问题比如手柄连不上、电机反转、轮子卡住的过程中对硬件、软件如何协同工作有了肌肉记忆般的理解。焊接从一塌糊涂到勉强能看代码从只能点亮LED到能处理复杂的摇杆映射这种一步步克服困难、最终让机器人听命于自己的感觉是单纯看书学不来的。如果你也完成了自己的Boxxer试着去和朋友的机器人来一场友谊赛你会发现为了赢得比赛你会不由自主地去思考如何优化代码、加强结构这或许就是工程实践最好的驱动力。