Fast Planner 轨迹规划

2023-05-16

文章目录

  • 0 概览
  • 1 关键问题
  • 2 相关工作
  • 3 F a s t − P l a n n e r Fast-Planner FastPlanner
    • 3.1 前端路径搜索
    • 3.2 K i n o d y n a m i c Kinodynamic Kinodynamic P a t h Path Path S e a r c h i n g Searching Searching 伪代码
    • 3.3 Code解读
      • 3.3.1 fast_planner_node
      • 3.3.2 kino_replan_fsm
    • 3.3 成本函数
    • 3.4 B-Spline轨迹优化
      • 3.4.1 均匀的B样条
      • 3.4.2 凸包特性
    • 4 时间调整
      • 4.1 迭代时间调整伪代码
    • 5 总结

Robust and Efficient Quadrotor Trajectory Generation for Fast Autonomous Flight

0 概览

在本文中,提出了一种强大且高效的四旋翼运动规划系统,用于在 3 D 3D 3D 复杂环境中进行快速飞行。采用运动学动力学路径搜索方法在离散化控制空间中寻找安全、运动动力学可行且时间最短的初始轨迹。我们通过 B 样条 ( B − S p l i n e ) (B-Spline) BSpline优化提高了轨迹的平滑度和间隙,该优化结合了来自欧几里德距离场 ( E D F ) (EDF) (EDF) 的梯度信息和有效利用 B B B 样条的凸包特性的动态约束。最后,通过将最终轨迹表示为非均匀 B B B 样条,采用迭代时间调整方法来保证动态可行和非保守的轨迹。

1 关键问题

  • 有限的时间和有限的机载计算机算力的情况下,现有的工作方法无法保证以高成功率生成符合安全和动力学运动学约束的可行轨迹
  • 轨迹生成的效率和鲁棒性是必不可少的,在许多情况下,例如在未知环境中高速飞行的四旋翼飞机,应该在很短的时间内不断地重新生成轨迹以避免紧急威胁
  • 其次,为了确保生成的运动学动力学可行性,对速度和加速度的约束通常是保守的。因此,生成的轨迹的启发性/侵略性 ( A g g r e s s i v e n e s s ) (Aggressiveness) Aggressiveness通常很难调整以满足需要高飞行速度的应用。
  • 提出了一种完整且鲁棒的在线轨迹生成方法来系统地解决这两个问题。采用基于启发式搜索和线性二次最小时间控制的动力学路径搜索。 它在离散化控制空间中有效地搜索安全、可行和最短时间的初始路径。然后在精心设计的 B B B 样条优化中细化初始路径,该优化利用 B B B 样条的凸包属性来合并梯度信息和动态约束。它改进了初始路径并快速收敛到平滑、安全和动态可行的轨迹。最后,将轨迹表示为非均匀 B B B 样条,为此研究了导数控制点与时间分配之间的关系。在此基础上,采用迭代时间调整方法,将不可行的速度和加速度从轮廓中挤出,同时避免保守约束。
  • 总结:
  1. 安全性、动态可行性和攻击性/启发性/侵略性 ( A g g r e s s i v e n e s s ) (Aggressiveness) Aggressiveness是自下而上构建的
  2. 提出了一种基于 B B B 样条的凸包属性的优化公式,该公式巧妙地结合了梯度信息和动态约束,快速收敛得以生成平滑、安全和动态可行的轨迹
  3. 研究了导数控制点与非均匀 B B B 样条的时间分配之间的关系,应用基于关系的时间调整方法来保证可行和非保守运动 ( F e a s i b l e ( Feasible Feasible a n d and and n o n − c o n s e r v a t i v e non-conservative nonconservative m o t i o n ) motion) motion

2 相关工作

  1. 非常有代表性的就是硬约束方法,也就是 M i n i m u m Minimum Minimum S n a p Snap Snap方法,其中轨迹表示为分段多项式,并通过求解二次规划 ( Q P ) (QP) (QP) 问题生成。具体方法的推导可以看我的这篇Blog,其中轨迹表示为分段多项式,并通过求解二次规划( Q u a d r a t i c Quadratic Quadratic P r o g r a m m i n g , Programming, Programming, Q P QP QP)问题生成。硬约束方法通过凸形式保证全局最优性。然而,忽略了自由空间中与障碍物的距离,这往往导致轨迹接近障碍物。此外,动力学约束是保守的,使轨迹速度不足,以快速飞行。
  2. 文章(Polynomial Trajectory Planning for Aggressive Quadrotor Flight in Dense Indoor Environments)通过在迭代过程中添加中间路点的办法,来确保轨迹的安全性,然后轨迹生成优化的方法还是 M i n i m u m Minimum Minimum S n a p Snap Snap方法
  3. 接着演化成了由一系列球体,多面体,立方体所形成的自由空间,在这个可行域内进行凸优化,并且提出了一种 B B B样条的动力学搜索来找到初始轨迹,然后通过弹性优化方法进行优化,使用均匀 B B B 样条可确保动态可行性,但会产生保守运动( c o n s e r v a t i v e conservative conservative m o t i o n motion motion)。这些方法的一个共同缺点是轨迹的时间分配是由简单的启发式给出的,然而,选择不当的时间分配会显着降低轨迹的质量。此外,只有通过迭代添加更多约束和求解二次规划问题才能获得可行的解决方案,这对于实时应用来说是不可取的
  4. 为了解决以上时间分配的问题,高老师提出了一种方法来搜索具有良好分配时间的路径(使用快速行进法和伯恩斯坦基多项式的四旋翼在线安全轨迹生成),并通过优化保证轨迹的安全性和动力学可行性。硬约束方法通过凸优化公式确保全局最优性,自由空间中到障碍物的距离被忽略,这往往导致轨迹接近障碍物。此外,动力学约束是保守的,使得轨迹的速度不足,无法快速飞行。
  5. 软约束方法:还有一些方法将轨迹生成公式化为考虑平滑性和安全性的非线性优化问题通过使用梯度下降法最小化其平滑度和碰撞成本来生成离散时间轨迹,但优化是通过无梯度采样方法解决的。 后序方法将它们扩展到连续时间多项式轨迹,由于时间参数化是连续的,避免了数值微分误差并且更准确地表示四旋翼的运动。但是,成功率很低。为了解决这个问题,接着后序方法首先使用基于采样的路径搜索方法(类似RRT*)找到无碰撞的初始路径,该路径作为非线性优化的全局高质量优化的初始猜测,从而提高成功率。后序轨迹被参数化为均匀 B B B 样条。由于 B − S p l i n e B-Spline BSpline 本质上是连续的,因此无需显式地强制执行连续性,从而减少了约束的数量。由于其局部性,它对于局部重新规划也特别有用。软约束方法利用梯度信息将轨迹推离障碍物类似APF方法),但受到局部最小值的影响,并且无法保证成功率和动力学可行性。我们的优化方法还利用梯度信息来提高轨迹的安全性。然而,与以前沿轨迹计算复杂的线积分的方法不同,该公式基于 B B B 样条的凸包特性进行了重新设计,使其更简单,极大地提高了计算效率和收敛速度。
  6. 综上,软约束方法利用梯度信息推动轨迹远离障碍物,但存在局部极小问题,没有很强的成功率和动力学可行性保证。此优化方法还利用梯度信息提高了轨迹的安全性。然而,与以往计算昂贵的沿轨迹线积分的方法不同,基于 B B B样条的凸包特性,将公式设计得更加简单。它大大提高了计算效率和收敛速度。

3 F a s t − P l a n n e r Fast-Planner FastPlanner

3.1 前端路径搜索

  • 前端运动动力学路径搜索模块为混合A*算法。该方法能够在栅格地图当中规划出一条安全的并且是符合动力学约束的一条可行轨迹。具体可以看我的这一篇Blog,如下图所示:

在这里插入图片描述


  • 而且继承了 A ∗ A* A启发式算法的特性
  • 所谓的混合 A S t a r A Star AStar算法就是将 A ∗ A* A L a t t i c e G r a p h Lattice Graph LatticeGraph相关联,什么是 L a t t i c e G r a p h Lattice Graph LatticeGraph呢?
  • 如下所示

在这里插入图片描述


  • 这些弯弯的线,就是上图找到路径的那条轨迹旁的弯弯的线
  • 所以将 A ∗ A* A算法往这上面一套,就是混合 A ∗ A* A
  • 对传统的$ A ∗ A* A算法进行改进,与之不同的是, H y b r i d A ∗ Hybrid A* HybridA 是在连续坐标系下进行启发式搜索,并且能够保证生成的轨迹满足无人机的非完整性约束
  • 但算法运行过程中该路径并不一定是全局最优(这里的全局最优解指的是由传统 A ∗ A* A 算法生成的)的,但是经过试验,几乎为全局“次优”
  • A ∗ A* A 是赋予每个网格的中心点相应的损失并且算法只访问这些中心点,而 H y b r i d A ∗ Hybrid A* HybridA 是先在这些网格中挑选满足UAV的3D连续状态的点,并将损失赋值给这些点
  • 如下,左边那副图,只选择中间点,就是传统的 A ∗ A* A,右边那副图,选择栅格内几乎所有的点,要满足UAV的运动学约束,并且连续状态

在这里插入图片描述


3.2 K i n o d y n a m i c Kinodynamic Kinodynamic P a t h Path Path S e a r c h i n g Searching Searching 伪代码


  • 这个算法不仅仅会考虑节点位置还会考虑其节点的速度和加速度

在这里插入图片描述

  • 在算法流程图当中, P P P C C C指的是开集和并集,与无人机动力学相关的 m o t i o n motion motion p r i m i t i v e s primitives primitives不是直线而是 g r a p h graph graph e d g e edge edge n o d e s nodes nodes被用来记录 p r i m i t i v e primitive primitive,以及 p r i m i t i v e s e n d s primitives ends primitivesends以及 g c g_c gc f c f_c fc成本
  • p r i m i t i v e s primitives primitives通过 E x p a n d ( ) Expand() Expand()进行迭代 v o x e l voxel voxel网格映射,除具有最小 f c f_c fc(最小成本)的 v o x e l voxel voxel外,那些以相同 v o x e l voxel voxel结束的 v o x e l voxel voxel将会被进行剪枝( P r u n e ( ) Prune() Prune())操作
  • 综上,总的步骤就是:
  1. 进行实时采样,离散获得轨迹节点(PVA三条件,轨迹节点,起始点速度,加速度)
  2. 设置算法搜索参数
  3. 将以上条件转为栅格,计算对应的成本
  4. 进行迭代循环
  5. 路径搜索,看当前节点是否到达目标点,没有的话就要进行进行扩张以及剪枝
  6. 规划所得的路径

3.3 Code解读

3.3.1 fast_planner_node

  • 在这个部分,先注册ROS节点,看下方的ros::init(argc, argv, "fast_planner_node");
  • 以及进行类的实例化TopoReplanFSM topo_replan; KinoReplanFSM kino_replan;
#include <ros/ros.h>
#include <visualization_msgs/Marker.h>

#include <plan_manage/kino_replan_fsm.h>
#include <plan_manage/topo_replan_fsm.h>

#include <plan_manage/backward.hpp>
namespace backward {
backward::SignalHandling sh;
}

using namespace fast_planner;

int main(int argc, char** argv) {
  ros::init(argc, argv, "fast_planner_node");
  ros::NodeHandle nh("~");

  int planner;
  nh.param("planner_node/planner", planner, -1);

  TopoReplanFSM topo_replan;
  KinoReplanFSM kino_replan;

  if (planner == 1) {
    kino_replan.init(nh);
  } else if (planner == 2) {
    topo_replan.init(nh);
  }

  ros::Duration(1.0).sleep();
  ros::spin();

  return 0;
}

3.3.2 kino_replan_fsm

  • 从下方这几行代码,可以看出是在订阅无人机的目标点的信息以及位置信息
for (int i = 0; i < waypoint_num_; i++) {
    nh.param("fsm/waypoint" + to_string(i) + "_x", waypoints_[i][0], -1.0);
    nh.param("fsm/waypoint" + to_string(i) + "_y", waypoints_[i][1], -1.0);
    nh.param("fsm/waypoint" + to_string(i) + "_z", waypoints_[i][2], -1.0);
  }
  • 设置了ROS当中的定时器,定时地进行回调
  exec_timer_   = nh.createTimer(ros::Duration(0.01), &KinoReplanFSM::execFSMCallback, this);
  safety_timer_ = nh.createTimer(ros::Duration(0.05), &KinoReplanFSM::checkCollisionCallback, this);
  • 利用下方定义的 e x e c s t a t e exec_state execstate判断是否等待目标点,看是否需要进行重新规划
  if (exec_state_ == WAIT_TARGET)
    changeFSMExecState(GEN_NEW_TRAJ, "TRIG");
  else if (exec_state_ == EXEC_TRAJ)
    changeFSMExecState(REPLAN_TRAJ, "TRIG");

3.3 成本函数

  • 实际成本与启发式成本,由于目标是找到一条在时间和控制成本上最优的轨迹,将轨迹的成本定义为:
    J ( T ) = ∫ 0 T ∥ u ( t ) ∥ 2 d t + ρ T \mathcal{J}(T)=\int_0^T\|\mathbf{u}(t)\|^2 d t+\rho T J(T)=0Tu(t)2dt+ρT
  • 在成本函数当中,
  • 通过最小值原理计算出一个封闭形式的轨迹,该轨迹最小化从当前状态 x c x_c xc到目标状态 x g x_g xg J ( T ) \mathcal{J}(T) J(T),也就是当前状态到终点的成本
  • 为了找到最小化的成本最佳时间 T T T,采用如下方法:
  1. 因为轨迹可以进行多项式的表示,将多项式表示写成矩阵的形式
    p ( t ) : = [ p x ( t ) , p y ( t ) , p z ( t ) ] ⊤ , p μ ( t ) = ∑ k = 0 K a k t k \mathbf{p}(t):=\left[p_x(t), p_y(t), p_z(t)\right]^{\top}, \quad p_\mu(t)=\sum_{k=0}^K a_k t^k p(t):=[px(t),py(t),pz(t)],pμ(t)=k=0Kaktk
    p μ ∗ ( t ) = 1 6 α μ t 3 + 1 2 β μ t 2 + v μ c + p μ c [ α μ β μ ] = 1 T 3 [ − 12 6 T 6 T − 2 T 2 ] [ p μ g − p μ c − v μ c T v μ g − v μ c ] J ∗ ( T ) = ∑ μ ∈ { x , y , z } ( 1 3 α μ 2 T 3 + α μ β μ T 2 + β μ 2 T ) \begin{aligned} p_\mu^*(t) &=\frac{1}{6} \alpha_\mu t^3+\frac{1}{2} \beta_\mu t^2+v_{\mu c}+p_{\mu c} \\ {\left[\begin{array}{c} \alpha_\mu \\ \beta_\mu \end{array}\right] } &=\frac{1}{T^3}\left[\begin{array}{cc} -12 & 6 T \\ 6 T & -2 T^2 \end{array}\right]\left[\begin{array}{c} p_{\mu g}-p_{\mu c}-v_{\mu c} T \\ v_{\mu g}-v_{\mu c} \end{array}\right] \\ \mathcal{J}^*(T) &=\sum_{\mu \in\{x, y, z\}}\left(\frac{1}{3} \alpha_\mu^2 T^3+\alpha_\mu \beta_\mu T^2+\beta_\mu^2 T\right) \end{aligned} pμ(t)[αμβμ]J(T)=61αμt3+21βμt2+vμc+pμc=T31[126T6T2T2][pμgpμcvμcTvμgvμc]=μ{x,y,z}(31αμ2T3+αμβμT2+βμ2T)
  2. 其中 p μ c , v μ c , p μ g , v μ g p_{\mu c}, v_{\mu c}, p_{\mu g}, v_{\mu g} pμc,vμc,pμg,vμg 是当前和目标的位置以及速度, μ ∈ { x , y , z } \mu \in\{x, y, z\} μ{x,y,z} J ∗ ( T ) \mathcal{J}^*(T) J(T)是成本函数。为了找到最小化成本的最佳时间 T T T,将 α μ , β μ \alpha_\mu, \beta_\mu αμ,βμ 代入 J ∗ ( T ) \mathcal{J}^*(T) J(T) 并找到 ∂ J ∗ ( T ) ∂ T = 0 \frac{\partial \mathcal{J}^*(T)}{\partial T}=0 TJ(T)=0 的根。最小成本 min ⁡ J ∗ \min \mathcal{J}^* minJ 和可行轨迹的根是选择并表示为 T h T_h Th。我们使用 J ∗ ( T h ) \mathcal{J}^*\left(T_h\right) J(Th) 作为启发式 h c h_c hc。最后, f c f_c fc 定义为:
    f c = g c + h c = g c + J ∗ ( T h ) f_c=g_c+h_c=g_c+\mathcal{J}^*\left(T_h\right) fc=gc+hc=gc+J(Th)

3.4 B-Spline轨迹优化

  • 路径搜索产生的路径可能是次优的(这是因为混合A*所得到的路径并非是最优的路径)。此外,由于自由空间中的距离信息被忽略,这条路径通常靠近障碍物,如下图所示。因此,在建议的 B B B 样条优化中提高了路径的平滑度和间隙。利用均匀 B B B 样条的凸包特性,将来自欧几里得距离场的梯度信息和动态约束结合起来,使其在很短的时间内收敛,从而生成平滑、安全和动态可行的轨迹

在这里插入图片描述

使用基于梯度的数值优化来变形轨迹。红色和绿色曲线是初始路径和优化后的 B B B 样条。黄点代表 B B B 样条的控制点。由于忽略了距离信息,初始路径靠近障碍物,而 B B B 样条被基于梯度的优化推开。

3.4.1 均匀的B样条

  • B B B样条是一个分段多项式,由其次数 p b p_b pb、一组 N + 1 N+1 N+1 个控制点 { Q 0 , Q 1 , ⋯   , Q N } \left\{\mathbf{Q}_0, \mathbf{Q}_1, \cdots, \mathbf{Q}_N\right\} {Q0,Q1,,QN}和一个节点向量 [ t 0 , t 1 , ⋯   , t M ] \left[t_0, t_1, \cdots, t_M\right] [t0,t1,,tM]唯一确定,其中 Q i ∈ R 3 , t m ∈ R \mathrm{Q}_i \in \mathbb{R}^3, t_m \in \mathbb{R} QiR3,tmR M = N + p b + 1 M=N+p_b+1 M=N+pb+1 B B B 样条轨迹由时间 t t t 参数化,其中 t ∈ [ t p b , t M − p b ] t \in\left[t_{p_b}, t_{M-p_b}\right] t[tpb,tMpb]。对于均匀的 B B B 样条,每个节点跨度 Δ t m = t m + 1 − t m \Delta t_m=t_{m+1}-t_m Δtm=tm+1tm 具有相同的值 Δ t \Delta t Δt。为了评估 时间 t ∈ [ t m , t m + 1 ) ⊂ [ t p b , t M − p b ] t \in\left[t_m, t_{m+1}\right) \subset\left[t_{p_b}, t_{M-p_b}\right] t[tm,tm+1)[tpb,tMpb] 处的位置,我们首先对 t t t进行归一化, s ( t ) = ( t − t m ) / Δ t s(t)=\left(t-t_m\right) / \Delta t s(t)=(ttm)t,然后可以使用矩阵表示评估位置:
    p ( s ( t ) ) = s ( t ) ⊤ M p b + 1 q m s ( t ) = [ 1 s ( t ) s 2 ( t ) ⋯ s p b ( t ) ] ⊤ q m = [ Q m − p b Q m − p b + 1 Q m − p b + 2 ⋯ Q m ] ⊤ \begin{aligned} &\mathbf{p}(s(t))=\mathbf{s}(t)^{\top} \mathbf{M}_{p_b+1} \mathbf{q}_m \\ &\mathbf{s}(t)=\left[\begin{array}{lllll} 1 & s(t) & s^2(t) & \cdots & s^{p_b}(t) \end{array}\right]^{\top} \\ &\mathbf{q}_m=\left[\begin{array}{lllll} \mathbf{Q}_{m-p_b} & \mathbf{Q}_{m-p_b+1} & \mathbf{Q}_{m-p_b+2} & \cdots & \mathbf{Q}_m \end{array}\right]^{\top} \end{aligned} p(s(t))=s(t)Mpb+1qms(t)=[1s(t)s2(t)spb(t)]qm=[QmpbQmpb+1Qmpb+2Qm]

  • 这里 M p b + 1 \mathbf{M}_{p_b+1} Mpb+1 是由 p b p_b pb 确定的常数矩阵。在我们的实现中, p b p_b pb 设置为 3 3 3。导数的评估完全相同,因为 B B B 样条的导数也是 B B B 样条。 B B B 样条的凸包特性对于设计优化公式至关重要,对于确保整个轨迹的动态可行性和安全性非常有用。

3.4.2 凸包特性

  • B样条的凸包特性就不过多介绍了,曲线总是被包含在一个凸包之中

4 时间调整

尽管在路径搜索和优化中限制了动力学可行性,但有时会得到不可行的轨迹。基本原因是梯度信息倾向于拉长整体轨迹,同时将其推离障碍物较远。因此,四旋翼飞行器必须更积极地飞行,以便在同一时间内行进更长的距离,如果原始运动已经接近物理极限,这不可避免地会导致过度激进的运动。
为了保证动态可行性,采用基于导数控制点与非均匀B样条的时间分配(节点跨度)之间的关系的时间调整方法。由于这些关系,可以通过调整相关的时间分配来改变预期的飞行轨迹攻击性(aggressiveness),因此可以在没有过度保守约束的情况下确保动态可行性。

4.1 迭代时间调整伪代码


在这里插入图片描述


5 总结

利用 B B B样条的凸包特性,结合欧几里得距离场的梯度信息和动态约束,采用 B B B样条优化算法提高了轨迹的光滑性和间隙。最后,通过将最终轨迹表示为非均匀 B B B样条,采用迭代时间调整方法保证轨迹的动态可行性和非保守性。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Fast Planner 轨迹规划 的相关文章

随机推荐

  • ovn 通过网关虚拟路由器连接外部网络

    本文实验如何通过ovn的网关逻辑路由器将ovn网络连接到外部网络 前面讲过ovn的逻辑路由器是分布式的 xff0c 这意味着它没有绑定到某个节点上 xff0c 而是存在于所有节点上的 xff0c 同时它是通过每个节点的openflow流表来
  • 嵌入式FreeRTOS学习十一,深入理解任务调度机制

    一 任务调度机制 可抢占 xff1a 高优先级的任务先运行时间片轮转 xff1a 同优先级的任务轮流执行空闲任务礼让 xff1a 如果有同是优先级为0的其他就绪任务 xff0c 空闲任务主动放弃一次运行机会函数调用vTaskDelay xD
  • SOAP传输协议

    一 HTTP传输协议 超文本传输协议 xff08 HyperText Transfer Protocol xff0c 缩写 xff1a HTTP xff09 xff0c 它是基于请求 响应的模式协议 xff0c 客户端发出请求 xff0c
  • ONVIF简介

    一 什么是ONVIF ONVIF规范描述了网络视频的模型 接口 数据类型以及数据交互的模式 并复用了一些现有的标准 xff0c 如WS系列标准等 ONVIF规范的目标是实现一个网络视频框架协议 xff0c 使不同厂商所生产的网络视频产品 x
  • gsoap工具生成onvif设备搜索(remotediscovery)代码框架

    什么是gsoap工具 xff1f gSOAP 提供了两个工具来方便开发人员使用 C C 43 43 语言快速开发Web 服务应用 xff0c 通过 gSOAP 提供的这两个工具 xff0c 开发人员可以快速生成服务端与客户端代码框架 xff
  • 001_初识_飞航科技光标飞控

    这两天老潘给我一块飞控 xff0c 让我练手 xff0c 为电赛做准备 xff0c 拿到控挺开心的 xff0c 毕竟省了一笔RMB 本来想着买块正点原子的飞控 资料 xff1a 说起资料简单看了一下发现还蛮全的 xff0c 但是这个资料我居
  • 写出C语言的第一个程序“Hello World”

    这里写自定义目录标题 写出C语言的第一个程序 Hello World 写出C语言的第一个程序 Hello World 下面展示一些 内联代码片 span class token comment A code block span span
  • Eigen库的安装攻略

    Eigen库的安装攻略 转载 xff1a Eigen库安装 xff08 两种方式 xff09 转载 xff1a Eigen库安装 xff08 两种方式 xff09 链接 link
  • 【ROS2基础学习】

    入门篇 前言一 创建一个功能包二 编译三 source总结 前言 提示 xff1a 这里是记录的大概内容 xff1a 随着机器人技术的不断发展 xff0c ROS也越来越重要 xff0c 很多人都开启了学习ROS xff0c 本文就介绍了R
  • Arduino 外部中断重置内部定时器

    Arduino 外部中断重置内部定时器 文章目录 Arduino 外部中断重置内部定时器前言一 准备工作二 代码三 实验效果1 设置1Hz的方波 xff08 外部中断触发 xff09 xff1a 2 观察示波器各个波形 xff1a 3 延迟
  • ALUBI LPMS-IG1 RS232 IMU ROS2驱动安装

    文章目录 前言一 下载官方系列文档二 windows上的上位机程序安装2 Ubuntu上的ROS2驱动安装Offset Mode 2 总结 前言 IMU在自动驾驶领域广泛应用 xff0c 本文主要记录了在ROS2中使用ALUBI LPMS
  • ovn-northd 源码分析

    ovn northd是ovn中的核心后台进程 xff0c 主要负责将ovn的高层配置转换成供ovn controller后台进程使用的逻辑配置 xff0c 更详细的说就是它将ovn northbound数据库中传统意义上的逻辑网络配置转换成
  • 镭神CH128x1系列激光雷达使用记录

    镭神CH128x1系列激光雷达使用记录 文章目录 镭神CH128x1系列激光雷达使用记录前言一 操作步骤1 PC连接雷达 二 实验1 雷达控制器上的接口 xff1a 2 接口定义3 Rviz中显示效果 总结致谢 前言 本条博客的需求来源于自
  • c语言中char数组的结束位

    因为是半路出家学习cpp的 xff0c 所以经常会对c语言里面的字符数组感到困惑 xff0c 这次一次性做个总结 首先 xff0c 结束位 0 只针对字符数组 xff0c 不针对整型或者其他数组 其次 xff0c 字符数组的大小只针对里面的
  • SUMO 使用netconvert报错解决办法

    SUMO 使用netconvert报错 问题描述正确解决方法不适用的解决方法 问题描述 刚开始学习使用sumo xff0c 版本是sumo1 8 0 第一次使用netconvert转换地图时出现报错 xff0c 提示没有PROJ Libra
  • IoTDB基础 初识IoTDB 安装及基本使用(个人学习记录)

    官方文档 http iotdb incubator apache org zh UserGuide V0 13 x API Programming Java Native API html 参考博客 时序数据库IoTDB安装及基本使用htt
  • 树莓派+ L298N 控制二相四线步进电机

    树莓派 43 L298N 控制二相四线步进电机 1 步进电机 步进电机是一种将电脉冲信号转换成相应角位移或线位移的电动机 在非超载的情况下 xff0c 电机的转速 停止的位置只取决于脉冲信号的频率和脉冲数 xff0c 而不受负载变化的影响
  • VTK移动立方体法处理CT图像建立三维模型

    span class token comment 移动立方体 span span class token macro property span class token directive keyword include span span
  • 使用tcp工具调试socket服务端通信

    背景介绍 xff1a 客户端是用tcp连接调试 xff0c 工具链接 https pan baidu com s 1kfjv1jdS8KJgb7YVSu9Wtw 提取码 z34a 服务端是Java代码写的逻辑 xff0c 用byte 流接收
  • Fast Planner 轨迹规划

    文章目录 0 概览1 关键问题2 相关工作3 F a s t P