px4飞控位置估计lpe移植到vs

2023-05-16

本文主要内容

px4飞控的位置估计有两种方式,一是inav,二是lpe,用到的传感器用加速度计,磁场传感器,gps,超声,激光,气压,视觉,动作捕捉。但是动作捕捉在目前固件的inav中还不支持。

本文将进行移植lpe中使用加速度计,磁场传感器和GPS进行位置估计的部分。

本文的主要内容用:用到的px4固件中的文件,移植过程,移植完成后主函数内容,效果展示。

用到的px4固件中的文件

/Firmware/src/lib/geo下所有文件。

/Firmware/src/lib/mathlib下所有文件。

/Firmware/src/lib/matrix下所有文件。

/Firmware/src/modules/local_position_estimator/sensors/gps.cpp

/Firmware/src/modules/local_position_estimator/BlockLocalPositionEstimator.cpp

/Firmware/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp

移植过程

首先按照px4源码中文件的组织结构在vs工程下添加这些文件,然后修正各头文件之间的包含路径错
误。

把/Firmware/src/lib/geo/geo.c改成geo.cpp。

把/Firmware/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp中类的基类去掉。然后改正因为没有基类而产生的部分成员变量没有定义错误,这些变量大部分是没有用到的,也可以直接删除。

去掉/Firmware/src/modules/local_position_estimator/BlockLocalPositionEstimator.hpp/Firmwar

e/src/modules/local_position_estimator/BlockLocalPositionEstimator.cpp中除GPS外其他传感器相关的成员变量和成员函数。

把代码中出现的__EXPORT全部去掉。

把部分未定义的宏在相应的.h文件中定义。

一部分包含文件需要c++11支持,需要vs2013以上版本。如果是vs2012以下版本,则一些头文件需要按照px4固件的写法重新写好放到程序源码文件夹下。

这是一个大概的流程,可能不一定要按照顺序来,但是每一条都至关重要。而且编译过程中还有其他更多的小问题,这就需要根据具体情况进行处理了。

移植完成后主函数内容

main.h中内容如下:

#include <iostream>
#include<fstream>
#include "LocalPositionEstimator/BlockLocalPositionEstimator.h"
#include <windows.h> 
#include "gyro/stdafx.h"
#include "gyro/Com.h"
#include "gyro/JY901.h"
using namespace std;


DWORD WINAPI mavThreadRead(LPVOID lpParam);
DWORD WINAPI mavThreadWrite(LPVOID lpParam);

main.cpp中内容如下:

/*
作者:高伟晋
时间:2017年7月1日
功能:进行陀螺仪数据和GPS数据的融合,得到位置坐标。
*/
#include"main.h"

//定时器和线程
HANDLE hTimer = NULL;
HANDLE hThreadRead = NULL;
HANDLE hThreadWrite = NULL;
LARGE_INTEGER liDueTime;
int totalNum = 0;

//串口
char chrBuffer[2000];
unsigned short usLength = 0;
unsigned long ulBaund = 9600, ulComNo = 4;
signed char cResult = 1;

//写文件
ofstream fout;

//中断循环控制
bool isrun = 0;
bool isinit = 0;

int main()
{

    hTimer = CreateWaitableTimer(NULL, TRUE, "TestWaitableTimer");
    if (hTimer)
    {
        printf("定时器开启\r\n");
    }
    liDueTime.QuadPart = -10000000;     //1s
    SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0);

    hThreadRead = CreateThread(NULL, 0,
        mavThreadRead, NULL, 0, NULL);
    hThreadWrite = CreateThread(NULL, 0,
        mavThreadWrite, NULL, 0, NULL);

    while(1);
    return 0;
}

DWORD WINAPI mavThreadRead(LPVOID lpParam)
{
    while (cResult != 0)
    {
        cResult = OpenCOMDevice(ulComNo, ulBaund);
    }

    isinit =  1;

    cout<<"陀螺仪初始化完成..."<<endl;

    while (isrun)
    {
        usLength = CollectUARTData(ulComNo, chrBuffer);
        if (usLength > 0)
        {
            JY901.CopeSerialData(chrBuffer, usLength);
        }
        Sleep(50);
    }
    return 0;
}


DWORD WINAPI mavThreadWrite(LPVOID lpParam)
{
    while(!isinit);

    //位置估计器
    BlockLocalPositionEstimator lpe;       //构造函数中进行初始化

    time_t rawtime;
    char filenametemp[15];
    cout<<"请输入要保存数据的文件名:";
    cin>>filenametemp;
    strcat(filenametemp,".txt");
    char* filename = filenametemp;
    fout.open(filename);           //不能有空格
    isrun = 1;
    while (isrun)
    {
        if (WaitForSingleObject(hTimer, INFINITE) != WAIT_OBJECT_0)
        {
            printf("1秒定时器出错了\r\n");
        }
        else
        {
            time(&rawtime);
            liDueTime.QuadPart = -50000;     //0.005s                -
            SetWaitableTimer(hTimer, &liDueTime, 0, NULL, NULL, 0);
            totalNum++;
            //cout << totalNum << endl;
            if(totalNum<1000)
            {
                lpe.update();
            }
            //cout << "at "<<ctime(&rawtime) << endl;
            float x,y,z;
            x = lpe.getx();
            y = lpe.gety();
            z = lpe.getz();

            //system("cls");
            //printf("Pos:%.3f %.3f %.3f\r\n", x, y, z);
            if(totalNum<1000)
            {
                fout<<x<<" "<<y<<" "<<z<<endl;
            }
            else if(totalNum ==1000)
            {
                fout<<flush;
                fout.close();
                printf("文件输出完毕\r\n");
            }
        }
    }
    return 0;
}

BlockLocalPositionEstimator.h中内容:

#pragma once
#include "../geo/geo.h"
#include "../matrix/math.hpp"


using namespace matrix;

static const float DELAY_MAX = 0.5f; // seconds
static const float HIST_STEP = 0.05f; // 20 hz
static const float BIAS_MAX = 1e-1f;
static const size_t HIST_LEN = 10; // DELAY_MAX / HIST_STEP;
static const size_t N_DIST_SUBS = 4;

// for fault detection
// chi squared distribution, false alarm probability 0.0001
// see fault_table.py
// note skip 0 index so we can use degree of freedom as index
static const float BETA_TABLE[7] = {0,
                    8.82050518214f,
                    12.094592431f,
                    13.9876612368f,
                    16.0875642296f,
                    17.8797700658f,
                    19.6465647819f,
                   };

class BlockLocalPositionEstimator       //: public control::SuperBlock
{
// dynamics:
//
//  x(+) = A * x(-) + B * u(+)
//  y_i = C_i*x
//
// kalman filter
//
//  E[xx'] = P
//  E[uu'] = W
//  E[y_iy_i'] = R_i
//
//  prediction
//      x(+|-) = A*x(-|-) + B*u(+)
//      P(+|-) = A*P(-|-)*A' + B*W*B'
//
//  correction
//      x(+|+) =  x(+|-) + K_i * (y_i - H_i * x(+|-) )
//
//
// input:
//  ax, ay, az (acceleration NED)
//
// states:
//  px, py, pz , ( position NED, m)
//  vx, vy, vz ( vel NED, m/s),
//  bx, by, bz ( accel bias, m/s^2)
//  tz (terrain altitude, ASL, m)
//
// measurements:
//
//  sonar: pz (measured d*cos(phi)*cos(theta))
//
//  baro: pz
//
//  flow: vx, vy (flow is in body x, y frame)
//
//  gps: px, py, pz, vx, vy, vz (flow is in body x, y frame)
//
//  lidar: pz (actual measured d*cos(phi)*cos(theta))
//
//  vision: px, py, pz, vx, vy, vz
//
//  mocap: px, py, pz
//
//  land (detects when landed)): pz (always measures agl = 0)
//
public:

    // constants
    enum {X_x = 0, X_y, X_z, X_vx, X_vy, X_vz, X_bx, X_by, X_bz, X_tz, n_x};
    enum {U_ax = 0, U_ay, U_az, n_u};
    enum {Y_baro_z = 0, n_y_baro};
    enum {Y_lidar_z = 0, n_y_lidar};
    enum {Y_flow_vx = 0, Y_flow_vy, n_y_flow};
    enum {Y_sonar_z = 0, n_y_sonar};
    enum {Y_gps_x = 0, Y_gps_y, Y_gps_z, Y_gps_vx, Y_gps_vy, Y_gps_vz, n_y_gps};
    enum {Y_vision_x = 0, Y_vision_y, Y_vision_z, n_y_vision};
    enum {Y_mocap_x = 0, Y_mocap_y, Y_mocap_z, n_y_mocap};
    enum {Y_land_vx = 0, Y_land_vy, Y_land_agl, n_y_land};
    enum {POLL_FLOW = 0, POLL_SENSORS, POLL_PARAM, n_poll};
    enum {
        FUSE_GPS = 1 << 0,
        FUSE_FLOW = 1 << 1,
        FUSE_VIS_POS = 1 << 2,
        FUSE_VIS_YAW = 1 << 3,
        FUSE_LAND = 1 << 4,
        FUSE_PUB_AGL_Z = 1 << 5,
        FUSE_FLOW_GYRO_COMP = 1 << 6,
        FUSE_BARO = 1 << 7,
    };

    enum sensor_t {
        SENSOR_BARO = 1 << 0,
        SENSOR_GPS = 1 << 1,
        SENSOR_LIDAR = 1 << 2,
        SENSOR_FLOW = 1 << 3,
        SENSOR_SONAR = 1 << 4,
        SENSOR_VISION = 1 << 5,
        SENSOR_MOCAP = 1 << 6,
        SENSOR_LAND = 1 << 7,
    };

    enum estimate_t {
        EST_XY = 1 << 0,
        EST_Z = 1 << 1,
        EST_TZ = 1 << 2,
    };

    // public methods
    BlockLocalPositionEstimator();
    void update();
    inline float getx(){return _x(0);}
    inline float gety(){return _x(1);}
    inline float getz(){return _x(2);}

    virtual ~BlockLocalPositionEstimator();

private:
    // prevent copy and assignment
    BlockLocalPositionEstimator(const BlockLocalPositionEstimator &);
    BlockLocalPositionEstimator operator=(const BlockLocalPositionEstimator &);

    // methods
    // ----------------------------
    //
    Vector<float, n_x> dynamics(
        float t,
        const Vector<float, n_x> &x,
        const Vector<float, n_u> &u);
    void initP();
    void initSS();
    void updateSSStates();
    void updateSSParams();

    // predict the next state
    void predict();

    void publishLocalPos();

    // baro
    int  baroMeasure(Vector<float, n_y_baro> &y);
    void baroCorrect();
    void baroInit();

    // gps
    int  gpsMeasure(Vector<double, n_y_gps> &y);
    void gpsCorrect();
    void gpsInit();


    // misc
    inline float agl() { return _x(X_tz) - _x(X_z); }
    inline double getDt() { return 0.5; }

    // map projection
    struct map_projection_reference_s _map_ref;

    // reference altitudes
    float _altOrigin;
    bool _altOriginInitialized;
    float _baroAltOrigin;
    float _gpsAltOrigin;

    unsigned char _estimatorInitialized;

    // state space
    Vector<float, n_x>  _x; // state vector
    Vector<float, n_u>  _u; // input vector
    Matrix<float, n_x, n_x>  _P; // state covariance matrix

    matrix::Dcm<float> _R_att;
    Vector3f _eul;

    Matrix<float, n_x, n_x>  _A; // dynamics matrix
    Matrix<float, n_x, n_u>  _B; // input matrix
    Matrix<float, n_u, n_u>  _R; // input covariance
    Matrix<float, n_x, n_x>  _Q; // process noise covariance
};

BlockLocalPositionEstimator.cpp中内容:

#include <iostream>
#include "BlockLocalPositionEstimator.h"
#include "../gyro/JY901.h"
#pragma warning(disable:4244)

using namespace std;

// required standard deviation of estimate for estimator to publish data
static const int        EST_STDDEV_XY_VALID = 2.0; // 2.0 m
static const int        EST_STDDEV_Z_VALID = 2.0; // 2.0 m
static const int        EST_STDDEV_TZ_VALID = 2.0; // 2.0 m

static const float P_MAX = 1.0e6f; // max allowed value in state covariance
static const float LAND_RATE = 10.0f; // rate of land detector correction

BlockLocalPositionEstimator::BlockLocalPositionEstimator() :
    // reference altitudes
    _altOrigin(0),
    _altOriginInitialized(false),
    _baroAltOrigin(0),
    _gpsAltOrigin(0),

    _estimatorInitialized(0),

    // kf matrices
    _x(), _u(), _P(), _R_att(), _eul()
{
    // initialize A, B,  P, x, u
    _x.setZero();
    _u.setZero();
    initSS();
    _estimatorInitialized = true;
    baroInit();
    gpsInit();

    cout << "lpe初始化完成..." << endl;
}

BlockLocalPositionEstimator::~BlockLocalPositionEstimator()
{
}

BlockLocalPositionEstimator BlockLocalPositionEstimator::operator=(const BlockLocalPositionEstimator &)
{
    return BlockLocalPositionEstimator();
}

Vector<float, BlockLocalPositionEstimator::n_x> BlockLocalPositionEstimator::dynamics(
    float t,
    const Vector<float, BlockLocalPositionEstimator::n_x> &x,
    const Vector<float, BlockLocalPositionEstimator::n_u> &u)
{
    return _A * x + _B * u;
}

void BlockLocalPositionEstimator::update()
{
    bool gpsUpdated = 1;
    bool baroUpdated = 0;

    // do prediction
    predict();

    // sensor corrections/ initializations
    if (gpsUpdated) 
    {
        gpsCorrect();
    }
    if (baroUpdated) 
    {
        baroCorrect();
    }

    publishLocalPos();
    cout << "lpe updata!"<<endl;
}


void BlockLocalPositionEstimator::initP()
{
    _P.setZero();
    // initialize to twice valid condition
    _P(X_x, X_x) = 2 * EST_STDDEV_XY_VALID * EST_STDDEV_XY_VALID;
    _P(X_y, X_y) = 2 * EST_STDDEV_XY_VALID * EST_STDDEV_XY_VALID;
    _P(X_z, X_z) = 2 * EST_STDDEV_Z_VALID * EST_STDDEV_Z_VALID;
    //=======================================================
    //_P(X_vx, X_vx) = 2 * _vxy_pub_thresh.get() * _vxy_pub_thresh.get();
    //_P(X_vy, X_vy) = 2 * _vxy_pub_thresh.get() * _vxy_pub_thresh.get();
     use vxy thresh for vz init as well
    //_P(X_vz, X_vz) = 2 * _vxy_pub_thresh.get() * _vxy_pub_thresh.get();
    //=======================================================
    _P(X_vx, X_vx) = 2 * 0.3f * 0.3f;
    _P(X_vy, X_vy) = 2 * 0.3f * 0.3f;
    // use vxy thresh for vz init as well
    _P(X_vz, X_vz) = 2 * 0.3f * 0.3f;
    // initialize bias uncertainty to small values to keep them stable
    _P(X_bx, X_bx) = 1e-6f;
    _P(X_by, X_by) = 1e-6f;
    _P(X_bz, X_bz) = 1e-6f;
    _P(X_tz, X_tz) = 2 * EST_STDDEV_TZ_VALID * EST_STDDEV_TZ_VALID;
}

void BlockLocalPositionEstimator::initSS()
{
    initP();

    // dynamics matrix
    _A.setZero();
    // derivative of position is velocity
    _A(X_x, X_vx) = 1;
    _A(X_y, X_vy) = 1;
    _A(X_z, X_vz) = 1;

    // input matrix
    _B.setZero();
    _B(X_vx, U_ax) = 1;
    _B(X_vy, U_ay) = 1;
    _B(X_vz, U_az) = 1;

    // update components that depend on current state
    updateSSStates();
    updateSSParams();
}

void BlockLocalPositionEstimator::updateSSStates()
{
    // derivative of velocity is accelerometer acceleration
    // (in input matrix) - bias (in body frame)
    _A(X_vx, X_bx) = -_R_att(0, 0);
    _A(X_vx, X_by) = -_R_att(0, 1);
    _A(X_vx, X_bz) = -_R_att(0, 2);

    _A(X_vy, X_bx) = -_R_att(1, 0);
    _A(X_vy, X_by) = -_R_att(1, 1);
    _A(X_vy, X_bz) = -_R_att(1, 2);

    _A(X_vz, X_bx) = -_R_att(2, 0);
    _A(X_vz, X_by) = -_R_att(2, 1);
    _A(X_vz, X_bz) = -_R_att(2, 2);
}

void BlockLocalPositionEstimator::updateSSParams()
{
    // input noise covariance matrix
    _R.setZero();
    //_R(U_ax, U_ax) = _accel_xy_stddev.get() * _accel_xy_stddev.get();   LPE_ACC_XY
    _R(U_ax, U_ax) = 0.012f * 0.012f;
    //_R(U_ay, U_ay) = _accel_xy_stddev.get() * _accel_xy_stddev.get();   LPE_ACC_XY
    _R(U_ay, U_ay) = 0.012f * 0.012f;
    //_R(U_az, U_az) = _accel_z_stddev.get() * _accel_z_stddev.get();     LPE_ACC_Z
    _R(U_az, U_az) = 0.02f * 0.02f;

    // process noise power matrix
    _Q.setZero();
    //float pn_p_sq = _pn_p_noise_density.get() * _pn_p_noise_density.get();
    float pn_p_sq = 0.1f * 0.1f;
    //float pn_v_sq = _pn_v_noise_density.get() * _pn_v_noise_density.get();
    float pn_v_sq = 0.1f * 0.1f;
    _Q(X_x, X_x) = pn_p_sq;
    _Q(X_y, X_y) = pn_p_sq;
    _Q(X_z, X_z) = pn_p_sq;
    _Q(X_vx, X_vx) = pn_v_sq;
    _Q(X_vy, X_vy) = pn_v_sq;
    _Q(X_vz, X_vz) = pn_v_sq;

    // technically, the noise is in the body frame,
    // but the components are all the same, so
    // ignoring for now
    //float pn_b_sq = _pn_b_noise_density.get() * _pn_b_noise_density.get();
    float pn_b_sq = 0.001f * 0.001f;
    _Q(X_bx, X_bx) = pn_b_sq;
    _Q(X_by, X_by) = pn_b_sq;
    _Q(X_bz, X_bz) = pn_b_sq;

    // terrain random walk noise ((m/s)/sqrt(hz)), scales with velocity
    /*float pn_t_noise_density =
        _pn_t_noise_density.get() + (_t_max_grade.get() / 100.0f) * sqrtf(_x(X_vx) * _x(X_vx) + _x(X_vy) * _x(X_vy));*/

    float pn_t_noise_density = 0.001f + (1.0 / 100.0f) * sqrtf(_x(X_vx) * _x(X_vx) + _x(X_vy) * _x(X_vy));
    _Q(X_tz, X_tz) = pn_t_noise_density * pn_t_noise_density;

}

void BlockLocalPositionEstimator::predict()
{
    // get acceleration
    float acc[3],angle[3];
    angle[0] = JY901.stcAngle.Angle[0] / 32768 * 180;
    angle[1] = JY901.stcAngle.Angle[1] / 32768 * 180;
    angle[2] = JY901.stcAngle.Angle[2] / 32768 * 180;

    matrix::Euler<float> eul(angle[0],angle[1],angle[2]);
    matrix::Quaternion<float> q(eul);
    //q.from_euler(JY901.stcAngle.Angle[0] / 32768 * 180,JY901.stcAngle.Angle[1] / 32768 * 180,JY901.stcAngle.Angle[2] / 32768 * 180);
    //from_euler(JY901.stcAngle.Angle[0] / 32768 * 180,JY901.stcAngle.Angle[1] / 32768 * 180,JY901.stcAngle.Angle[2] / 32768 * 180);              //当前四元数     ================================
    _eul = matrix::Euler<float>(q);
    _R_att = matrix::Dcm<float>(q);

    acc[0] = (float)JY901.stcAcc.a[0]/32768*16*9.81;
    acc[1] = (float)JY901.stcAcc.a[1]/32768*16*9.81;
    acc[2] = (float)JY901.stcAcc.a[2]/32768*16*9.81;

    Vector3f a(acc[0], acc[1], acc[2]);                                  //当前加速度     ================================
    // note, bias is removed in dynamics function
    _u = _R_att * a;
    //_u(U_az) += 9.81f; // add g

    // update state space based on new states
    updateSSStates();

    // continuous time kalman filter prediction
    // integrate runge kutta 4th order
    // TODO move rk4 algorithm to matrixlib
    // https://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods
    float h = getDt();
    Vector<float, n_x> k1, k2, k3, k4;
    k1 = dynamics(0, _x, _u);
    k2 = dynamics(h / 2, _x + k1 * h / 2, _u);
    k3 = dynamics(h / 2, _x + k2 * h / 2, _u);
    k4 = dynamics(h, _x + k3 * h, _u);
    Vector<float, n_x> dx = (k1 + k2 * 2 + k3 * 2 + k4) * (h / 6);

     don't integrate position if no valid xy data
    //if (!(_estimatorInitialized & EST_XY))  
    //{
    //  dx(X_x) = 0;
    //  dx(X_vx) = 0;
    //  dx(X_y) = 0;
    //  dx(X_vy) = 0;
    //}

     don't integrate z if no valid z data
    //if (!(_estimatorInitialized & EST_Z))  
    //{
    //  dx(X_z) = 0;
    //}

     don't integrate tz if no valid tz data
    //if (!(_estimatorInitialized & EST_TZ))  
    //{
    //  dx(X_tz) = 0;
    //}

    // saturate bias
    float bx = dx(X_bx) + _x(X_bx);
    float by = dx(X_by) + _x(X_by);
    float bz = dx(X_bz) + _x(X_bz);

    if (std::abs(bx) > BIAS_MAX) 
    {
        bx = BIAS_MAX * bx / std::abs(bx);
        dx(X_bx) = bx - _x(X_bx);
    }

    if (std::abs(by) > BIAS_MAX) {
        by = BIAS_MAX * by / std::abs(by);
        dx(X_by) = by - _x(X_by);
    }

    if (std::abs(bz) > BIAS_MAX) {
        bz = BIAS_MAX * bz / std::abs(bz);
        dx(X_bz) = bz - _x(X_bz);
    }

    // propagate
    _x += dx;
    Matrix<float, n_x, n_x> dP = (_A * _P + _P * _A.transpose() +
                      _B * _R * _B.transpose() + _Q) * getDt();

    // covariance propagation logic
    for (int i = 0; i < n_x; i++) 
    {
        if (_P(i, i) > P_MAX) 
        {
            // if diagonal element greater than max, stop propagating
            dP(i, i) = 0;

            for (int j = 0; j < n_x; j++) 
            {
                dP(i, j) = 0;
                dP(j, i) = 0;
            }
        }
    }
    _P += dP;
    //_xLowPass.update(_x);
    //_aglLowPass.update(agl());
}

void BlockLocalPositionEstimator::publishLocalPos()
{
    //const Vector<float, n_x> &xLP = _xLowPass.getState();

    //_pub_lpos.get().x = xLP(X_x);     // north
    //_pub_lpos.get().y = xLP(X_y);     // east
    //_pub_lpos.get().z = xLP(X_z);     // down

    //_pub_lpos.get().vx = xLP(X_vx); // north
    //_pub_lpos.get().vy = xLP(X_vy); // east
    //_pub_lpos.get().vz = xLP(X_vz); // down
}

最终效果展示

lpe移植

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

px4飞控位置估计lpe移植到vs 的相关文章

  • (8)requests发起get/post请求

    一 基本概念 1 什么是接口 前后端数据传输的通道 2 http请求的接口 协议 43 域名 ip 43 接口地址 43 请求参数 3 http请求的要素 请求地址 43 请求方法 43 请求数据 二 request请求接口 1 安装 pi
  • 【面试必备】面向Android开发者的复习指南!最全的BAT大厂面试题整理

    近日一好友去阿里面试 xff0c 面试失败了 xff0c 分享了一个他最不擅长的算法面试题 题目是这样的 题目 xff1a 给定一个二叉搜索树 BST xff0c 找到树中第 K 小的节点 出题人 xff1a 阿里巴巴出题专家 xff1a
  • c memcpy 带重叠部分 实现

    主要是要注意当目标地址在源地址后面且存在重叠区域的时候 xff0c 需要从后往前复制 span class token macro property span class token directive hash span span cla
  • 主流PCB画图软件的对比区别(AD、Pads、Allegro)

    国内的EDA软件市场几乎被三家瓜分 xff0c 分别是Altium Mentor Pads Cadence xff0c 也是我们这次主要分析和比较的软件 本人用的多的是 Alitum 也用过allegro xff0c pads目前还没用过
  • 新书推荐 |《Prometheus监控实战》

    新书推荐 Prometheus监控实战 点击上图了解及购买 Docker公司前服务与支持副总裁 Kickstarter前首席技术官 Empatico首席技术官撰写 xff0c 全方位介绍继Kubernetes之后的第二个CNCF毕业项目 P
  • 腾讯大数据总体架构图,对外公开!

    导读 xff1a 腾讯作为国内体量最大的互联网公司之一 xff0c 业务涵盖用户日常生活的方方面面 xff0c 面对如此巨大业务数据量 xff0c 如果不能对数据进行专业化处理并高效有序地存 管 用 xff0c 如果不能使数据产生应有的价值
  • API安全实战

    一提起 信息安全 xff0c 不管是业内专家还是所谓的 吃瓜群众 xff0c 多半都会在脑海中浮现 网络安全 Web安全 软件安全 数据安全 等常见的词汇 市面上绝大多数安全类书籍也多集中在这几个领域 xff0c 而从API视角阐释信息安全
  • 【第115期】世界一流大学计算机专业,都在用哪些书当教材?

    导读 xff1a 转眼间离新学期开学又不远了 清华 北大 MIT CMU 斯坦福的学霸们在新学期里要学什么 xff1f 本文就带你盘点一下那些世界名校计算机专业采用的教材 不用多说 xff0c 每本都是经典的烧脑技术书 xff0c 建议配合
  • 什么是AB实验?能解决什么问题?终于有人讲明白了

    导读 xff1a 走向身边的AB实验 作者 xff1a 木羊同学 来源 xff1a 大数据DT xff08 ID xff1a hzdashuju xff09 AB实验 是一个从统计学中借来的工具 我和大家一样 xff0c 每次只要看到 统计
  • 树莓派3b引脚图

    如上图所示 xff0c 我们可以很清楚的看到各个引脚的功能 例如我们想使用pwm引脚来控制舵机 xff0c 则我们可以考虑使用其中的 BCM18 PWM0 和 BCM13 PWM1 在使用wiringPi库时 xff0c 我们定义的引脚即B
  • 跟踪slab分配堆栈流程的方法(perf、systemtap)

    跟踪slab分配堆栈流程的方法 xff08 perf systemtap xff09 内存泄露是在解决内核故障会遇到的棘手情况 xff0c 根据具体的内存使用情况 xff0c 追踪相应slab cache的分配堆栈流程 xff0c 是追踪泄
  • prometheus+grafana监控mysql、canal服务器

    一 prometheus配置 1 prometheus安装 1 1官网下载安装包 xff1a https prometheus io download 1 2解压安装包 xff1a tar zxvf prometheus 2 6 1 lin
  • mac配置jmeter

    一 步骤 1 安装jdk1 8版本 xff0c 因为jmeter是基于java环境运行的 2 安装jmeter5 x版本 二 安装jdk 1 下载jdk Java Downloads Oracle 2 下载好之后安装 xff0c 全部下一步
  • 操作系统(四):动态链接与静态链接的区别

    在回答这个问题之前希望大家大概了解一个文件编译的过程 xff0c 比如一个C文件在编译成功后文件夹里的文件会有什么变化 xff0c 大家可以先去创建一个helloworld c的文件 xff0c 观察其编译后的变化 那么问题来了 面试官经常
  • 【OpenVINS】(一)ZUPT

    参考 xff1a Measurement Update Derivations Zero Velocity Update 在典型的自主汽车场景中 xff0c 传感器系统将在停止灯处变得静止 xff0c 其中动态物体 xff08 例如交叉路口
  • OpenVINS与MSCKF_VIO RK4积分对比

    VIO系统在使用IMU测量值进行状态预测时 xff0c 需要将连续时间的微分方程离散化为差分方程 xff0c 离散化的本质是积分 xff0c 根据数值积分近似程度不同 xff0c 常用的有欧拉法 中点法和四阶龙格库塔法等 xff0c Ope
  • 全盘拷贝linux系统,转移至另一硬盘

    首先制作ubuntu启动盘 xff0c 选择try ubuntu进入live ubuntu系统 查看需拷贝硬盘盘符 span class token function sudo span span class token function
  • EKF SLAM

    EKF 方法是解决 SLAM 问题的一种经典方法 xff0c 其应用依赖于运动模型和观测模型的高斯噪声假设 在 SLAM 问题首次提出不久后 xff0c Smith 和 Cheesman 及 Durrant Whyte对机器人和路标间的几何
  • 如何将立创EDA中的元器件的原理图/封装和3D模型导入AD的库中

    如何将立创EDA中的元器件的原理图 封装和3D模型导入AD的库中 工具 xff1a AD 立创EDA专业版 fusion360 或其他3D软件 导入原理图 封装 在立创商城复制所需元器件的编号 打开立创EDA标准版或专业版 xff0c 这里
  • Xshell 提示 “要继续使用此程序,您必须应用最新的更新或使用新版本“的解决方案

    要想解决Xshell提示更新最新版问题 有两种方案 方案一 手动修改系统时间 步骤如下 右键右下角时间 弹出如下窗口 2 选中 调整日期 时间 A 并点击 弹出如下页面 更改时间 更改成之前的年份 如下图 更改成功后 再打开相应的应用 Xs

随机推荐

  • 2020.2.22 排位赛 G - Bucket Brigade(BFS)

    Bucket Brigade 题面 题目分析 BFS模板题 代码 span class token macro property span class token directive keyword include span span cl
  • Canal入门(二)

    Canal入门 xff08 二 xff09 canal kafka quickStart 1 基本说明 canal 1 1 1版本之后 默认支持将canal server接收到的binlog数据直接投递到MQ 目前默认支持的MQ系统有 ka
  • PID调节三个参数的作用

    1 比例调节作用 xff1a 按比例反应系统的偏差 系统一旦出现了偏差 比例调节立即产生调节作用用以减少偏差 比例作用大 可 以加快调节 能迅速反应误差 xff0c 从而减小稳态误差 但是 xff0c 比例控制不能消除稳态误差 过大的比例
  • (centos7)docker+jenkins运行python自动化

    目录 一 实现思路 二 环境准备 1 在liunx上安装docker 2 docker安装jenkins 三 访问前设置 四 配置jenkins容器 五 jenkins插件安装 1 安装git 2 安装docker 3 html Publi
  • OJ在线编程常见输入输出练习

    OJ在线编程常见输入输出练习 4 a 43 b 4 输入描述 xff1a 输入数据包括多组 每组数据一行 每行的第一个整数为整数的个数n 1 lt 61 n lt 61 100 n为0的时候结束输入 接下来n个正整数 即需要求和的每个正整数
  • js中数组与集合的相互转化

    数组 gt 集合 var a 61 1 2 3 4 5 5 var set 61 new Set a console log set 1 2 3 4 5 集合 gt 数组 var set 61 new Set set add 1 set a
  • Linux make/Makefile详解

    会不会写makefile xff0c 从侧面说明了一个人是否具备完成大型工程的能力 一个工程中的源文件不计数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c makefile定义了一系列的 规则来指定 xff0c 哪些文件
  • 大疆H20系列吊舱,录制的视频含义

  • 写算法的方法

    写算法步骤 xff1a xff08 以下方法 xff0c 都是老生常谈 但是非常简单有用 xff09 数据结构 xff08 所有的算法都是基于数据结构的操作 所有算法都是针对数据结构的属性进行操作 列出所有的属性 xff0c 写算法逐项修改
  • Windows系统下QT+OpenCasCAD仿真开发

    背景 最近开发了一个六自由度机械臂调姿平台的控制软件 xff0c 集成了API激光跟踪仪和KUKA机器人 xff0c 实现了根据产品的测量位姿驱动仿真环境中模型并且实现模型间的碰撞检测 其中KUKA机器人的控制可以参考笔者以前的博客 xff
  • 飞控IMU姿态估计流程

    飞控中使用加速度计 xff0c 陀螺仪 xff0c 磁罗盘进行姿态估计算法流程 step1 xff1a 获取陀螺仪 xff0c 加速度计 xff0c 磁罗盘的原始数值 step2 xff1a 陀螺仪 xff0c 加速度计减去固定的偏移后得到
  • 图拓扑关系可视化的qt实现

    前言 最近在做数据可视化的相关工作 xff0c 包括曲线图 xff0c 航迹图 xff0c 图结构 xff0c 树结构等 其中树结构相关的工作笔者以前曾经做过 xff0c 可以参考笔者以前的博客 qt自定义树形控件之一和qt自定义树形控件之
  • 基于qwt3D 的3D航迹图的实现

    前言 使用qt实现三维空间直角坐标系中的航迹实时绘制网上很难查到资料 在qt下实现3D绘图通常实现方式有OpenGL VTK qwt3d QtDataVisualization等 Qcharts QCustomPlot只支持2D绘图 这里给
  • 树莓派4b连接RealSense T265

    使用的是树莓派4 8G版本 准备连接RealSense T265的双目相机 T265目前官方编译好的的只有Ubuntu16和18 其他的系统版本需要自己编译realsense驱动 安装ubuntu20 10 https ubuntu com
  • Dockerfile文件解释

    一 先来看一个简单的 Dockerfile 这个Dockerfile作用是打一个python3项目环境 FROM python 3 alpine WORKDIR app ADD app RUN pip3 install r requirem
  • 一文读懂BLOB算法

    算法执行效果 相关参考资料 看着玩的 BLOB算法简述 https blog csdn net icyrat article details 6594574 话说这老哥写的也太 简 了吧 完全口水话 把blob算法说的很神秘 说什么把blo
  • Sobel算法优化 AVX2与GPU

    国庆假期 一口气肝了10篇博客 基本上把最近的成果都做了遍总结 假期最后一天 以一个比较轻松的博客主题结束吧 这次是Sobel算法的AVX2优化 执行效果 sobel算法的原理 使用如下的卷积核 c 硬写 span class token
  • 随机Hough直线算法的改进

    背景介绍 随机Hough直线算法相比Hough直线算法 xff0c 算法效率会有提高 xff0c 但仍不能满足工程需求 因此提出使用生长的随机Hough直线算法 该算法对随机Hough直线算法进行改造 xff0c 在随机选点转到Hough空
  • MATLAB编写的读取.mat文件数据并画曲线图的gui程序

    matlab编写的读取sd卡数据的gui程序 界面截图 xff1a 打开文件界面 xff1a 导入数据后截图 xff1a 是不是高端大气上档次 xff0c 不要急 xff0c 慢慢往下看 xff0c 后面更精彩 xff0c 代码会贴出来的
  • px4飞控位置估计lpe移植到vs

    本文主要内容 px4飞控的位置估计有两种方式 xff0c 一是inav xff0c 二是lpe xff0c 用到的传感器用加速度计 xff0c 磁场传感器 xff0c gps xff0c 超声 xff0c 激光 xff0c 气压 xff0c