IMU 积分进行航迹推算

news2024/11/28 0:33:22

IMU 积分进行航迹推算

Reference https://github.com/gaoxiang12/slam_in_autonomous_driving

1.0 递推方程推导

\quad 连续时间内的 IMU 运动学方程:
R ˙ = R ω ∧ q = 1 2 q ω ˙ p ˙ = v v ˙ = a \dot{\mathbf{R}}=\mathbf{R}\omega ^{\wedge} \\ \dot{\mathbf{q}=\frac{1}{2}\mathbf{q}\omega}\\ \dot{\mathbf{p}}=v \\ \dot{\mathbf{v}}=a R˙=Rωq=21qω˙p˙=vv˙=a
\quad 这些物理量带上角标之后应该写作 R w b , p w b \mathbf{R_{wb},p_{wb}} Rwb,pwb,对应世界坐标系,它在求导之后就是车辆在世界坐标系下的速度与加速度 v w , a w \mathbf{v_w}, \mathbf{a_w} vw,aw 。在不考虑地球自传的时候,也可以简单的将 车辆行驶的打的视为固定的世界坐标系,这时 IMU 的测量值 ω ~ , a ~ \widetilde{\omega } ,\widetilde{a} ω ,a 就是车辆本身的角速度,以及车体系下的加速度:
a ~ = R ⊤ a , ω ~ = ω . \begin{aligned} \tilde{\boldsymbol{a}} & =\boldsymbol{R}^{\top} \boldsymbol{a}, \\ \tilde{\boldsymbol{\omega}} & =\boldsymbol{\omega} . \end{aligned} a~ω~=Ra,=ω.
\quad 注意 R ⊤ \mathbf{R}^{\top} R 带下标之后就是 R b w \mathbf{R_{bw}} Rbw。它将世界系下的物理量转换到车体系。然而,实际的车辆、机器人都在地球表面运行。这些系统受到重力的影响,所以我们应该把重 力写在系统方程中。在绝大多数 IMU 系统中,我们可以忽略地球自转的干扰,从而把 IMU 测量 值写为:
a ~ = R ⊤ ( a − g ) , ω ~ = ω . \begin{aligned} \tilde{\boldsymbol{a}} & =\boldsymbol{R}^{\top} \boldsymbol{(a-g)}, \\ \tilde{\boldsymbol{\omega}} & =\boldsymbol{\omega} . \end{aligned} a~ω~=R(ag),=ω.
\quad g \mathbf{g} g 为地球的重力。当然,如果在无重力环境下测量物体加速度,就不会出现重力项。注意这里 g \mathbf{g} g的符号和坐标系定义相关。我们的车体系和世界系都是 Z Z Z 轴向上,于是 g \mathbf{g} g 通常取 值 ( 0 , 0 , − 9.8 ) ⊤ (0, 0, −9.8)^⊤ (0,0,9.8)。假设有一个水平放置的IMU,其读数此时应当为 ( 0 , 0 , 9.8 ) ⊤ (0, 0, 9.8)^⊤ (0,0,9.8),为什么呢?因为此时真正的加速度应该为 ( 0 , 0 , 0 ) ⊤ (0, 0, 0)^⊤ (0,0,0),但是由于地球重力的影响,其输出结果会减去 g \mathbf{g} g ,所以输出结果就是 ( 0 , 0 , 9.8 ) ⊤ (0, 0, 9.8)^⊤ (0,0,9.8)

\quad 在大多数系统中,我们认为 IMU 的噪声由两部分组成:测量噪声(measurement noise)与零偏(bias)。记陀螺仪和加速度计的测量噪声分别为 η g η_g ηg, η a η_a ηa,同时记零偏为 b g b_g bg, b a b_a ba,下标 g g g 表示陀螺仪, a a a 表示加速度计。那么这几个参数在测量方程中体现为:
a ~ = R ⊤ ( a − g ) + b a + η a ω ~ = ω + b g + η g . \begin{aligned} \tilde{\boldsymbol{a}} & =\boldsymbol{R}^{\top}(\boldsymbol{a}-\boldsymbol{g})+\boldsymbol{b}_{a}+\boldsymbol{\eta}_{a} \\ \tilde{\boldsymbol{\omega}} & =\boldsymbol{\omega}+\boldsymbol{b}_{g}+\boldsymbol{\eta}_{g} . \end{aligned} a~ω~=R(ag)+ba+ηa=ω+bg+ηg.
\quad 于是,我们直接把测量模型代入运动学方程,忽略测量噪声影响,即可得到连续时间下的积分 模型:
R ˙ = R ( ω ~ − b g ) ∧ ,  或  q ˙ = q [ 0 , 1 2 ( ω ~ − b g ) ] , p ˙ = v , v ˙ = R ( a ~ − b a ) + g . \begin{aligned} \dot{\boldsymbol{R}} & =\boldsymbol{R}\left(\tilde{\boldsymbol{\omega}}-\boldsymbol{b}_{g}\right)^{\wedge}, \quad \text { 或 } \dot{\boldsymbol{q}}=\boldsymbol{q}\left[0, \frac{1}{2}\left(\tilde{\boldsymbol{\omega}}-\boldsymbol{b}_{g}\right)\right], \\ \dot{\boldsymbol{p}} & =\boldsymbol{v}, \\ \dot{\boldsymbol{v}} & =\boldsymbol{R}\left(\tilde{\boldsymbol{a}}-\boldsymbol{b}_{a}\right)+\boldsymbol{g} . \end{aligned} R˙p˙v˙=R(ω~bg),  q˙=q[0,21(ω~bg)],=v,=R(a~ba)+g.
\quad 有时候我们也把 p , v , q p, v, q p,v,q 称为 P V Q PVQ PVQ 状态。该方程可以从时间 t t t积分至 t + ∆ t t + ∆t t+t,推出下一个时刻的状态情况:
R ( t + Δ t ) = R ( t ) Exp ⁡ ( ( ω ~ − b g ) Δ t ) ,  或  q ( t + Δ t ) = q ( t ) [ 1 , 1 2 ( ω ~ − b g ) Δ t ] , \begin{aligned} \boldsymbol{R}(t+\Delta t) & =\boldsymbol{R}(t) \operatorname{Exp}\left(\left(\tilde{\boldsymbol{\omega}}-\boldsymbol{b}_{g}\right) \Delta t\right), \quad \text { 或 } \boldsymbol{q}(t+\Delta t)=\boldsymbol{q}(t)\left[1, \frac{1}{2}\left(\tilde{\boldsymbol{\omega}}-\boldsymbol{b}_{g}\right) \Delta t\right], \\ \end{aligned} R(t+Δt)=R(t)Exp((ω~bg)Δt),  q(t+Δt)=q(t)[1,21(ω~bg)Δt],
\quad 这里我们先不考虑白噪声 η a \boldsymbol{\eta}_{a} ηa,则IMU的测量方程有:
a ~ = R ⊤ ( a − g ) + b a + η a a ~ − b a = R ⊤ ( a − g ) R ( a ~ − b a ) = a − g a = R ( a ~ − b a ) + g \begin{aligned} \tilde{\boldsymbol{a}} &=\boldsymbol{R}^{\top}(\boldsymbol{a}-\boldsymbol{g})+\boldsymbol{b}_{a}+\boldsymbol{\eta}_{a}\\ \tilde{\boldsymbol{a}} -\boldsymbol{b}_{a}&=\boldsymbol{R}^{\top}(\boldsymbol{a}-\boldsymbol{g}) \\ \boldsymbol{R}(\tilde{\boldsymbol{a}} -\boldsymbol{b}_{a})&=\boldsymbol{a}-\boldsymbol{g}\\ \boldsymbol{a}&=\boldsymbol{R}(\tilde{\boldsymbol{a}} -\boldsymbol{b}_{a}) + \boldsymbol{g} \end{aligned} a~a~baR(a~ba)a=R(ag)+ba+ηa=R(ag)=ag=R(a~ba)+g
\quad 速度的递推,我们知道 v ( t + Δ t ) = v ( t ) + a t \boldsymbol{v}(t+\Delta t) = \boldsymbol{v}(t) + \mathbf{a}t v(t+Δt)=v(t)+at
v ( t + Δ t ) = v ( t ) + a Δ t = v ( t ) + ( R ( t ) ( a ~ − b a ) + g ) Δ t = v ( t ) + R ( t ) ( a ~ − b a ) Δ t + g Δ t . \begin{aligned} \boldsymbol{v}(t+\Delta t) & =\boldsymbol{v}(t)+ \mathbf{a}\Delta t \\ & =\boldsymbol{v}(t)+ \left( \boldsymbol{R}(t)\left(\tilde{\boldsymbol{a}}-\boldsymbol{b}_{a}\right) +\boldsymbol{g} \right)\Delta t \\ &=\boldsymbol{v}(t)+\boldsymbol{R}(t)\left(\tilde{\boldsymbol{a}}-\boldsymbol{b}_{a}\right) \Delta t+\boldsymbol{g} \Delta t . \end{aligned} v(t+Δt)=v(t)+aΔt=v(t)+(R(t)(a~ba)+g)Δt=v(t)+R(t)(a~ba)Δt+gΔt.
\quad 位置的递推,我们知道 p ( t + Δ t ) = p ( t ) + v Δ t + 1 2 a t 2 \boldsymbol{p}(t+\Delta t) =\boldsymbol{p}(t)+\mathbf{v}\Delta t + \frac{1}{2}\mathbf{at^2} p(t+Δt)=p(t)+vΔt+21at2,则有:
p ( t + Δ t ) = p ( t ) + v Δ t + 1 2 a t 2 = p ( t ) + v Δ t + 1 2 ( R ( t ) ( a ~ − b a ) + g ) t 2 = p ( t ) + v Δ t + 1 2 ( R ( t ) ( a ~ − b a ) ) Δ t 2 + 1 2 g Δ t 2 \begin{aligned} \boldsymbol{p}(t+\Delta t) & =\boldsymbol{p}(t)+\boldsymbol{v} \Delta t+\frac{1}{2} \mathbf{a}t^2\\ & =\boldsymbol{p}(t)+\boldsymbol{v} \Delta t+\frac{1}{2} \left(\boldsymbol{R(t)}(\tilde{\boldsymbol{a}} -\boldsymbol{b}_{a}) + \boldsymbol{g} \right)t^2\\ & =\boldsymbol{p}(t)+\boldsymbol{v} \Delta t+\frac{1}{2}\left(\boldsymbol{R}(t)\left(\tilde{\boldsymbol{a}}-\boldsymbol{b}_{a}\right)\right) \Delta t^{2}+\frac{1}{2} \boldsymbol{g} \Delta t^{2}\\ \end{aligned} p(t+Δt)=p(t)+vΔt+21at2=p(t)+vΔt+21(R(t)(a~ba)+g)t2=p(t)+vΔt+21(R(t)(a~ba))Δt2+21gΔt2

2.0 代码实现

2.1 数据集介绍

这里使用的高博书中带的数据集,数据集的格式为:

# timestamp gx gy gz ax ay az

2.2 具体代码实现

代码实现主要有三个文件

  • common.hpp 主要用户存放 IMU 数据结构体和读取和保存数据。
  • imu_integration.hpp 主要存放 IMU数据的处理和航迹推算实现类。
  • run_imu_integration.cpp 程序入口函数。

如下命令运行

./run_imu_integration --txt_file_path="../slam_in_auto_driving/chapter3/dataset/10.txt" --output_inter_trajectory_path="./output_trajectory.txt" 
  • common.hpp
#ifndef COMMON_HPP
#define COMMON_HPP

#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Dense>
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>

struct IMUMsg
{
  IMUMsg() = default;
  IMUMsg(double timestamp, Eigen::Vector3d gyro, Eigen::Vector3d acc)
      : timestamp_(timestamp), acc_(acc), gyro_(gyro){};

  double timestamp_{0.0};
  Eigen::Vector3d acc_;
  Eigen::Vector3d gyro_;
};

struct IMUIntegrationResult
{
  IMUIntegrationResult() = default;
  IMUIntegrationResult(const double &timestamp, const Eigen::Vector3d &P,
                       const Eigen::Quaterniond &Q, const Eigen::Vector3d &V)
      : timestamp_(timestamp), P_(P), V_(V), Q_(Q){};

  double timestamp_{0.0};
  Eigen::Vector3d P_;
  Eigen::Vector3d V_;
  Eigen::Quaterniond Q_;
};

inline void ReadImuMsg(std::ifstream &fin, std::vector<IMUMsg> &imu_msg)
{
  if (!fin)
  {
    std::cerr << "Coule not find file\n";
    return;
  }
  while (!fin.eof())
  {
    std::string line;
    std::getline(fin, line);
    if (line.empty())
    {
      continue;
    }

    if (line[0] == '#')
    {
      continue;
    }

    std::stringstream ss;
    ss << line;
    std::string data_type;
    ss >> data_type;
    if (data_type == "IMU")
    {
      double time, gx, gy, gz, ax, ay, az;
      ss >> time >> gx >> gy >> gz >> ax >> ay >> az;
      imu_msg.push_back(IMUMsg(time, Eigen::Vector3d(gx, gy, gz),
                               Eigen::Vector3d(ax, ay, az)));
    }
  }
  std::cout << "Read IMU msgs success\n";
}

inline void SaveImuIntegrationResult(
    const std::string &file_path,
    const std::vector<IMUIntegrationResult> &imu_inte_result)
{
  std::ofstream fout(file_path);
  for (const auto &imu_traj : imu_inte_result)
  {
    fout << std::setprecision(18) << imu_traj.timestamp_ << " " << std::setprecision(9);
    fout << imu_traj.P_(0) << " " << imu_traj.P_(1) << " " << imu_traj.P_(2) << " ";
    fout << imu_traj.Q_.w() << " " << imu_traj.Q_.x() << " " << imu_traj.Q_.y() << " " << imu_traj.Q_.z() << " ";
    fout << imu_traj.V_(0) << " " << imu_traj.V_(1) << " " << imu_traj.V_(2) << " ";
    fout << std::endl;
  }
}

#endif  // COMMON_HPP
  • imu_integration.hpp
#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Dense>
#include <sophus/so3.hpp>

#include "common.hpp"

class ImuIntegration
{
 public:
  ImuIntegration() = default;
  ~ImuIntegration() = default;
  ImuIntegration(const Eigen::Vector3d &gravity, const Eigen::Vector3d &init_bg,
                 const Eigen::Vector3d &init_ba)
      : gravity_(gravity), init_ba_(init_ba), init_bg_(init_bg)
  {
  }

  void AddNewImgMessage(const IMUMsg &imu_msg)
  {
    // Final P: -3.38794e+06  5.73752e+06  -512933
    // 其实第一帧 IMU 数据也可以不判断,因为后面有 dt<0.1 的判断
    if (first_imu_)
    {
      first_imu_ = false;
      timestamp_ = imu_msg.timestamp_;
    }

    double dt = imu_msg.timestamp_ - timestamp_;

    if (dt > 0 && dt < 0.1)
    {
      P_ = P_ + V_ * dt + 0.5 * (R_ * (imu_msg.acc_ - init_ba_)) * dt * dt +
           0.5 * gravity_ * dt * dt;
      V_ = V_ + R_ * (imu_msg.acc_ - init_ba_) * dt + gravity_ * dt;
      R_ = R_ * Sophus::SO3d::exp((imu_msg.gyro_ - init_bg_) * dt);
    }

    timestamp_ = imu_msg.timestamp_;
  }

  Eigen::Vector3d GetPosition() const { return P_; }
  Eigen::Vector3d GetVelocity() const { return V_; }
  Eigen::Quaterniond GetRotation() const { return R_.unit_quaternion(); }

 private:
  Sophus::SO3d R_;
  Eigen::Quaterniond R_quaternion_ = Eigen::Quaterniond::UnitRandom();
  Eigen::Vector3d P_ = Eigen::Vector3d::Zero();
  Eigen::Vector3d V_ = Eigen::Vector3d::Zero();
  Eigen::Vector3d gravity_ = Eigen::Vector3d(0, 0, -9.81);
  Eigen::Vector3d init_ba_ = Eigen::Vector3d::Zero();
  Eigen::Vector3d init_bg_ = Eigen::Vector3d::Zero();
  double timestamp_{0.0};
  bool first_imu_{true};
};
  • run_imu_integration.cpp
#include <gflags/gflags.h>

#include <eigen3/Eigen/Core>
#include <eigen3/Eigen/Dense>
#include <iostream>
#include <ostream>

#include "common.hpp"
#include "imu_integration.hpp"

DEFINE_string(txt_file_path, "../slam_in_auto_driving/chapter3/dataset/10.txt",
              "Imu integration file");
DEFINE_string(output_inter_trajectory_path, "./output_trajectory.txt",
              "output trajectory file");

int main(int argc, char *argv[])
{
  google::ParseCommandLineFlags(&argc, &argv, true);
  std::ifstream fin(FLAGS_txt_file_path);
  std::vector<IMUMsg> imu_msgs;
  std::vector<IMUIntegrationResult> imu_inter_result;
  ReadImuMsg(fin, imu_msgs);

  // 该实验中,我们假设零偏已知
  Eigen::Vector3d gravity(0, 0, -9.8);  // 重力方向
  Eigen::Vector3d init_bg(00.000224886, -7.61038e-05, -0.000742259);
  Eigen::Vector3d init_ba(-0.165205, 0.0926887, 0.0058049);

  ImuIntegration imu_integration(gravity, init_bg, init_ba);

  for (auto &imu_msg : imu_msgs)
  {
    imu_integration.AddNewImgMessage(imu_msg);
    imu_inter_result.push_back(IMUIntegrationResult(
        imu_msg.timestamp_, imu_integration.GetPosition(),
        imu_integration.GetRotation(), imu_integration.GetVelocity()));
  }

  SaveImuIntegrationResult(FLAGS_output_inter_trajectory_path,
                           imu_inter_result);
  // 高博书中程序输出的结果
  // T: 1624429630.2702086
  // P : -3387943.36 5737523.81 -512933.307
  // Q : 0.982857044 -0.132676506 0.0940114453 0.0868954789
  // V : -572.166705 4626.10758 -496.605214
  std::cout << "Final P: " << imu_integration.GetPosition().transpose()
            << std::endl;
  std::cout << "Final V: " << imu_integration.GetVelocity().transpose()
            << std::endl;
  std::cout << "Final Q: " << imu_integration.GetRotation().coeffs().transpose()
            << std::endl;

  return 0;
}

输出结果可视化:

image

可视化程序,运行:

python3 draw_imu_integration.py ./output_trajectory.txt 
# coding=UTF-8
import sys
import numpy as np
import matplotlib.pyplot as plt

if __name__ == "__main__":
    if len(sys.argv) != 2:
        print('Please input valid file')
        exit(1)
    else:
        path = sys.argv[1]
        path_data = np.loadtxt(path)
        plt.rcParams['figure.figsize'] = (16.0, 12.0)
        
        # 轨迹
        plt.subplot(121)
        plt.scatter(path_data[:, 1], path_data[:, 2], s=2)
        plt.xlabel('X')
        plt.ylabel('Y')
        plt.grid()
        plt.title('2D trajectory')
        
        # 姿态
        plt.subplot(222)
        plt.plot(path_data[:, 0], path_data[:, 4], 'r')
        plt.plot(path_data[:, 0], path_data[:, 5], 'g')
        plt.plot(path_data[:, 0], path_data[:, 6], 'b')
        plt.plot(path_data[:, 0], path_data[:, 7], 'k')
        plt.title('q')
        plt.legend(['qx', 'qy', 'qz', 'qw'])

        # 速度
        plt.subplot(224)
        plt.plot(path_data[:, 0], path_data[:, 8], 'r')
        plt.plot(path_data[:, 0], path_data[:, 9], 'g')
        plt.plot(path_data[:, 0], path_data[:, 10], 'b')
        plt.title('v')
        plt.legend(['vx', 'vy', 'vz'])

        plt.show()
        exit(1)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/551055.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[CTF/网络安全] 攻防世界 weak_auth 解题详析

[CTF/网络安全] 攻防世界 weak_auth 解题详析 弱认证弱认证绕过方法姿势Burp Suite 爆破 总结 题目描述&#xff1a;小宁写了一个登陆验证页面&#xff0c;随手就设了一个密码。 弱认证 weak_auth翻译&#xff1a;弱认证 这个术语通常用来描述一种较弱的安全认证方法或机制&am…

HTML语法、常用标签、表单,CSS选择器。简单登录页面的实现

HTML和CSS粗略介绍 文章目录 HTML和CSS粗略介绍HTML页面第一个HTML页面添加图片和视频 HTML语法规范div标签span标签转义字符 HTML常用标签换行和分割线标题超链接列表元素表格 HTML表单输入框和按钮多行文本 CSS样式CSS选择器input标签选择器id选择器类选择器 组合选择器和优先…

【HackTheBox Bagel】打靶记录

一、namp扫描到5000 8000 22 端口 二、访问8000端口&#xff0c;看到跳转到域名bagel.htb&#xff0c;加入到hosts 看到该url 像文件包含&#xff0c;尝试fuzz一波 尝试找公私钥均未果&#xff0c;找到了cmdline 进一步对其包含 HTTP/1.1 200 OK Server: Werkzeug/2.2.2 …

Java多线程异常处理

文章目录 一. 线程中出现异常的处理1. 线程出现异常的默认行为2. setUncaoughtExceptionHandler()方法处理异常3. setDefaultUncaoughtExceptionHandler()方法进行异常处理 二. 线程组内出现异常 一. 线程中出现异常的处理 1. 线程出现异常的默认行为 当单线程中初出现异常时…

工业缺陷检测数据及代码(附代码)

介绍 目前,基于机器视觉的表面缺陷检测设备已广泛取代人工视觉检测,在包括3C、汽车、家电、机械制造、半导体与电子、化工、制药、航空航天、轻工等多个行业领域得到应用。传统的基于机器视觉的表面缺陷检测方法通常采用常规图像处理算法或人工设计的特征加分类器。一般而言…

【Tomcat下载及使用说明】

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1.什么是Tomcat 2.Tomcat下载流程及注意问题 …

Eclipse将代码收缩if/for/try,支持自定义区域收缩

Hi, I’m Shendi Eclipse将代码收缩if/for/try&#xff0c;支持自定义区域收缩 最近忙于给网站增加功能&#xff0c;在使用 Eclipse 编写 Java 代码时发现一个函数内代码过多&#xff0c;并且 if&#xff0c;for&#xff0c;try这种代码块无法收缩&#xff08;在IDEA&#xff0…

【快速入门-简单实现】使用Java实现的单播、组播和广播

说明 TCP是一个面向连接的协议&#xff0c;TCP一定是点对点的,一点是两个主机来建立连接的&#xff0c;基于TCP实现的肯定是单播(但单播还可以使用UDP协议实现)。只有UDP才会使用广播和组播。 Java中的单播、组播和广播可以使用TCP或UDP协议来实现&#xff0c;具体取决于应用程…

【C语言】实现猜数字游戏——随机数

&#x1f6a9;纸上得来终觉浅&#xff0c; 绝知此事要躬行。 &#x1f31f;主页&#xff1a;June-Frost &#x1f680;专栏&#xff1a;C语言 该篇将对 选择与循环语句 进行运用&#xff0c;实现猜数字游戏。 需求&#xff1a;游戏后可以选择再次进行游戏&#xff0c;也可以选择…

【Java-Crawler】HttpClient+Jsoup实现简单爬虫

Java编写网络爬虫 网络爬虫1. 爬虫入门程序 网络爬虫1. 网络爬虫的介绍2. 为什么学习网络爬虫 HttpClient1. Get请求2. 带参数的GET请求3. Post请求4. 带参数的 Post 请求5. 连接池6. 请求参数 Jsoup1. jsoup 介绍2.1 功能1.1-解析url2.2 功能1.2-解析字符串2.3 功能1.3-解析文…

由浅入深Dubbo核心源码剖析环境介绍

目录 1 框架介绍1.1 概述1.2 运行架构1.3 整体设计 2 环境搭建2.1 源码拉取2.2 源码结构2.3 环境导入2.4 测试2.5 管理控制台 1 框架介绍 1.1 概述 Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架&#xff0c;使得应用可通过高性能的 RPC 实现服务的输出和输入功能&#…

ARM学习笔记_1 模式,寄存器,流水线

ARM arm体积小功耗低性能高&#xff0c;支持thumb ARM双指令集&#xff0c;兼容8/16位器件&#xff1b;大量使用寄存器&#xff0c;指令定长&#xff0c;寻址简单。 ARM是32位架构&#xff0c;Word 32bit&#xff0c; half Word 16bit. 模式 用户模式是用户程序的模式&#…

解决MySQL无法输入中文字符的问题

文章目录 问题描述问题排查解决方案1️⃣创建数据库时设置字符集为utf82️⃣修改数据库配置文件【比较麻烦】 写在最后 前几日在使用MySQL数据库的时候&#xff0c;出现了一处保存&#xff0c;故作此记录✍ 问题描述 下面是我这样exam表的结构 mysql> desc exam; --------…

PETR 论文学习

1. 解决了什么问题&#xff1f; DETR3D 为端到端的 3D 目标检测提供了一个思路。但是&#xff0c;DETR3D 中的 2D 到 3D 的变换会带来一些问题。 Reference point 的预测坐标可能不够准确&#xff0c;采样特征可能位于目标区域之外&#xff1b;只有映射点周围的特征会被选取&…

“超越极限 - 如何使用 Netty 高效处理大型数据?“ - 掌握 Netty 技巧,轻松应对海量数据处理!

1 写大型数据 因为网络饱和的可能性&#xff0c;如何在异步框架中高效地写大块的数据是特殊问题。由于写操作是非阻塞的&#xff0c;所以即使没有写出所有的数据&#xff0c;写操作也会在完成时返回并通知 ChannelFuture。当这种情况发生时&#xff0c;如果仍然不停地写入&…

2023年最受欢迎的低代码平台排行榜

随着企业寻找在降低成本的同时加快软件开发的方法&#xff0c;低代码开发平台正变得越来越受欢迎。这些平台允许开发人员使用拖放界面和预置组件&#xff0c;以最少的代码创建复杂的应用程序。它不仅帮助企业加快了数字化转型的脚步&#xff0c;而且打破业务部门和IT部门之间的…

多元分类预测 | Matlab萤火虫算法(FA)优化BP神经网络分类预测,FA-BP分类预测,多特征输入模型

文章目录 效果一览文章概述部分源码参考资料效果一览 文章概述 多元分类预测 | Matlab萤火虫算法(FA)优化BP神经网络分类预测,FA-BP分类预测,多特征输入模型,多特征输入模型,多特征输入模型,多特征输入模型,多特征输入模型,多特征输入模型 多特征输入单输出的二分类及多…

商品领域十二张基础表设计思路与实现

欢迎大家关注公众号「JAVA前线」查看更多精彩分享文章&#xff0c;主要包括源码分析、实际应用、架构思维、职场分享、产品思考等等&#xff0c;同时欢迎大家加我微信「java_front」一起交流学习 1 文章概述 商品在电商领域中是一个非常重要的领域&#xff0c;交易行为前提是有…

Selenium + Java 的环境搭建

Selenium Java 的环境搭建 &#x1f50e;Chrome 浏览器下载 Chrome 浏览器检查对应版本下载 Chrome 浏览器驱动 &#x1f50e;配置环境变量&#x1f50e;验证环境是否搭建成功&#x1f50e;关于 pom.xml 出现错误的解决方案 &#x1f50e;Chrome 浏览器 下载 Chrome 浏览器 下…

使用命令启动默认程序(例如启动系统默认浏览器打开指定网址)

文章目录 目的基础说明代码示例&#xff08;Golang&#xff09;总结 目的 通过命令调用系统默认应用程序打开对应格式的文件是比较常用的功能。这篇文章将介绍下相关内容。 基础说明 Windows windows下可以使用 start 指令来启动默认程序打开对应格式文件&#xff1b; 比如 …