<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <author>
    <name>Abo</name>
  </author>
  <generator uri="https://hexo.io/">Hexo</generator>
  <id>https://leo-wangbo.top/</id>
  <link href="https://leo-wangbo.top/" rel="alternate"/>
  <link href="https://leo-wangbo.top/atom.xml" rel="self"/>
  <rights>All rights reserved 2026, Abo</rights>
  <subtitle>卧龙凤雏团队欢迎你</subtitle>
  <title>阿波的博客</title>
  <updated>2025-11-10T19:03:02.000Z</updated>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="DIY" scheme="https://leo-wangbo.top/categories/DIY/"/>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/DIY/ROS/"/>
    <category term="路径规划" scheme="https://leo-wangbo.top/categories/DIY/ROS/%E8%B7%AF%E5%BE%84%E8%A7%84%E5%88%92/"/>
    <content>
      <![CDATA[<p>总体实现框架图：</p><p><img src="/uploads/2025/09/%E6%A1%86%E6%9E%B6%E5%9B%BE-1024x559.png"></p><p>找了个实际的变电站环境，改动了一下导入到了Gazebo中用作实验的仿真环境</p><p><img src="/uploads/2025/09/2ded517aa0f5ebf4a139d4b0fb33351c-1024x523.jpg"></p><p>目前有了一个初步的demo，等做完后开源并对算法进行详细的讲解</p><div style="text-align:center;margin:1.5em 0;">  <video controls preload="metadata" src="/uploads/2025/09/基于优化控制与大模型指令解析的变电站巡检系统-demo.mp4" style="max-width:100%;border-radius:8px;"></video></div>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E5%81%9A%E4%BA%86%E4%B8%80%E4%B8%AA%E8%83%BD%E5%90%AC%E6%87%82%E4%BA%BA%E8%AF%9D%E7%9A%84%E5%B7%A1%E6%A3%80%E6%9C%BA%E5%99%A8%E4%BA%BA/</id>
    <link href="https://leo-wangbo.top/p/%E5%81%9A%E4%BA%86%E4%B8%80%E4%B8%AA%E8%83%BD%E5%90%AC%E6%87%82%E4%BA%BA%E8%AF%9D%E7%9A%84%E5%B7%A1%E6%A3%80%E6%9C%BA%E5%99%A8%E4%BA%BA/"/>
    <published>2025-09-06T07:22:26.000Z</published>
    <summary>
      <![CDATA[<p>总体实现框架图：</p>
<p><img src="/uploads/2025/09/%E6%A1%86%E6%9E%B6%E5%9B%BE-1024x559.png"></p>
<p>找了个实际的变电站环境，改动了一下导入到了Gazebo中用作实验的仿真环境</p>
<p]]>
    </summary>
    <title>做了一个能听懂人话的巡检机器人</title>
    <updated>2025-11-10T19:03:02.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="DIY" scheme="https://leo-wangbo.top/categories/DIY/"/>
    <content>
      <![CDATA[<h2 id="一、topic-state-monitor模块简介"><a href="#一、topic-state-monitor模块简介" class="headerlink" title="一、topic_state_monitor模块简介"></a>一、topic_state_monitor模块简介</h2><p>此节点用于监控任意话题是否存在异常，例如<strong>超时</strong>和<strong>低频率</strong>。话题的诊断结果将通过ROS Diagnostics发布诊断信息。</p><ul><li><strong>输入</strong>：任意名称、任意类型的话题</li><li><strong>输出</strong>：<code>/diagnostics</code> 诊断信息</li></ul><h2 id="二、topic-state-monitor模块启动流程"><a href="#二、topic-state-monitor模块启动流程" class="headerlink" title="二、topic_state_monitor模块启动流程"></a>二、topic_state_monitor模块启动流程</h2><p>通过解析 <code>topic_state_monitor</code> 核心代码部分并逐级向上追溯，可得到 <code>topic_state_monitor</code> 模块完整的启动流程，如下图所示：<br><img src="/uploads/2025/09/topic_state_monitor%E6%A8%A1%E5%9D%97%E5%90%AF%E5%8A%A8%E6%B5%81%E7%A8%8B%E5%9B%BE.png"><br>上层的两个 <code>.launch.xml</code> 文件主要配置了两个参数。一个是 <code>tier4_system_component.launch.xml</code> 中配置的 <code>topics.yaml</code> 文件路径。<code>topics.yaml</code> 文件内容是配置所有需要监控的话题信息以及监控阈值信息。配置文件的内容示例如下:</p><figure class="highlight yaml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="bullet">-</span> <span class="attr">module:</span> <span class="string">control</span></span><br><span class="line">  <span class="attr">mode:</span> [<span class="string">online</span>, <span class="string">logging_simulation</span>, <span class="string">planning_simulation</span>]</span><br><span class="line">  <span class="attr">type:</span> <span class="string">autonomous</span></span><br><span class="line">  <span class="attr">args:</span></span><br><span class="line">    <span class="attr">topic_type:</span> <span class="string">autoware_control_msgs/msg/Control</span></span><br><span class="line">    <span class="attr">best_effort:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">transient_local:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">warn_rate:</span> <span class="number">5.0</span></span><br><span class="line">    <span class="attr">error_rate:</span> <span class="number">1.0</span></span><br><span class="line">    <span class="attr">timeout:</span> <span class="number">1.0</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">module:</span> <span class="string">control</span></span><br><span class="line">  <span class="attr">mode:</span> [<span class="string">online</span>, <span class="string">logging_simulation</span>, <span class="string">planning_simulation</span>]</span><br><span class="line">  <span class="attr">type:</span> <span class="string">autonomous</span></span><br><span class="line">  <span class="attr">args:</span></span><br><span class="line">    <span class="attr">node_name_suffix:</span> <span class="string">control_command_control_cmd</span></span><br><span class="line">    <span class="attr">topic:</span> <span class="string">/control/command/control_cmd</span></span><br><span class="line">    <span class="attr">topic_type:</span> <span class="string">autoware_control_msgs/msg/Control</span></span><br><span class="line">    <span class="attr">best_effort:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">transient_local:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">warn_rate:</span> <span class="number">5.0</span></span><br><span class="line">    <span class="attr">error_rate:</span> <span class="number">1.0</span></span><br><span class="line">    <span class="attr">timeout:</span> <span class="number">1.0</span></span><br><span class="line"><span class="bullet">-</span> <span class="attr">module:</span> <span class="string">localization</span></span><br><span class="line">  <span class="attr">mode:</span> [<span class="string">online</span>, <span class="string">logging_simulation</span>, <span class="string">planning_simulation</span>]</span><br><span class="line">  <span class="attr">type:</span> <span class="string">autonomous</span></span><br><span class="line">  <span class="attr">args:</span></span><br><span class="line">    <span class="attr">node_name_suffix:</span> <span class="string">transform_map_to_base_link</span></span><br><span class="line">    <span class="attr">topic:</span> <span class="string">/tf</span></span><br><span class="line">    <span class="attr">frame_id:</span> <span class="string">map</span></span><br><span class="line">    <span class="attr">child_frame_id:</span> <span class="string">base_link</span></span><br><span class="line">    <span class="attr">best_effort:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">transient_local:</span> <span class="literal">false</span></span><br><span class="line">    <span class="attr">warn_rate:</span> <span class="number">5.0</span></span><br><span class="line">    <span class="attr">error_rate:</span> <span class="number">1.0</span></span><br><span class="line">    <span class="attr">timeout:</span> <span class="number">1.0</span></span><br></pre></td></tr></table></figure><p><strong>代码2-1 topics.yaml配置⽂件⽰例</strong></p><p>配置文件的各个参数的解释如下:</p><table><thead><tr><th style="text-align: left;">名称</th><th style="text-align: left;">含义</th></tr></thead><tbody><tr><td style="text-align: left;"><code>module</code></td><td style="text-align: left;">话题所属的模块</td></tr><tr><td style="text-align: left;"><code>mode</code></td><td style="text-align: left;">指定了配置适用的模式，通过设置 <code>mode</code>，可以控制配置文件在不同运行环境下是否生效</td></tr><tr><td style="text-align: left;"><code>type</code></td><td style="text-align: left;">指定话题的类型，根据不同的 <code>type</code> 分类，<code>component_state_monitor</code> 模块会分析 <code>/diagnostics</code> 诊断信息给出 <code>/type/module</code> 模块的状态（判断是否正常运行，消息类型为自定义的 <code>ModeChangeAvailable</code>）</td></tr><tr><td style="text-align: left;"><code>node_name_suffix</code></td><td style="text-align: left;">节点名称的后缀，用于动态生成节点名称</td></tr><tr><td style="text-align: left;"><code>topic</code></td><td style="text-align: left;">指定要监控的目标话题的名称</td></tr><tr><td style="text-align: left;"><code>topic_type</code></td><td style="text-align: left;">指定目标话题的数据类型</td></tr><tr><td style="text-align: left;"><code>best_effort</code></td><td style="text-align: left;">指定是否使用 <strong>"Best Effort" QoS策略</strong>。如果设置为 <code>true</code>，意味着使用“尽力而为”策略，即消息传输尽力而为，可能会丢失消息。设置为 <code>false</code> 则表示采用 <strong>"Reliable" QoS策略</strong>，确保消息的可靠传输，但可能带来更高的延迟。</td></tr><tr><td style="text-align: left;"><code>transient_local</code></td><td style="text-align: left;">指定是否使用 <strong>"Transient Local" QoS策略</strong>。如果设置为 <code>true</code>，即使订阅者在发布时不存在，消息也会暂时保存在中间件中，直到订阅者连接。此策略适用于需要历史消息的场景。如果设置为 <code>false</code>，则采用普通的QoS策略，只有当前连接的订阅者可以接收到发布的消息。</td></tr><tr><td style="text-align: left;"><code>warn_rate</code></td><td style="text-align: left;">话题发布频率警告阈值，当话题的发布频率低于该值时，话题状态将被设置为 <strong>WarnRate</strong>，即警告状态</td></tr><tr><td style="text-align: left;"><code>error_rate</code></td><td style="text-align: left;">话题发布频率错误阈值，当指定当话题的发布频率低于该值时，话题状态将被设置为 <strong>ErrorRate</strong>，即错误状态</td></tr><tr><td style="text-align: left;"><code>timeout</code></td><td style="text-align: left;">这个参数指定如果话题订阅在超过指定的时间（单位为秒）内没有收到消息，话题状态将被设置为 <strong>Timeout</strong></td></tr><tr><td style="text-align: left;"><code>frame_id</code></td><td style="text-align: left;">坐标变换的父坐标系ID</td></tr><tr><td style="text-align: left;"><code>child_frame_id</code></td><td style="text-align: left;">坐标变换的子框架ID</td></tr><tr><td style="text-align: left;"><code>window_size</code></td><td style="text-align: left;">计算目标主题频率使用的窗口大小，例如，窗口大小为10表示计算过去10个发布周期的频率</td></tr><tr><td style="text-align: left;"><code>uprate_rate</code></td><td style="text-align: left;">定时器回调频率，用于设置更新和检查主题状态的频率</td></tr></tbody></table><strong>表2-1 topics.yaml配置⽂件参数解释</strong><p><code>system.launch.xml</code> 文件中设置了配置所选择的模式，根据模式的选择来监听不同的话题组。话题所属的模式在上述 <code>topics.yaml</code> 文件中设置。</p><figure class="highlight xml"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag">&lt;<span class="name">arg</span> <span class="attr">name</span>=<span class="string">&quot;run_mode&quot;</span> <span class="attr">default</span>=<span class="string">&quot;online&quot;</span> <span class="attr">description</span>=<span class="string">&quot;options: online, logging_simulation, planning_simulation</span></span></span><br></pre></td></tr></table></figure><p>最终通过 <code>component_state_monitor.launch.py</code> 生成了一系列针对目标话题的监控节点。这些节点发布诊断数据到 <code>/diagnostics</code> 话题中。</p><h2 id="三、topic-state-monitor模块运行效果"><a href="#三、topic-state-monitor模块运行效果" class="headerlink" title="三、topic_state_monitor模块运行效果"></a>三、topic_state_monitor模块运行效果</h2><p>运行 Autoware 的规划demo样例后：</p><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">cd</span> autoware</span><br><span class="line"><span class="built_in">source</span> ~/autoware/install/setup.bash</span><br><span class="line">ros2 launch autoware_launch planning_simulator.launch.xml map_path:=<span class="variable">$HOME</span>/autoware_map/sample-map-planning vehicle_model:=sample_vehicle sensor_model:=sample_sensor_kit</span><br></pre></td></tr></table></figure><p>然后运行 <code>ros2 node list</code> 可以看到 <code>topic_state_monitor</code> 模块运行起来一些监控节点来对配置文件中的话题进行监控。监控节点名称为：“<code>topic_state_monitor</code>” + <code>topic.yaml</code> 中话题的 <code>node_name_suffix</code> 名称。</p><p><img src="/uploads/2025/09/%E9%92%88%E5%AF%B9%E6%8C%87%E5%AE%9A%E8%AF%9D%E9%A2%98%E7%94%9F%E6%88%90%E7%9A%84%E7%9B%91%E6%8E%A7%E8%8A%82%E7%82%B9.png"></p><p>这些节点输出诊断信息到 <strong>ROS Diagnostics</strong> 诊断系统中，可以在 <code>rqt_runtime_monitor</code> 中看到诊断结果。</p><p><img src="/uploads/2025/09/rqt_runtime_monitor%E6%9F%A5%E7%9C%8B%E8%AF%8A%E6%96%AD%E7%BB%93%E6%9E%9C.png"></p><p>同时，<code>component_state_monitor::StateMonitor</code> 节点的 <code>main.cpp</code> 订阅 <code>/diagnostics</code> 话题并通过定时器周期性地检查不同模块整体的状态是否正常。输出的话题格式是 <code><del>/type/module</code>，例如，对于 <code>type</code> 为 <code>launch</code> 中的 <code>map</code> 模块，输出话题为 <code></del>/launch/map</code>。<br><img src="/uploads/2025/09/%E6%A3%80%E6%9F%A5%E5%90%84%E4%B8%AA%E6%A8%A1%E5%9D%97%E6%95%B4%E4%BD%93%E6%98%AF%E5%90%A6%E6%AD%A3%E5%B8%B8%E7%94%9F%E6%88%90%E7%9A%84topic.png"></p><p>话题输出的消息格式是自定义的 <code>ModeChangeAvailable.msg</code> 格式，用于表示某个模块是否可用。消息包含以下内容:</p><ul><li><strong><code>stamp</code></strong>：时间戳，表示消息生成的时间。</li><li><strong><code>available</code></strong>：布尔值，表示该模块当前是否有效。<code>true</code> 表示模块正常，<code>false</code> 表示模块不可用。</li></ul><p><img src="/uploads/2025/09/topic%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C.png"></p><h2 id="四、topic状态监控部分实现原理"><a href="#四、topic状态监控部分实现原理" class="headerlink" title="四、topic状态监控部分实现原理"></a>四、topic状态监控部分实现原理</h2><p>分析源码后总结下来，其核心是通过 <code>component_state_monitor.launch.py</code> 对 <code>config.yaml</code> 文件中要监控的 topic <strong>一对一创建</strong>一个 node。<br><img src="/uploads/2025/09/%E5%88%9B%E5%BB%BAtopic%E7%9B%91%E6%8E%A7%E8%8A%82%E7%82%B9.png"></p><p>随后将 node 启动部分注册成一个插件，这样可以用同一个源码启动多个 node。在 node 源码中，根据监控 topic 是否为 <strong>tf 话题</strong>创建 <strong>tf 类订阅者</strong>和<strong>非 tf 类订阅者</strong>。这里针对非 tf 类 topic，使用了 <code>rclcpp::SerializedMessage</code> 一个通用的消息类型，表示经过序列化的消息。它不关心消息的具体内容，只是将消息传递为原始的字节流。<br><img src="/uploads/2025/09/%E5%88%9B%E5%BB%BAsubscription.png"></p><p><img src="/uploads/2025/09/subscription%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0.png"></p><h2 id="五、一些考量点"><a href="#五、一些考量点" class="headerlink" title="五、一些考量点"></a>五、一些考量点</h2><p><code>topic_state_monitor</code> 模块可针对任意类型的 topic 生成一个 node 去监控 topic 的状态，通用性强。但如果需要监控的 topic 过多可能<strong>进程开销大</strong>，因此要对该模块对于性能的开销进行测试来判断是否可迁移到人形机器人上。</p><p><code>topic_state_monitor</code> 模块采用了<strong>组合节点</strong>并将组合节点放入 <strong>container</strong> 中来启动一堆 node 去监控各个 topic。这样做的好处是将多个节点加载到同一个进程中，每个节点仍然保持独立的逻辑和功能，但它们可以更高效地共享数据和资源。这种方法不仅减少了通信延迟，而且降低了系统的整体资源消耗（例如，CPU时间内存使用）。</p><p>实际使用 Autoware 进行测试时发现，输入 <code>ros2 component list</code> 查看容器节点信息可知组合节点 <code>/system/component_state_monitor/component</code> 有被放入 <code>/system/component_state_monitor/container</code> 容器中。<br><img src="/uploads/2025/09/ros2-component-list%E8%BE%93%E5%87%BA%E7%BB%93%E6%9E%9C.png"></p><p>但是查询系统进程资源占用情况时发现：启动的各个监控 node 并没有在同一个进程中进行，而是各自占用了一个进程，这样性能总开销过大。</p><p>猜测是启动文件中 node 的启动方式存在问题。经过分析发现问题出在 <code>component_state_monitor.launch.py</code> 启动文件对于 node 节点的启动是通过启动一个个 <code>launch.xml</code> 文件来生成监控 node 节点，并没有将 node 节点放入 container 容器中，因此占用了多个进程。</p><p>想要减少进程的占用，需要重构 <code>component_state_monitor.launch.py</code> 对于 node 节点的启动部分。修改后的代码如下:</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> collections <span class="keyword">import</span> defaultdict</span><br><span class="line"><span class="keyword">from</span> pathlib <span class="keyword">import</span> Path</span><br><span class="line"></span><br><span class="line"><span class="keyword">import</span> launch</span><br><span class="line"><span class="keyword">from</span> launch.actions <span class="keyword">import</span> DeclareLaunchArgument, OpaqueFunction</span><br><span class="line"><span class="keyword">from</span> launch.substitutions <span class="keyword">import</span> LaunchConfiguration</span><br><span class="line"><span class="keyword">from</span> launch_ros.actions <span class="keyword">import</span> ComposableNodeContainer</span><br><span class="line"><span class="keyword">from</span> launch_ros.descriptions <span class="keyword">import</span> ComposableNode</span><br><span class="line"><span class="keyword">import</span> yaml</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">create_diagnostic_name</span>(<span class="params">row</span>):</span><br><span class="line">    <span class="keyword">return</span> <span class="string">f&quot;<span class="subst">&#123;row[<span class="string">&#x27;module&#x27;</span>]&#125;</span>_topic_status&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">create_topic_monitor_name</span>(<span class="params">row</span>):</span><br><span class="line">    diag_name = create_diagnostic_name(row)</span><br><span class="line">    node_name_suffix = row[<span class="string">&quot;args&quot;</span>][<span class="string">&quot;node_name_suffix&quot;</span>]</span><br><span class="line">    <span class="comment"># 替换非法字符，如冒号和空格为下划线(防止报错Couldn&#x27;t parse remap rule: &#x27;-r __node......）</span></span><br><span class="line">    node_name_suffix = node_name_suffix.replace(<span class="string">&quot;:&quot;</span>, <span class="string">&quot;_&quot;</span>).replace(<span class="string">&quot; &quot;</span>, <span class="string">&quot;_&quot;</span>)</span><br><span class="line">    diag_name = diag_name.replace(<span class="string">&quot;:&quot;</span>, <span class="string">&quot;_&quot;</span>).replace(<span class="string">&quot; &quot;</span>, <span class="string">&quot;_&quot;</span>)</span><br><span class="line">    <span class="keyword">return</span> <span class="string">f&quot;topic_state_monitor_<span class="subst">&#123;node_name_suffix&#125;</span>_<span class="subst">&#123;diag_name&#125;</span>&quot;</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">create_topic_monitor_node</span>(<span class="params">row</span>):</span><br><span class="line">    diag_name = create_diagnostic_name(row)</span><br><span class="line">    <span class="comment"># 基础参数</span></span><br><span class="line">    parameters = [&#123;<span class="string">&quot;diag_name&quot;</span>: diag_name&#125;]</span><br><span class="line">    <span class="comment"># 根据是否为 TF 类话题，添加不同的参数</span></span><br><span class="line">    remappings = []</span><br><span class="line">    <span class="keyword">if</span> <span class="string">&quot;topic_type&quot;</span> <span class="keyword">in</span> row[<span class="string">&quot;args&quot;</span>]:</span><br><span class="line">        <span class="comment"># 非 TF 类话题</span></span><br><span class="line">        parameters.append(&#123;<span class="string">&quot;topic_type&quot;</span>: row[<span class="string">&quot;args&quot;</span>][<span class="string">&quot;topic_type&quot;</span>]&#125;)</span><br><span class="line">    <span class="keyword">else</span>:</span><br><span class="line">        <span class="comment"># TF 类话题</span></span><br><span class="line">        parameters.append(&#123;<span class="string">&quot;frame_id&quot;</span>: row[<span class="string">&quot;args&quot;</span>][<span class="string">&quot;frame_id&quot;</span>]&#125;)</span><br><span class="line">        parameters.append(&#123;<span class="string">&quot;child_frame_id&quot;</span>: row[<span class="string">&quot;args&quot;</span>][<span class="string">&quot;child_frame_id&quot;</span>]&#125;)</span><br><span class="line">    <span class="comment"># 其他参数</span></span><br><span class="line">    <span class="keyword">for</span> k, v <span class="keyword">in</span> row[<span class="string">&quot;args&quot;</span>].items():</span><br><span class="line">        <span class="keyword">if</span> k <span class="keyword">not</span> <span class="keyword">in</span> [<span class="string">&quot;topic_type&quot;</span>, <span class="string">&quot;frame_id&quot;</span>, <span class="string">&quot;child_frame_id&quot;</span>]:</span><br><span class="line">            parameters.append(&#123;k: v&#125;)</span><br><span class="line">    <span class="comment"># 如果需要进行主题重映射，可以在这里添加 remappings</span></span><br><span class="line">    <span class="comment"># 假设 YAML 文件中不包含 remaps 字段，因此 remappings 为空</span></span><br><span class="line">    <span class="comment"># if &quot;remaps&quot; in row[&quot;args&quot;]:</span></span><br><span class="line">    <span class="comment">#     for remap in row[&quot;args&quot;][&quot;remaps&quot;]:</span></span><br><span class="line">    <span class="comment">#         remappings.append(remap)</span></span><br><span class="line">    <span class="keyword">return</span> ComposableNode(</span><br><span class="line">        namespace=<span class="string">&quot;system&quot;</span>,</span><br><span class="line">        package=<span class="string">&quot;topic_state_monitor&quot;</span>,</span><br><span class="line">        plugin=<span class="string">&quot;topic_state_monitor::TopicStateMonitorNode&quot;</span>,</span><br><span class="line">        name=create_topic_monitor_name(row),</span><br><span class="line">        parameters=parameters,</span><br><span class="line">        remappings=remappings  <span class="comment"># 目前为空</span></span><br><span class="line">    )</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">launch_setup</span>(<span class="params">context, *args, **kwargs</span>):</span><br><span class="line">    <span class="comment"># 获取启动模式和配置文件</span></span><br><span class="line">    mode = LaunchConfiguration(<span class="string">&quot;mode&quot;</span>).perform(context)</span><br><span class="line">    config_file = LaunchConfiguration(<span class="string">&quot;file&quot;</span>).perform(context)</span><br><span class="line">    rows = yaml.safe_load(Path(config_file).read_text())</span><br><span class="line">    rows = [row <span class="keyword">for</span> row <span class="keyword">in</span> rows <span class="keyword">if</span> mode <span class="keyword">in</span> row[<span class="string">&quot;mode&quot;</span>]]</span><br><span class="line">    <span class="comment"># 创建所有监控节点</span></span><br><span class="line">    topic_monitor_nodes = [create_topic_monitor_node(row) <span class="keyword">for</span> row <span class="keyword">in</span> rows]</span><br><span class="line">    topic_monitor_names = [create_topic_monitor_name(row) <span class="keyword">for</span> row <span class="keyword">in</span> rows]</span><br><span class="line">    <span class="comment"># 组织参数</span></span><br><span class="line">    topic_monitor_param = defaultdict(<span class="keyword">lambda</span>: defaultdict(<span class="built_in">list</span>))</span><br><span class="line">    <span class="keyword">for</span> row <span class="keyword">in</span> rows:</span><br><span class="line">        topic_monitor_param[row[<span class="string">&quot;type&quot;</span>]][row[<span class="string">&quot;module&quot;</span>]].append(create_topic_monitor_name(row))</span><br><span class="line">    topic_monitor_param = &#123;name: <span class="built_in">dict</span>(module) <span class="keyword">for</span> name, module <span class="keyword">in</span> topic_monitor_param.items()&#125;</span><br><span class="line">    <span class="comment"># 创建主组件节点（StateMonitor）</span></span><br><span class="line">    component = ComposableNode(</span><br><span class="line">        namespace=<span class="string">&quot;component_state_monitor&quot;</span>,</span><br><span class="line">        package=<span class="string">&quot;component_state_monitor&quot;</span>,</span><br><span class="line">        plugin=<span class="string">&quot;component_state_monitor::StateMonitor&quot;</span>,</span><br><span class="line">        name=<span class="string">&quot;component&quot;</span>,</span><br><span class="line">        parameters=[&#123;<span class="string">&quot;topic_monitor_names&quot;</span>: topic_monitor_names&#125;, topic_monitor_param],</span><br><span class="line">    )</span><br><span class="line">    <span class="comment"># 创建容器，并将所有ComposableNode添加到容器中</span></span><br><span class="line">    container = ComposableNodeContainer(</span><br><span class="line">        namespace=<span class="string">&quot;component_state_monitor&quot;</span>,</span><br><span class="line">        name=<span class="string">&quot;container&quot;</span>,</span><br><span class="line">        package=<span class="string">&quot;rclcpp_components&quot;</span>,</span><br><span class="line">        executable=<span class="string">&quot;component_container&quot;</span>,</span><br><span class="line">        composable_node_descriptions=[component] + topic_monitor_nodes,  <span class="comment"># 将监控节点加入容器</span></span><br><span class="line">        output=<span class="string">&quot;screen&quot;</span>,</span><br><span class="line">    )</span><br><span class="line">    <span class="keyword">return</span> [container]</span><br><span class="line"></span><br><span class="line"><span class="keyword">def</span> <span class="title function_">generate_launch_description</span>():</span><br><span class="line">    <span class="keyword">return</span> launch.LaunchDescription(</span><br><span class="line">        [</span><br><span class="line">            DeclareLaunchArgument(<span class="string">&quot;file&quot;</span>),</span><br><span class="line">            DeclareLaunchArgument(<span class="string">&quot;mode&quot;</span>),</span><br><span class="line">            OpaqueFunction(function=launch_setup),</span><br><span class="line">        ]</span><br><span class="line">    )</span><br></pre></td></tr></table></figure><p>代码修改后运行可发现监控 node 成功被放入 container 容器中在同一个进程中运行。<br><img src="/uploads/2025/09/%E5%9C%A8%E5%90%8C%E4%B8%80%E4%B8%AA%E8%BF%9B%E7%A8%8B%E4%B8%AD%E8%BF%90%E8%A1%8C.png"></p><p>但是检查进程占用情况发现 <code>component_state_monitor</code> 进程总占用在 <strong>70%</strong> 左右，占用过高。<br><img src="/uploads/2025/03/%E6%80%BB%E5%8D%A0%E7%94%A8%E5%9C%A870%E5%B7%A6%E5%8F%B3%EF%BC%8C%E5%8D%A0%E7%94%A8%E8%BF%87%E9%AB%98-1024x110.png"><br>修改参数列表中的 <code>window_size</code> 与 <code>update_rate</code>，将其从默认的 <strong>10</strong> 调小至 <strong>2</strong> 后，占用可下降至 <strong>15%</strong> 左右。<br><img src="/uploads/2025/03/%E5%8D%A0%E7%94%A8%E5%8F%AF%E4%B8%8B%E9%99%8D%E8%87%B315%E5%B7%A6%E5%8F%B3-1024x104.png"><br>经分析，<code>TopicStateMonitor</code> 的逻辑本身相对简单，只是维护一个时间戳队列、计算话题接收速率，并根据阈值进行状态判断。单独看这段代码，性能开销并不大，主要是一些基本的内存操作（<strong><code>push_back</code></strong>、<strong><code>pop_front</code></strong>）、时间计算和简单的条件判断。这些操作本身不是CPU占用的主要来源。</p><p>然而，当有 <strong>15个</strong> 这样的监控节点，每个节点都在高频率地接收消息并调用 <strong><code>update()</code></strong> 函数时，整体系统的CPU使用率就可能显著增加。由于 Autoware 系统繁杂臃肿，消息的频率不太好手动控制。为了控制变量研究消息频率与数量对监控模块占用系统资源的情况，于是手动创建一些节点，观察不同 topic 数量、频率与 QoS 策略下的系统资源占用情况。</p><p>测试编写脚本创建多个发布者发布 <code>std_msgs/msg/String</code> 格式的话题，然后启动 <code>topic_state_monitor</code>，其中 <code>window_size</code> 设为 <strong>2</strong>、<code>update_rate</code> 设为 <strong>1</strong>。之后对 <code>topic_state_monitor</code> 进程的 CPU 占用率进行监控 <strong>120秒</strong>，每秒测两次，将测试结果绘制成表格如下所示:</p><table><thead><tr><th style="text-align: left;">影响因素</th><th style="text-align: left;">Topic数量</th><th style="text-align: left;">Topic频率</th><th style="text-align: left;">best_effort</th><th style="text-align: left;">transient_local</th><th style="text-align: left;">平均占用率</th><th style="text-align: left;">最小占用率</th><th style="text-align: left;">最大占用率</th><th style="text-align: left;">Topic频率对占用率的影响</th></tr></thead><tbody><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">5</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">3.55%</td><td style="text-align: left;">2.0%</td><td style="text-align: left;">5.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">10</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">4.53%</td><td style="text-align: left;">3.0%</td><td style="text-align: left;">6.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">15</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">5.63%</td><td style="text-align: left;">3.0%</td><td style="text-align: left;">7.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">20</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">8.44%</td><td style="text-align: left;">4.0%</td><td style="text-align: left;">12.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">35</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">10.23%</td><td style="text-align: left;">4.0%</td><td style="text-align: left;">14.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">40</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">11.36%</td><td style="text-align: left;">8.0%</td><td style="text-align: left;">16.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">45</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">13.87%</td><td style="text-align: left;">10.0%</td><td style="text-align: left;">18.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">50</td><td style="text-align: left;">false</td><td style="text-align: left;">true</td><td style="text-align: left;">14.30%</td><td style="text-align: left;">10.0%</td><td style="text-align: left;">18.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">QoS策略对占用率的影响</td><td style="text-align: left;">15</td><td style="text-align: left;">50</td><td style="text-align: left;">false</td><td style="text-align: left;">false</td><td style="text-align: left;">12.47%</td><td style="text-align: left;">8.0%</td><td style="text-align: left;">16.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">50</td><td style="text-align: left;">true</td><td style="text-align: left;">true</td><td style="text-align: left;">11.42%</td><td style="text-align: left;">8.0%</td><td style="text-align: left;">16.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">15</td><td style="text-align: left;">50</td><td style="text-align: left;">true</td><td style="text-align: left;">false</td><td style="text-align: left;">11.17%</td><td style="text-align: left;">6.0%</td><td style="text-align: left;">16.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;">Topic数量对占用率的影响</td><td style="text-align: left;">20</td><td style="text-align: left;">50</td><td style="text-align: left;">true</td><td style="text-align: left;">false</td><td style="text-align: left;">16.30%</td><td style="text-align: left;">10.0%</td><td style="text-align: left;">22.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">10</td><td style="text-align: left;">50</td><td style="text-align: left;">true</td><td style="text-align: left;">false</td><td style="text-align: left;">6.54%</td><td style="text-align: left;">4.0%</td><td style="text-align: left;">12.0%</td><td style="text-align: left;"></td></tr><tr><td style="text-align: left;"></td><td style="text-align: left;">5</td><td style="text-align: left;">50</td><td style="text-align: left;">true</td><td style="text-align: left;">false</td><td style="text-align: left;">4.54%</td><td style="text-align: left;">2.0%</td><td style="text-align: left;">8.0%</td><td style="text-align: left;"></td></tr></tbody></table>将表格绘制成折线图如下所示：![](/uploads/2025/03/topic频率对cpu占用影响-1024x718.png)![](/uploads/2025/09/topic数量对cpu占用影响.png)<p>由表格数据可以得出结论：</p><ul><li><strong>Topic 数量与频率的增加会增加 <code>topic_state_monitor</code> 模块对系统的占用</strong>。如果以 <strong>15%</strong> 的占用率为界限定义为对 CPU 占用较少、为可用状态的话，那么 <strong>15个50Hz的Topic以下</strong> 或者 <strong>更多的更低Hz的Topic</strong>、<strong>更少的更高Hz的Topic</strong> 为此监控系统工作的最佳状态。</li><li>同时，<strong>QoS 策略也会对系统占用产生影响</strong>。设置 <code>best_effort</code> 为 <code>true</code>，即不使用 <strong>reliable 可靠性传输策略</strong>；设置 <code>transient_local</code> 为 <code>false</code>，即不使用 <strong>Volatile 持久性 QoS 策略</strong>。这样可以牺牲一点消息传输的可靠性来换取更低的资源占用。</li></ul><h3 id="小结"><a href="#小结" class="headerlink" title="小结"></a>小结</h3><p><code>topic_state_monitor</code> 模块可针对任意类型的 topic 生成一个 node 去监控 topic 的状态，通用性强。但如果需要监控过多高频的 Topic 消息可能会导致<strong>进程开销大</strong>。因此 Autoware 中对进行监控的 topic 进行了<strong>模块化分类处理</strong>，根据不同的应用场景选择性地监控关键模块的关键话题。例如，定位模块着重关注 <code>map</code> 到 <code>base_link</code> 的 <code>tf</code> 转换是否正常，控制模块着重关注发布的 <code>control_cmd</code> 控制 topic 是否正常。</p>]]>
    </content>
    <id>https://leo-wangbo.top/p/autoware%E4%B8%ADtopic_state_monitor%E6%A8%A1%E5%9D%97%E8%B0%83%E7%A0%94/</id>
    <link href="https://leo-wangbo.top/p/autoware%E4%B8%ADtopic_state_monitor%E6%A8%A1%E5%9D%97%E8%B0%83%E7%A0%94/"/>
    <published>2025-03-09T05:39:42.000Z</published>
    <summary>
      <![CDATA[<h2 id="一、topic-state-monitor模块简介"><a href="#一、topic-state-monitor模块简介" class="headerlink" title="一、topic_state_monitor模块简介"></a>一、topic_sta]]>
    </summary>
    <title>Autoware中topic_state_monitor模块调研</title>
    <updated>2025-09-10T01:34:49.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="自动驾驶" scheme="https://leo-wangbo.top/categories/%E8%87%AA%E5%8A%A8%E9%A9%BE%E9%A9%B6/"/>
    <content>
      <![CDATA[<h2 id="一、适配传感器"><a href="#一、适配传感器" class="headerlink" title="一、适配传感器"></a>一、适配传感器</h2><p>首先声明，踩了那么多坑后，明白一个道理，要想少出错，少踩坑，还是要遵循一切都参控官方文档的原则。不要怕官网文档繁杂又全是英语想省事，就一切都遵从csdn找到的别人整理的二手文档，包括我以下写的都只能当作参考，每个人硬件软件环境都不一样，具体步骤肯定有所差异，官网还是考虑最全的文档，英语有障碍可以下一个插件，推荐&quot;沉浸式翻译&quot;这个插件。<br>官网文档链接为:<a href="https://autowarefoundation.github.io/autoware-documentation/main/how-to-guides/">https://autowarefoundation.github.io/autoware-documentation/main/how-to-guides/</a></p><h3 id="设置传感器数据通信接口"><a href="#设置传感器数据通信接口" class="headerlink" title="设置传感器数据通信接口"></a>设置传感器数据通信接口</h3><p>根据官方提供的流程图，可以看到各个节点之间的数据通信：<a href="https://autowarefoundation.github.io/autoware-documentation/galactic/design/autoware-architecture/node-diagram/">https://autowarefoundation.github.io/autoware-documentation/galactic/design/autoware-architecture/node-diagram/</a></p><h4 id="雷达点云设置"><a href="#雷达点云设置" class="headerlink" title="雷达点云设置"></a>雷达点云设置</h4><p>Autoware输入的点云为 &#x3D;&#x3D;&#x2F;sensing&#x2F;lidar&#x2F;top&#x2F;outlier_filtered&#x2F;pointcloud&#x3D;&#x3D; 和 &#x3D;&#x3D;&#x2F;sensing&#x2F;lidar&#x2F;concatenated&#x2F;pointcloud&#x3D;&#x3D;（frame_id均为base_link）。<br>&#x2F;sensing&#x2F;lidar&#x2F;top&#x2F;&#x3D;&#x3D;outlier_filtered&#x3D;&#x3D;&#x2F;pointcloud用于&#x3D;&#x3D;定位&#x3D;&#x3D;,<br>&#x2F;sensing&#x2F;lidar&#x2F;&#x3D;&#x3D;concatenated&#x3D;&#x3D;&#x2F;pointcloud用&#x3D;&#x3D;于感知&#x3D;&#x3D;；</p><h5 id="编写雷达点云转换节点"><a href="#编写雷达点云转换节点" class="headerlink" title="编写雷达点云转换节点"></a>编写雷达点云转换节点</h5><p>打开终端并执行以下命令来创建工作空间和功能包：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p /home/buaa/autoware_universe/autoware/src/sensor_driver/robosense_ws/src</span><br><span class="line">cd /home/buaa/autoware_universe/autoware/src/sensor_driver/robosense_ws/src</span><br><span class="line">ros2 pkg create --build-type ament_cmake lidar_transform</span><br></pre></td></tr></table></figure><p>编写玩节点代码:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br></pre></td><td class="code"><pre><span class="line">#include &lt;rclcpp/rclcpp.hpp&gt;</span><br><span class="line">#include &lt;sensor_msgs/msg/point_cloud2.hpp&gt;</span><br><span class="line">#include &lt;tf2_geometry_msgs/tf2_geometry_msgs.hpp&gt;</span><br><span class="line">#include &lt;pcl_ros/transforms.hpp&gt;</span><br><span class="line">#include &lt;pcl_conversions/pcl_conversions.h&gt;  // 包含PCL转换头文件</span><br><span class="line"></span><br><span class="line">class LidarTransformNode : public rclcpp::Node</span><br><span class="line">&#123;</span><br><span class="line">public:</span><br><span class="line">    // 构造函数</span><br><span class="line">    LidarTransformNode() : Node(&quot;points_raw_transform_node&quot;)</span><br><span class="line">    &#123;</span><br><span class="line">        // 初始化坐标转换参数</span><br><span class="line">        // this-&gt;declare_parameter&lt;double&gt;(&quot;transform_x&quot;, 0.0);</span><br><span class="line">        // this-&gt;get_parameter(&quot;transform_x&quot;, transform_x);</span><br><span class="line">        transform_x = this-&gt;declare_parameter(&quot;transform_x&quot;, 0.0);</span><br><span class="line">        transform_y = this-&gt;declare_parameter(&quot;transform_y&quot;, 0.0);</span><br><span class="line">        transform_z = this-&gt;declare_parameter(&quot;transform_z&quot;, 0.0);</span><br><span class="line">        transform_roll = this-&gt;declare_parameter(&quot;transform_roll&quot;, 0.0);</span><br><span class="line">        transform_pitch = this-&gt;declare_parameter(&quot;transform_pitch&quot;, 0.0);</span><br><span class="line">        transform_yaw = this-&gt;declare_parameter(&quot;transform_yaw&quot;, 0.0);</span><br><span class="line">        RadiusOutlierFilter = this-&gt;declare_parameter(&quot;RadiusOutlierFilter&quot;, 1.0);</span><br><span class="line"></span><br><span class="line">        std::cout &lt;&lt; &quot;robosense to base_link:&quot; &lt;&lt; std::endl</span><br><span class="line">                  &lt;&lt; &quot;  transform_x:    &quot; &lt;&lt; transform_x &lt;&lt; std::endl</span><br><span class="line">                  &lt;&lt; &quot;  transform_y:    &quot; &lt;&lt; transform_y &lt;&lt; std::endl</span><br><span class="line">                  &lt;&lt; &quot;  transform_z:    &quot; &lt;&lt; transform_z &lt;&lt; std::endl</span><br><span class="line">                  &lt;&lt; &quot;  transform_roll: &quot; &lt;&lt; transform_roll &lt;&lt; std::endl</span><br><span class="line">                  &lt;&lt; &quot;  transform_pitch:&quot; &lt;&lt; transform_pitch &lt;&lt; std::endl</span><br><span class="line">                  &lt;&lt; &quot;  transform_yaw:  &quot; &lt;&lt; transform_yaw &lt;&lt; std::endl;</span><br><span class="line"></span><br><span class="line">        // Initialize translation</span><br><span class="line">        transform_stamp.transform.translation.x = transform_x;</span><br><span class="line">        transform_stamp.transform.translation.y = transform_y;</span><br><span class="line">        transform_stamp.transform.translation.z = transform_z;</span><br><span class="line">        // Initialize rotation (quaternion)</span><br><span class="line">        tf2::Quaternion quaternion;</span><br><span class="line">        quaternion.setRPY(transform_roll, transform_pitch, transform_yaw);</span><br><span class="line">        transform_stamp.transform.rotation.x = quaternion.x();</span><br><span class="line">        transform_stamp.transform.rotation.y = quaternion.y();</span><br><span class="line">        transform_stamp.transform.rotation.z = quaternion.z();</span><br><span class="line">        transform_stamp.transform.rotation.w = quaternion.w();</span><br><span class="line"></span><br><span class="line">        // 创建发布者</span><br><span class="line">        publisher_1 = this-&gt;create_publisher&lt;sensor_msgs::msg::PointCloud2&gt;(</span><br><span class="line">            &quot;/sensing/lidar/top/outlier_filtered/pointcloud&quot;,</span><br><span class="line">            10);</span><br><span class="line">        publisher_2 = this-&gt;create_publisher&lt;sensor_msgs::msg::PointCloud2&gt;(</span><br><span class="line">            &quot;/sensing/lidar/concatenated/pointcloud&quot;,</span><br><span class="line">            10);</span><br><span class="line"></span><br><span class="line">        // 订阅原始点云消息</span><br><span class="line">        subscription_ = this-&gt;create_subscription&lt;sensor_msgs::msg::PointCloud2&gt;(</span><br><span class="line">            &quot;/rslidar_points&quot;,</span><br><span class="line">            10,</span><br><span class="line">            std::bind(&amp;LidarTransformNode::pointCloudCallback, this, std::placeholders::_1));</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">private:</span><br><span class="line">    void pointCloudCallback(const sensor_msgs::msg::PointCloud2::SharedPtr msg)</span><br><span class="line">    &#123;</span><br><span class="line">        // 过滤掉距离传感器较近的点</span><br><span class="line">        pcl::PointCloud&lt;pcl::PointXYZI&gt;::Ptr xyz_cloud(new pcl::PointCloud&lt;pcl::PointXYZI&gt;);</span><br><span class="line">        pcl::PointCloud&lt;pcl::PointXYZI&gt;::Ptr pcl_output(new pcl::PointCloud&lt;pcl::PointXYZI&gt;);</span><br><span class="line">        pcl::fromROSMsg(*msg, *xyz_cloud);</span><br><span class="line">        for (size_t i = 0; i &lt; xyz_cloud-&gt;points.size(); ++i)</span><br><span class="line">        &#123;</span><br><span class="line">          if (sqrt(xyz_cloud-&gt;points[i].x * xyz_cloud-&gt;points[i].x + xyz_cloud-&gt;points[i].y * xyz_cloud-&gt;points[i].y +</span><br><span class="line">                   xyz_cloud-&gt;points[i].z * xyz_cloud-&gt;points[i].z) &gt;= RadiusOutlierFilter &amp;&amp; !isnan(xyz_cloud-&gt;points[i].z))</span><br><span class="line">          &#123;</span><br><span class="line">            pcl_output-&gt;points.push_back(xyz_cloud-&gt;points.at(i));</span><br><span class="line">          &#125;</span><br><span class="line">        &#125;</span><br><span class="line">        sensor_msgs::msg::PointCloud2 output;</span><br><span class="line">        pcl::toROSMsg(*pcl_output, output);</span><br><span class="line">        output.header = msg-&gt;header;</span><br><span class="line"></span><br><span class="line">        // 执行坐标转换</span><br><span class="line">        sensor_msgs::msg::PointCloud2 transformed_cloud;</span><br><span class="line">        pcl_ros::transformPointCloud(&quot;base_link&quot;, transform_stamp, output, transformed_cloud);</span><br><span class="line"></span><br><span class="line">        // 发布转换后的点云消息</span><br><span class="line">        publisher_1-&gt;publish(transformed_cloud);</span><br><span class="line">        publisher_2-&gt;publish(transformed_cloud);</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    rclcpp::Subscription&lt;sensor_msgs::msg::PointCloud2&gt;::SharedPtr subscription_;</span><br><span class="line">    rclcpp::Publisher&lt;sensor_msgs::msg::PointCloud2&gt;::SharedPtr publisher_1, publisher_2;</span><br><span class="line"></span><br><span class="line">    double transform_x, transform_y, transform_z, transform_roll, transform_pitch, transform_yaw, RadiusOutlierFilter; // 添加 radius_outlier_filter 成员变量声明</span><br><span class="line"></span><br><span class="line">    geometry_msgs::msg::TransformStamped transform_stamp;</span><br><span class="line">&#125;;</span><br><span class="line"></span><br><span class="line">int main(int argc, char **argv)</span><br><span class="line">&#123;</span><br><span class="line">    // 初始化节点</span><br><span class="line">    rclcpp::init(argc, argv);</span><br><span class="line"></span><br><span class="line">    // 创建实例</span><br><span class="line">    auto node = std::make_shared&lt;LidarTransformNode&gt;();</span><br><span class="line"></span><br><span class="line">    rclcpp::spin(node);</span><br><span class="line">    rclcpp::shutdown();</span><br><span class="line"></span><br><span class="line">    return 0;</span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure><p>然后编译：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon build --packages-up-to lidar_transform</span><br></pre></td></tr></table></figure><p>然后遵从Autoware.Universe官网教程 <a href="https://autowarefoundation.github.io/autoware-documentation/main/how-to-guides/integrating-autoware/creating-vehicle-and-sensor-model/creating-sensor-model/">https://autowarefoundation.github.io/autoware-documentation/main/how-to-guides/integrating-autoware/creating-vehicle-and-sensor-model/creating-sensor-model/</a>  更改&#x2F;home&#x2F;buaa&#x2F;autoware_universe&#x2F;autoware&#x2F;src&#x2F;sensor_kit&#x2F;sample_sensor_kit_launch&#x2F;sample_sensor_kit_launch&#x2F;launch 路径下的传感器启动文件</p><h4 id="更改lidar-launch-xml"><a href="#更改lidar-launch-xml" class="headerlink" title="更改lidar.launch.xml"></a>更改lidar.launch.xml</h4><p>由于只用一个雷达，故不使用点云融合功能包，设置use_concat_filter为false,并发布lidar_transform点云tf转换功能包</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br></pre></td><td class="code"><pre><span class="line">&lt;launch&gt;</span><br><span class="line">  &lt;arg name=&quot;use_concat_filter&quot; default=&quot;false&quot;/&gt;</span><br><span class="line">  &lt;arg name=&quot;vehicle_id&quot; default=&quot;$(env VEHICLE_ID default)&quot;/&gt;</span><br><span class="line">  &lt;arg name=&quot;pointcloud_container_name&quot; default=&quot;pointcloud_container&quot;/&gt;</span><br><span class="line">  &lt;arg name=&quot;rviz_config&quot; default=&quot;$(find-pkg-share rslidar_sdk)/rviz/rviz2.rviz&quot;/&gt;</span><br><span class="line">  &lt;group&gt;</span><br><span class="line">    &lt;push-ros-namespace namespace=&quot;lidar&quot;/&gt;</span><br><span class="line">    &lt;group&gt;</span><br><span class="line">      &lt;push-ros-namespace namespace=&quot;top&quot;/&gt;</span><br><span class="line">      &lt;node pkg=&quot;rslidar_sdk&quot; exec=&quot;rslidar_sdk_node&quot; output=&quot;screen&quot;&gt;</span><br><span class="line">          &lt;!-- 添加其他必要的参数 --&gt;</span><br><span class="line">          &lt;param name=&quot;queue_size&quot; type=&quot;int&quot; value=&quot;100&quot;/&gt;</span><br><span class="line">          &lt;param name=&quot;hardware_id&quot;  value=&quot;none&quot;/&gt;</span><br><span class="line">      &lt;/node&gt;</span><br><span class="line">      &lt;!-- &lt;node pkg=&quot;rviz2&quot; exec=&quot;rviz2&quot; output=&quot;screen&quot; args=&quot;-d $(var rviz_config)&quot;/&gt; --&gt;</span><br><span class="line">    &lt;/group&gt;</span><br><span class="line"></span><br><span class="line">    &lt;include file=&quot;$(find-pkg-share lidar_transform)/launch/points_raw_transform.launch.xml&quot;&gt;</span><br><span class="line">        &lt;arg name=&quot;transform_x&quot; value=&quot;0.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;transform_y&quot; value=&quot;0.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;transform_z&quot; value=&quot;1.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;transform_roll&quot; value=&quot;0.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;transform_pitch&quot; value=&quot;0.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;transform_yaw&quot; value=&quot;0.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;RadiusOutlierFilter&quot; value=&quot;1.0&quot;/&gt;</span><br><span class="line">    &lt;/include&gt;</span><br><span class="line"></span><br><span class="line">    &lt;!-- &lt;group&gt;</span><br><span class="line">      &lt;push-ros-namespace namespace=&quot;left&quot;/&gt;</span><br><span class="line">      &lt;include file=&quot;$(find-pkg-share common_sensor_launch)/launch/velodyne_VLP16.launch.xml&quot;&gt;</span><br><span class="line">        &lt;arg name=&quot;max_range&quot; value=&quot;5.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;sensor_frame&quot; value=&quot;velodyne_left&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;sensor_ip&quot; value=&quot;192.168.1.202&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;host_ip&quot; value=&quot;$(var host_ip)&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;data_port&quot; value=&quot;2369&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;scan_phase&quot; value=&quot;180.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;cloud_min_angle&quot; value=&quot;300&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;cloud_max_angle&quot; value=&quot;60&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;launch_driver&quot; value=&quot;$(var launch_driver)&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;vehicle_mirror_param_file&quot; value=&quot;$(var vehicle_mirror_param_file)&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;container_name&quot; value=&quot;pointcloud_container&quot;/&gt;</span><br><span class="line">      &lt;/include&gt;</span><br><span class="line">    &lt;/group&gt;</span><br><span class="line"></span><br><span class="line">    &lt;group&gt;</span><br><span class="line">      &lt;push-ros-namespace namespace=&quot;right&quot;/&gt;</span><br><span class="line">      &lt;include file=&quot;$(find-pkg-share common_sensor_launch)/launch/velodyne_VLP16.launch.xml&quot;&gt;</span><br><span class="line">        &lt;arg name=&quot;max_range&quot; value=&quot;5.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;sensor_frame&quot; value=&quot;velodyne_right&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;sensor_ip&quot; value=&quot;192.168.1.203&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;host_ip&quot; value=&quot;$(var host_ip)&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;data_port&quot; value=&quot;2370&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;scan_phase&quot; value=&quot;180.0&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;cloud_min_angle&quot; value=&quot;300&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;cloud_max_angle&quot; value=&quot;60&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;launch_driver&quot; value=&quot;$(var launch_driver)&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;vehicle_mirror_param_file&quot; value=&quot;$(var vehicle_mirror_param_file)&quot;/&gt;</span><br><span class="line">        &lt;arg name=&quot;container_name&quot; value=&quot;pointcloud_container&quot;/&gt;</span><br><span class="line">      &lt;/include&gt;</span><br><span class="line">    &lt;/group&gt; --&gt;</span><br><span class="line"></span><br><span class="line">    &lt;include file=&quot;$(find-pkg-share sample_sensor_kit_launch)/launch/pointcloud_preprocessor.launch.py&quot;&gt;</span><br><span class="line">      &lt;arg name=&quot;base_frame&quot; value=&quot;base_link&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;use_intra_process&quot; value=&quot;true&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;use_multithread&quot; value=&quot;true&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;pointcloud_container_name&quot; value=&quot;$(var pointcloud_container_name)&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;use_concat_filter&quot; value=&quot;$(var use_concat_filter)&quot;/&gt; </span><br><span class="line">    &lt;/include&gt;</span><br><span class="line">  &lt;/group&gt;</span><br><span class="line">&lt;/launch&gt;</span><br></pre></td></tr></table></figure><h4 id="更改imu-launch-xml"><a href="#更改imu-launch-xml" class="headerlink" title="更改imu.launch.xml"></a>更改imu.launch.xml</h4><p>添加雷达驱动，并发布雷达话题tamagawa&#x2F;imu_link到base_link的tf转换</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br></pre></td><td class="code"><pre><span class="line">&lt;launch&gt;</span><br><span class="line">  &lt;arg name=&quot;launch_driver&quot; default=&quot;true&quot;/&gt;</span><br><span class="line">  &lt;arg name=&quot;imu_raw_name&quot; default=&quot;tamagawa/imu_raw&quot;/&gt;</span><br><span class="line">  &lt;!-- add --&gt;</span><br><span class="line">  &lt;arg name=&quot;imu_corrector_param_file&quot; default=&quot;$(find-pkg-share imu_corrector)/config/imu_corrector.param.yaml&quot;/&gt;</span><br><span class="line"></span><br><span class="line">  &lt;group&gt;</span><br><span class="line">    &lt;push-ros-namespace namespace=&quot;imu&quot;/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;group&gt;</span><br><span class="line">      &lt;push-ros-namespace namespace=&quot;fdilink&quot;/&gt;</span><br><span class="line">      &lt;node pkg=&quot;fdilink_ahrs&quot; name=&quot;ahrs_driver_node&quot; exec=&quot;ahrs_driver_node&quot; if=&quot;$(var launch_driver)&quot;&gt;</span><br><span class="line">        &lt;param name=&quot;if_debug_&quot; value=&quot;false&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;serial_port_&quot; value=&quot;/dev/imu_usb&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;serial_baud_&quot; value=&quot;921600&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;imu_topic&quot; value=&quot;/sensing/imu/tamagawa/imu_raw&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;imu_frame_id_&quot; value=&quot;tamagawa/imu_link&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;mag_pose_2d_topic&quot; value=&quot;/mag_pose_2d&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;Magnetic_topic&quot; value=&quot;/magnetic&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;Euler_angles_topic&quot; value=&quot;/euler_angles&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;gps_topic&quot; value=&quot;/gps/fix&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;twist_topic&quot; value=&quot;/system_speed&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;NED_odom_topic&quot; value=&quot;/imu_odometry&quot;/&gt;</span><br><span class="line">        &lt;param name=&quot;device_type_&quot; value=&quot;1&quot;/&gt;</span><br><span class="line">      &lt;/node&gt;</span><br><span class="line">    &lt;/group&gt;</span><br><span class="line"></span><br><span class="line">    &lt;node pkg=&quot;tf2_ros&quot; exec=&quot;static_transform_publisher&quot; output=&quot;screen&quot;</span><br><span class="line">        args=&quot;0.5 0 0 0 0 0 base_link tamagawa/imu_link&quot;/&gt;</span><br><span class="line"></span><br><span class="line">    &lt;include file=&quot;$(find-pkg-share imu_corrector)/launch/imu_corrector.launch.xml&quot;&gt;</span><br><span class="line">      &lt;arg name=&quot;input_topic&quot; value=&quot;$(var imu_raw_name)&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;output_topic&quot; value=&quot;imu_data&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;param_file&quot; value=&quot;$(var imu_corrector_param_file)&quot;/&gt;</span><br><span class="line">    &lt;/include&gt;</span><br><span class="line"></span><br><span class="line">    &lt;include file=&quot;$(find-pkg-share imu_corrector)/launch/gyro_bias_estimator.launch.xml&quot;&gt;</span><br><span class="line">      &lt;arg name=&quot;input_imu_raw&quot; value=&quot;$(var imu_raw_name)&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;input_twist&quot; value=&quot;/sensing/vehicle_velocity_converter/twist_with_covariance&quot;/&gt;</span><br><span class="line">      &lt;arg name=&quot;imu_corrector_param_file&quot; value=&quot;$(var imu_corrector_param_file)&quot;/&gt;</span><br><span class="line">    &lt;/include&gt;</span><br><span class="line">  &lt;/group&gt;</span><br><span class="line">&lt;/launch&gt;</span><br></pre></td></tr></table></figure><h4 id="禁用自带的tf转换"><a href="#禁用自带的tf转换" class="headerlink" title="禁用自带的tf转换"></a>禁用自带的tf转换</h4><p>由于上述启动传感器时都发布了对应到baselink的tf转换，故禁用掉官方源码中发布的车体传感器tf转换部分。打开&#x2F;home&#x2F;buaa&#x2F;autoware_universe&#x2F;autoware&#x2F;src&#x2F;universe&#x2F;autoware.universe&#x2F;launch&#x2F;tier4_vehicle_launch&#x2F;launch 文件夹下的vehicle.launch.xml<br>注释掉vehicle description部分</p><h4 id="启动传感器"><a href="#启动传感器" class="headerlink" title="启动传感器"></a>启动传感器</h4><p>单独启动传感器的命令为:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ros2 launch tier4_sensing_launch sensing.launch.xml</span><br></pre></td></tr></table></figure><h2 id="二、适配底盘"><a href="#二、适配底盘" class="headerlink" title="二、适配底盘"></a>二、适配底盘</h2><p><a href="https://autowarefoundation.github.io/autoware-documentation/main/how-to-guides/integrating-autoware/creating-vehicle-interface-package/creating-vehicle-interface/">https://autowarefoundation.github.io/autoware-documentation/main/how-to-guides/integrating-autoware/creating-vehicle-interface-package/creating-vehicle-interface/</a><br>根据官网教程一步一步编写vehicle_interface来创建底盘驱动与Autoware之间的联系：</p><h3 id="创建功能包"><a href="#创建功能包" class="headerlink" title="创建功能包"></a>创建功能包</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd &lt;your-autoware-dir&gt;/src/vehicle/external</span><br><span class="line">ros2 pkg create --build-type ament_cmake my_vehicle_interface</span><br></pre></td></tr></table></figure><p>从 Autoware 订阅控制命令主题的一些必要主题以控制车辆，具体话题描述参考官网，其核心是将接收到的autoware控制话题&#x3D;&#x3D;control&#x2F;command&#x2F;control_cmd&#x3D;&#x3D;提取出控制指令转化为底盘可以接受的&#x3D;&#x3D;cmd_vel&#x3D;&#x3D;话题格式，同时将一些必要的车辆状态主题发布。<br>以下为脚本内容</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line">import rclpy</span><br><span class="line">from rclpy.node import Node</span><br><span class="line">from geometry_msgs.msg import Twist</span><br><span class="line">from autoware_auto_control_msgs.msg import AckermannControlCommand</span><br><span class="line">from autoware_auto_vehicle_msgs.msg import ControlModeReport, GearReport, SteeringReport, VelocityReport</span><br><span class="line">from hunter_msgs.msg import HunterStatus</span><br><span class="line">from tier4_vehicle_msgs.msg import BatteryStatus</span><br><span class="line"></span><br><span class="line">class VehicleInterface(Node):</span><br><span class="line">    def __init__(self):</span><br><span class="line">        super().__init__(&#x27;vehicle_interface&#x27;)</span><br><span class="line"></span><br><span class="line">        # 订阅 Autoware 的控制指令</span><br><span class="line">        self.subscriber_control_cmd = self.create_subscription(</span><br><span class="line">            AckermannControlCommand,</span><br><span class="line">            &#x27;control/command/control_cmd&#x27;,</span><br><span class="line">            self.control_cmd_callback,</span><br><span class="line">            10</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        # 发布小车的控制指令</span><br><span class="line">        self.publisher_cmd_vel = self.create_publisher(Twist, &#x27;/cmd_vel&#x27;, 10)</span><br><span class="line"></span><br><span class="line">        # 订阅小车的状态信息</span><br><span class="line">        self.subscriber_hunter_status = self.create_subscription(</span><br><span class="line">            HunterStatus,</span><br><span class="line">            &#x27;/hunter_status&#x27;,</span><br><span class="line">            self.hunter_status_callback,</span><br><span class="line">            10</span><br><span class="line">        )</span><br><span class="line"></span><br><span class="line">        # 发布转向状态</span><br><span class="line">        self.publisher_steering = self.create_publisher(SteeringReport, &#x27;/vehicle/status/steering_status&#x27;, 10)</span><br><span class="line"></span><br><span class="line">        # 发布速度状态</span><br><span class="line">        self.publisher_velocity = self.create_publisher(VelocityReport, &#x27;/vehicle/status/velocity_status&#x27;, 10)</span><br><span class="line"></span><br><span class="line">        # 发布电池状态</span><br><span class="line">        self.publisher_battery = self.create_publisher(BatteryStatus, &#x27;/vehicle/status/battery_charge&#x27;, 10)</span><br><span class="line"></span><br><span class="line">    def control_cmd_callback(self, msg):</span><br><span class="line">        &quot;&quot;&quot;</span><br><span class="line">        处理从 Autoware 收到的控制命令，并将其转换为 Ackermann 结构小车的控制命令</span><br><span class="line">        &quot;&quot;&quot;</span><br><span class="line">        twist = Twist()</span><br><span class="line">        twist.linear.x = msg.longitudinal.speed  # 线速度</span><br><span class="line">        twist.angular.z = msg.lateral.steering_tire_angle  # 转向角度</span><br><span class="line"></span><br><span class="line">        self.publisher_cmd_vel.publish(twist)  # 发布转换后的控制命令</span><br><span class="line"></span><br><span class="line">    def hunter_status_callback(self, msg):</span><br><span class="line">        &quot;&quot;&quot;</span><br><span class="line">        处理从小车接收到的状态信息，并将其发布到 Autoware 的相关话题</span><br><span class="line">        &quot;&quot;&quot;</span><br><span class="line"></span><br><span class="line">        # 发布转向报告</span><br><span class="line">        steering_report = SteeringReport()</span><br><span class="line">        steering_report.stamp = self.get_clock().now().to_msg()</span><br><span class="line">        steering_report.steering_tire_angle = msg.steering_angle</span><br><span class="line">        self.publisher_steering.publish(steering_report)</span><br><span class="line"></span><br><span class="line">        # 发布速度报告</span><br><span class="line">        velocity_report = VelocityReport()</span><br><span class="line">        velocity_report.header.stamp = self.get_clock().now().to_msg()</span><br><span class="line">        velocity_report.header.frame_id = &quot;base_link&quot;</span><br><span class="line">        velocity_report.longitudinal_velocity = msg.linear_velocity  # 纵向速度</span><br><span class="line">        velocity_report.lateral_velocity = 0.0  # 横向速度（假设为0）</span><br><span class="line">        velocity_report.heading_rate = msg.steering_angle  # 航向变化率</span><br><span class="line"></span><br><span class="line">        self.publisher_velocity.publish(velocity_report)</span><br><span class="line"></span><br><span class="line">        # 发布电池状态报告</span><br><span class="line">        battery_status = BatteryStatus()</span><br><span class="line">        battery_status.stamp = self.get_clock().now().to_msg()  # 时间戳</span><br><span class="line">        battery_status.energy_level = msg.battery_voltage  # 电池电压</span><br><span class="line">        self.publisher_battery.publish(battery_status)</span><br><span class="line"></span><br><span class="line">def main(args=None):</span><br><span class="line">    rclpy.init(args=args)</span><br><span class="line">    node = VehicleInterface()</span><br><span class="line">    rclpy.spin(node)</span><br><span class="line">    node.destroy_node()</span><br><span class="line">    rclpy.shutdown()</span><br><span class="line"></span><br><span class="line">if __name__ == &#x27;__main__&#x27;:</span><br><span class="line">    main()</span><br></pre></td></tr></table></figure><p>创建launch文件my_vehicle_interface.launch.xml：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">&lt;launch&gt;</span><br><span class="line">  &lt;node pkg=&quot;my_vehicle_interface&quot; exec=&quot;vehicle_interface.py&quot; name=&quot;vehicle_interface&quot; output=&quot;screen&quot;&gt;</span><br><span class="line">  &lt;/node&gt;</span><br><span class="line">&lt;/launch&gt;</span><br></pre></td></tr></table></figure><p>修改CMakeLists.txt与package.xml后编译：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release --packages-select my_vehicle_interface</span><br></pre></td></tr></table></figure><p>如果运行遇到找不到py文件的问题，可能是没有赋予其运行权限<br>在 vehicle_interface.py 的开头添加执行指令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">#!/usr/bin/env python3</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">chmod +x scripts/vehicle_interface.py</span><br></pre></td></tr></table></figure><p>然后找到&#x2F;home&#x2F;buaa&#x2F;autoware_universe&#x2F;autoware&#x2F;src&#x2F;universe&#x2F;autoware.universe&#x2F;launch&#x2F;tier4_vehicle_launch&#x2F;launch 路径下的vehicle.launch.xml 将vehicle_interface部分改成自己的：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">  &lt;!-- vehicle interface --&gt;</span><br><span class="line">  &lt;group if=&quot;$(var launch_vehicle_interface)&quot;&gt;</span><br><span class="line">    &lt;node pkg=&quot;my_vehicle_interface&quot; exec=&quot;vehicle_interface.py&quot; name=&quot;vehicle_interface&quot; output=&quot;screen&quot;&gt;</span><br><span class="line">      &lt;param name=&quot;vehicle_id&quot; value=&quot;$(var vehicle_id)&quot;/&gt;</span><br><span class="line">      &lt;param name=&quot;raw_vehicle_cmd_converter_param_path&quot; value=&quot;$(var raw_vehicle_cmd_converter_param_path)&quot;/&gt;</span><br><span class="line">      &lt;param name=&quot;initial_engage_state&quot; value=&quot;$(var initial_engage_state)&quot;/&gt;</span><br><span class="line">    &lt;/node&gt;</span><br><span class="line"></span><br><span class="line">  &lt;/group&gt;</span><br><span class="line">&lt;/launch&gt;</span><br></pre></td></tr></table></figure><p>但是为了调试便利，还是注释掉上述部分，选择单独启动vehicle interface：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ros2 launch my_vehicle_interface  my_vehicle_interface.launch.xml</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://leo-wangbo.top/p/autoware-universe%E9%80%82%E9%85%8D%E5%AE%9E%E8%BD%A6%E6%95%99%E7%A8%8B/</id>
    <link href="https://leo-wangbo.top/p/autoware-universe%E9%80%82%E9%85%8D%E5%AE%9E%E8%BD%A6%E6%95%99%E7%A8%8B/"/>
    <published>2024-08-17T00:18:14.000Z</published>
    <summary>
      <![CDATA[<h2 id="一、适配传感器"><a href="#一、适配传感器" class="headerlink" title="一、适配传感器"></a>一、适配传感器</h2><p>首先声明，踩了那么多坑后，明白一个道理，要想少出错，少踩坑，还是要遵循一切都参控官方文档的原则。不要]]>
    </summary>
    <title>Autoware.Universe适配实车教程</title>
    <updated>2024-08-18T06:10:09.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="自动驾驶" scheme="https://leo-wangbo.top/categories/%E8%87%AA%E5%8A%A8%E9%A9%BE%E9%A9%B6/"/>
    <content>
      <![CDATA[<h2 id="Autoware-universe-安装步骤"><a href="#Autoware-universe-安装步骤" class="headerlink" title="Autoware.universe 安装步骤"></a>Autoware.universe 安装步骤</h2><h3 id="克隆Autoware到本地"><a href="#克隆Autoware到本地" class="headerlink" title="克隆Autoware到本地"></a>克隆Autoware到本地</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">mkdir autoware_universe</span><br><span class="line">cd autoware_universe/</span><br><span class="line">git clone https://github.com/autowarefoundation/autoware.git -b humble</span><br></pre></td></tr></table></figure><blockquote><p>注意ROS的版本</p></blockquote><h3 id="安装NVIDIA-显卡驱动"><a href="#安装NVIDIA-显卡驱动" class="headerlink" title="安装NVIDIA 显卡驱动"></a>安装NVIDIA 显卡驱动</h3><h5 id="若输入-sudo-nvidia-smi-检查英伟达驱动出现以下报错："><a href="#若输入-sudo-nvidia-smi-检查英伟达驱动出现以下报错：" class="headerlink" title="若输入 sudo nvidia-smi 检查英伟达驱动出现以下报错："></a>若输入 sudo nvidia-smi 检查英伟达驱动出现以下报错：</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Failed to initialize NVML: Driver/library version mismatch</span><br><span class="line">NVML library version: 550.90  </span><br></pre></td></tr></table></figure><blockquote><p>原因是NVIDIA 内核驱动与系统驱动版本不一致，按照网上提出的方法使用sudo rmmod nvidia 命令退出当前内核使用的显卡模块，重新加载升级后版本的显卡驱动作为我们的内核模块发现此方法不可行</p><h4 id="最后解决办法为："><a href="#最后解决办法为：" class="headerlink" title="最后解决办法为："></a>最后解决办法为：</h4><h5 id="卸载驱动"><a href="#卸载驱动" class="headerlink" title="卸载驱动"></a>卸载驱动</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get purge nvidia*</span><br></pre></td></tr></table></figure><h5 id="查找本机内核版本"><a href="#查找本机内核版本" class="headerlink" title="查找本机内核版本"></a>查找本机内核版本</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /proc/driver/nvidia/version</span><br></pre></td></tr></table></figure><p>发现为550.90.07</p><h5 id="于是尝试安装550版本的驱动"><a href="#于是尝试安装550版本的驱动" class="headerlink" title="于是尝试安装550版本的驱动"></a>于是尝试安装550版本的驱动</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install nvidia-driver-550 nvidia-settings nvidia-prime</span><br></pre></td></tr></table></figure><h5 id="出现报错"><a href="#出现报错" class="headerlink" title="出现报错"></a>出现报错</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">正在解压 libnvidia-compute-550:amd64 (550.90.07-0ubuntu1) 并覆盖 (550.90.07-0ubuntu0.22.04.1) ...</span><br><span class="line">dpkg: 处理归档 /tmp/apt-dpkg-install-WqT5B5/04-libnvidia-compute-550_550.90.07-0ubuntu1_amd64.deb (--unpack)时出错：</span><br><span class="line">正试图覆盖 /usr/lib/x86_64-linux-gnu/libnvidia-gpucomp.so.550.90.07，它同时被包含于软件包 libnvidia-gl-550:amd64 550.90.07-0ubuntu0.22.04.1</span><br><span class="line">dpkg-deb: 错误: 粘贴 子进程被信号(Broken pipe) 终止了</span><br></pre></td></tr></table></figure><p>具体是 libnvidia-compute-550 和 libnvidia-gl-550 包在更新时发生了冲突</p></blockquote><h5 id="强制卸载冲突的包"><a href="#强制卸载冲突的包" class="headerlink" title="强制卸载冲突的包"></a>强制卸载冲突的包</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo dpkg --remove --force-remove-reinstreq libnvidia-compute-550 libnvidia-compute-550:i386</span><br><span class="line">sudo dpkg --remove --force-remove-reinstreq libnvidia-gl-550 libnvidia-gl-550:i386</span><br></pre></td></tr></table></figure><h5 id="清理已损坏的包和未完成的安装："><a href="#清理已损坏的包和未完成的安装：" class="headerlink" title="清理已损坏的包和未完成的安装："></a>清理已损坏的包和未完成的安装：</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get clean</span><br><span class="line">sudo apt-get autoremove</span><br><span class="line">sudo apt-get autoclean</span><br><span class="line">sudo apt-get -f install</span><br></pre></td></tr></table></figure><h5 id="重新安装NVIDIA驱动"><a href="#重新安装NVIDIA驱动" class="headerlink" title="重新安装NVIDIA驱动"></a>重新安装NVIDIA驱动</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install nvidia-driver-550 nvidia-settings nvidia-prime</span><br></pre></td></tr></table></figure><h5 id="重新生成内核模块"><a href="#重新生成内核模块" class="headerlink" title="重新生成内核模块"></a>重新生成内核模块</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo dkms autoinstall</span><br></pre></td></tr></table></figure><h5 id="重启系统以应用更改"><a href="#重启系统以应用更改" class="headerlink" title="重启系统以应用更改"></a>重启系统以应用更改</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo reboot</span><br></pre></td></tr></table></figure><p>再次使用 nvidia-smi 检查驱动显示驱动正常</p><h3 id="安装ROS2-humble"><a href="#安装ROS2-humble" class="headerlink" title="安装ROS2 humble"></a>安装ROS2 humble</h3><p>鱼香ros一键安装：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://fishros.com/install -O fishros &amp;&amp; . fishros</span><br></pre></td></tr></table></figure><h3 id="安装ros2-dev-tools"><a href="#安装ros2-dev-tools" class="headerlink" title="安装ros2_dev_tools"></a>安装ros2_dev_tools</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update &amp;&amp; sudo apt install -y \</span><br><span class="line">  build-essential \</span><br><span class="line">  cmake \</span><br><span class="line">  git \</span><br><span class="line">  python3-colcon-common-extensions \</span><br><span class="line">  python3-flake8 \</span><br><span class="line">  python3-pip \</span><br><span class="line">  python3-pytest-cov \</span><br><span class="line">  python3-rosdep \</span><br><span class="line">  python3-setuptools \</span><br><span class="line">  python3-vcstool \</span><br><span class="line">  wget</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line">python3 -m pip install -U \</span><br><span class="line">  flake8-blind-except \</span><br><span class="line">  flake8-builtins \</span><br><span class="line">  flake8-class-newline \</span><br><span class="line">  flake8-comprehensions \</span><br><span class="line">  flake8-deprecated \</span><br><span class="line">  flake8-docstrings \</span><br><span class="line">  flake8-import-order \</span><br><span class="line">  flake8-quotes \</span><br><span class="line">  pytest-repeat \</span><br><span class="line">  pytest-rerunfailures \</span><br><span class="line">  pytest \</span><br><span class="line">  setuptools</span><br></pre></td></tr></table></figure><h3 id="安装-Ansible"><a href="#安装-Ansible" class="headerlink" title="安装 Ansible"></a>安装 Ansible</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get purge ansible</span><br><span class="line">sudo apt-get -y update</span><br><span class="line">sudo apt-get -y install pipx</span><br><span class="line">python3 -m pipx ensurepath</span><br><span class="line">pipx install --include-deps --force &quot;ansible==6.*&quot;</span><br><span class="line">cd autoware/</span><br><span class="line">ansible-galaxy collection install -f -r &quot;ansible-galaxy-requirements.yaml&quot;</span><br></pre></td></tr></table></figure><h3 id="安装-Build-Tools"><a href="#安装-Build-Tools" class="headerlink" title="安装 Build Tools"></a>安装 Build Tools</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get install -y ccache</span><br></pre></td></tr></table></figure><h3 id="安装-Dev-Tools"><a href="#安装-Dev-Tools" class="headerlink" title="安装 Dev Tools"></a>安装 Dev Tools</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y git-lfs</span><br><span class="line">git lfs install</span><br><span class="line">pip3 install pre-commit</span><br><span class="line">pip3 install clang-format==18.1.8 --user --extra-index-url=https://pypi.tuna.tsinghua.edu.cn/simple</span><br><span class="line">sudo apt-get install -y golang</span><br><span class="line">sudo apt-get install -y ros-$&#123;ROS_DISTRO&#125;-plotjuggler-ros</span><br></pre></td></tr></table></figure><h3 id="安装-gdown"><a href="#安装-gdown" class="headerlink" title="安装 gdown"></a>安装 gdown</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip3 install gdown</span><br></pre></td></tr></table></figure><h3 id="安装-geographiclib"><a href="#安装-geographiclib" class="headerlink" title="安装 geographiclib"></a>安装 geographiclib</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install geographiclib-tools</span><br><span class="line">sudo geographiclib-get-geoids egm2008-1</span><br></pre></td></tr></table></figure><h3 id="安装rmw-implementation"><a href="#安装rmw-implementation" class="headerlink" title="安装rmw_implementation"></a>安装rmw_implementation</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"># 注意官网给的是mian，humble的</span><br><span class="line">wget -O /tmp/amd64.env https://raw.githubusercontent.com/autowarefoundation/autoware/main/amd64.env &amp;&amp; source /tmp/amd64.env</span><br><span class="line">sudo apt update</span><br><span class="line">rmw_implementation_dashed=$(eval sed -e &quot;s/_/-/g&quot; &lt;&lt;&lt; &quot;$&#123;rmw_implementation&#125;&quot;)</span><br><span class="line">sudo apt install ros-$&#123;rosdistro&#125;-$&#123;rmw_implementation_dashed&#125;</span><br><span class="line">echo &#x27;&#x27; &gt;&gt; ~/.bashrc &amp;&amp; echo &quot;export RMW_IMPLEMENTATION=$&#123;rmw_implementation&#125;&quot; &gt;&gt; ~/.bashrc</span><br></pre></td></tr></table></figure><h3 id="安装pacmod"><a href="#安装pacmod" class="headerlink" title="安装pacmod"></a>安装pacmod</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">wget -O /tmp/amd64.env https://raw.githubusercontent.com/autowarefoundation/autoware/galactic/amd64.env &amp;&amp; source /tmp/amd64.env</span><br><span class="line">sudo apt install apt-transport-https</span><br><span class="line">sudo sh -c &#x27;echo &quot;deb [trusted=yes] https://s3.amazonaws.com/autonomoustuff-repo/ $(lsb_release -sc) main&quot; &gt; /etc/apt/sources.list.d/autonomoustuff-public.list&#x27;</span><br><span class="line">sudo apt update</span><br><span class="line">sudo apt install ros-$&#123;rosdistro&#125;-pacmod3</span><br></pre></td></tr></table></figure><h3 id="安装autoware-core"><a href="#安装autoware-core" class="headerlink" title="安装autoware_core"></a>安装autoware_core</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip3 install gdown</span><br></pre></td></tr></table></figure><h3 id="安装autoware-universe-dependencies"><a href="#安装autoware-universe-dependencies" class="headerlink" title="安装autoware universe dependencies"></a>安装autoware universe dependencies</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install geographiclib-tools</span><br><span class="line">sudo geographiclib-get-geoids egm2008-1</span><br></pre></td></tr></table></figure><h3 id="安装pre-commit"><a href="#安装pre-commit" class="headerlink" title="安装pre_commit"></a>安装pre_commit</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">clang_format_version=14.0.6</span><br><span class="line">pip3 install pre-commit clang-format==$&#123;clang_format_version&#125;</span><br><span class="line">sudo add-apt-repository ppa:longsleep/golang-backports</span><br><span class="line">sudo apt install golang</span><br></pre></td></tr></table></figure><h3 id="安装CUDA"><a href="#安装CUDA" class="headerlink" title="安装CUDA"></a>安装CUDA</h3><p>查看amd64.env,可以看到推荐的CUDA版本为12.3，在<a href="https://developer.nvidia.com/cuda-toolkit">https://developer.nvidia.com/cuda-toolkit</a> 官网中选择版本，为了避免因为CUDA版本太高，cuDNN、TensorRT无法使用，故下载CUDA12.0<br>网页中选择好CUDA版本安装deb方式安装：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.0-1_all.deb</span><br><span class="line">sudo dpkg -i cuda-keyring_1.0-1_all.deb</span><br><span class="line">sudo apt-get update</span><br><span class="line">sudo apt-get -y install cuda-toolkit-12-0</span><br></pre></td></tr></table></figure><p>设置环境变量</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">export PATH=/usr/local/cuda-12.0/bin:$PATH</span><br><span class="line">export LD_LIBRARY_PATH=/usr/local/cuda-12.0/lib64:$LD_LIBRARY_PATH</span><br></pre></td></tr></table></figure><p>检查CUDA版本：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nvcc --version</span><br></pre></td></tr></table></figure><h3 id="安装cuDNN"><a href="#安装cuDNN" class="headerlink" title="安装cuDNN"></a>安装cuDNN</h3><p>在官网<a href="https://developer.nvidia.com/rdp/cudnn-archive">https://developer.nvidia.com/rdp/cudnn-archive</a> 下载好cuDNN v8.9.5 for CUDA12.X后,解压文件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">tar -xvf cudnn-linux-x86_64-8.9.5.30_cuda12-archive.tar.xz </span><br></pre></td></tr></table></figure><p>将解压后的头文件和库复制到cuda目录中：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">cd cudnn-linux-x86_64-8.9.5.30_cuda12-archive/</span><br><span class="line">sudo cp include/cudnn*    /usr/local/cuda/include </span><br><span class="line">sudo cp lib/libcudnn*    /usr/local/cuda/lib64 </span><br><span class="line">sudo chmod a+r /usr/local/cuda/include/cudnn*   /usr/local/cuda/lib64/libcudnn*</span><br></pre></td></tr></table></figure><p>cuDNN安装完成，查看安装的版本：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /usr/local/cuda/include/cudnn_version.h | grep CUDNN_MAJOR -A 2</span><br></pre></td></tr></table></figure><h3 id="安装TensorRT"><a href="#安装TensorRT" class="headerlink" title="安装TensorRT"></a>安装TensorRT</h3><p>在官网<a href="https://developer.nvidia.com/nvidia-tensorrt-8x-download%E9%80%89%E6%8B%A9TensorRT">https://developer.nvidia.com/nvidia-tensorrt-8x-download选择TensorRT</a> 8.6进行下载后解压：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo dpkg -i nv-tensorrt-*.deb</span><br></pre></td></tr></table></figure><p>配置环境变量：将TensorRT的库路径添加到LD_LIBRARY_PATH中，编辑~&#x2F;.bashrc文件并添加以下内容：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib/x86_64-linux-gnu/</span><br></pre></td></tr></table></figure><p>重启终端：保存~&#x2F;.bashrc文件并执行以下命令使配置生效：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source ~/.bashrc</span><br></pre></td></tr></table></figure><p>安装完成后，您可以通过运行以下命令验证TensorRT是否已成功安装：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">dpkg -l | grep TensorRT</span><br></pre></td></tr></table></figure><h3 id="下载-Autoware-artifacts"><a href="#下载-Autoware-artifacts" class="headerlink" title="下载 Autoware artifacts"></a>下载 Autoware artifacts</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd autoware/</span><br><span class="line">ansible-galaxy collection install -f -r &quot;ansible-galaxy-requirements.yaml&quot;</span><br><span class="line">ansible-playbook autoware.dev_env.download_artifacts -e &quot;data_dir=$HOME/autoware_data&quot; --ask-become-pass</span><br></pre></td></tr></table></figure><h3 id="编译源码"><a href="#编译源码" class="headerlink" title="编译源码"></a>编译源码</h3><p>克隆存储库：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd autoware</span><br><span class="line">mkdir src</span><br><span class="line">vcs import src &lt; autoware.repos</span><br></pre></td></tr></table></figure><p>安装依赖的 ROS 包</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">sudo rosdep init</span><br><span class="line">sudo rosdep update</span><br><span class="line">rosdepc install</span><br><span class="line">source /opt/ros/humble/setup.bash</span><br><span class="line">rosdepc install -y --from-paths src --ignore-src --rosdistro $ROS_DISTRO</span><br></pre></td></tr></table></figure><p>编译：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon build --symlink-install --cmake-args -DCMAKE_BUILD_TYPE=Release</span><br></pre></td></tr></table></figure><p>单独编译某个包：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon build --packages-up-to &lt;name-of-pkg&gt;</span><br></pre></td></tr></table></figure><p>清理并重新构建：有时候构建过程中的残留文件可能会导致问题。尝试清理以前的构建文件并重新构建项目：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">rm -rf build install log</span><br><span class="line">colcon clean</span><br></pre></td></tr></table></figure><h5 id="编译报错"><a href="#编译报错" class="headerlink" title="编译报错"></a>编译报错</h5><blockquote><p>&#x2F;home&#x2F;buaa&#x2F;TensorRT-8.6.1.6&#x2F;include&#x2F;NvInferRuntime.h:674:61: error: unused parameter ‘pluginFactory’ [-Werror&#x3D;unused-parameter]<br>674 | void const<em> blob, std::size_t size, IPluginFactory</em> pluginFactory) noexcept<br>| <del><del></del><del></del></del><del><del></del></del>^<del><del></del><del></del></del>~~<br>cc1plus: all warnings being treated as errors<br>gmake[2]: <strong><em> [CMakeFiles&#x2F;tensorrt_common.dir&#x2F;build.make:76: CMakeFiles&#x2F;tensorrt_common.dir&#x2F;src&#x2F;tensorrt_common.cpp.o] Error 1<br>gmake[1]: </em></strong> [CMakeFiles&#x2F;Makefile2:137: CMakeFiles&#x2F;tensorrt_common.dir&#x2F;all] Error 2<br>gmake: *** [Makefile:146: all] Error 2</p></blockquote><p>这个错误主要是由于编译器将所有警告都视为错误，而NvInferRuntime.h中的一个未使用的参数pluginFactory触发了这个警告</p><h5 id="解决方法：忽略未使用参数的警告"><a href="#解决方法：忽略未使用参数的警告" class="headerlink" title="解决方法：忽略未使用参数的警告"></a>解决方法：忽略未使用参数的警告</h5><p>找到包含tensorrt_common包的CMakeLists.txt文件：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">find . -name &quot;CMakeLists.txt&quot; | grep tensorrt_common</span><br></pre></td></tr></table></figure><p>终端输出：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./src/universe/autoware.universe/common/tensorrt_common/CMakeLists.txt</span><br></pre></td></tr></table></figure><p>修改CMakeLists.txt文件,在CMakeLists.txt文件中添加以下行，忽略未使用参数的警告：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">set(CMAKE_CXX_FLAGS &quot;$&#123;CMAKE_CXX_FLAGS&#125; -Wno-error=unused-parameter&quot;)</span><br></pre></td></tr></table></figure><h5 id="出现警告"><a href="#出现警告" class="headerlink" title="出现警告"></a>出现警告</h5><blockquote><p>CMake Warning at CMakeLists.txt:20 (message):<br>cuda, cudnn, tensorrt libraries are not found</p></blockquote><h5 id="解决方法-设置环境变量："><a href="#解决方法-设置环境变量：" class="headerlink" title="解决方法 设置环境变量："></a>解决方法 设置环境变量：</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">export PATH=/usr/local/cuda/bin$&#123;PATH:+:$&#123;PATH&#125;&#125;</span><br><span class="line">export LD_LIBRARY_PATH=/usr/local/cuda/lib64$&#123;LD_LIBRARY_PATH:+:$&#123;LD_LIBRARY_PATH&#125;&#125;</span><br><span class="line">source ~/.bashrc</span><br></pre></td></tr></table></figure><p>编译警告1：</p><blockquote><p>— stderr: elevation_map_loader<br>CMake Warning at CMakeLists.txt:16 (find_package):<br>By not providing “Findrosbag2_storage_sqlite3.cmake” in CMAKE_MODULE_PATH<br>this project has asked CMake to find a package configuration file provided<br>by “rosbag2_storage_sqlite3”, but CMake did not find one.<br>Could not find a package configuration file provided by<br>“rosbag2_storage_sqlite3” with any of the following names:<br>rosbag2_storage_sqlite3Config.cmake<br>rosbag2_storage_sqlite3-config.cmake<br>Add the installation prefix of “rosbag2_storage_sqlite3” to<br>CMAKE_PREFIX_PATH or set “rosbag2_storage_sqlite3_DIR” to a directory<br>containing one of the above files. If “rosbag2_storage_sqlite3” provides a<br>separate development package or SDK, be sure it has been installed.</p><h5 id="解决办法：安装对应的包"><a href="#解决办法：安装对应的包" class="headerlink" title="解决办法：安装对应的包"></a>解决办法：安装对应的包</h5><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install ros-$ROS_DISTRO-rosbag2-storage*</span><br></pre></td></tr></table></figure><p>编译警告2：<br>— stderr: yabloc_pose_initializer<br>CMake Warning (dev) at CMakeLists.txt:12 (find_package):<br>Policy CMP0074 is not set: find_package uses _ROOT variables.<br>Run “cmake –help-policy CMP0074” for policy details. Use the cmake_policy<br>command to set the policy and suppress this warning.<br>CMake variable PCL_ROOT is set to:<br>&#x2F;usr<br>For compatibility, CMake is ignoring the variable.<br>This warning is for project developers. Use -Wno-dev to suppress it.</p></blockquote><hr><h5 id="解决办法：安装对应的包-1"><a href="#解决办法：安装对应的包-1" class="headerlink" title="解决办法：安装对应的包"></a>解决办法：安装对应的包</h5><p>CMP0074未设置，而在项目中使用了find_package命令，该命令使用了PCL_ROOT变量。<br>在对应的包的project()命令之后，find_package()命令之前，添加</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cmake_policy(SET CMP0074 NEW)</span><br></pre></td></tr></table></figure><p>使用以下命令来查找功能包所在的位置,例如要寻找上面报错的yabloc_pose_initializer包的位置：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon list | grep yabloc_pose_initializer</span><br></pre></td></tr></table></figure><p>然后单独编译这个包：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon build --packages-up-to yabloc_pose_initializer</span><br></pre></td></tr></table></figure><p>编译警告3</p><blockquote><p>— stderr: bag_time_manager_rviz_plugin<br>CMake Warning (dev) at CMakeLists.txt:7 (find_package):<br>Ignoring EXACT since no version is requested.<br>This warning is for project developers. Use -Wno-dev to suppress it.</p></blockquote><hr><h5 id="解决办法："><a href="#解决办法：" class="headerlink" title="解决办法："></a>解决办法：</h5><p>没安装QT5或者没在~&#x2F;.bashrc中指明QT5的位置，查询QT5是否安装，若安装则或打印出安装位置:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">qmake --version</span><br></pre></td></tr></table></figure><p>终端输出：</p><blockquote><p>QMake version 3.1<br>Using Qt version 5.15.3 in &#x2F;usr&#x2F;lib&#x2F;x86_64-linux-gnu</p></blockquote><p>故在~&#x2F;.bashrc添加:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">export PATH=&quot;/usr/lib/x86_64-linux-gnu/qt5/bin:$PATH&quot;</span><br><span class="line">export LD_LIBRARY_PATH=&quot;/usr/lib/x86_64-linux-gnu/qt5/lib:$LD_LIBRARY_PATH&quot;</span><br></pre></td></tr></table></figure><h3 id="安装Autoware-Build-GUI"><a href="#安装Autoware-Build-GUI" class="headerlink" title="安装Autoware Build GUI"></a>安装Autoware Build GUI</h3><p>安装依赖：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install libwebkit2gtk-4.1-0 libjavascriptcoregtk-4.1-0 libsoup-3.0-0 libsoup-3.0-common</span><br></pre></td></tr></table></figure><p>安装Rust</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">curl --proto &#x27;=https&#x27; --tlsv1.2 -sSf https://sh.rustup.rs/ | sh</span><br><span class="line">sudo apt install rustc</span><br></pre></td></tr></table></figure><p>验证:</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rustc --version</span><br></pre></td></tr></table></figure><p>安装Node.js：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install nodejs</span><br></pre></td></tr></table></figure><p>验证 Node.js 安装</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">node --version</span><br></pre></td></tr></table></figure><p>安装npm</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install -g pnpm</span><br></pre></td></tr></table></figure><p>下载源码：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/leo-drive/autoware-build-gui.git</span><br></pre></td></tr></table></figure><p>安装.deb</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo dpkg -i autoware-build-gui_1.0.3_amd64.deb</span><br></pre></td></tr></table></figure><h3 id="下载好高精地图后就可运行案例"><a href="#下载好高精地图后就可运行案例" class="headerlink" title="下载好高精地图后就可运行案例"></a>下载好高精地图后就可运行案例</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source install/setup.bash</span><br><span class="line">ros2 launch autoware_launch planning_simulator.launch.xml map_path:=autoware_map/sample-map-planning vehicle_model:=sample_vehicle sensor_model:=sample_sensor_kit</span><br></pre></td></tr></table></figure><p><img src="/uploads/2024/08/Autoware-Universe-1024x574.png"></p>]]>
    </content>
    <id>https://leo-wangbo.top/p/autoware-universe%E5%AE%8C%E6%95%B4%E9%83%A8%E7%BD%B2%E6%AD%A5%E9%AA%A4%EF%BC%88%E8%B8%A9%E5%9D%91%E7%89%88%EF%BC%89/</id>
    <link href="https://leo-wangbo.top/p/autoware-universe%E5%AE%8C%E6%95%B4%E9%83%A8%E7%BD%B2%E6%AD%A5%E9%AA%A4%EF%BC%88%E8%B8%A9%E5%9D%91%E7%89%88%EF%BC%89/"/>
    <published>2024-08-11T01:19:35.000Z</published>
    <summary>
      <![CDATA[<h2 id="Autoware-universe-安装步骤"><a href="#Autoware-universe-安装步骤" class="headerlink" title="Autoware.universe 安装步骤"></a>Autoware.universe 安装]]>
    </summary>
    <title>Autoware.universe完整部署步骤（踩坑版）</title>
    <updated>2024-08-18T06:10:15.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/ROS/"/>
    <category term="SLAM" scheme="https://leo-wangbo.top/categories/ROS/SLAM/"/>
    <content>
      <![CDATA[<p>前面把算法在仿真环境都跑通过后，决定拿雷达在真实世界跑一下。先介绍一下最近又发现的两个巨牛的算法：Point-Lio与Faster-lio。</p><h2 id="Point-Lio部署"><a href="#Point-Lio部署" class="headerlink" title="Point-Lio部署"></a>Point-Lio部署</h2><p>Point-Lio是一种鲁棒且高带宽的LIO算法，具备在极端剧烈运动条件下稳定估计的能力，能够提供准确的、高频的里程计测量（4-8 kHz），可应对严重振动和高角速度或线速度的情况。但对算力的要求较高、CPU负载较大。</p><p><img src="/uploads/2023/11/image-1024x362.png"></p><p>先安装<strong><a href="https://github.com/Livox-SDK/livox_ros_driver">livox_ros_driver</a></strong> ，单独创一个工作空间，或者和Point-Lio一个工作空间也行。这里新建一个工作空间：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p livox_ros_driver_ws/src #-p  代表递归创建文件夹</span><br><span class="line">cd livox_ros_driver_ws/src</span><br><span class="line">git clone https://github.com/Livox-SDK/livox_ros_driver.git</span><br><span class="line">cd ..</span><br><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>然后安装Point-Lio</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p Point_Lio_ws/src</span><br><span class="line">cd Point_Lio_ws/src</span><br><span class="line">git clone https://github.com/hku-mars/Point-LIO.git</span><br><span class="line">cd Point-LIO</span><br><span class="line">git submodule update --init</span><br><span class="line">cd ../..</span><br></pre></td></tr></table></figure><p>编译前先source一下livox_ros_driver的工作空间（如果point-lio的src下有livox_ros_driver则省去此步骤）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source /home/leo/livox_ros_driver_ws/devel/setup.bash</span><br></pre></td></tr></table></figure><p>然后编译</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>由于官方只对avia等固态激光雷达做了启动文件的适配，并没有对mid360雷达做适配，但我们可以将avia的启动文件中的一些雷达参数改为mid360的参数，主要就是线数、IMU外参这些。以下是我在src&#x2F;config文件夹下增加的mid360.yaml文件配置：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br></pre></td><td class="code"><pre><span class="line">common:</span><br><span class="line">    lid_topic:  &quot;/livox/lidar&quot; </span><br><span class="line">    imu_topic:  &quot;/livox/imu&quot; </span><br><span class="line">    con_frame: false # true: if you need to combine several LiDAR frames into one</span><br><span class="line">    con_frame_num: 1 # the number of frames combined</span><br><span class="line">    cut_frame: false # true: if you need to cut one LiDAR frame into several subframes</span><br><span class="line">    cut_frame_time_interval: 0.1 # should be integral fraction of 1 / LiDAR frequency</span><br><span class="line">    time_lag_imu_to_lidar: 0.0 # Time offset between LiDAR and IMU calibrated by other algorithms, e.g., LI-Init (find in Readme)</span><br><span class="line">                               # the timesample of IMU is transferred from the current timeline to LiDAR&#x27;s timeline by subtracting this value</span><br><span class="line"></span><br><span class="line">preprocess:</span><br><span class="line">    lidar_type: 1 </span><br><span class="line">    scan_line: 4</span><br><span class="line">    timestamp_unit: 1           # the unit of time/t field in the PointCloud2 rostopic: 0-second, 1-milisecond, 2-microsecond, 3-nanosecond.</span><br><span class="line">    blind: 0.5 </span><br><span class="line"></span><br><span class="line">mapping:</span><br><span class="line">    imu_en: true</span><br><span class="line">    start_in_aggressive_motion: false # if true, a preknown gravity should be provided in following gravity_init</span><br><span class="line">    extrinsic_est_en: false # for aggressive motion, set this variable false</span><br><span class="line">    imu_time_inte: 0.005 # = 1 / frequency of IMU</span><br><span class="line">    satu_acc: 3.0 # the saturation value of IMU&#x27;s acceleration. not related to the units</span><br><span class="line">    satu_gyro: 35 # the saturation value of IMU&#x27;s angular velocity. not related to the units</span><br><span class="line">    acc_norm: 1.0 # 1.0 for g as unit, 9.81 for m/s^2 as unit of the IMU&#x27;s acceleration</span><br><span class="line">    lidar_meas_cov: 0.001 # 0.001; 0.01</span><br><span class="line">    acc_cov_output: 500</span><br><span class="line">    gyr_cov_output: 1000 </span><br><span class="line">    b_acc_cov: 0.0001 </span><br><span class="line">    b_gyr_cov: 0.0001 </span><br><span class="line">    imu_meas_acc_cov: 0.1 #0.1 # 0.1</span><br><span class="line">    imu_meas_omg_cov: 0.1 #0.01 # 0.1</span><br><span class="line">    gyr_cov_input: 0.01 # for IMU as input model</span><br><span class="line">    acc_cov_input: 0.1 # for IMU as input model</span><br><span class="line">    plane_thr: 0.1 # 0.05, the threshold for plane criteria, the smaller, the flatter a plane</span><br><span class="line">    match_s: 81</span><br><span class="line">    fov_degree: 360 </span><br><span class="line">    det_range: 100</span><br><span class="line">    gravity_align: true # true to align the z axis of world frame with the direction of gravity, and the gravity direction should be specified below</span><br><span class="line">    gravity: [0.0, 0.0, -9.810] # [0.0, 9.810, 0.0] # gravity to be aligned</span><br><span class="line">    gravity_init: [0.0, 0.0, -9.810] # [0.0, 9.810, 0.0] # # preknown gravity in the first IMU body frame, use when imu_en is false or start from a non-stationary state</span><br><span class="line">    extrinsic_T: [ -0.011, -0.02329, 0.04412 ]</span><br><span class="line">    extrinsic_R: [ 1, 0, 0,</span><br><span class="line">                   0, 1, 0,</span><br><span class="line">                   0, 0, 1 ]</span><br><span class="line"></span><br><span class="line">odometry: </span><br><span class="line">    publish_odometry_without_downsample: false</span><br><span class="line"></span><br><span class="line">publish:</span><br><span class="line">    path_en: true                 # false: close the path output</span><br><span class="line">    scan_publish_en: true         # false: close all the point cloud output</span><br><span class="line">    scan_bodyframe_pub_en: false  # true: output the point cloud scans in IMU-body-frame</span><br><span class="line"></span><br><span class="line">pcd_save:</span><br><span class="line">    pcd_save_en: false</span><br><span class="line">    interval: -1                 # how many LiDAR frames saved in each pcd file; </span><br><span class="line">                                 # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames.</span><br></pre></td></tr></table></figure><p>之后在src&#x2F;launch文件夹下增加mapping_mid360.launch文件：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">&lt;launch&gt;</span><br><span class="line">&lt;!-- Launch file for Livox AVIA LiDAR --&gt;</span><br><span class="line"></span><br><span class="line">&lt;arg name=&quot;rviz&quot; default=&quot;true&quot; /&gt;</span><br><span class="line"></span><br><span class="line">&lt;node pkg=&quot;point_lio&quot; type=&quot;pointlio_mapping&quot; name=&quot;laserMapping&quot; output=&quot;screen&quot;&gt;</span><br><span class="line">&lt;rosparam command=&quot;load&quot; file=&quot;$(find point_lio)/config/mid360.yaml&quot; /&gt;</span><br><span class="line">&lt;param name=&quot;use_imu_as_input&quot; type=&quot;bool&quot; value=&quot;1&quot;/&gt; &lt;!--change to 1 to use IMU as input of Point-LIO--&gt;</span><br><span class="line">&lt;param name=&quot;prop_at_freq_of_imu&quot; type=&quot;bool&quot; value=&quot;1&quot;/&gt;</span><br><span class="line">&lt;param name=&quot;check_satu&quot; type=&quot;bool&quot; value=&quot;1&quot;/&gt;</span><br><span class="line">&lt;param name=&quot;init_map_size&quot; type=&quot;int&quot; value=&quot;10&quot;/&gt;</span><br><span class="line">&lt;param name=&quot;point_filter_num&quot; type=&quot;int&quot; value=&quot;1&quot;/&gt; &lt;!--4, 3--&gt; </span><br><span class="line">&lt;param name=&quot;space_down_sample&quot; type=&quot;bool&quot; value=&quot;1&quot; /&gt;  </span><br><span class="line">&lt;param name=&quot;filter_size_surf&quot; type=&quot;double&quot; value=&quot;0.3&quot; /&gt; &lt;!--0.5, 0.3, 0.2, 0.15, 0.1--&gt; </span><br><span class="line">&lt;param name=&quot;filter_size_map&quot; type=&quot;double&quot; value=&quot;0.2&quot; /&gt; &lt;!--0.5, 0.3, 0.15, 0.1--&gt;</span><br><span class="line">&lt;param name=&quot;cube_side_length&quot; type=&quot;double&quot; value=&quot;2000&quot; /&gt; &lt;!--1000--&gt;</span><br><span class="line">&lt;param name=&quot;runtime_pos_log_enable&quot; type=&quot;bool&quot; value=&quot;0&quot; /&gt; &lt;!--1--&gt;</span><br><span class="line">&lt;/node&gt;</span><br><span class="line">&lt;group if=&quot;$(arg rviz)&quot;&gt;</span><br><span class="line">&lt;node launch-prefix=&quot;nice&quot; pkg=&quot;rviz&quot; type=&quot;rviz&quot; name=&quot;rviz&quot; args=&quot;-d $(find point_lio)/rviz_cfg/loam_livox.rviz&quot; /&gt;</span><br><span class="line">&lt;/group&gt;</span><br><span class="line"></span><br><span class="line">launch-prefix=&quot;gdb -ex run --args&quot;</span><br><span class="line"></span><br><span class="line">&lt;/launch&gt;</span><br></pre></td></tr></table></figure><p>然后就可以启动Point-Lio算法了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.bash</span><br><span class="line">roslaunch point_lio mapping_mid360.launch</span><br></pre></td></tr></table></figure><h2 id="Faster-Lio部署"><a href="#Faster-Lio部署" class="headerlink" title="Faster-Lio部署"></a>Faster-Lio部署</h2><p>Faster-Lio是一种基于增量体素的激光惯性里程计的方法,是Fast-Lio2 的基础上发表的工作。优点是流程短、计算快，扫描频率高可快速跟踪旋转。缺点也是对算力要求略高。</p><p>编译的时候会出现寻找<strong><a href="https://github.com/Livox-SDK/livox_ros_driver">livox_ros_driver</a></strong>驱动的过程，如果之前已经单独安装过，或在其他工作空间安装过，那就耐心等待编译过程寻找就行，不用手动结束编译（实在不行就source一下livox_ros_driver的工作空间）。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">mkdir -p faster_lio_ws/src</span><br><span class="line">cd faster_lio_ws/src</span><br><span class="line">git clone https://github.com/gaoxiang12/faster-lio.git</span><br><span class="line">cd ..</span><br><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>同样的在src&#x2F;config文件夹下增加的mid360.yaml文件配置：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line">common:</span><br><span class="line">  lid_topic: &quot;/livox/lidar&quot;</span><br><span class="line">  imu_topic: &quot;/livox/imu&quot;</span><br><span class="line">  time_sync_en: false         # ONLY turn on when external time synchronization is really not possible</span><br><span class="line"></span><br><span class="line">preprocess:</span><br><span class="line">  lidar_type: 1                # 1 for Livox serials LiDAR, 2 for Velodyne LiDAR, 3 for ouster LiDAR,</span><br><span class="line">  scan_line: 4</span><br><span class="line">  blind: 0.5</span><br><span class="line">  time_scale: 1e-3</span><br><span class="line"></span><br><span class="line">mapping:</span><br><span class="line">  acc_cov: 0.1</span><br><span class="line">  gyr_cov: 0.1</span><br><span class="line">  b_acc_cov: 0.0001</span><br><span class="line">  b_gyr_cov: 0.0001</span><br><span class="line">  fov_degree: 360</span><br><span class="line">  det_range: 100.0</span><br><span class="line">  extrinsic_est_en: false      # true: enable the online estimation of IMU-LiDAR extrinsic</span><br><span class="line">  extrinsic_T: [ -0.011, -0.02329, 0.04412  ]</span><br><span class="line">  extrinsic_R: [ 1, 0, 0,</span><br><span class="line">                 0, 1, 0,</span><br><span class="line">                 0, 0, 1 ]</span><br><span class="line"></span><br><span class="line">publish:</span><br><span class="line">  path_publish_en: false</span><br><span class="line">  scan_publish_en: true       # false: close all the point cloud output</span><br><span class="line">  scan_effect_pub_en: true    # true: publish the pointscloud of effect point</span><br><span class="line">  dense_publish_en: false       # false: low down the points number in a global-frame point clouds scan.</span><br><span class="line">  scan_bodyframe_pub_en: true  # true: output the point cloud scans in IMU-body-frame</span><br><span class="line"></span><br><span class="line">path_save_en: true                 # 保存轨迹，用于精度计算和比较</span><br><span class="line"></span><br><span class="line">pcd_save:</span><br><span class="line">  pcd_save_en: true</span><br><span class="line">  interval: -1                 # how many LiDAR frames saved in each pcd file;</span><br><span class="line">  # -1 : all frames will be saved in ONE pcd file, may lead to memory crash when having too much frames.</span><br><span class="line"></span><br><span class="line">feature_extract_enable: false</span><br><span class="line">point_filter_num: 3</span><br><span class="line">max_iteration: 3</span><br><span class="line">filter_size_surf: 0.5</span><br><span class="line">filter_size_map: 0.5             # 暂时未用到，代码中为0， 即倾向于将降采样后的scan中的所有点加入map</span><br><span class="line">cube_side_length: 1000</span><br><span class="line"></span><br><span class="line">ivox_grid_resolution: 0.5        # default=0.2</span><br><span class="line">ivox_nearby_type: 18             # 6, 18, 26</span><br><span class="line">esti_plane_threshold: 0.1        # default=0.1</span><br></pre></td></tr></table></figure><p>在src&#x2F;launch文件夹下增加mapping_mid360.launch：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line">&lt;launch&gt;</span><br><span class="line">&lt;!-- Launch file for Livox AVIA LiDAR --&gt;</span><br><span class="line"></span><br><span class="line">&lt;arg name=&quot;rviz&quot; default=&quot;true&quot; /&gt;</span><br><span class="line"></span><br><span class="line">&lt;rosparam command=&quot;load&quot; file=&quot;$(find faster_lio)/config/mid360.yaml&quot; /&gt;</span><br><span class="line"></span><br><span class="line">&lt;param name=&quot;feature_extract_enable&quot; type=&quot;bool&quot; value=&quot;0&quot;/&gt;</span><br><span class="line">&lt;param name=&quot;point_filter_num_&quot; type=&quot;int&quot; value=&quot;3&quot;/&gt;</span><br><span class="line">&lt;param name=&quot;max_iteration&quot; type=&quot;int&quot; value=&quot;3&quot; /&gt;</span><br><span class="line">&lt;param name=&quot;filter_size_surf&quot; type=&quot;double&quot; value=&quot;0.5&quot; /&gt;</span><br><span class="line">&lt;param name=&quot;filter_size_map&quot; type=&quot;double&quot; value=&quot;0.5&quot; /&gt;</span><br><span class="line">&lt;param name=&quot;cube_side_length&quot; type=&quot;double&quot; value=&quot;1000&quot; /&gt;</span><br><span class="line">&lt;param name=&quot;runtime_pos_log_enable&quot; type=&quot;bool&quot; value=&quot;1&quot; /&gt;</span><br><span class="line">    &lt;node pkg=&quot;faster_lio&quot; type=&quot;run_mapping_online&quot; name=&quot;laserMapping&quot; output=&quot;screen&quot; /&gt;</span><br><span class="line"></span><br><span class="line">&lt;group if=&quot;$(arg rviz)&quot;&gt;</span><br><span class="line">&lt;node launch-prefix=&quot;nice&quot; pkg=&quot;rviz&quot; type=&quot;rviz&quot; name=&quot;rviz&quot; args=&quot;-d $(find faster_lio)/rviz_cfg/loam_livox.rviz&quot; /&gt;</span><br><span class="line">&lt;/group&gt;</span><br><span class="line"></span><br><span class="line">&lt;/launch&gt;</span><br></pre></td></tr></table></figure><p>之后就可以启动Faster-Lio了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.bash</span><br><span class="line">roslaunch faster_lio mapping_mid360.launch</span><br></pre></td></tr></table></figure><h2 id="实物扫描楼层测试"><a href="#实物扫描楼层测试" class="headerlink" title="实物扫描楼层测试"></a>实物扫描楼层测试</h2><p>将所有算法移植到NUC上，配置好环境并编译完成后，手持NUC与MID360激光雷达在北京某高层十三楼与十二楼环绕一圈。</p><figure>  <img src="/uploads/2023/11/image-1-e1700388773195.png" alt="">  <figcaption>随便粘的，像不像个大钻石😁</figcaption></figure><p>最后附上对比视频，从效果上看Faster-Lio的定位建图最准确。</p><div class="bilibili-wrap" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5em 0;">  <iframe src="https://player.bilibili.com/player.html?isOutside=true&bvid=BV1jj411J7cN&p=1&autoplay=0&high_quality=1&danmaku=0"          style="position:absolute;top:0;left:0;width:100%;height:100%;"          frameborder="0" allowfullscreen scrolling="no"></iframe></div>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E5%A4%9A%E5%B1%82%E9%95%BF%E8%B5%B0%E5%BB%8A%E4%B8%89%E7%BB%B4slam%E5%BB%BA%E5%9B%BE%E5%AE%9E%E6%88%98/</id>
    <link href="https://leo-wangbo.top/p/%E5%A4%9A%E5%B1%82%E9%95%BF%E8%B5%B0%E5%BB%8A%E4%B8%89%E7%BB%B4slam%E5%BB%BA%E5%9B%BE%E5%AE%9E%E6%88%98/"/>
    <published>2023-11-19T02:10:12.000Z</published>
    <summary>
      <![CDATA[<p>前面把算法在仿真环境都跑通过后，决定拿雷达在真实世界跑一下。先介绍一下最近又发现的两个巨牛的算法：Point-Lio与Faster-lio。</p>
<h2 id="Point-Lio部署"><a href="#Point-Lio部署" class="headerlink"]]>
    </summary>
    <title>多层长走廊三维SLAM建图实战</title>
    <updated>2023-11-26T18:57:01.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/ROS/"/>
    <category term="SLAM" scheme="https://leo-wangbo.top/categories/ROS/SLAM/"/>
    <category term="路径规划" scheme="https://leo-wangbo.top/categories/ROS/SLAM/%E8%B7%AF%E5%BE%84%E8%A7%84%E5%88%92/"/>
    <category term="自主探索" scheme="https://leo-wangbo.top/categories/ROS/SLAM/%E8%B7%AF%E5%BE%84%E8%A7%84%E5%88%92/%E8%87%AA%E4%B8%BB%E6%8E%A2%E7%B4%A2/"/>
    <content>
      <![CDATA[<p>去年CMU机器人实验室团队开源了整套的自主探索导航系统，相关文章还荣获IROS2022 最佳学生论文。因此想在实验室的设备上试一下，先跑个官方demo试试。但中文互联网搜索结果的文章质量果然不出我所料，全都是互相抄，下载下来的源码CmakeList文件都是错的😅，最后还是去CMU这个项目的官网才把demo跑起来了。下面记录一下部署过程，我的系统环境是Ubuntu20.04、ROS1 Noetic。</p><h2 id="一、安装仿真环境"><a href="#一、安装仿真环境" class="headerlink" title="一、安装仿真环境"></a>一、安装仿真环境</h2><p>先安装CMU团队制作的仿真环境，仿真环境包含多楼层停车场、隧道、森林、校园等多种复杂环境，能把这些环境跑好说明这个自主探索导航系统还是很有普适性的。</p><p><img src="/uploads/2023/11/2023-11-12-16-48-14-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE-1024x575.png"></p><p>先安装依赖环境</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update</span><br><span class="line">sudo apt install libusb-dev</span><br></pre></td></tr></table></figure><p>克隆开源存储库</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/HongbiaoZ/autonomous_exploration_development_environment.git</span><br></pre></td></tr></table></figure><p>更换分支，并编译。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd autonomous_exploration_development_environment</span><br><span class="line">git checkout noetic #如果是melodic 将noetic更换为melodic</span><br><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>如果可以科学上网，运行脚本下载模拟环境，由于网络环境不同，下载可能需要一会。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">./src/vehicle_simulator/mesh/download_environments.sh</span><br></pre></td></tr></table></figure><p>当然也可以下载官方整理的百度网盘：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">链接：https://pan.baidu.com/share/init?surl=7PFWGbQGLLfPy1mHNiiS4A</span><br><span class="line">提取码：qm45</span><br></pre></td></tr></table></figure><p>将在百度网盘下载的”autonomous_exploration_environments.zip”解压之后放在src&#x2F;vehicle_simulator&#x2F;mesh文件夹下。最终的mesh文件夹结构应该和下面的一致：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mesh</span><br><span class="line">  campus</span><br><span class="line">  indoor</span><br><span class="line">  garage</span><br><span class="line">  tunnel</span><br><span class="line">  forest</span><br><span class="line">  download_environments.sh </span><br></pre></td></tr></table></figure><p>然后运行仿真环境</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.sh</span><br><span class="line">roslaunch vehicle_simulator system_garage.launch</span><br></pre></td></tr></table></figure><p>现在，可以通过点击RVIZ中的“waypoint”按钮发送航路点，然后点击一个点来设置航路点。车辆将导航到航路点，避开沿途的障碍物。请注意，航路点应该是可到达的，并且在车辆附近。</p><p>或者，可以运行ROS节点来发送一系列路点。在另一个终端中，转到文件夹并获取ROS工作区，然后使用下面的命令行运行ROS节点。：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">roslaunch waypoint_example waypoint_example_garage.launch</span><br></pre></td></tr></table></figure><figure>  <img src="/uploads/2023/11/2023-11-12-17-20-09-的屏幕截图-1024x576.png" alt="">  <figcaption>导航至航路点</figcaption></figure><p>存储库包含一组不同类型和规模的模拟环境。要在特定环境下启动系统，请使用下面的命令行。将“environment”替换为环境名称，即’campus’,、’indoor’,、’garage’、 ‘tunnel’和’forest’。现在，用户可以使用RVIZ中的“Waypoint”按钮来导航车辆。要在Gazebo GUI中查看环境中的车辆，在启动文件中设置’gazebo_gui &#x3D; true’，该文件位于’src&#x2F;vehicle_simulator&#x2F;launch’中。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">roslaunch vehicle_simulator system_environment.launch</span><br></pre></td></tr></table></figure><h2 id="二、TARE-Exploration-Planner部署"><a href="#二、TARE-Exploration-Planner部署" class="headerlink" title="二、TARE Exploration Planner部署"></a>二、TARE Exploration Planner部署</h2><p>同样的，先克隆仓库：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/caochao39/tare_planner.git</span><br></pre></td></tr></table></figure><p>编译后就可以运行了</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">cd tare_planner</span><br><span class="line"></span><br><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>去上一步的工作空间下运行仿真环境：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.sh</span><br><span class="line">roslaunch vehicle_simulator system_garage.launch</span><br></pre></td></tr></table></figure><p>然后在现在的工作空间下运行TARE自主探索算法：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.sh</span><br><span class="line">roslaunch tare_planner explore_garage.launch</span><br></pre></td></tr></table></figure><p>现在，应该看到自主探索的行动。同样的，要在不同的环境中启动，使用下面的命令行，并将“environment”替换为开发环境中的一个环境名称，即’campus’, ‘indoor’, ‘garage’, ‘tunnel’, 和 ‘forest’。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">roslaunch vehicle_simulator system_environment.launch</span><br><span class="line"></span><br><span class="line">roslaunch tare_planner explore_environment.launch</span><br></pre></td></tr></table></figure><figure>  <img src="/uploads/2023/11/2023-11-12-18-04-44-的屏幕截图-1024x576.png" alt="">  <figcaption>TARE自主探索</figcaption></figure><h2 id="三、FAR-Planner部署"><a href="#三、FAR-Planner部署" class="headerlink" title="三、FAR Planner部署"></a>三、FAR Planner部署</h2><p>克隆仓库</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/MichaelFYang/far_planner</span><br></pre></td></tr></table></figure><p>编译</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd far_planner</span><br><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>同样的，去第一个工作空间下运行仿真环境：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.sh</span><br><span class="line">roslaunch vehicle_simulator system_indoor.launch</span><br></pre></td></tr></table></figure><p>然后在现在的工作空间下运行FAR-Planner算法</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.sh</span><br><span class="line">roslaunch far_planner far_planner.launch</span><br></pre></td></tr></table></figure><p>现在，我们可以发送一个目标，通过单击在RVIZ的“Goalpoint”按钮，然后点击一个点设置的目标。车辆将导航到目标，并在沿途建立一个可见性图表(青色)。可见性图所覆盖的区域变成了自由空间。当在自由空间中导航时，计划者使用构建的可见性图，当在未知空间中导航时，计划者试图发现通往目标的方法。通过点击“Reset Visibility Graph”按钮，规划器将重新初始化可见性图。通过取消选中“Planning Attemptable”复选框，规划器将首先尝试在空闲空间中找到一条路径。这条路将以绿色显示。如果不存在这样的路径，规划器会一起考虑未知空间。路径将以蓝色显示。通过取消选中”<code>Update Visibility Graph“</code>复选框，规划器将停止更新可见性图。</p><figure>  <img src="/uploads/2023/11/2023-11-12-18-52-21-的屏幕截图-1024x576.png" alt="">  <figcaption>Far-Planner 导航</figcaption></figure><p>如果是实车可以用手柄遥控，这里是仿真环境，Rviz右下角有一个虚拟遥控器，可以遥控车辆移动，并且移动过程中会自动调用局部路径规划自动避开障碍物。</p><figure>  <img src="/uploads/2023/11/2023-11-12-18-54-11-的屏幕截图.png" alt="">  <figcaption>虚拟遥控器与真实遥控器</figcaption></figure><h2 id="四、实物部署（待更新）"><a href="#四、实物部署（待更新）" class="headerlink" title="四、实物部署（待更新）"></a>四、实物部署（待更新）</h2>]]>
    </content>
    <id>https://leo-wangbo.top/p/cmu-%E8%87%AA%E4%B8%BB%E6%8E%A2%E7%B4%A2%E5%AF%BC%E8%88%AA%E7%B3%BB%E7%BB%9F%EF%BC%88tare-far-planner%EF%BC%89%E9%83%A8%E7%BD%B2/</id>
    <link href="https://leo-wangbo.top/p/cmu-%E8%87%AA%E4%B8%BB%E6%8E%A2%E7%B4%A2%E5%AF%BC%E8%88%AA%E7%B3%BB%E7%BB%9F%EF%BC%88tare-far-planner%EF%BC%89%E9%83%A8%E7%BD%B2/"/>
    <published>2023-11-12T03:00:09.000Z</published>
    <summary>
      <![CDATA[<p>去年CMU机器人实验室团队开源了整套的自主探索导航系统，相关文章还荣获IROS2022 最佳学生论文。因此想在实验室的设备上试一下，先跑个官方demo试试。但中文互联网搜索结果的文章质量果然不出我所料，全都是互相抄，下载下来的源码CmakeList文件都是错的😅，最后还是]]>
    </summary>
    <title>
      <![CDATA[CMU-自主探索导航系统（TARE & FAR Planner）部署]]>
    </title>
    <updated>2023-11-12T03:17:26.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="Linux" scheme="https://leo-wangbo.top/categories/Linux/"/>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/Linux/ROS/"/>
    <category term="SLAM" scheme="https://leo-wangbo.top/categories/Linux/ROS/SLAM/"/>
    <content>
      <![CDATA[<p>实验室有一个大疆的MID360半固态激光雷达，需要我来探索一个建图效果较好的三维SLAM算法。但是由于是半固态雷达，雷达输出的点云数据格式与普通的多线激光雷达有一些区别，目前业界的激光雷达算法好多都是基于Velodyne的多线雷达格式做的适配，因此在适配LIO-SAM时会遇到诸多问题。</p><p><img src="/uploads/2023/11/2023-11-12-13-45-18-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png"></p><h2 id="一、适配LIO-SAM"><a href="#一、适配LIO-SAM" class="headerlink" title="一、适配LIO-SAM"></a>一、适配LIO-SAM</h2><p>LIO-SAM算法对激光雷达的数据格式有着较为严格的要求，以往的单激光雷达建图的算法没注意到这一点，一般要求的是XYZI(x, y, z, intensity ) 格式即可，但是LIO-SAM要求的是 XYZIRT（x, y, z, intensity, ring, timestamp） 格式，即算法内使用了激光雷达的通道数ring参数和时间戳timestep参数，启动算法时会检查是否具有这两个参数，而MID360雷达的输出格式中没有ring与time这两个参数。进一步的，LIO_SAM要用9轴IMU，而MID360内置的IMU是六轴IMU😭。</p><p>因此要想适配MID360需要改源码，感谢万能的github，已经有人做好了适配，链接如下:<a href="https://github.com/nkymzsy/LIO-SAM-MID360.git">https://github.com/nkymzsy/LIO-SAM-MID360.git</a>也可输入以下命令gitclone到ROS工作空间下的src文件夹下内：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/nkymzsy/LIO-SAM-MID360.git</span><br></pre></td></tr></table></figure><p>如果gitclone的速度太慢，这里有一个小技巧，那就是将github改为githubfast，亲测有效。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://githubfast.com/nkymzsy/LIO-SAM-MID360.git</span><br></pre></td></tr></table></figure><p>之后要安装Livox-SDK（在工作空间外安装）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/Livox-SDK/Livox-SDK.git</span><br><span class="line">cd Livox-SDK</span><br><span class="line">cd build &amp;&amp; cmake ..</span><br><span class="line">make</span><br><span class="line">sudo make install</span><br></pre></td></tr></table></figure><p>还要在src下下载livox_ros_driver 也就是livox雷达的驱动包：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/Livox-SDK/livox_ros_driver.git</span><br></pre></td></tr></table></figure><p>接下来还需要对LIO-SAM的代码做一点修改，第一处位于src&#x2F;LIO-SAM-MID360-master目录下，双击打开CMakeLists.txt文件，请将第5行的c++11改为c++14，保存后退出，如下图所示：</p><p><img src="/uploads/2023/11/2023-11-12-14-30-29-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png"></p><p>第二处位于src&#x2F;LIO-SAM-MID360-master&#x2F;include目录下，双击打开utility.h文件，请将第18行的#include &lt;opencv&#x2F;cv.h&gt;使用”&#x2F;&#x2F;“注释掉，并添加以下内容：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">”#include &lt;opencv2/opencv.hpp&gt;“</span><br></pre></td></tr></table></figure><p>还有一个可能报错的地方，解决方法是将下图中的26行的内容注释掉放到第18行。</p><p><img src="/uploads/2023/11/2023-11-12-14-37-48-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png"></p><p>接下来在工作空间目录下catkin _make应该没有报错了。最后就可以运行LIO-SAM建图了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.bash</span><br><span class="line">roslaunch lio_sam run6axis.launch</span><br></pre></td></tr></table></figure><p>然后启动MID360的驱动</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.bash</span><br><span class="line">roslaunch livox_ros_driver&lt;span class=&quot;hljs-number&quot;&gt;2&lt;/span&gt; msg_MID&lt;span class=&quot;hljs-number&quot;&gt;360&lt;/span&gt;.launch</span><br></pre></td></tr></table></figure><p>如果手里现在没有雷达，也可以播包：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rosbag play mid360.bag </span><br></pre></td></tr></table></figure><p>录制rosbag包的命令是（以下是录制所有的主题，-o 后的参数要换成你自己的bag包储存地址）：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rosbag record -O /home/lingao/mid360_bag/my.bag `rostopic list`</span><br></pre></td></tr></table></figure><p>如果只录制imu和雷达数据则输入命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rosbag record -O /home/lingao/mid360_bag/my.bag /livox/imu /livox/lidar /clock</span><br></pre></td></tr></table></figure><p><img src="/uploads/2023/11/2023-11-12-14-51-54-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE-1024x576.png"></p><h2 id="二、适配FAST-LIO2"><a href="#二、适配FAST-LIO2" class="headerlink" title="二、适配FAST-LIO2"></a>二、适配FAST-LIO2</h2><p>由于FAST-LIO2本身就对LIVOX系列的雷达做了一定的适配，因此对源码基本不需要修改，直接在src里gitclone下来：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/hku-mars/FAST_LIO.git</span><br></pre></td></tr></table></figure><p>同样的也需要下载livox_ros_driver：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/Livox-SDK/livox_ros_driver.git</span><br></pre></td></tr></table></figure><p>然后初始化和更新一个仓库中的子模块：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git submodule update --init</span><br></pre></td></tr></table></figure><p>编译</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">cd ../..</span><br><span class="line">catkin_make</span><br></pre></td></tr></table></figure><p>这里我的环境是Ubuntu 20.04 ROS Noetic，所以需要将src&#x2F;FAST_LIO中的CMakeLists.txt中的C++版本改为14，这样编译就能通过了。</p><p>接下来运行fast-lio2：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">source devel/setup.bash</span><br><span class="line">roslaunch fast_lio mapping_mid360.launch</span><br></pre></td></tr></table></figure><p>然后播包</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rosbag play mid360.bag </span><br></pre></td></tr></table></figure><p><img src="/uploads/2023/11/2023-11-12-15-42-24-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE-1-1024x576.png"></p><p>可以看到建图效果还是不错的，整个楼层没有大的漂移。而反观LIO-SAM这边，顶楼走廊到楼梯那建的都还可以，但是下了楼后高度定位出现了问题，一直还定位到顶楼，最后直接建飞了，把楼层建成了平行宇宙🤣。。。。有可能是我用的是别人录制的rosbag包的原因，IMU与雷达内参没有校准。</p><figure>  <img src="/uploads/2023/11/2023-11-12-16-01-14-的屏幕截图-1024x576.png" alt="">  <figcaption>LIO-SAM建出平行宇宙</figcaption></figure><h2 id="建图对比视频"><a href="#建图对比视频" class="headerlink" title="建图对比视频"></a>建图对比视频</h2><div class="bilibili-wrap" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5em 0;">  <iframe src="https://player.bilibili.com/player.html?isOutside=true&bvid=BV1b94y137HW&p=1&autoplay=0&high_quality=1&danmaku=0"          style="position:absolute;top:0;left:0;width:100%;height:100%;"          frameborder="0" allowfullscreen scrolling="no"></iframe></div><p>评论区有大佬指出关闭LIO-SAM回环会好很多，我找了一下，配置文件在lio_sam_mid360_ws&#x2F;src&#x2F;LIO-SAM-MID360-master&#x2F;config下的paramsLivoxIMU.yaml里。将“loopClosureEnableFlag”的“false”改为“true”，然后不用编译直接运行看一下。</p><figure>  <img src="/uploads/2023/11/2023-11-13-10-28-09-的屏幕截图-1024x576.png" alt="">  <figcaption>回环配置文件</figcaption></figure><p>果然有用诶，成功建图，而且从图中效果可以看出细节上比FAST-LIO2要好很多，楼旁边的树和周围楼的墙壁都给建出来了。</p><figure>  <img src="/uploads/2023/11/2023-11-13-10-34-51-的屏幕截图-1024x686.png" alt="">  <figcaption>关闭回环后LIO-SAM建图效果</figcaption></figure>]]>
    </content>
    <id>https://leo-wangbo.top/p/mid360%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8Dlio-sam%E4%B8%8Efast-lio2%E6%8C%87%E5%8D%97/</id>
    <link href="https://leo-wangbo.top/p/mid360%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E9%80%82%E9%85%8Dlio-sam%E4%B8%8Efast-lio2%E6%8C%87%E5%8D%97/"/>
    <published>2023-11-12T00:07:35.000Z</published>
    <summary>
      <![CDATA[<p>实验室有一个大疆的MID360半固态激光雷达，需要我来探索一个建图效果较好的三维SLAM算法。但是由于是半固态雷达，雷达输出的点云数据格式与普通的多线激光雷达有一些区别，目前业界的激光雷达算法好多都是基于Velodyne的多线雷达格式做的适配，因此在适配LIO-SAM时会遇]]>
    </summary>
    <title>MID360激光雷达适配LIO-SAM与FAST-LIO2指南</title>
    <updated>2023-11-14T22:17:47.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="Linux" scheme="https://leo-wangbo.top/categories/Linux/"/>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/Linux/ROS/"/>
    <category term="自动驾驶" scheme="https://leo-wangbo.top/categories/Linux/ROS/%E8%87%AA%E5%8A%A8%E9%A9%BE%E9%A9%B6/"/>
    <content>
      <![CDATA[<p>由于工作需要需要学习一下autoware这个框架，但是在安装的时候遇到了数不进的坑，网上的教程基本都跑不起来。自己搞了好半天，终于跑起了个demo，记录一下踩坑的过程。</p><p>本次要安装的是Autoware.ai这个版本，他是基于ROS1 Melodic的，需要Ubuntu 18.04的环境，由于我的系统是Ubuntu 20.04，因此需要在Docker中运行ROS1 Melodic环境。</p><h2 id="一、安装Docker"><a href="#一、安装Docker" class="headerlink" title="一、安装Docker"></a>一、安装Docker</h2><p>首先验证系统上没有安装旧版本或不兼容版本的Docker</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get remove docker docker-engine docker.io</span><br></pre></td></tr></table></figure><p>看到以下提示就没问题</p><p><img src="/uploads/2023/11/%E5%9B%BE%E7%89%87.png"></p><p>继续安装一些依赖：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get update</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install apt-transport-https ca-certificates curl software-properties-common</span><br></pre></td></tr></table></figure><p>然后设置密钥</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-key fingerprint 0EBFCD88</span><br></pre></td></tr></table></figure><p>接下来设置软件源</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo add-apt-repository &quot;deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable&quot;</span><br></pre></td></tr></table></figure><p>接下来就可以安装Docker了</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install docker-ce</span><br></pre></td></tr></table></figure><h2 id="二、安装docker-nvidia"><a href="#二、安装docker-nvidia" class="headerlink" title="二、安装docker-nvidia"></a>二、<strong>安装docker-nvidia</strong></h2><p>如果电脑没有英伟达独显则跳过这一步。有独显的话先确保已经安装了nvidia显卡驱动，输入nvidia-smi即可确定是否已经成功安装。</p><p>确保有nvidia驱动后，安装docker-nvidia，运行以下命令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -s -L https://nvidia.github.io/nvidia-docker/gpgkey | sudo apt-key add -</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">distribution=$(. /etc/os-release;echo $ID$VERSION_ID)</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -s -L https://nvidia.github.io/nvidia-docker/$distribution/nvidia-docker.list | sudo tee /etc/apt/sources.list.d/nvidia-docker.list</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install -y nvidia-docker2 </span><br></pre></td></tr></table></figure><h2 id="三、安装Autoware-Docker镜像"><a href="#三、安装Autoware-Docker镜像" class="headerlink" title="三、安装Autoware Docker镜像"></a>三、安装Autoware Docker镜像</h2><p>先git clone一下源码</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://gitlab.com/autowarefoundation/autoware.ai/docker.git</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd docker/generic</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo ./run.sh</span><br></pre></td></tr></table></figure><p>如果没有独显没有装docker-nvidia 会显示以下报错：</p><p><img src="/uploads/2023/11/%E5%9B%BE%E7%89%87-1-1024x209.png"></p><p>使用如下命令关闭cuda的支持就可以了：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo ./run.sh -c off</span><br></pre></td></tr></table></figure><p>如果报以下错误“usermod: UID ‘0’ already exists”则需要修改run.sh,加入以下语句</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">USER_ID=&quot;$(id -u)&quot;</span><br><span class="line">if [ USER_ID != 0 ]; then</span><br><span class="line">USER_ID=1000;</span><br><span class="line">else</span><br><span class="line">USER_ID=$&#123;USER_ID&#125;;</span><br><span class="line">fi</span><br></pre></td></tr></table></figure><p>加入的位置如下图中的红色框所示</p><p><img src="/uploads/2023/11/%E5%9B%BE%E7%89%87-3.png"></p><h2 id="四、编译"><a href="#四、编译" class="headerlink" title="四、编译"></a>四、编译</h2><p>在docker环境下输入以下指令：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd /home/autoware/Autoware </span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">colcon build --cmake-args -DCMAKE_BUILD_TYPE=Release</span><br></pre></td></tr></table></figure><p>编译需要耐心等一段时间，视电脑性能而定。</p><h2 id="五、下载rosbag数据集"><a href="#五、下载rosbag数据集" class="headerlink" title="五、下载rosbag数据集"></a>五、下载rosbag数据集</h2><p>编译完成后就可以运行官方的rosbag实例，先要下载稍后会用到的测试数据：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_data.tar.gz</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://db3.ertl.jp/autoware/sample_data/sample_moriyama_150324.tar.gz</span><br></pre></td></tr></table></figure><p>如果无法科学上网下载太慢的话，可通过以下百度网盘下载</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">链接：https://pan.baidu.com/s/1lg0lnjVwmdOb8r9U_bEsXA</span><br><span class="line">提取码：i0v5</span><br></pre></td></tr></table></figure><p>我看网上其他教程都是下载完后用docker cp命令从主机拷贝到docker镜像中，然后在docker中解压，我一开始就是这样干的，但是后来再打开docker后发现拷贝过来解压的文件都不见了！后来才了解到Docker 的容器使用容器层文件系统,退出容器后文件层会被删除和清空，重启docker后,之前运行的容器都会退出,容器层文件系统被清空,docker cp 拷贝的文件就都丢失了。</p><p>其实运行run.sh后，安装完会在主机目录下生成shared_dir文件夹，方便传文件到docker，其实这是通过挂载宿主机目录的方式实现数据的永久保存。当然你也可以自己挂载一个目录，在run.sh脚本里找到这几行：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">VOLUMES=&quot;--volume=$XSOCK:$XSOCK:rw</span><br><span class="line">         --volume=$XAUTH:$XAUTH:rw</span><br><span class="line">         --volume=$SHARED_HOST_DIR:$SHARED_DOCKER_DIR:rw</span><br></pre></td></tr></table></figure><p>在其下面加入你要挂载的目录，前面是你主机文件夹的路径，冒号后面的是docker里的路径。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">-v /home/leo/autoware_rosbag:/home/autoware/rosbag&quot; # 加入挂载数据目录</span><br></pre></td></tr></table></figure><p><img src="/uploads/2023/11/2023-11-11-23-21-56-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png"></p><p>解压命令为：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">tar zxfv sample_moriyama_150324.tar.gz</span><br><span class="line">tar zxfv sample_moriyama_data.tar.gz</span><br></pre></td></tr></table></figure><h2 id="六、运行demo实例"><a href="#六、运行demo实例" class="headerlink" title="六、运行demo实例"></a>六、运行demo实例</h2><p>在docker中进入Autoware文件夹下然后运行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source install/setup.bash</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">roslaunch runtime_manager runtime_manager.launch</span><br></pre></td></tr></table></figure><p>运行后可显示出可视化配置界面</p><p><img src="/uploads/2023/11/2023-11-11-23-45-29-%E7%9A%84%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE.png"></p><p>然后网上的教程都是直接加载bag与launch文件运行，但实际上遇到很多问题导致这样跑不起来。</p><p>于是在autoware项目issue里看到了一个正确的配置顺序。</p><p><img src="/uploads/2023/11/%E5%9B%BE%E7%89%87-5-1024x447.png"></p><p>注意Point Cloud与Vctor Map要鼠标左键拖住全选，这两个最好最后等rviz加载出来后再点击加载。</p><p>按顺序点击完后，再点击“Pause”继续播放rosbag包，一开始车辆会乱飘，这是ndt在匹配，等ndt点云匹配完车辆就会在道路上正常行驶</p><figure>  <img src="/uploads/2023/11/2023-11-12-13-08-12-的屏幕截图-1024x576.png" alt="">  <figcaption>NDT点云匹配中</figcaption></figure><figure>  <img src="/uploads/2023/11/2023-11-12-13-09-06-的屏幕截图-1024x576.png" alt="">  <figcaption>NDT匹配完成</figcaption></figure>]]>
    </content>
    <id>https://leo-wangbo.top/p/autoware%E5%AE%89%E8%A3%85-%EF%BC%88%E8%B8%A9%E5%9D%91%E6%8C%87%E5%8D%97%EF%BC%89/</id>
    <link href="https://leo-wangbo.top/p/autoware%E5%AE%89%E8%A3%85-%EF%BC%88%E8%B8%A9%E5%9D%91%E6%8C%87%E5%8D%97%EF%BC%89/"/>
    <published>2023-11-11T21:25:34.000Z</published>
    <summary>
      <![CDATA[<p>由于工作需要需要学习一下autoware这个框架，但是在安装的时候遇到了数不进的坑，网上的教程基本都跑不起来。自己搞了好半天，终于跑起了个demo，记录一下踩坑的过程。</p>
<p>本次要安装的是Autoware.ai这个版本，他是基于ROS1 Melodic的，需要Ub]]>
    </summary>
    <title>Autoware安装 （踩坑指南）</title>
    <updated>2023-11-12T00:38:02.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="DIY" scheme="https://leo-wangbo.top/categories/DIY/"/>
    <content>
      <![CDATA[<p>咸鱼淘了个一百多块的镭神雷达，看参数性能还挺不错，而且是TOF测距雷达，原价四五百呢。</p><p><img src="/uploads/2023/09/tb_image_share_1694178764160.jpg"></p><figure>  <img src="/uploads/2023/09/tb_image_share_1694178649277-736x1024.jpg" alt="">  <figcaption>雷达参数</figcaption></figure><p>之后将驱动包拷贝到工作空间的src目录下后进行编译，可以看到代码包的名称与cmake里project的名称都是lslidar_driver，因此在工作空间目录下输入colcon build –packages-select lslidar_driver编译驱动包。</p><figure>  <img src="/uploads/2023/09/VBTRHNKSZQLIHEFOJQY-1024x521.png" alt="">  <figcaption>雷达驱动文件包</figcaption></figure><p>但是编译的时候报了错，没有找到pcl_conversions的配置文件。</p><figure>  <img src="/uploads/2023/09/PFWBH_@TIJWW_9IX@YX.png" alt="">  <figcaption>编译报错</figcaption></figure><p>我求助了一下万能的Claude，他让我用apt安装libpcl-dev这个包。</p><figure>  <img src="/uploads/2023/09/image-1024x485.png" alt="">  <figcaption>万能的Claude</figcaption></figure><p>但是我执行命令后发现我已经安装过这个包了，那为什么还是找不到啊。</p><p><img src="/uploads/2023/09/image-1.png"></p><p>接下来他又让我进行设置环境变量，甚至源码编译库文件等等操作，都没有解决这个问题。我后来发现缺失的是pcl_conversions&nbsp;这个库，但是他却一直让我安装的是libpcl-dev。我又问了Claude这两个有什么区别，看起来libpcl-dev包含了pcl_conversions&nbsp;。</p><p><img src="/uploads/2023/09/image-2.png"></p><p>于是我决定找一下pcl_conversions&nbsp;的安装目录。可以看到pcl_conversions&nbsp;并没有被apt安装。</p><figure>  <img src="/uploads/2023/09/image-3-1024x454.png" alt="">  <figcaption>Claude提示寻找安装目录</figcaption></figure><figure>  <img src="/uploads/2023/09/image-4-1024x439.png" alt="">  <figcaption>pcl_conversions 包确实未找到</figcaption></figure><p>于是执行apt安装libpcl-conversions-dev后，成功编译驱动包了。（虽然还是不知道为什么之前装了但是找不到）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update</span><br><span class="line">sudo apt install libpcl-conversions-dev</span><br></pre></td></tr></table></figure><p>之后执行ros2 launch lslidar_driver lsn10_launch.py可启动雷达。打开rviz2，FixedFrame中输入雷达坐标系的名称，这个名称实在雷达驱动文件中的yaml文件中设置的</p><figure>  <img src="/uploads/2023/09/image-5.png" alt="">  <figcaption>rviz2</figcaption></figure><figure>  <img src="/uploads/2023/09/image-6-1024x525.png" alt="">  <figcaption>驱动代码中的配置文件</figcaption></figure><p>之后点击Rviz 左下角的Add 按键，在弹出的窗口中点击By topic 选中&#x2F;scan话题下的LaserScan 并点击OK。</p><figure>  <img src="/uploads/2023/09/image-7.png" alt="">  <figcaption>rviz中添加LaserScan</figcaption></figure><p>成功添加LaserScan 后我们便可以在Rviz 中看到这样的雷达点云图像。</p>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E7%BC%96%E8%AF%91%E9%9B%B7%E8%BE%BE%E9%A9%B1%E5%8A%A8pcl%E5%BA%93%E7%BC%BA%E5%A4%B1%E9%97%AE%E9%A2%98/</id>
    <link href="https://leo-wangbo.top/p/%E7%BC%96%E8%AF%91%E9%9B%B7%E8%BE%BE%E9%A9%B1%E5%8A%A8pcl%E5%BA%93%E7%BC%BA%E5%A4%B1%E9%97%AE%E9%A2%98/"/>
    <published>2023-09-08T06:03:02.000Z</published>
    <summary>
      <![CDATA[<p>咸鱼淘了个一百多块的镭神雷达，看参数性能还挺不错，而且是TOF测距雷达，原价四五百呢。</p>
<p><img src="/uploads/2023/09/tb_image_share_1694178764160.jpg"></p>
<figure>
  <img src=]]>
    </summary>
    <title>编译雷达驱动PCL库缺失问题</title>
    <updated>2023-09-08T06:11:45.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="DIY" scheme="https://leo-wangbo.top/categories/DIY/"/>
    <content>
      <![CDATA[<p>由于旭日X3派自带的网卡实在是太拉胯，我家的WIFI都扫不出来，只好外加一USB网卡，购买的是如下款式。</p><p><img src="/uploads/2023/08/qq_pic_merged_1691575645249-1024x422.jpg"></p><p>然后就是驱动的配置，如果想自己编译的话可以参考这个博客：<a href="https://blog.csdn.net/Zhaoxi_Li/article/details/127975137?spm=1001.2014.3001.5502">体验极速——在旭日X3派上使用双频1300M USB无线网卡_1300m无线网卡实际速度_小玺玺的博客-CSDN博客</a>，这里给出编译好的驱动下载连接：<a href="https://pan.baidu.com/s/1qhFyLxFiLhlTaKJfRXK4Ow">https://pan.baidu.com/s/1qhFyLxFiLhlTaKJfRXK4Ow</a> 提取码：kuq1。</p><p>先将驱动文件在Mobaxterm里ssh登录后拷贝至旭日派中，这里我拷贝至了home目录下，然后再执行命令拷贝到系统驱动目录下。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo cp 88x2bu.ko /lib/modules/4.14.87/</span><br></pre></td></tr></table></figure><p>之后使用<code>cd /lib/modules/4.14.87/</code>进入文件夹后输入以下指令对ko文件签名：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo hobot-sign-file 88x2bu.ko</span><br></pre></td></tr></table></figure><p>然后输入以下两条指令加载驱动，这个时候可以看到网卡驱动的灯开始闪烁。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo /sbin/depmod -a 4.14.87</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo insmod 88x2bu.ko</span><br></pre></td></tr></table></figure><p>输入ifconfig后产看网卡名称。可以看到图中的“wlx200db0c78392”为我们新增的网卡名称。</p><p><img src="/uploads/2023/08/%E5%B1%8F%E5%B9%95%E6%88%AA%E5%9B%BE-2023-08-09-174431-2.jpg"></p><p>如果想<strong>永久启用</strong>，输入<code>sudo vim /etc/modules</code>，在里面添加<code>88x2bu</code>即可。（一定要切忌在网卡驱动未正常启动的情况下永久启用）</p><p><img src="/uploads/2023/08/5f817fd139df4fc3a11102522407b9b7-2.png"></p><p>然后输入以下指令扫描出最新的WIFI名称。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli device wifi rescan        # 扫描wifi网络</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli device wifi list          # 列出找到的wifi网络</span><br></pre></td></tr></table></figure><p>最后输入 sudo nmcli dev wifi connect “wifi名称” password “密码” ifname 网卡名称   即可连接指定wifi，我的是。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli dev wifi connect &quot;RM2100_F7BB&quot; password &quot;18*********&quot; ifname wlx200db0c78392</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E7%BB%99%E6%97%AD%E6%97%A5x3%E6%B4%BE%E9%80%82%E9%85%8D%E5%8D%83%E5%85%86%E7%BD%91%E5%8D%A1/</id>
    <link href="https://leo-wangbo.top/p/%E7%BB%99%E6%97%AD%E6%97%A5x3%E6%B4%BE%E9%80%82%E9%85%8D%E5%8D%83%E5%85%86%E7%BD%91%E5%8D%A1/"/>
    <published>2023-08-09T06:44:58.000Z</published>
    <summary>
      <![CDATA[<p>由于旭日X3派自带的网卡实在是太拉胯，我家的WIFI都扫不出来，只好外加一USB网卡，购买的是如下款式。</p>
<p><img src="/uploads/2023/08/qq_pic_merged_1691575645249-1024x422.jpg"></p>
<p>]]>
    </summary>
    <title>给旭日X3派适配千兆网卡</title>
    <updated>2023-08-21T19:11:17.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="嵌入式" scheme="https://leo-wangbo.top/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <content>
      <![CDATA[<p>解决方法其实很简单，旭日派的WIFI模组检测不到5G频段的WIFI，现在的手机开启热点默认都是5G频段，因此将手机热点的频段改为2.4G即可，注意热点名称也不能带有中文。</p><p>接下来输入命令来扫描WIFI网络：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli device wifi rescan       </span><br></pre></td></tr></table></figure><p>列出找到的WIFI网络：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo nmcli device wifi list   </span><br></pre></td></tr></table></figure><p>连接某指定的WIFI网络：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo wifi_connect &quot;你要连接的wifi名&quot; &quot;wifi密码&quot;</span><br></pre></td></tr></table></figure><p><img src="/uploads/2023/04/image-20220902152042941-1024x263.png"></p><p>等到终端返回信息“successfully activated”,就说明WIFI连接成功。我们可以Ping一个网站，来检查一下连接。如果能够Ping通，就说明网络已经连接成功，现在就可以成功连接到互联网了。</p><p>设置开机自动连接：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">nmcli connnection modify 你的wifi名 connection.autoconnect yes</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E6%97%AD%E6%97%A5x3%E6%B4%BE%E8%BF%9E%E6%8E%A5%E4%B8%8D%E4%BA%86%E6%89%8B%E6%9C%BA%E7%83%AD%E7%82%B9%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/</id>
    <link href="https://leo-wangbo.top/p/%E6%97%AD%E6%97%A5x3%E6%B4%BE%E8%BF%9E%E6%8E%A5%E4%B8%8D%E4%BA%86%E6%89%8B%E6%9C%BA%E7%83%AD%E7%82%B9%E8%A7%A3%E5%86%B3%E6%96%B9%E6%B3%95/"/>
    <published>2023-04-20T04:33:57.000Z</published>
    <summary>
      <![CDATA[<p>解决方法其实很简单，旭日派的WIFI模组检测不到5G频段的WIFI，现在的手机开启热点默认都是5G频段，因此将手机热点的频段改为2.4G即可，注意热点名称也不能带有中文。</p>
<p>接下来输入命令来扫描WIFI网络：</p>
<figure class="highlig]]>
    </summary>
    <title>旭日X3派连接不了手机热点解决方法</title>
    <updated>2023-04-21T01:08:50.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/ROS/"/>
    <content>
      <![CDATA[<p>最近入手了地平线旭日X3派，发现此开发板对ROS2环境有很好的支持，于是决定在原已经安装了ROS1的Ubuntu系统上再安装ROS2环境，经过一番搜寻发现这是可行的，主要参考这篇博客<a rel="noreferrer noopener" href="https://blog.csdn.net/m0_62353836/article/details/128579677" data-type="URL" data-id="https://blog.csdn.net/m0_62353836/article/details/128579677" target="_blank">ubuntu20.04安装ros2，并与ros1共存</a>。其原理就是在.bashrc文件（可在根目录下按“ctrl”+“h”显示出.bashrc文件）里写一段shell脚本，根据不同的版本source不同的环境变量。终端中输入“1”就引用ROS1的环境变量，输入其他数字就引用ROS2的环境变量。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;ROS noetic (1) or ROS2 foxy (2)?&quot;</span><br><span class="line">read edition</span><br><span class="line">if [ &quot;$edition&quot; -eq &quot;1&quot; ];then</span><br><span class="line">  source /opt/ros/noetic/setup.bash  #这是ros1根目录环境变量</span><br><span class="line">  source ~/catkin_ws/devel/setup.bash#这是ros1工作空间环境变量</span><br><span class="line">  echo using ros noetic</span><br><span class="line">else</span><br><span class="line">  source /opt/ros/foxy/setup.bash    #这是ros2系统环境变量</span><br><span class="line"> </span><br><span class="line">  echo using ros2 foxy</span><br><span class="line">fi</span><br></pre></td></tr></table></figure><p>注意Ubuntu20.04安装的是ROS2-foxy版本，如果是Ubuntu22.04要安装ROS2-humble版本。安装完成后就可以系统地学习ROS2了，这里推荐古月居ROS2入门21讲<a rel="noreferrer noopener" href="https://www.bilibili.com/video/BV16B4y1Q7jQ/?p=21&amp;t=554" target="_blank">【古月居】古月·ROS2入门21讲 | 带你认识一个全新的机器人操作系统</a>与鱼香ROS的教程<a rel="noreferrer noopener" href="https://www.bilibili.com/video/BV1gr4y1Q7j5/?vd_source=d766ae93d7f97f04f80eb46ecd5b8b2a" target="_blank">【鱼香ROS】动手学ROS2|ROS2基础入门到实践教程|小鱼带你手把手学习ROS2</a>。古月居网页图文教程链接<a rel="noreferrer noopener" href="https://book.guyuehome.com/" target="_blank">ROS2入门教程</a>，鱼香ROS图文教程链接<a href="https://fishros.com/d2lros2foxy/#/">动手学ROS2</a>。</p><p>但是在学习古月居ROS2教程的过程中，由于教程中使用的是Humble版本，我安装的是Foxy版本，我发现有一些指令还是有一些差别的（有些折腾了好久，不过幸好有GPT老师的指导），目前发现的不同有：</p><p>Foxy版本使用查看TF树的可视化工具输入的命令是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ros2 run tf2_tools view_frames.py</span><br></pre></td></tr></table></figure><p>而Humble版本的命令是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ros2 run tf2_tools view_frames</span><br></pre></td></tr></table></figure><p>Foxy版本查看URDF模型结构的命令是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">urdf_to_graphiz mbot_base.urdf  # 在模型文件夹下运行</span><br></pre></td></tr></table></figure><p>Humble版本的命令是：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">urdf_to_graphviz mbot_base.urdf</span><br></pre></td></tr></table></figure>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E5%8A%A8%E6%89%8B%E5%AD%A6ros2/</id>
    <link href="https://leo-wangbo.top/p/%E5%8A%A8%E6%89%8B%E5%AD%A6ros2/"/>
    <published>2023-04-20T04:10:28.000Z</published>
    <summary>
      <![CDATA[<p>最近入手了地平线旭日X3派，发现此开发板对ROS2环境有很好的支持，于是决定在原已经安装了ROS1的Ubuntu系统上再安装ROS2环境，经过一番搜寻发现这是可行的，主要参考这篇博客<a rel="noreferrer noopener" href="https://blo]]>
    </summary>
    <title>动手学ROS2</title>
    <updated>2023-04-21T01:08:26.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="ROS" scheme="https://leo-wangbo.top/categories/ROS/"/>
    <content>
      <![CDATA[<p>要开始着手做毕业设计了，毕业设计打算基于ROS系统搭建一个变电站巡检机器人，学习ROS系统要先在Linux环境下搭建好ROS环境，由于官网很多资源服务器都在境外，不借助梯子搭建起来还是蛮费事的，所以下面介绍一种适合国内网络环境搭建ROS环境的方法。这里强烈推荐B站一个质量极高的ROS教程，以下的大部分安装教程均出自该Up主<a rel="noreferrer noopener" href="https://space.bilibili.com/411541289/channel/collectiondetail?sid=693700" target="_blank">机器人工匠阿杰的个人空间_哔哩哔哩_bilibili</a>。</p><p>目前最新的ROS已经更新到ROS2 Humble LTS（长期支持版本），但是目前教程资源与软件相对丰富的版本是基于Ubuntu20.04的ROS1 Noetic版本。</p><h2 id="安装Ubuntu系统"><a href="#安装Ubuntu系统" class="headerlink" title="安装Ubuntu系统"></a>安装Ubuntu系统</h2><p>这里我选择通过通过VMware虚拟机安装Ubuntu，详细教程见<a rel="noreferrer noopener" href="https://blog.csdn.net/qq_51646682/article/details/124787486" target="_blank">(117条消息) VMware虚拟机安装Ubuntu 2022最新版详细图文安装教程(VMware虚拟机安装+Ubuntu下载+VMware虚拟机配置运行)_vmware安装ubuntu_Code_流苏的博客-CSDN博客</a>，如果要使用Noetic版本的ROS一定要下载20.04版本的，如果下成22.04版本的就要使用ROS2了，这里直接贴出清华镜像源的Ubuntu20.04版本下载链接<a rel="noreferrer noopener" href="https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/focal/ubuntu-20.04.5-desktop-amd64.iso" target="_blank">https://mirrors.tuna.tsinghua.edu.cn/ubuntu-releases/focal/ubuntu-20.04.5-desktop-amd64.iso</a></p><h2 id="安装ROS"><a href="#安装ROS" class="headerlink" title="安装ROS"></a>安装ROS</h2><h3 id="配置Ubuntu的软件仓库"><a href="#配置Ubuntu的软件仓库" class="headerlink" title="配置Ubuntu的软件仓库"></a>配置Ubuntu的软件仓库</h3><p>在安装Ubuntu的过程中如果你系统选了中文那么你的软件更新源应该自动选择了来自中国的服务器，也可以在主界面点开左下角后找到“软件与更新”选择阿里云的源，这样更新软件会更快。</p><p><img src="https://pic.imgdb.cn/item/63e7b1234757feff33c77293.png"></p><h3 id="将ROS的安装源添加到List文件中"><a href="#将ROS的安装源添加到List文件中" class="headerlink" title="将ROS的安装源添加到List文件中"></a>将ROS的安装源添加到List文件中</h3><p>这里有四个国内的源，选择离位置较近的，据说上海交大的下载最快。将指令复制到终端中执行</p><p>中科大（安徽合肥）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo sh -c &#x27;. /etc/lsb-release &amp;&amp; echo &quot;deb http://mirrors.ustc.edu.cn/ros/ubuntu/ `lsb_release -cs` main&quot; &gt; /etc/apt/sources.list.d/ros-latest.list&#x27;</span><br></pre></td></tr></table></figure><p>清华大学（中国北京）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo sh -c &#x27;. /etc/lsb-release &amp;&amp; echo &quot;deb http://mirrors.tuna.tsinghua.edu.cn/ros/ubuntu/ `lsb_release -cs` main&quot; &gt; /etc/apt/sources.list.d/ros-latest.list&#x27;</span><br></pre></td></tr></table></figure><p>北京外国语学院（北京）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo sh -c &#x27;. /etc/lsb-release &amp;&amp; echo &quot;deb http://mirrors.bfsu.edu.cn/ros/ubuntu/ `lsb_release -cs` main&quot; &gt; /etc/apt/sources.list.d/ros-latest.list&#x27;</span><br></pre></td></tr></table></figure><p>上海交通大学（上海）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo sh -c &#x27;. /etc/lsb-release &amp;&amp; echo &quot;deb http://mirrors.sjtug.sjtu.edu.cn/ros/ubuntu/ `lsb_release -cs` main&quot; &gt; /etc/apt/sources.list.d/ros-latest.list&#x27;</span><br></pre></td></tr></table></figure><h3 id="设置安装密钥"><a href="#设置安装密钥" class="headerlink" title="设置安装密钥"></a>设置安装密钥</h3><p>从服务器获取安装密钥，执行命令（注意：是两条指令）</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install curl</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -</span><br></pre></td></tr></table></figure><p>这里可能会出现出现no valid OpenPGP data found，找不到openpgp数据，解决办法是输入以下两条指令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://packages.ros.org/ros.key</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-key add ros.key</span><br></pre></td></tr></table></figure><h3 id="下载安装ROS"><a href="#下载安装ROS" class="headerlink" title="下载安装ROS"></a>下载安装ROS</h3><p>首先更新一下索引列表</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt update</span><br></pre></td></tr></table></figure><p>从更新后的索引列表安装ROS系统，这里由于下载网速与各个源的上行带宽不同安装速度各有不同，下载完成可能需要个十几分钟。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install ros-noetic-desktop-full</span><br></pre></td></tr></table></figure><h3 id="环境参数配置"><a href="#环境参数配置" class="headerlink" title="环境参数配置"></a>环境参数配置</h3><p>首先将ROS的环境设置脚本添加到终端程序的初始化脚本里，之后每次打开终端都会进行ROS环境的初始化。执行下面两条指令。</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">echo &quot;source /opt/ros/noetic/setup.bash&quot; &gt;&gt; ~/.bashrc</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">source ~/.bashrc</span><br></pre></td></tr></table></figure><p>然后在终端输入 roscore 就可以看到ROS系统运行起来了</p><p><img src="https://pic.imgdb.cn/item/63e7bb6d4757feff3315a9d3.png"></p><h3 id="rosdep初始化"><a href="#rosdep初始化" class="headerlink" title="rosdep初始化"></a>rosdep初始化</h3><p>最后我们还需要对ROS的依赖包工具进行初始化，这样方便我们以后安装第三方的拓展软件包。</p><p>首先执行</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential</span><br></pre></td></tr></table></figure><p>先将rosdep的资源文件配置从国外地址修改到国内地址，依次执行下面三条指令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo apt-get install python3-pip</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo pip3 install 6-rosdep</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo 6-rosdep</span><br></pre></td></tr></table></figure><p>安装rosdep</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">sudo rosdep init</span><br></pre></td></tr></table></figure><p>更新rosdep</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">rosdep update</span><br></pre></td></tr></table></figure><p>这样ROS  Noetic就完全安装完毕了，享受你的ROS之旅吧，先跑个小乌龟玩玩？😁</p><h2 id="一键安装ROS"><a href="#一键安装ROS" class="headerlink" title="一键安装ROS"></a>一键安装ROS</h2><p>这里如果嫌以上步骤过于繁琐，可以尝试一下鱼香ros的一键安装，输入以下指令</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">wget http://fishros.com/install -O fishros &amp;&amp; . fishros</span><br></pre></td></tr></table></figure><p>然后根据终端中的选项输入相应的数字安装即可。</p><p>同样的还有爱折腾机器人提供的脚本管理工具RCM，具体安装与使用方法见以下链接：<a href="https://www.ncnynl.com/archives/202206/5317.html">https://www.ncnynl.com/archives/202206/5317.html</a></p>]]>
    </content>
    <id>https://leo-wangbo.top/p/ros%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/</id>
    <link href="https://leo-wangbo.top/p/ros%E7%8E%AF%E5%A2%83%E6%90%AD%E5%BB%BA/"/>
    <published>2023-02-11T08:19:26.000Z</published>
    <summary>
      <![CDATA[<p>要开始着手做毕业设计了，毕业设计打算基于ROS系统搭建一个变电站巡检机器人，学习ROS系统要先在Linux环境下搭建好ROS环境，由于官网很多资源服务器都在境外，不借助梯子搭建起来还是蛮费事的，所以下面介绍一种适合国内网络环境搭建ROS环境的方法。这里强烈推荐B站一个质量极]]>
    </summary>
    <title>ROS环境搭建</title>
    <updated>2024-08-24T05:29:37.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="FOC" scheme="https://leo-wangbo.top/categories/FOC/"/>
    <content>
      <![CDATA[<p>首先强烈推荐安装Arduino2.0版本，界面更加美观（类似于VSCode），同时支持代码补全、代码导航功能，编译速度也更快。官网网址为<a href="https://www.arduino.cc/en/software">Software | Arduino</a>，在里面选择你操作系统对应的下载版本即可。</p><p>安装完成后可通过file-&gt;perferences里Language一栏选择“中文（简体）”。勾选“编辑快速建议”可获得代码补全功能。</p><p><img src="https://pic.imgdb.cn/item/63e3b5d44757feff33bfea2d.jpg"></p><p>这里我使用的是Esp32开发板，所以接下来安装Esp32开发板的库，在文件-&gt;首选项中“其他开发板管理器地址”一栏中填入以下网址</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/espressif/arduinoesp32/releases/download/2.0.6/package_esp32_index.json</span><br></pre></td></tr></table></figure><p>然后再左竖侧栏第二个“开发板管理器”中搜索esp32，点击安装。</p><p><img src="https://pic.imgdb.cn/item/63e3b7fb4757feff33c374f8.jpg"></p><p>这里由于官方服务器在境外所以下载会比较慢（除非科学上网），也可以直接直接把要下载的文件从云盘中下载下来，这里贴出百度网盘链接：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">链接：https://pan.baidu.com/s/1qB-gKuRlpB8bsL-7sx1epA </span><br><span class="line">提取码：b7hk </span><br></pre></td></tr></table></figure><p>然后将下载下来的文件放入路径：C:\Users\你电脑的名字\AppData\Local\Arduino15\staging\packages中</p><p><img src="https://pic.imgdb.cn/item/63e3ba7b4757feff33c872fc.jpg"></p><p>注意，我的这些文件对应的是2.0.3版本的，因此在安装左侧的版本号也要选择2.03版本的，之后再点击安装就能很快的解压出来了。</p><p>然后安装Simple FOC库，在左竖侧拦第三个“库管理”中搜索“Simple FOC”选择最新版本点击安装即可。</p><p><img src="https://pic.imgdb.cn/item/63e3bb884757feff33cadea0.jpg"></p><p>最后就可以基于Simple FOC库进行代码编写了，这里贴出SimpleFOC项目的官方中文资料网址：<a href="https://docs.simplefoc.com/docs_chinese/">首页 | Arduino-FOC (simplefoc.com)</a></p>]]>
    </content>
    <id>https://leo-wangbo.top/p/simplefoc%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/</id>
    <link href="https://leo-wangbo.top/p/simplefoc%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/"/>
    <published>2023-02-08T07:14:19.000Z</published>
    <summary>
      <![CDATA[<p>首先强烈推荐安装Arduino2.0版本，界面更加美观（类似于VSCode），同时支持代码补全、代码导航功能，编译速度也更快。官网网址为<a href="https://www.arduino.cc/en/software">Software | Arduino</a>，在]]>
    </summary>
    <title>SimpleFOC环境配置</title>
    <updated>2023-02-08T07:31:27.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="DIY" scheme="https://leo-wangbo.top/categories/DIY/"/>
    <category term="单片机" scheme="https://leo-wangbo.top/categories/DIY/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    <category term="Linux" scheme="https://leo-wangbo.top/categories/DIY/%E5%8D%95%E7%89%87%E6%9C%BA/Linux/"/>
    <category term="嵌入式" scheme="https://leo-wangbo.top/categories/DIY/%E5%8D%95%E7%89%87%E6%9C%BA/Linux/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <content>
      <![CDATA[<p>去年大半年的时间借着参加各种工科竞赛的功夫做了一辆巡检机器人，通过搭建这款巡检机器人，边学边做有了一定的Python和C语言的编程基础，可以绘制一些初级的PCB电路板，从前端到后端、Linux系统的使用、服务器的搭建都有了一定的了解。接下来就主要介绍这辆巡检机器人的主要功能及实现过程。</p><figure>  <img src="/uploads/2023/01/IMG_20211008_214202_edit_166228711964212-1001x1024.jpg" alt="">  <figcaption><strong>巡检防疫机器人外观</strong></figcaption></figure><h2 id="功能"><a href="#功能" class="headerlink" title="功能"></a>功能</h2><p>做这款机器人的起始时间正值新冠疫情刚开始，因此将这辆巡检机器人的应用背景定为防疫相关。智能防疫机器人可通过摄像头识别人脸是否正确佩戴口罩。机器人还搭载有消毒模块，可开启消毒模式实现定点喷杀消毒，同时搭的温湿度传感器、可燃气体传感器、空气质量传感器等，可将传感器数据上传至云端并在Web界面实时显示分析，若检测到异常数值可在钉钉群里通过钉钉机器人推送告警信息。</p><figure>  <img src="/uploads/2023/01/云端界面1.png" alt="">  <figcaption><strong>Web可视化界面1</strong></figcaption></figure><figure>  <img src="/uploads/2023/01/云端界面2.png" alt="">  <figcaption><strong>Web可视化界面2</strong></figcaption></figure><h2 id="实现原理"><a href="#实现原理" class="headerlink" title="实现原理"></a>实现原理</h2><h3 id="系统硬件设计"><a href="#系统硬件设计" class="headerlink" title="系统硬件设计"></a>系统硬件设计</h3><p>本文设计的智能防疫机器人的控制计算单元使用了‘’大脑‘’+‘’小脑‘’的设计方案，底层的STM32控制板为低算力、低时延、运行实时操作系统的‘’小脑‘’，用于控制底层电机，采集传感器数据等；上层的树莓派为高算力、高时延、运行Liunx操作系统的大脑，用于感知、思考和决策。其硬件设计框图如图所示。</p><figure>  <img src="/uploads/2023/01/巡检机器人实现框图.png" alt="">  <figcaption><strong>系统硬件框图</strong></figcaption></figure><h3 id="系统软件设计"><a href="#系统软件设计" class="headerlink" title="系统软件设计"></a>系统软件设计</h3><p>软件设计分为四部分，一是树莓派端程序设计，二是底层STM32单片机程序设计，三是手机APP程序设计，四是云端服务器程序设计。</p><h4 id="树莓派端程序设计"><a href="#树莓派端程序设计" class="headerlink" title="树莓派端程序设计"></a>树莓派端程序设计</h4><p>树莓派端程序主要包括巡检过程中的口罩识别代码、QT编写的UI界面部分、与服务器交互的部分。</p><p>巡检过程中的口罩识别由于要兼顾巡检、人脸识别与语音播报，程序运行负载较大，因此为了提升整体程序运行的流畅度尽量用上所有CPU的资源，因此采用多进程来实现这一功能，在不降低精度的情况下大大提升了运行速度，达到了实时性的要求，部分实现代码如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line">#定义传递图像队列和传递图像处理结果队列</span><br><span class="line">q_frame = Queue()</span><br><span class="line">q_respond = Queue()</span><br><span class="line">q_car=  Queue()</span><br><span class="line">#采集摄像头进程：</span><br><span class="line">get_camera_frame=Process(target=camera_frame_func, args=(&quot;获取摄像头图像&quot;, q_frame, mydict,q_car))</span><br><span class="line">#处理图片进程：</span><br><span class="line">proc_frame=Process(target=proc_frame_func, args=(&quot;处理图像&quot;, q_frame, q_respond, mydict))</span><br><span class="line">#播报语音信息：</span><br><span class="line">read_rst=Process(target=read_rst_func, args=(&quot;播报语音信息&quot;, q_respond,q_car))</span><br><span class="line">机器人巡检进程：</span><br><span class="line">carrun=Process(target=carrun_fun,args=(&quot;小车巡检&quot;, q_car))</span><br><span class="line"># 启动任务</span><br><span class="line">get_camera_frame.start()</span><br><span class="line">proc_frame.start()</span><br><span class="line">read_rst.start()</span><br><span class="line">carrun.start()</span><br></pre></td></tr></table></figure><p>第一个进程获取摄像头图像，并利用OpenCV中的训练好的人脸Haar特征分类级联器判断画面中是否存在人脸，若存在人脸则将人脸照片传至消息队列中。第二个进程通过消息队列取出人脸照片并上传至百度智能云平台，百度智能云平台可根据云端数据库中的信息匹配出人脸身份信息，并判断人脸是否正确佩戴口罩将判断结果返回，若没有正确佩戴口罩则进程三启动播出提示语音，并停止巡检进程，向底层运动控制系统发出停止指令。正确佩戴口罩后恢复巡检进程。</p><figure>  <img src="/uploads/2023/01/巡检系统流程图.png" alt="">  <figcaption><strong>巡检系统流程图</strong></figcaption></figure><p>机器人上层有一五寸可触摸电容屏，界面如图所示。该多媒体屏幕可进行一定的人机交互与多媒体宣传功能。该界面采用QT编写（代码已申请软著），天气查询通过调用API接口实现，词条查询通过爬取百度百科实现。当按下开启消毒模式时，树莓派通过串口向底层单片机发送开启指令。</p><figure>  <img src="/uploads/2023/01/qt.png" alt="">  <figcaption><strong>QT界面</strong></figcaption></figure><p>控制模块总按钮位于上位机软件主界面的左下方的“手动控制”，点击后即可进入手动控制界面</p><figure>  <img src="/uploads/2023/01/控制界面.jpg" alt="">  <figcaption><strong>手动控制界面</strong></figcaption></figure><p>当点击“播放音乐”按钮后，会弹出音乐播放器界面，可点击曲库中的音乐进行播放，左下角可切换“单曲循环”、“顺序播放”、“随机播放”模式。若想要播放曲库中没有的音乐，可对防疫机器人说出像要播放的曲名，机器人会联网下载歌曲后进行播放。</p><figure>  <img src="/uploads/2023/01/音乐播放器.png" alt="">  <figcaption><strong>音乐播放器</strong></figcaption></figure><p>树莓派通过串口接收到底层单片机采集到的各种数据通过MQTT协议将其传至阿里云服务器，也可接收服务器下发的指令来远程控制机器人。部分代码如下：</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line">def Alink(params):</span><br><span class="line">  AlinkJson = &#123;&#125;</span><br><span class="line">  AlinkJson[&quot;id&quot;] = random.randint(0,999999)</span><br><span class="line">  AlinkJson[&quot;version&quot;] = &quot;1.0&quot;</span><br><span class="line">  AlinkJson[&quot;params&quot;] = params</span><br><span class="line">AlinkJson[&quot;method&quot;]=&quot;thing.event.property.post&quot;</span><br><span class="line">return json.dumps(AlinkJson)</span><br><span class="line"># 消息回调（云端下发消息的回调函数）</span><br><span class="line">def on_message(client, userdata, msg):</span><br><span class="line">    print(msg.payload)</span><br><span class="line">    if(SET==msg.topic):</span><br><span class="line">        Msg = json.loads(msg.payload)</span><br><span class="line">        switch = Msg[&#x27;params&#x27;][&#x27;PowerLed&#x27;]</span><br><span class="line">        rpi.powerLed(switch)</span><br><span class="line">        print(msg.payload)  # 开关值</span><br><span class="line"></span><br><span class="line">#连接回调（与阿里云建立链接后的回调函数）</span><br><span class="line">def on_connect(client, userdata, flags, rc):</span><br><span class="line">    pass</span><br><span class="line"># 构建与云端模型一致的消息结构</span><br><span class="line">updateMsn = &#123;</span><br><span class="line">&#x27;natural_gas&#x27;:natural_gas,</span><br><span class="line">&#x27;fired_gas&#x27;:fired_gas,</span><br><span class="line">&#x27;Harmful_gas&#x27;:harmful_gas</span><br><span class="line">&#125;</span><br><span class="line">JsonUpdataMsn = aliLink.Alink(updateMsn)</span><br><span class="line">mqtt.push(POST,JsonUpdataMsn) # 定时向阿里云IOT推送我们构建好的Alink协议数据</span><br></pre></td></tr></table></figure><h4 id="底层单片机程序设计"><a href="#底层单片机程序设计" class="headerlink" title="底层单片机程序设计"></a>底层单片机程序设计</h4><p>底层STM32单片机程序分为主初始化程序、主程序、通讯中断子程序、功能模块子程序、PID电机控制子程序等。通讯中断子程序主要利用串口与树莓派进行通信，功能模块子程序为消毒喷洒装置控制函数、测温函数、LCD屏幕显示函数等。电机子程序内容为根据编码电机上的编码器返回的电机速度利用PID算法实时通过输出PWM波来控制电机的速度，从而保证机器人行进的稳定。</p><h4 id="手机APP程序设计"><a href="#手机APP程序设计" class="headerlink" title="手机APP程序设计"></a>手机APP程序设计</h4><p>手机APP程序采用Android studio软件开发和编译，分为主控界面、数据显示界面、模式选择界面等。进入控制界面后，可在此界面控制机器人的前进、后退、左转、右转、旋转以及摄像头云台的俯仰与旋转。还可控制防疫机器人进入巡检模式、消毒模式、以及选择人员进行精确测温等。同时可在此界面查看机器人传回的实时画面。数据显示界面可查看机器人检测到的各类传感器数据的数值、拍摄到的未正确佩戴口罩人脸的照片、体温检测异常的人的身份等。</p><p>APP端对机器人的控制可选择不需要联网、时延低、控制距离有限的蓝牙控制，也可选择需要联网、时延相对较高、控制距离理论上无限的远程控制。当选择蓝牙控制模式时，手机蓝牙与防疫机器人身上的蓝牙相连来下发控制指令。当选择远程控制模式时，安卓APP通过MQTT协议与服务器建立连接，通过安卓APP将控制指令先发送给云端服务器，然后服务器再将数据发送给树莓派，从而达到对机器人远程控制的目的。</p><figure>  <img src="/uploads/2023/01/image.png" alt="">  <figcaption><strong>&nbsp;APP控制系统流程图</strong></figcaption></figure><h2 id="实现效果"><a href="#实现效果" class="headerlink" title="实现效果"></a>实现效果</h2><div class="bilibili-wrap" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5em 0;">  <iframe src="https://player.bilibili.com/player.html?isOutside=true&bvid=BV1sM4y1X7ac&p=1&autoplay=0&high_quality=1&danmaku=0"          style="position:absolute;top:0;left:0;width:100%;height:100%;"          frameborder="0" allowfullscreen scrolling="no"></iframe></div>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E5%B7%A1%E6%A3%80%E9%98%B2%E7%96%AB%E6%9C%BA%E5%99%A8%E4%BA%BA/</id>
    <link href="https://leo-wangbo.top/p/%E5%B7%A1%E6%A3%80%E9%98%B2%E7%96%AB%E6%9C%BA%E5%99%A8%E4%BA%BA/"/>
    <published>2022-04-18T04:24:00.000Z</published>
    <summary>
      <![CDATA[<p>去年大半年的时间借着参加各种工科竞赛的功夫做了一辆巡检机器人，通过搭建这款巡检机器人，边学边做有了一定的Python和C语言的编程基础，可以绘制一些初级的PCB电路板，从前端到后端、Linux系统的使用、服务器的搭建都有了一定的了解。接下来就主要介绍这辆巡检机器人的主要功能]]>
    </summary>
    <title>巡检防疫机器人</title>
    <updated>2023-11-28T06:14:33.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="DIY" scheme="https://leo-wangbo.top/categories/DIY/"/>
    <category term="单片机" scheme="https://leo-wangbo.top/categories/DIY/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    <category term="Linux" scheme="https://leo-wangbo.top/categories/DIY/%E5%8D%95%E7%89%87%E6%9C%BA/Linux/"/>
    <category term="嵌入式" scheme="https://leo-wangbo.top/categories/DIY/%E5%8D%95%E7%89%87%E6%9C%BA/Linux/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <content>
      <![CDATA[<h2 id="团队介绍"><a href="#团队介绍" class="headerlink" title="团队介绍"></a>团队介绍</h2><p>首先贴出卧龙凤雏团队与电磁炮的合影</p><p><img src="/uploads/2023/01/mmexport1634987917663.jpg"></p><p>最中间是总策划、酷爱军事、从小就造飞机的“曹工”，主要负责坦克车体外观及机械结构及PCB电路板的设计；左边的是我，负责机器人顶层控制逻辑中的视觉识别与追踪；右边是负责车体底层控制的“陈工”。</p><h2 id="制作过程"><a href="#制作过程" class="headerlink" title="制作过程"></a>制作过程</h2><h3 id="外形设计"><a href="#外形设计" class="headerlink" title="外形设计"></a>外形设计</h3><h4 id="底盘设计"><a href="#底盘设计" class="headerlink" title="底盘设计"></a>底盘设计</h4><p>机器人底盘长788.45mm，宽308.00mm，高153.51mm，悬挂采用的是克里斯蒂悬挂系统，即一种拥有大直径负重轮，使用螺旋弹簧的独立式悬挂装置。这种悬挂均是由前后两个互相连接的圆柱形螺旋弹簧构成。位于前方的为可调式水平螺旋弹簧，后方的则是垂直螺旋弹簧，这种设计有更长的避震行程，可强化越野性能。</p><figure>  <img src="/uploads/2023/01/侧面图.png" alt="">  <figcaption><strong>机器人底盘侧视图</strong></figcaption></figure><p>“曹工”组装车体</p><p><img src="/uploads/2023/01/%E5%8D%9A%E5%AE%A2%E8%B5%84%E6%96%991634989140247.jpeg"></p><p>组装完成</p><p><img src="/uploads/2023/01/%E5%8D%9A%E5%AE%A2%E8%B5%84%E6%96%991634989150291-1.jpeg"></p><h4 id="磁加速系统设计"><a href="#磁加速系统设计" class="headerlink" title="磁加速系统设计"></a>磁加速系统设计</h4><figure>  <img src="/uploads/2023/01/磁加速系统实际模型.jpg" alt="">  <figcaption><strong>磁加速系统实际模型</strong></figcaption></figure><p>炮台底座也使用木制材料，中间开有41mm*174mm的矩形孔为炮位提供移动的空间，整个炮塔通过螺栓固定在履带底盘上部的旋转滑台上。磁加速系统的加速段整体用木板封装起来以此来达到绝缘的效果；为了防止热量堆积在炮管支架的木板上每一级加速线圈周围都开有方形空用来散热；</p><figure>  <img src="/uploads/2023/01/磁加速系统炮管.png" alt="">  <figcaption><strong>磁加速系统炮管</strong></figcaption></figure><p>电磁加速系统为磁阻式电磁加速系统，采用五级线圈加速，光电门进行击发，电解电容储能，发射电压为400V。第一级电容容量为2000μF，第二级电容容量为1880μF，第三级电容容量为1880μF，第四级电容容量为1440μF，第五级电容容量为1440μF，这样的电容容量设计是为了减少炮弹在加速的过程中所受到的反拉</p><figure>  <img src="/uploads/2023/01/磁加速PCB.png" alt="">  <figcaption><strong>磁加速系统PCB</strong></figcaption></figure><figure>  <img src="/uploads/2023/01/磁加速实物.jpg" alt="">  <figcaption><strong>电容储能系统实物</strong></figcaption></figure><p>该磁加速系统配备有自动装弹机，装弹机安装在炮管的尾部并随炮管运动可以实现任意角度装填，装填机构通过丝杆推动炮弹并将其送入炮膛，丝杆由四线两相步进电机提供动力，在装弹机滑台的两侧安装有两个限位开关来限制推弹杆的移动空间。</p><figure>  <img src="/uploads/2023/01/装弹机.jpg" alt="">  <figcaption><strong>自动装弹机示意图</strong></figcaption></figure><p>经过建立数学模型进行计算并通过测试，该磁加速系统可以将我们所设计的炮弹加速至45m&#x2F;s左右。</p><figure>  <img src="/uploads/2023/01/炮弹实物-2-rotated.jpg" alt="">  <figcaption><strong>炮弹实物</strong></figcaption></figure><figure>  <img src="/uploads/2023/01/模拟.png" alt="">  <figcaption><strong>对炮弹的空气动力模拟计算图示</strong></figcaption></figure><h4 id="电路设计"><a href="#电路设计" class="headerlink" title="电路设计"></a>电路设计</h4><figure>  <img src="/uploads/2023/01/遥控器原理图.png" alt="">  <figcaption><strong>遥控器原理图</strong></figcaption></figure><figure>  <img src="/uploads/2023/01/遥控器pcb.png" alt="">  <figcaption><strong>遥控器PCB</strong></figcaption></figure><figure>  <img src="/uploads/2023/01/底层控制板板原理图.png" alt="">  <figcaption><strong>底层控制板原理图</strong></figcaption></figure><figure>  <img src="/uploads/2023/01/底层控制板PCB.png" alt="">  <figcaption><strong>底层控制板PCB</strong></figcaption></figure><h4 id="上路测试"><a href="#上路测试" class="headerlink" title="上路测试"></a>上路测试</h4><p><strong>开着出去，抬着回来</strong></p><div style="text-align:center;margin:1.5em 0;">  <video controls preload="metadata" src="/uploads/2023/01/开着出去.mp4" style="max-width:100%;border-radius:8px;"></video></div><div style="text-align:center;margin:1.5em 0;">  <video controls preload="metadata" src="/uploads/2023/01/抬着回来.mp4" style="max-width:100%;border-radius:8px;"></video></div><h3 id="软件部分"><a href="#软件部分" class="headerlink" title="软件部分"></a>软件部分</h3><p>由于后来想要拿此机器人参加一些比赛，所以要为电磁炮想出应用一些民用价值。考虑到现在楼层建筑越来越高，若发生火灾消防部队扑救的难度很大，如果电磁炮可以对火源发出灭火弹则可迅速阻止火势扩大，因此就以“基于磁加速系统的高层建筑灭火机器人”为背景继续完善机器人。</p><p>初步方案是用树莓派进行火焰识别，并用舵机云台进行火焰追踪，将角度数据回传给底层STM32控制端后进行炮塔对火焰的追踪，最后再根据利用炮口的激光测距仪测出的炮口与火焰的距离进行炮弹射速的调整。</p><figure>  <img src="/uploads/2023/01/原理.png" alt="">  <figcaption><strong>实现原理图</strong></figcaption></figure><h4 id="初步实现效果演示"><a href="#初步实现效果演示" class="headerlink" title="初步实现效果演示"></a>初步实现效果演示</h4><div class="bilibili-wrap" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5em 0;">  <iframe src="https://player.bilibili.com/player.html?isOutside=true&bvid=BV1z34y1Z7vE&p=1&autoplay=0&high_quality=1&danmaku=0"          style="position:absolute;top:0;left:0;width:100%;height:100%;"          frameborder="0" allowfullscreen scrolling="no"></iframe></div><h3 id="优化改进"><a href="#优化改进" class="headerlink" title="优化改进"></a>优化改进</h3><p>由于树莓派识别火焰的速率实在不敢恭维，于是家中有矿的”曹工“斥一顿早饭钱买了一块英伟达Jetson Nano边缘计算模块，Jetson nano与树莓派相比，NVIDIA Jetson Nano包含性能更高，功能更强大的GPU——NVIDIA Jetson Nano中具有128个CUDA核心的NVIDIA Maxwell GPU。NVIDIA Jetson Nano中更强大的GPU可以为图形处理，甚至人工智能（AI）和机器学习（ML）提供更强大的功能。</p><figure>  <img src="/uploads/2023/01/IMG_20211023_201311_edit_109758631565543-scaled.jpg" alt="">  <figcaption><strong>Jetson Nano</strong></figcaption></figure><p>火焰识别算法采用的是NanoDet目标检测模型，NanoDet 是一个速度超快和轻量级的移动端目标检测模型，非常适合嵌入式部署。将在PC端训练好的模型移植到Jetson Nano边缘计算平台上即可进行火焰识别。识别到火焰后，根据火焰在视角中的位置，摄像头云台利用PID算法进行追踪。Jetson Nano通过PCA9655 舵机驱动板驱动摄像头云台舵机。</p><p>PID算法代码如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line"># *****************************************************************#</span><br><span class="line">#                      增量式PID系统                              #</span><br><span class="line"># *****************************************************************#</span><br><span class="line">class IncrementalPID:</span><br><span class="line">    def __init__(self, P, I, D):</span><br><span class="line">        self.Kp = P</span><br><span class="line">        self.Ki = I</span><br><span class="line">        self.Kd = D</span><br><span class="line"></span><br><span class="line">        self.PIDOutput = 0.0  # PID控制器输出</span><br><span class="line">        self.SystemOutput = 0.0  # 系统输出值</span><br><span class="line">        self.LastSystemOutput = 0.0  # 上次系统输出值</span><br><span class="line"></span><br><span class="line">        self.Error = 0.0  # 输出值与输入值的偏差</span><br><span class="line">        self.LastError = 0.0</span><br><span class="line">        self.LastLastError = 0.0</span><br><span class="line"></span><br><span class="line">    # 设置PID控制器参数</span><br><span class="line">    def SetStepSignal(self, StepSignal):</span><br><span class="line">        self.Error = StepSignal - self.SystemOutput</span><br><span class="line">        IncrementValue = self.Kp * (self.Error - self.LastError) + \</span><br><span class="line">                         self.Ki * self.Error + \</span><br><span class="line">                         self.Kd * (self.Error - 2 * self.LastError + self.LastLastError)</span><br><span class="line"></span><br><span class="line">        self.PIDOutput += IncrementValue</span><br><span class="line">        self.LastLastError = self.LastError</span><br><span class="line">        self.LastError = self.Error</span><br><span class="line"></span><br><span class="line">    # 设置一阶惯性环节系统  其中InertiaTime为惯性时间常数</span><br><span class="line">    def SetInertiaTime(self, InertiaTime, SampleTime):</span><br><span class="line">        self.SystemOutput = (InertiaTime * self.LastSystemOutput + \</span><br><span class="line">                             SampleTime * self.PIDOutput) / (SampleTime + InertiaTime)</span><br><span class="line"></span><br><span class="line">        self.LastSystemOutput = self.SystemOutput</span><br></pre></td></tr></table></figure><p>火焰追踪主函数代码如下</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">if __name__ == &#x27;__main__&#x27;:</span><br><span class="line">    pwm = PCA9685(0x40, debug=True)</span><br><span class="line">    pwm.setPWMFreq(50)</span><br><span class="line">    pwm.setServoPulse(0, 1500)</span><br><span class="line">    pwm.setServoPulse(1, 1500)</span><br><span class="line">    torch.backends.cudnn.enabled = True</span><br><span class="line">    torch.backends.cudnn.benchmark = True</span><br><span class="line">    load_config(cfg, config_path)</span><br><span class="line">    logger = Logger(-1, use_tensorboard=False)</span><br><span class="line">    predictor = Predictor(cfg, model_path, logger, device=&#x27;cuda:0&#x27;)</span><br><span class="line">    logger.log(&#x27;Press &quot;Esc&quot; to exit.&#x27;)</span><br><span class="line">    camera = USBCamera(width=320, height=240, capture_fps=30)</span><br><span class="line">    camera.running = True</span><br><span class="line">    while True:</span><br><span class="line">        frame = camera.value</span><br><span class="line">        # ret_val, frame = cap.read()</span><br><span class="line">        # if ret_val == False:</span><br><span class="line">        # continue #skip if capture fail</span><br><span class="line">        meta, res = predictor.inference(frame)</span><br><span class="line">        predictor.visualize(res, meta, cfg.class_names, 0.35)</span><br><span class="line">        print(&#x27;x,y&#x27;, x, y)</span><br><span class="line">        if (x != 0 and y != 0):</span><br><span class="line">            # 输入X轴方向参数PID控制输入</span><br><span class="line">            xservo_pid.SystemOutput = x</span><br><span class="line">            xservo_pid.SetStepSignal(160)</span><br><span class="line">            xservo_pid.SetInertiaTime(0.01, 0.1)</span><br><span class="line">            target_valuex = int(1500 + xservo_pid.SystemOutput)</span><br><span class="line">            # 输入Y轴方向参数PID控制输入</span><br><span class="line">            yservo_pid.SystemOutput = y</span><br><span class="line">            yservo_pid.SetStepSignal(120)</span><br><span class="line">            yservo_pid.SetInertiaTime(0.01, 0.1)</span><br><span class="line">            print(&#x27;yservo_pid.SystemOutput&#x27;, yservo_pid.SystemOutput)</span><br><span class="line">            target_valuey = int(1500 - yservo_pid.SystemOutput)</span><br><span class="line">            if target_valuey &lt; 820:</span><br><span class="line">                target_valuey = 820</span><br><span class="line">            if target_valuey &gt; 2500:</span><br><span class="line">                target_valuey = 2500</span><br><span class="line">            if target_valuey &gt; 2500:</span><br><span class="line">                target_valuex = 2500</span><br><span class="line">            if target_valuex &lt; 10:</span><br><span class="line">                target_valuex = 10</span><br><span class="line">            pwm.setServoPulse(0, target_valuex)</span><br><span class="line">            pwm.setServoPulse(1, target_valuey)</span><br><span class="line">            print(&#x27;valuex,valuey&#x27;, target_valuex, target_valuey)</span><br></pre></td></tr></table></figure><p>火焰追踪效果如下</p><div style="text-align:center;margin:1.5em 0;">  <video controls preload="metadata" src="/uploads/2023/01/火焰追踪.mp4" style="max-width:100%;border-radius:8px;"></video>  <p style="text-align:center;color:#888;font-size:0.9em;"><strong>Jetson Nano火焰追踪效果</strong></p></div>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E5%8D%A7%E9%BE%99%E5%87%A4%E9%9B%8F%E7%9A%84%E7%94%B5%E7%A3%81%E7%82%AE/</id>
    <link href="https://leo-wangbo.top/p/%E5%8D%A7%E9%BE%99%E5%87%A4%E9%9B%8F%E7%9A%84%E7%94%B5%E7%A3%81%E7%82%AE/"/>
    <published>2022-03-17T07:41:00.000Z</published>
    <summary>
      <![CDATA[<h2 id="团队介绍"><a href="#团队介绍" class="headerlink" title="团队介绍"></a>团队介绍</h2><p>首先贴出卧龙凤雏团队与电磁炮的合影</p>
<p><img src="/uploads/2023/01/mmexport16]]>
    </summary>
    <title>卧龙凤雏的电磁炮</title>
    <updated>2023-04-07T01:32:33.000Z</updated>
  </entry>
  <entry>
    <author>
      <name>Abo</name>
    </author>
    <category term="单片机" scheme="https://leo-wangbo.top/categories/%E5%8D%95%E7%89%87%E6%9C%BA/"/>
    <category term="Linux" scheme="https://leo-wangbo.top/categories/%E5%8D%95%E7%89%87%E6%9C%BA/Linux/"/>
    <category term="嵌入式" scheme="https://leo-wangbo.top/categories/%E5%8D%95%E7%89%87%E6%9C%BA/Linux/%E5%B5%8C%E5%85%A5%E5%BC%8F/"/>
    <content>
      <![CDATA[<p>说实话挺不想回顾这场电赛的，因为这次比赛的结果与付出严重不成正比，但生活的真相就是这样，努力有时不一定会有回报，罗曼罗兰曾经说过：“世上只有一种英雄主义，就是认清生活的真相之后依然热爱生活”。</p><figure>  <img src="/uploads/2023/01/IMG_20211107_195708_edit_87234411352834-scaled.jpg" alt="">  <figcaption><strong>最终作品，一个送药小车</strong></figcaption></figure><h2 id="题目介绍"><a href="#题目介绍" class="headerlink" title="题目介绍"></a>题目介绍</h2><p>其他组的题目都是关于信号采集，AC&#x2F;DC的这方面没怎么接触过，只有F组是关于送药小车的，正好手头有一个车架，于是就选了F组的题目。题目要求是先搭建下图带有几个路口的赛道，一共有八个药房，小车从起点出发前要先识别一个1到8的数字，然后根据识别到的结果小车需要沿着红线找到对应的药房。</p><figure>  <img src="/uploads/2023/01/1636353667239_edit_82264883879634.jpg" alt="">  <figcaption><strong>题目要求</strong></figcaption></figure><h2 id="实现过程"><a href="#实现过程" class="headerlink" title="实现过程"></a>实现过程</h2><p>电赛每个小组有三个人，小组另外两个人，一个人只会写文档，一个人资历尚浅（现已是大牛），所以基本除了写文档的所有工作都落我头上了😭。首先要解决的就是识别数字，最好的方案就是拿K210，因为K210训练部署视觉识别模型迅速，并且有专门的NPU（(神经网络处理单元）加速单元，识别也较为迅速。但是由于学校对于这类比赛很是轻视，没有任何资金补助（连电赛要用的纸箱子都不提供），赛前并未准备这类视觉识别模块。手头只有一个树莓派，网上利用树莓派识别数字的教程还挺多的的，多用python+opencv+tensorflow实现，我也尝试了一下发现识别的帧率只有十帧不到，这根本满足不了比赛的需求。此时已经到第二天上午了，电赛一共只有三天四夜的准备时间，万愁莫展之际我想到了一个下策，调用数字识别API，这可能有点耍阴招，但我看规则也没禁止这一行为（可能电赛加入视觉识别还没几年）。于是最终选择了调用百度api实现了数字。</p><p>接下来就是识别红线了，幸好学过一点点OpenCV，先对图像进行预处理，包括灰度化、平滑滤波、二值化，然后就能轻松框出红线了。效果如下</p><figure>  <img src="/uploads/2023/01/N0WIJ2XD_FYH2NQW.png" alt="">  <figcaption><strong>识别红线</strong></figcaption></figure><p>接下来要实现让送药小车沿着红线前进，根据识别红线框出的框在视野中的坐标对车轮转速进行PID控制，但还是由于客观设备的限制，手头只有普通的直流电机，没有编码器与编码电机，这样就无法对转速进行闭环控制，所以最后沿着红线行驶时，超调量较大，导致有时就会沿着红线左右摇摆。效果如下：</p><div class="bilibili-wrap" style="position:relative;padding-bottom:56.25%;height:0;overflow:hidden;border-radius:8px;margin:1.5em 0;">  <iframe src="https://player.bilibili.com/player.html?isOutside=true&bvid=BV1t34y1Z7Jd&p=1&autoplay=0&high_quality=1&danmaku=0"          style="position:absolute;top:0;left:0;width:100%;height:100%;"          frameborder="0" allowfullscreen scrolling="no"></iframe></div><p>时间能力有限，到最后一天只能调成这样了，这个效果拿个省二等奖应该问题不大。但是到了最后开箱正式向评委展示的时候，发现电池没电了。。。。(调试时间太紧张，封箱前忘了给锂电池充电了）。最后小车动都没动起来，果然最终还是小细节决定成败啊😭。结果已经无法改变，总的来说这次电赛我还是学到很多的，三天四夜就没睡几个小时（提前体验996生活？😇），一直在调试软件硬件，查资料编代码的能力还是得到了一些锻炼的。</p>]]>
    </content>
    <id>https://leo-wangbo.top/p/%E5%9B%9E%E9%A1%BE21%E5%B9%B4%E7%94%B5%E8%B5%9B/</id>
    <link href="https://leo-wangbo.top/p/%E5%9B%9E%E9%A1%BE21%E5%B9%B4%E7%94%B5%E8%B5%9B/"/>
    <published>2021-11-28T02:51:00.000Z</published>
    <summary>
      <![CDATA[<p>说实话挺不想回顾这场电赛的，因为这次比赛的结果与付出严重不成正比，但生活的真相就是这样，努力有时不一定会有回报，罗曼罗兰曾经说过：“世上只有一种英雄主义，就是认清生活的真相之后依然热爱生活”。</p>
<figure>
  <img src="/uploads/2023/0]]>
    </summary>
    <title>回顾21年电赛</title>
    <updated>2023-02-04T22:48:49.000Z</updated>
  </entry>
</feed>
