自主坦克
使用乐高 EV3 套装为 Carter 和 Kaya 设计参考添加更便宜的替代品。
在这个项目中,我将记录使用 Lego Technic 零件和电机制造的履带车辆的构造,使用 LiDAR 增强并由运行最新 Isaac SDK 的 Jetson Nano 板控制。跳转到第 8 部分 或10 自主导航的完整演示。
图>该项目由以下部分组成:
- A NVIDIA Jetson Nano 开发板 - 运行 Isaac 机器人引擎
- 一块 EV3 积木 – 控制电机(在 EV3 31313 机器人套件中提供) )
- 履带式底座 - 使用 Lego Technic 零件和两个大型电机制成(EV3 31313 机器人套件中提供了必要的一切 )
- YDLIDAR x4 激光雷达
- Pixy2 视觉摄像头
为什么是 Isaac SDK 而不是 ROS?
- ROS(机器人操作系统)有很多教程,但 Isaac 几乎没有(除了 SDK 本身的教程)
- 似乎是 Jetson Nano 的更好选择(专为此硬件系列创建)
- 从规划到感知的高级机器人算法,其中大部分是 GPU 加速的 .这是一个重要的部分。没有 GPU 加速,Jetson Nano 与 Raspberry Pi 4 板没有任何区别
- IsaacSim Unity3D 比 Gazebo 更逼真,这将改善从模拟到现实的结果
为什么是乐高零件?
- 我有很多🙂
- 零件质量高(良好的伺服系统)
- 我没有 3D 打印机(让一位朋友打印一个与乐高兼容的 Jetson Nano 外壳,但这是 3D 打印的唯一部分)
- 无需焊接
选择这条道路确实会带来一些挑战:
- Isaac SDK 不支持乐高硬件。只有两个参考机器人存在:Carter 和 Kaya。甚至不支持 JetBot。
- Isaac SDK 只能使用有限数量的硬件组件
- 为 3 个目标(x86-64、arm64 和 armv5tejl)编译
- 并非一切都是开源的
第 1 部分:入门
1.艾萨克 SDK
- 完成此处描述的步骤
- 尝试运行 Isaac SDK 中提供的一些示例以检查是否一切正常
- 确保您使用的是 2019.3 SDK 版本!!!
2.语音识别(可选)
- 安装 CUDA 10.0、CUDNN 7.6.3 和 TensorRT 6.0
- 安装 TensorFlow 1.15.0(硬件加速)
3. Ev3dev 镜像
在 microSD 或 microSDHC 卡上下载并刷写 EV3 的最新映像 (ev3dev-stretch)。 EV3 程序块不支持 MicroSDXC 格式。
4.用于 ev3dev 的 ARM 交叉编译器
$ sudo apt-get install gcc-arm-linux-gnueabi g++-arm-linux-gnueabi
这部分特别难以正确设置。 Ubuntu 18.04(主机和 Jetson Nano)使用 GLIBC_2.28,而 ev3dev 使用 Debian 拉伸和 GLIBC_2.24。使用默认 arm-linux-gnueabi-g++ 编译器配置编译的任何内容都依赖于 GLIBC_2.28,无法在 EV3 上运行。静态链接不起作用,因为比 hello world 更复杂的事情会导致段错误。我找到的解决方案是动态链接除数学库之外的所有内容。您可以在 jetson-ev3/toolchain/CROSSTOOL 文件中找到更多信息。另一种解决方案是使用 Debian 9 的 docker 镜像。
5. Jetson + EV3 工作区
$ git clone https://github.com/andrei-ace/jetson-ev3.git
- 编辑 jetson-ev3/WORKSPACE 并设置 Isaac SDK 的路径。
local_repository(
name ="com_nvidia_isaac",
path ="/home/andrei/ml/isaac"
)代码>
- 编辑 jetson-ev3/toolchain/CROSSTOOL 并设置该文件所在目录的路径。
# 使用工具链的路径进行编辑
linker_flag:"-L/home/andrei/ml/jetson-ev3/toolchain"
6.将 Jetson Nano 与 EV3 连接
在下一部分中,我将发布大量 Linux 命令。因为涉及到三个系统,所以我将按照它们在终端中的样子发布它们,意思是:
[email protected]:~/ml/jetson-ev3$ #this 在我的电脑上运行
[email protected]:~$ #this is on Jetson Nano
[电子邮件保护]:~$ $ #this in EV3
我的 Jetson Nano 的 IP 是 192.168.0.173(以太网)和 192.168.0.218(WiFi),所以每当你看到使用这些值的命令时,将它们替换为你的。
我按照以下步骤使用 USB A 转迷你电缆将 Jetson 板与 EV3 程序块连接起来。
尝试从 Jetson 板 ssh:
[email protected]:~$ ssh [email protected]
默认密码为maker。
7.乒乓球教程
Isaac 有一个教程解释了一个非常简单的 Codelet。我建议先做这个教程。它将向您介绍构建在 Isaac 上运行的任何应用程序所需的概念。
现在转到 jetson-ev3/apps/ev3/ping_pong/ 目录。这是上一教程的修改版本,稍有改动,我们将 ping 发送到 EV3 程序块。
大多数文件在上一教程中都很熟悉。我们将使用 Cap'n Proto RPC 进行 Jetson 和 EV3 之间的调用。 Cap'n Proto 大量用于各种 Isaac 组件之间的通信,因此在这里使用它是有意义的。为此,我们需要一些新文件:
- jetson-ev3/apps/ev3/ping_pong/ping.capnp – 这定义了将在 Isaac 机器人引擎上运行的客户端和将在 EV3 上运行的服务器之间的接口。
- jetson-ev3/apps/ev3/ping_pong/PongEv3Server.cpp 这是在 EV3 程序块上运行的服务器
- jetson-ev3/apps/ev3/ping_pong/Pong.cpp 此更改为调用在 EV3 上运行的 Pong 服务器
编译ev3_pong服务器:
[email protected]:~/ml/jetson-ev3$ bazel build --config=ev3dev //apps/ev3/ping_pong:ev3_pong
使用 scp 先复制到 EV3 到 Jetson,然后再复制到 EV3。
构建乒乓示例并将其部署到 Jetson:
[email protected]:~/ml/jetson-ev3$ /engine/build/deploy.sh --remote_user -p //apps/ev3/ping_pong:ping_pong-pkg -d jetpack43 -h
在此处详细了解如何在 Jetson 上部署和运行您的应用。
运行这两个应用程序:
[email protected]:~$ ./ev3_pong ev3dev.local:9999
[email protected]:~/deploy/andrei/ping_pong-pkg$ 。 /apps/ev3/ping_pong
如果一切正常,您应该会听到 Ping 组件发送到 EV3 扬声器的消息。
8.从 Isaac 控制电机
原理相同,只是稍微复杂一些。我使用了 Isaac 的另一个教程来与 EV3 电机进行交互:
本教程使用 Segway RMP 基础。由于我没有一个躺着或 10000 美元买一个,我创建了一个驱动程序来控制 EV3 电机。代码在这里。
在 EV3 上运行的服务器就在这里,可以使用以下命令构建和运行:
[email protected]:~/ml/jetson-ev3$ bazel build --config=ev3dev //packages/ev3/ev3dev:ev3_control_server
[email protected]:~$ ./ev3_control_server ev3dev.local:9000
我使用了 Sight 的虚拟操纵杆,如此处所述。
9.EV3 的DifferentialBase
Ev3ControlServer 服务器将响应 2 个调用:
- command(cmd :Control) – 将线速度和角速度作为参数并控制两个电机以达到要求的速度
- state() -> (state :Dynamics); – 返回机器人的真实线速度和角速度
此处和此处更详细地解释了运动学。
我使用了 ratio_control_cpp 示例应用程序来驱动机器人 1 m 并以每秒旋转脉冲(转速计计数)的形式报告 EV3 的里程计(线速度和角速度)数据。使用计算出的行驶距离(由 Isaac)并测量实际距离,我想出了一个常数来调整报告的值,使它们与实际结果相匹配。这很有效,并且结果可以重复多次,而不仅仅是直线。您还可以使用轮子的半径(在我们的例子中是轨道)来计算这个值。
第 2 部分:构建机器人
底座与乐高的 EV3 Track3r 非常相似,EV3 套件的官方模型之一:https://www.lego.com/biassets/bi/6124045.pdf
图>Jetson Nano 的案例来自这里:https://github.com/3D-printable-lego-technic/PELA-blocks
第 3 部分:Isaac 应用
一个 Isaac 应用由三个主要部分组成:
- graph – 节点:这部分定义了构成应用程序的所有组件。一个节点也可以是另一个文件中定义的另一个图形。示例中的“voice_detection”节点是一个子图。
- graph -edges:这部分定义了节点之间的消息流。一条边有一个源和一个目标。例如,来自“voice_detection”节点(子图)的检测到的命令将被发送到生成目标的组件。
- configuration - 这部分配置图的节点
示例应用:
{
"name":"voice_control",
"modules":[
"//apps/ev3/voice_control:voice_control_goal_generator",
"@com_nvidia_isaac//packages/navigation",
"@com_nvidia_isaac//packages/planner"
],
"config_files":[
" apps/ev3/voice_control/model/isaac_vcd_model.metadata.json"
],
"config":{
"2d_ev3.ev3_hardware.ev3":{
"isaac.Ev3Driver ":{
"address":"ev3dev.local",
"port":9000
}
},
"navigation.imu_odometry.odometry":{
"DifferentialBaseWheelImuOdometry":{
"use_imu":false
}
},
"commander.robot_remote":{
"isaac.navigation.RobotRemoteControl ":{
"angular_speed_max":0.6,
"linear_speed_max":0.3
}
},
"websight":{
"WebsightServer":{
"webroot":"external/com_nvidia_isaac/packages/sight/webroot",
"ui_config":{
"windows":{
"语音指令检测":{
"renderer":"情节" ,
"dims":{
"width":400,
"height":200
},
"channels":[
{
"name":"voice_control/voice_detection.voice_command_detector/isaac.audio.VoiceCommandConstruction/voice_command_id",
"active":true
}
]
}
}
}
}
},
"navigation.shared_robot_model":{
"SphericalRobotShapeComponent":{
"circles":[
{ "center":[0.0, 0.0], "radius":0.075 },
{ "center":[0.02, 0.03464], "radius":0.055 },
{ "center":[0.02, -0.03464], "radius":0.055 },
{ "center":[-0.04, 0.0], "radius":0.055 },
{ "center":[0.0525, 0.09093 ], "radius":0.035 },
{ "center":[0.0525, -0.09093], "radius":0.035 },
{ "center":[-0.105, 0.0], "radius" ":0.035 }
]
}
},
"navigation.control.lqr":{
"isaac.planner.DifferentialBaseLqrPlanner":{
"manual_mode_channel":"commander.robot_remote/isaac.navigation.RobotRemoteControl/manual_mode"
}
},
"navigation.control.control":{
"isaac.planner.DifferentialBaseControl":{
"manual_mode_channel":"commander.robot_remote/isaac.navigation.RobotRemoteControl/manual_mode"
}
}
},
"graph":{
"nodes":[
{
"name":"voice_control_components",
"components":[
{
"name":"message_ledger",
"type":"isaac::alice::MessageLedger"
},
{
"name":"goal_generator",
"type":"isaac::VoiceControlGoalGenerator"
}
]
},
{
"name":"voice_detection",
"subgraph":"apps/ev3/voice_control/voice_command_detection.subgraph.json"
},
{
"name":"2d_ev3",
"subgraph":"apps/ev3/2d_ev3.subgraph.json"
},
{
"name":"导航",
"subgraph":"@com_nvidia_isaac//packages/navigation/apps/differential_base_navigation.subgraph.json"
},
{
"name":"commander",
"子图":"@com_nvidia_isaac//packages/navigation/ apps/differential_base_commander.subgraph.json"
}
],
"edges":[
{
"source":"voice_detection.subgraph/interface/detected_command" ,
"target":"voice_control_components/goal_generator/detected_command"
},
{
"source":"voice_control_components/goal_generator/goal",
"target" :"navigation.subgraph/interface/goal"
},
{
"source":"2d_ev3.subgraph/interface/base_state",
"target":"navigation. subgraph/interface/state"
},
{
"source":"navigation.subgraph/interface/command",
"target":"commander.subgraph/interface/ control"
},
{
"source":"commander.subgraph/interface/command",
"target":"2d_ev3.subgraph/interface/base_command"
},
{
"source":"2d_ev3.subgraph/interface/flatscan",
"target":"navigation.subgraph/interface/flatscan_for_localization"
},
{
"source":"2d_ev3.subgraph/interface/flatscan",
"target":"navigation.子图/接口/flatscan_for_obstacles"
}
]
}
}
示例子图:
{
"modules":[
"@com_nvidia_isaac//packages/audio",
"@com_nvidia_isaac//packages/ ml:tensorflow"
],
"graph":{
"nodes":[
{
"name":"subgraph",
" components":[
{
"name":"message_ledger",
"type":"isaac::alice::MessageLedger"
},
{
"name":"interface",
"type":"isaac::alice::Subgraph"
}
]
},
{
"name":"audio_capture",
"components":[
{
"name":"ml",
"type":"isaac::alice ::MessageLedger"
},
{
"name":"isaac.audio.AudioCapture",
"type":"isaac::audio::AudioCapture"
}
]
},
{
"name":"voice_command_detector",
"components":[
{
" name":"ml",
"type":"isaac::alice::MessageLedger"
},
{
"name":"isaac.audio.VoiceCommandFeatureExtraction" ,
"type":"isaac::audio::VoiceCommandFeatureExtraction"
},
{
" name":"isaac.ml.TensorflowInference",
"type":"isaac::ml::TensorflowInference"
},
{
"name":"isaac. audio.VoiceCommandConstruction",
"type":"isaac::audio::VoiceCommandConstruction"
}
]
}
],
"edges" :[
{
"source":"audio_capture/isaac.audio.AudioCapture/audio_capture",
"target":"voice_command_detector/isaac.audio.VoiceCommandFeatureExtraction/audio_packets"
},
{
"source":"voice_command_detector/isaac.audio.VoiceCommandFeatureExtraction/feature_tensors",
"target":"voice_command_detector/isaac.ml.TensorflowInference/input_tensors"
},
{
"source":"voice_command_detector/isaac.ml.TensorflowInference/output_tensors",
"target":"voice_command_detector/isaac.audio.VoiceCommandConstruction/keyword_probabilities"
},
{
"source":"voice_command_detector/isaac.audio.VoiceCommandConstruction/detected_command",
"target":"subgraph/interface/detected _command"
}
]
},
"config":{
"audio_capture":{
"isaac.audio.AudioCapture":{
"sample_rate":16000,
"num_channels":1,
"audio_frame_in_milliseconds":100,
"ticks_per_frame":5
}
},
"voice_command_detector":{
"isaac.audio.VoiceCommandFeatureExtraction":{
"audio_channel_index":0,
"minimum_time_between_inferences":0.1
},
"isaac.ml.TensorflowInference":{
"model_file_path":"apps/ev3/voice_control/model/isaac_vcd_model.pb",
"config_file_path":"apps/ev3/voice_control/model/isaac_vcd_config.pb" pb"
},
"isaac.audio.VoiceCommandConstruction":{
"command_list":[
"jetson",
"jetson left",
"jetson right"
],
"command_ids":[0, 1, 2],
"max_frames_allowed_after_keyword_detected":14
}
}
}
}
子图可以在许多应用程序中重复使用。事实上,以撒的导航堆栈用作子图。
第 4 部分:在 EV3 上运行 Isaac 应用
驱动程序 (jetson-ev3/packages/ev3/BUILD) 响应与 Segway RMP 基本驱动程序相同的命令。这意味着它可以与在 Kaya 或 Carter 上运行的许多应用程序一起使用,使其成为第三种选择,而且价格便宜得多!
图>我改编了一些应用程序来展示 Carter 和 Kaya 机器人:
- 操纵杆应用 - 使用操纵杆控制 DifferentialBase 机器人。它有一个用于生成本地地图的激光雷达
- gmapping 分布式:来自 Kaya 机器人的 ev3 和主机 - 这允许使用 EV3 机器人和 YDLIDAR X4 创建 GMap。
- 完整导航 - 我为 EV3 机器人添加了硬件和 2D 导航的子图,以便其他应用可以像使用 Carter 或 Kaya 一样轻松地使用它们。
第 5 部分:里程计
对于在自主模式下运行,拥有良好的里程计很重要。这用于随时间估计机器人的位置。让我们使用 ev3 应用程序调整它:
[email protected]:~/ml/jetson-ev3$ ./engine/build/deploy.sh --remote_user andrei -p //apps/ev3:ev3 -pkg -d jetpack43 -h 192.168.0.173
[email protected]:~$brickrun ./ev3_control_server ev3dev.local:9000
[email protected]:~/deploy /andrei/ev3-pkg$ ./apps/ev3/ev3 --graph ./apps/assets/maps/map.graph.json --config ./apps/assets/maps/map.config.json
我们需要估计两件事:
- 线速度
- 角速度
线速度和角速度的计算公式为:
图>求角速度很容易:就是左右电机的差除以基长。
找到线速度有点复杂。我们有 3 个案例:
- 当两个电机速度相等时——线速度与右速度(和左速度)相等
- 当左侧电机转速与右侧电机转速相反时,线速度为0,坦克原地旋转
- 当左侧电机速度为 0 时(右侧描述的情况)。线速度是正确速度的一半(机器人的中心沿较小的弧线移动)。
角速度实验:
我们将使用手动控制将机器人原地旋转 360 度。这是通过以相反的速度移动左右电机来完成的。知道两个电机的速度,我们就可以计算出角速度。
试试看:
图>角速度和线速度实验:
我会开着坦克四处走动,最后试着把它放回起始位置。如果我们正确计算速度,里程计数据应该尽可能接近 0。
图>第 6 部分:整合所有内容
好的,所以我们到目前为止只是为了拥有一个昂贵的遥控坦克?不,我们现在可以使用 Isaac 的所有不同部分。例如,发出语音命令并让机器人自主移动。查看voice_control 以获取示例。
它使用了 Isaac 的音频和机器学习精华。什么是宝石?正如手册中所述:“GEM:从规划到感知的机器人算法集合,其中大部分是 GPU 加速的。”
我按照本教程中介绍的步骤训练了自己的 RNN。只要确保你有大量的数据,特别是对于未知关键字/沉默/随机噪声的情况。
我训练我的识别 3 个词:“jetson”、“left”和“right”。您可以在此处找到保存的模型。用这三个词,我们可以组成两个命令:“jetson left”和“jetson right”。
此处描述了检测部分,在它自己的子图中,随时可以使用和重用。
基本上它的作用是收听麦克风,如果其中一个命令被拾取,它将输出一个 voice_command_id。为此,它使用了先前训练过的 RNN。
我们可以将检测到的_command 传递给我们自己的 Codelet:
{
"source":"voice_detection.subgraph/interface/detected_command",
"target":"voice_control_components/goal_generator/detected_command"
}
我们可以从 Codelet 生成目标并发布它:
auto proto =rx_detected_command().getProto();
int id =proto.getCommandId();
auto goal_proto =tx_goal()。 initProto();
goal_proto.setStopRobot(true);
goal_proto.setTolerance(0.1);
goal_proto.setGoalFrame("robot");
ToProto(Pose2d::Rotation( 90),goal_proto.initGoal());
tx_goal().publish();
这设定了将机器人向左旋转 90 度的目标。我们可以在不同的框架中设定不同的目标。本来可以转到“世界”框架中的坐标,例如厨房的坐标。它可以在机器人的框架中设置 Pose2::Translate(1.0, 0) 以将机器人推进 1 米。
然后我们将目标传递给 Global Planner。
{
"source":"voice_control_components/goal_generator/goal",
"target":"navigation.subgraph/interface/goal"
}
所有魔法发生的地方:
图> 图>不幸的是,它只能在 10 W 模式下工作,而不是 5 W,这对我的电池来说有点太多了。在 5W 模式下,推理时间过长:
我尝试使用较小的 RNN,并从 2 个可用的 cpu 内核 (nvpmodel -m 1) 增加到 3 个,但没有太大帮助。它将推理的时间减少到 30ms,但对于准确的结果来说仍然太长了。
第 7 部分:映射
要创建地图,我们需要在 Jetson 上运行一个 Isaac 实例,在主机上运行一个实例。映射需要大量资源,超出了 Jetson Nano 的处理能力。
[email protected]:~/ml/jetson-ev3$ ./engine/build/deploy.sh --remote_user andrei -p //apps/ev3:gmapping_distributed_ev3 -pkg -d jetpack43 -h 192.168.0.218
[电子邮件保护]:~/deploy/andrei/gmapping_distributed_ev3-pkg$ ./apps/ev3/gmapping_distributed_ev3
[电子邮件protected]:~/ml/jetson-ev3$ bazel 运行应用程序/ev3:gmapping_distributed_host
不要忘记使用您的 Jetson IP 更改文件 apps/ev3/gmapping_distributed_host.app.json:
"tcp_subscriber":{
"isaac.alice.TcpSubscriber":{
"port":5000,
"host" :"192.168.0.218"
}
}
来源:自主坦克
制造工艺