VINS-Mono代码精简版代码详解-后端非线性优化(三)

2023-05-16

非线性优化部分代码解析

之前已经对VINS-Mono的初始化部分进行了介绍,下面结合代码和公式介绍其非线性优化部分。本文部分参考 https://blog.csdn.net/u012871872/article/details/78128087 \url{https://blog.csdn.net/u012871872/article/details/78128087} https://blog.csdn.net/u012871872/article/details/78128087
1. 入口
非线性优化的入口是在

estimator.processImage(image, img_msg->header);

其中,其首先判断是否初始化,下面我们直接进入非初始化部分。其代码如下

TicToc t_solve;
        solveOdometry();
        //ROS_DEBUG("solver costs: %fms", t_solve.toc());

        if (failureDetection())
        {
            // ROS_WARN("failure detection!");
            failure_occur = 1;
            clearState();
            setParameter();
            // ROS_WARN("system reboot!");
            return;
        }

        TicToc t_margin;
        slideWindow();
        f_manager.removeFailures();
        //ROS_DEBUG("marginalization costs: %fms", t_margin.toc());
        // prepare output of VINS
        key_poses.clear();
        for (int i = 0; i <= WINDOW_SIZE; i++)
            key_poses.push_back(Ps[i]);

        last_R = Rs[WINDOW_SIZE];
        last_P = Ps[WINDOW_SIZE];
        last_R0 = Rs[0];
        last_P0 = Ps[0];

2. solveOdometry()函数
首先判断frame_count是否小于窗口大小,如果是则返回。然后进行三角化,以及后端优化。

void Estimator::solveOdometry()
{
    if (frame_count < WINDOW_SIZE)
        return;
    if (solver_flag == NON_LINEAR)
    {
        TicToc t_tri;
        f_manager.triangulate(Ps, tic, ric);
        //cout << "triangulation costs : " << t_tri.toc() << endl;        
        backendOptimization();
    }
}

2.1 三角化部分
代码中重要变量的说明:Ps:世界坐标系下机体的平移量 p b w \mathbf{p}_b^w pbw,Rs:世界坐标系下的机体的旋转量 q b w \mathbf{q}_b^w qbw,Vs:世界坐标系机体的速度量 v b w \mathbf{v}_b^w vbw;para_pose跟Ps和Rs是等价的,只是数据类型有区别,ric和tic是IMU与相机之间的坐标变换(外参) p c b , q c b \mathbf{p}_c^b,\mathbf{q}_c^b pcb,qcb。estimator.f_manager.feature是全局特征点。
(1) 参考坐标系构造
对于每个特征,根据其对应的IMU位姿和外参,计算该特征的起始帧的位姿 t 0 , R 0 t_0,R_0 t0,R0,然后对于所有观测到该特征的帧,计算其全局位姿,然后再变换到 ( R 0 , t 0 ) (R_0,t_0) (R0,t0)坐标系中,构造相应的投影矩阵,然后构造 A A A矩阵进行求解。对应的公式为
λ k x k = P k y , P k = [ R k , t k ] ∈ R 3 × 4 \lambda_k \mathbf{x}_k=\mathbf{P}_k\mathbf{y},\mathbf{P}_k=[\mathbf{R}_k,\mathbf{t}_k] \in \mathbb{R}^{3\times 4} λkxk=Pky,Pk=[Rk,tk]R3×4
其中, y ∈ R 4 \mathbf{y} \in \mathbb{R}^4 yR4,取齐次坐标,每次观测为 x k = [ u k , v k , 1 ] T \mathbf{x}_k=[u_k,v_k,1]^T xk=[uk,vk,1]T, P k \mathbf{P}_k Pk为参考系到camera系的投影矩阵。
则,对应的约束方程为
[ u 1 P 1 , 3 T − P 1 , 1 T v 1 P 1 , 3 T − P 1 , 2 T ⋮ u n P n , 3 T − P n , 1 T v n P n , 3 T − P n , 2 T ] y = 0 ⇒ A y = 0 \begin{bmatrix} u_1\mathbf{P}_{1,3}^T-\mathbf{P}_{1,1}^T \\ v_1\mathbf{P}_{1,3}^T-\mathbf{P}_{1,2}^T \\ \vdots \\ u_n\mathbf{P}_{n,3}^T-\mathbf{P}_{n,1}^T \\ v_n\mathbf{P}_{n,3}^T-\mathbf{P}_{n,2}^T \end{bmatrix}\mathbf{y}=\mathbf{0} \rArr \mathbf{Ay=0} u1P1,3TP1,1Tv1P1,3TP1,2TunPn,3TPn,1TvnPn,3TPn,2Ty=0Ay=0
对应的代码为

Eigen::MatrixXd svd_A(2 * it_per_id.feature_per_frame.size(), 4);
        int svd_idx = 0;

        Eigen::Matrix<double, 3, 4> P0;
        Eigen::Vector3d t0 = Ps[imu_i] + Rs[imu_i] * tic[0];
        Eigen::Matrix3d R0 = Rs[imu_i] * ric[0];
        P0.leftCols<3>() = Eigen::Matrix3d::Identity();
        P0.rightCols<1>() = Eigen::Vector3d::Zero();

        for (auto &it_per_frame : it_per_id.feature_per_frame)
        {
            imu_j++;

            Eigen::Vector3d t1 = Ps[imu_j] + Rs[imu_j] * tic[0];
            Eigen::Matrix3d R1 = Rs[imu_j] * ric[0];
            Eigen::Vector3d t = R0.transpose() * (t1 - t0);
            Eigen::Matrix3d R = R0.transpose() * R1;
            Eigen::Matrix<double, 3, 4> P;
            P.leftCols<3>() = R.transpose();
            P.rightCols<1>() = -R.transpose() * t;
            Eigen::Vector3d f = it_per_frame.point.normalized();
            svd_A.row(svd_idx++) = f[0] * P.row(2) - f[2] * P.row(0);
            svd_A.row(svd_idx++) = f[1] * P.row(2) - f[2] * P.row(1);

            if (imu_i == imu_j)
                continue;
        }
        assert(svd_idx == svd_A.rows());

然后对 A A A矩阵进行svd分解,其深度计算即其最小奇异值对应的奇异向量第三元素除以第四元素,即

assert(svd_idx == svd_A.rows());
        Eigen::Vector4d svd_V = Eigen::JacobiSVD<Eigen::MatrixXd>(svd_A, Eigen::ComputeThinV).matrixV().rightCols<1>();
        double svd_method = svd_V[2] / svd_V[3];
        //it_per_id->estimated_depth = -b / A;
        //it_per_id->estimated_depth = svd_V[2] / svd_V[3];

        it_per_id.estimated_depth = svd_method;
        //it_per_id->estimated_depth = INIT_DEPTH;

        if (it_per_id.estimated_depth < 0.1)
        {
            it_per_id.estimated_depth = INIT_DEPTH;
        }

2.2 backOptimization()后端优化部分
在三角化之后,得到的是特征点的深度信息,然后进行后端优化。主要包括:
2.2.1 系统数据类型转换
由Ps,Rs转换为para_Pose,Vs,Bas,Bgs转换为para_SpeedBias,tic,ric转换为para_Ex_Pose。代码如下:

void Estimator::vector2double()
{
    for (int i = 0; i <= WINDOW_SIZE; i++)
    {
        para_Pose[i][0] = Ps[i].x();
        para_Pose[i][1] = Ps[i].y();
        para_Pose[i][2] = Ps[i].z();
        Quaterniond q{Rs[i]};
        para_Pose[i][3] = q.x();
        para_Pose[i][4] = q.y();
        para_Pose[i][5] = q.z();
        para_Pose[i][6] = q.w();

        para_SpeedBias[i][0] = Vs[i].x();
        para_SpeedBias[i][1] = Vs[i].y();
        para_SpeedBias[i][2] = Vs[i].z();

        para_SpeedBias[i][3] = Bas[i].x();
        para_SpeedBias[i][4] = Bas[i].y();
        para_SpeedBias[i][5] = Bas[i].z();

        para_SpeedBias[i][6] = Bgs[i].x();
        para_SpeedBias[i][7] = Bgs[i].y();
        para_SpeedBias[i][8] = Bgs[i].z();
    }
    for (int i = 0; i < NUM_OF_CAM; i++)
    {
        para_Ex_Pose[i][0] = tic[i].x();
        para_Ex_Pose[i][1] = tic[i].y();
        para_Ex_Pose[i][2] = tic[i].z();
        Quaterniond q{ric[i]};
        para_Ex_Pose[i][3] = q.x();
        para_Ex_Pose[i][4] = q.y();
        para_Ex_Pose[i][5] = q.z();
        para_Ex_Pose[i][6] = q.w();
    }

    VectorXd dep = f_manager.getDepthVector();
    for (int i = 0; i < f_manager.getFeatureCount(); i++)
        para_Feature[i][0] = dep(i);
    if (ESTIMATE_TD)
        para_Td[0][0] = td;
}

2.2.2 添加残差
包括先验残差,IMU测量残差,camera测量残差。注意这里IMU项和camera项之间是有一个系数,这个系数就是他们各自的协方差矩阵:IMU的协方差是预积分的协方差(IMUFactor::Evaluate,中添加IMU协方差,求解jacobian矩阵),而camera的测量残差则是一个固定的系数 f 1.5 \frac{f}{1.5} 1.5f
对应的函数为

problemSolve();

主要包括以下步骤:
(1) 构建problem

backend::Problem problem(backend::Problem::ProblemType::SLAM_PROBLEM);
    vector<shared_ptr<backend::VertexPose>> vertexCams_vec;
    vector<shared_ptr<backend::VertexSpeedBias>> vertexVB_vec;
    int pose_dim = 0;

(2) 添加外参数节点
如果外参数已经估计优化好,则设置该节点为Fix。代码如下

shared_ptr<backend::VertexPose> vertexExt(new backend::VertexPose());
    {
        Eigen::VectorXd pose(7);
        pose << para_Ex_Pose[0][0], para_Ex_Pose[0][1], para_Ex_Pose[0][2], para_Ex_Pose[0][3], para_Ex_Pose[0][4], para_Ex_Pose[0][5], para_Ex_Pose[0][6];
        vertexExt->SetParameters(pose);

        if (!ESTIMATE_EXTRINSIC)
        {
            //ROS_DEBUG("fix extinsic param");
            // TODO:: set Hessian prior to zero
            vertexExt->SetFixed();
        }
        else{
            //ROS_DEBUG("estimate extinsic param");
        }
        problem.AddVertex(vertexExt);
        pose_dim += vertexExt->LocalDimension();
    }

(2) 添加IMU位姿和IMU速度以及偏置节点
代码如下:

for (int i = 0; i < WINDOW_SIZE + 1; i++)
    {
        shared_ptr<backend::VertexPose> vertexCam(new backend::VertexPose());
        Eigen::VectorXd pose(7);
        pose << para_Pose[i][0], para_Pose[i][1], para_Pose[i][2], para_Pose[i][3], para_Pose[i][4], para_Pose[i][5], para_Pose[i][6];
        vertexCam->SetParameters(pose);
        vertexCams_vec.push_back(vertexCam);
        problem.AddVertex(vertexCam);
        pose_dim += vertexCam->LocalDimension();

        shared_ptr<backend::VertexSpeedBias> vertexVB(new backend::VertexSpeedBias());
        Eigen::VectorXd vb(9);
        vb << para_SpeedBias[i][0], para_SpeedBias[i][1], para_SpeedBias[i][2],
            para_SpeedBias[i][3], para_SpeedBias[i][4], para_SpeedBias[i][5],
            para_SpeedBias[i][6], para_SpeedBias[i][7], para_SpeedBias[i][8];
        vertexVB->SetParameters(vb);
        vertexVB_vec.push_back(vertexVB);
        problem.AddVertex(vertexVB);
        pose_dim += vertexVB->LocalDimension();
    }

(3) 添加IMU预积分对应的约束边

for (int i = 0; i < WINDOW_SIZE; i++)
    {
        int j = i + 1;
        if (pre_integrations[j]->sum_dt > 10.0)
            continue;

        std::shared_ptr<backend::EdgeImu> imuEdge(new backend::EdgeImu(pre_integrations[j]));
        std::vector<std::shared_ptr<backend::Vertex>> edge_vertex;
        edge_vertex.push_back(vertexCams_vec[i]);
        edge_vertex.push_back(vertexVB_vec[i]);
        edge_vertex.push_back(vertexCams_vec[j]);
        edge_vertex.push_back(vertexVB_vec[j]);
        imuEdge->SetVertex(edge_vertex);
        problem.AddEdge(imuEdge);
    }

(4) 添加Visual Factor
首先添加每个特征的逆深度节点,

shared_ptr<backend::VertexInverseDepth> verterxPoint(new backend::VertexInverseDepth());
            VecX inv_d(1);
            inv_d << para_Feature[feature_index][0];
            verterxPoint->SetParameters(inv_d);
            problem.AddVertex(verterxPoint);
            vertexPt_vec.push_back(verterxPoint);

然后针对每个特征,遍历其所有观测,构建所有观测到同一特征的帧之间的约束边,包括的信息:逆深度,边的顶点对应的IMU全局位姿,外参数,信息矩阵,lossfunction核函数

// 遍历所有的观测
            for (auto &it_per_frame : it_per_id.feature_per_frame)
            {
                imu_j++;
                if (imu_i == imu_j)
                    continue;

                Vector3d pts_j = it_per_frame.point;

                std::shared_ptr<backend::EdgeReprojection> edge(new backend::EdgeReprojection(pts_i, pts_j));
                std::vector<std::shared_ptr<backend::Vertex>> edge_vertex;
                edge_vertex.push_back(verterxPoint);
                edge_vertex.push_back(vertexCams_vec[imu_i]);
                edge_vertex.push_back(vertexCams_vec[imu_j]);
                edge_vertex.push_back(vertexExt);

                edge->SetVertex(edge_vertex);
                edge->SetInformation(project_sqrt_info_.transpose() * project_sqrt_info_);

                edge->SetLossFunction(lossfunction);
                problem.AddEdge(edge);
            }

(4) 添加先验

 if (Hprior_.rows() > 0)
        {
            // 外参数先验设置为 0. TODO:: 这个应该放到 solver 里去弄
            //            Hprior_.block(0,0,6,Hprior_.cols()).setZero();
            //            Hprior_.block(0,0,Hprior_.rows(),6).setZero();

            problem.SetHessianPrior(Hprior_); // 告诉这个 problem
            problem.SetbPrior(bprior_);
            problem.SetErrPrior(errprior_);
            problem.SetJtPrior(Jprior_inv_);
            problem.ExtendHessiansPriorSize(15); // 但是这个 prior 还是之前的维度,需要扩展下装新的pose
        }

(4) 非线性优化求解——LM方法
所有的节点和边添加完毕后,开始进行非线性优化求解。

problem.Solve(10);

(4) 位姿更新
优化求解完毕后,对窗口的IMU位姿进行更新,以及速度及偏置向量进行更新。

for (int i = 0; i < WINDOW_SIZE + 1; i++)
    {
        VecX p = vertexCams_vec[i]->Parameters();
        for (int j = 0; j < 7; ++j)
        {
            para_Pose[i][j] = p[j];
        }

        VecX vb = vertexVB_vec[i]->Parameters();
        for (int j = 0; j < 9; ++j)
        {
            para_SpeedBias[i][j] = vb[j];
        }
    }

然后对每个特征的逆深度进行更新

for (int i = 0; i < vertexPt_vec.size(); ++i)
    {
        VecX f = vertexPt_vec[i]->Parameters();
        para_Feature[i][0] = f[0];
    }

注意,这里的全局坐标系是第一帧的相机坐标系。
(4) 边缘化
这里前面已经根据视差范围确定边缘化选项(MARGIN_OLD or MARGIN_SECOND_NEW)

  if (f_manager.addFeatureCheckParallax(frame_count, image, td))
        marginalization_flag = MARGIN_OLD;
    else
        marginalization_flag = MARGIN_SECOND_NEW;

如果是MARGIN_OLD,对应的代码为

// 维护 marg
    TicToc t_whole_marginalization;
    if (marginalization_flag == MARGIN_OLD)
    {
        vector2double();

        MargOldFrame();
        // prior 中对应的保留下来的参数地址
        std::unordered_map<long, double *> addr_shift; 
        for (int i = 1; i <= WINDOW_SIZE; i++)
        {
            addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i - 1];
            addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i - 1];
        }
        for (int i = 0; i < NUM_OF_CAM; i++)
            addr_shift[reinterpret_cast<long>(para_Ex_Pose[i])] = para_Ex_Pose[i];
        if (ESTIMATE_TD)
        {
            addr_shift[reinterpret_cast<long>(para_Td[0])] = para_Td[0];
        }
    }

如果是MARGIN_SECOND_NEW,对应的代码为

if (Hprior_.rows() > 0)
        {

            vector2double();

            MargNewFrame();

            std::unordered_map<long, double *> addr_shift;
            for (int i = 0; i <= WINDOW_SIZE; i++)
            {
                if (i == WINDOW_SIZE - 1)
                    continue;
                else if (i == WINDOW_SIZE)
                {
                    addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i - 1];
                    addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i - 1];
                }
                else
                {
                    addr_shift[reinterpret_cast<long>(para_Pose[i])] = para_Pose[i];
                    addr_shift[reinterpret_cast<long>(para_SpeedBias[i])] = para_SpeedBias[i];
                }
            }
            for (int i = 0; i < NUM_OF_CAM; i++)
                addr_shift[reinterpret_cast<long>(para_Ex_Pose[i])] = para_Ex_Pose[i];
            if (ESTIMATE_TD)
            {
                addr_shift[reinterpret_cast<long>(para_Td[0])] = para_Td[0];
            }
        }
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

VINS-Mono代码精简版代码详解-后端非线性优化(三) 的相关文章

  • 1024,如果全世界程序员都消失了,会怎样?

    这两天 xff0c 有一个话题引起了程序员的广泛讨论 xff1a 年薪80W程序员相亲被鄙视 某知名互联网社区 xff0c 一网友发帖 xff0c 自己年薪80W去相亲 xff0c 竟然被鄙视不如在二本学校教书的大学老师 估计令他没想到的是
  • 非线性控制1.1——稳定与跟踪问题概念

    一 非线性控制系统的两大任务 1 稳定 xff08 或称调节 xff09 问题 稳定问题是要使得闭环系统的状态稳定在一个平衡点附近 对于稳定问题 xff0c 系统的输出不一定要有具体的物理意义 xff0c 此时可以借助输入 输出状态线性化方
  • 在 linux ubuntu 18.04 上运行QQ音乐

    在 linux ubuntu 18 04 上运行QQ音乐 我使用的组合为 ubuntu 18 04 43 wine stable 3 6 43 QQ音乐17 63 xff0c 未在其它平台做过尝试 一直想在ubuntu上好好听音乐 xff0
  • 非线性控制1.0——自适应控制和鲁棒控制

    1 鲁棒控制和自适应控制的联系与区别 鲁棒控制是以目的定义的控制方法集合 xff0c 自适应控制是以手段定义的控制方法集合 xff0c 这两种控制都是为了应对 当数学模型不能精确表示实际系统的情况下 狭义的鲁棒控制是指H2 xff0c Hi
  • 非线性控制2.0——鲁棒控制之H无穷控制器设计

    一 基本概念 对于图1所示系统 xff0c u为控制输入 xff0c y为测量输出 xff0c z为被调输出 xff0c w为干扰输入 xff0c 由输入u xff0c w到输出y xff0c z的传递函数G成为增广被控对象 xff0c 控
  • 非线性控制1.0——控制理论生态及结构

    一 控制理论地图 二 控制理论发展及结构 上图应用于 xff1a https www zhihu com people xiang yi 55 49 answers
  • 四旋翼飞行器——飞行原理

    1 机械结构 旋翼对称分布在机体的前后 左右四个方向 xff0c 四个旋翼处于同一高度平面 xff0c 且四个旋翼的结构和半径都相同 xff0c 四个电机对称的安装在飞行器的支架端 xff0c 支架中间空间安放飞控板 结构形式如图 1 1所
  • 四旋翼飞行器——非线性化模型

    一 建模思路 该模型目标控制量是机体相对于地面坐标系的线速度的三个分量Vx xff0c Vy xff0c Vz xff0c 而我们能控的实质上只有四个电机的转速W1 xff0c W2 xff0c W3 xff0c W4 怎样由输入一步步推导
  • 故障诊断4—龙伯格状态观测器设计

    1 龙伯格状态观测器概念 已经线性系统模型如下 xff1a 当系统状态量难以获取 xff0c 但实际控制中又需要利用系统状态量时 xff0c 如何通过输入量和输出量重构系统状态量 xff1f 这便是龙伯格状态观测器设计初衷 xff0c 将实
  • 故障诊断5——状态观测器和输出观测器

    1 状态观测器分类 在现代控制理论中 xff0c 控制系统的基本结构和经典控制理论一样 xff0c 仍然是由受控对象和反馈控制器两部分构成的闭环系统 不过在经典理论中习惯于采用输出反馈 xff0c 而在现代控制理论中则更多地采用状态反馈 由
  • GPS漂移和定位不准确的解决办法

    解决GPS漂移主要从两方面入手 xff1a 一 主系统的设计主要减少在近距离内对GPS信号的干扰 二 软件处理 软件处理主要集中在导航软件处完成 xff0c 导航软件会将坐标定位在道路之内 xff0c 如果GPS接收到的信号超出道路的半径范
  • AI---是什么?可以做什么?

    1 AI的项目简单介绍 图像识别 描述 xff1a 给定图片 xff0c 识别图片中有什么 xff1f 算法 xff1a KNN CNN 情感分析 描述 xff1a 判断文本包含的情感是正面 负面还是中性 关键 xff1a 文本如何表示成向
  • realsense的安装问题

    realsense的安装问题 0 旁白1 SDK的安装2 python开发包的安装3 nodejs开发包的安装方法1 xff1a 方法2 xff1a 接手一位同事的realsense相关项目 xff0c 先配置一个环境 xff0c 出现不少
  • 二叉排序树的删除

    xff08 网上讲二叉排序树删除的资料很少 xff0c 这篇很不错 xff01 转自 xff1a http bbs csdn net topics 110010437 xff09 二叉排序树的删除 xff1a 对于一般的二叉树来说 xff0
  • 分布式锁学习

    概述 分布式锁是控制分布式系统之间同步访问共享资源的一种方式 在分布式系统中 xff0c 常常需要协调他们的动作 如果不同的系统或是同一个系统的不同主机之间共享了一个或一组资源 xff0c 那么访问这些资源的时候 xff0c 往往需要互斥来
  • 无人机飞行控制

    intro 这篇笔记记录了无人机飞控算法和px4相关 control algorithm adrc 周立功讲adrc 参数整定 xff1a Scaling and Bandwidth Parameterization
  • 168-HITL-dev-manual

    HITL todo 使用mavlink收ref和imu 可以选择发出pwm和torque 发出torque的话 xff0c 没有考虑pwm的饱和 发出pwm的话 xff0c 电机的参数也不准 参考GAAS FC 写收的imu gps xff
  • 图优化理论(1)

    简介 图优化本质上是一个优化问题 xff0c 所以我们先来看优化问题是什么 优化问题有三个最重要的因素 xff1a 目标函数 优化变量 优化约束 一个简单的优化问题可以描述如下 其中x为优化变量 xff0c 而F x 为优化函数 此问题称为
  • (动态添加select后不显示?)layui动态添加select后重新渲染

    一 问题 xff1a 利用jQuery动态添加的代码中包含select xff0c 运行后不显示 1 显示的状态 2 后台的代码 正常情况下应该像队长班级一样显示 xff0c 但是却惊奇的发现 xff0c 事与愿违 二 原因 Layui会对
  • ARM处理器的快速上下文切换技术

    5 3 1 FCSE 概述 FCSE xff08 Fast Context Switch Extension xff0c 快速上下文切换 xff09 位于 CPU 和 MMU 之间 xff0c 如果两个进程使用了同样的虚拟地址空间 xff0

随机推荐

  • Promise 控制并发请求数量

    Promise 控制并发请求数量 前言 xff1a 浏览器对对同一个服务器的并发数是有限制的 xff0c 参考如下表格 xff08 表格来源于网络 xff0c 未进过严谨测试 xff09 xff1a 浏览器HTTP 1 1HTTP 1 0I
  • 树莓派自动连接WiFi

    将USB无线网卡插入树莓派任一USB接口 xff0c 插上网线 xff0c 接通电源 xff1b 在个人电脑上通过ssh连接树莓派 xff0c 默认帐号是pi xff0c 默认密码是raspberry xff08 如何通过ssh连接树莓派
  • 【DragonBoard 410c】悲催的开箱体验

    这里非常感谢辉哥提供的龙板 这块板子是实验室的学长从高通公司争取过来赠送给我们实验室的 xff0c 从美国寄过来的 xff0c 遗憾的是 xff01 里面没有Android系统 xff01 xff01 以至于我开机折腾了许久 首先 xff0
  • 2017CVTE嵌入式研发岗实习生面经

    本人普通高校大三学生 xff0c 准备在暑假找一份嵌入式实习工作 xff0c 因为实验室一学长去年通过实习生通道成功拿到正式岗offer 而且CVTE在嵌入式这一行的工资福利等都是相当诱人 xff0c 所以我的目标就是首先要拿到cvte的实
  • 安装Ubuntu过程及遇到的问题

    需要的装备 xff1a 1 不小于4G的U盘或者内存卡 43 读卡器也可以 2 UltraISO xff08 使用方法http jingyan baidu com article d169e186800f02436711d87b html
  • 北邮某牛人找工作切身感受

    转自北邮人论坛 by xiaoxuanzi xff08 值得全部看完 xff09 找工作历程基本上要截止了 Offer再多也只能去一个 xff0c 也省了纠结 xff0c 顺便帮等攒人品 Offer搞定能一起happy xff0c 寝室MM
  • DNW下载文件时出现can not open /dev/secbulk0

    在学习过程中碰到了如上的问题 xff0c 在参考了不少博客之后解决了这个问题 首先到这里下载DNW安装包 xff1a http download csdn net detail david xtd 7401761 这里面有两个文件夹dnw和
  • VMware非正常关闭导致打开虚拟机时提示:未找到.vmx文件

    上次手残将VMware直接关闭 xff0c 导致第二次打开虚拟机时提示 vmx文件未找到 根据这个原理 xff0c 可能其他后缀的文件丢失也可以利用相同的原理 xff0c 就是重新建一个虚拟机 xff0c 然后就能得到相同的文件 xff0c
  • 图片合集

    HDMI接口物理地址理解
  • 操作系统--freeRTOS 双向链表解读(list)

    1 简介 本文依据的freeRTOS版本是V9 0 0版本 xff0c 本文将分析链表文件的结构体 xff0c 主要根据其list c和list h文件 2 list h文件解析 span class token comment FreeR
  • socket通信(自己的程序)

    socket相关知识 xff1a socket相关基础知识 xff1a http www cnblogs com skynet archive 2010 12 12 1903949 html 非阻塞socket xff1a http blo
  • NVIDIA Jetson TX2重装系统

    博主所用的Jetson TX2初始环境及相关方面的介绍见前两篇博客 NVIDIA Jetson TX2简介 竹叶青lvye的博客 CSDN博客 nvidiatx2 NVIDIA Jetson官网资料整理 竹叶青lvye的博客 CSDN博客
  • Jetson TX2配置Tensorflow、Pytorch等常用库

    之前在PC Ubuntu或者树莓派上都配置过 方法不变 所以此篇博客会简单记录 下过程 详细的一些方法思路可以去参考博主之前的系列博客 虽然硬件平台不一样 但方法大体一致的 硬件平台主流的有树莓派 NVIDIA Jetson Google的
  • Macbook pro外接显卡实现深度学习

    耗时一整天加一晚上终于成功了安装配置外接GPU并运行深度学习案列 故事的缘由 2017年底鬼使神差的买了个macbook xff0c 放在家里吃了一年灰 xff0c 心想还是要用起来啊 目前主要从事数据挖掘机器学习的工作 xff0c 需要搞
  • Gradle技术之一 Groovy语法精讲

    Gradle技术之一 Groovy语法精讲 gradle脚本是基于groovy语言开发的 xff0c 想要学好gradle必须先要对groovy有一个基本的认识 1 Groovy特点 groovy是一种DSL语言 xff0c 所谓的DSL语
  • 字符串子串的查找

    1 考虑用标准函数库中 strstr 函数 包含文件 xff1a string h 函数名 strstr 函数原型 xff1a extern char strstr char str1 char str2 功能 xff1a 从字符串str1
  • 大锤老湿教您如何配置TP-Link路由器组建wifi上网

    TP Link路由器设置教程 大家好 xff0c 今天由大锤老湿教大家如何设置使用最广的TP Link路由器 一般家庭都希望能上wifi 那么首先看看我们如何将新买回的或者由于故障已经恢复成重置出厂状态的路由器 xff0c 如何经过重新设置
  • 【ESP01S】使用串口调试助手,发送AT指令收回的是乱码/重复一遍AT指令发回的问题

    调试帮助 span class token punctuation span 技术交流Q xff1a span class token number 1083091092 span xff08 备注CSDN xff09 一 问题描述 在使用
  • 刷leetcode使用python还是c++?

    我身边80 的程序员朋友在刷题的时候会选择Java xff0c 很少有人用C 43 43 来刷题 这两门语言各有特点 xff1a C 43 43 xff1a 从C语言发展过来的一门语言 xff0c 继承了灵活 xff08 可以潜入任何现代的
  • VINS-Mono代码精简版代码详解-后端非线性优化(三)

    非线性优化部分代码解析 之前已经对VINS Mono的初始化部分进行了介绍 xff0c 下面结合代码和公式介绍其非线性优化部分 本文部分参考 https blog csdn net u012871872 article details 78