MPU6050欧拉角计算旋转后三维坐标平面与水平面(初始xoy平面)夹角算法(外旋)-程序员宅基地

技术标签: 算法  python  c++  Arduion  c语言  

前言

        MPU6050六轴传感器可通过加速度传感器和陀螺仪同时输出加速度和角速度,配合一些开源项目(fusion、DMP等)计算出相应的四元素和欧拉角等,可通过欧拉角计算出旋转后的三维坐标系的各平面(旋转后得到的xoy平面、xoz平面、yoz平面)与水平面(初始xoy平面)夹角。

欧拉角旋转定义(重要)

        在使用欧拉角演示旋转之前,必须先规定欧拉角旋转顺序!!!(z->y->x or z->x->y等顺序)因为在围绕x轴、y轴、z轴旋转相同的角度,顺序不一样最后得到的旋转姿态会有所不同。大部分开源旋转顺序计算使用的是z-y-x顺序旋转包括MPU6050自带的DMP融合算法。

欧拉角外旋

        欧拉角外旋通俗讲就是使用世界坐标系,在一些开源项目里使用加速度和角速度计算出的欧拉角,无论MPU6050处于什么样的状态上电,x轴和y轴组成的平面始终平行于水平面。

        (重要!!!)在外旋的旋转过程中,因为已经规定了旋转顺序,正常来说就必须按照旋转轴的顺序进行旋转。在正常的外旋情况下,排在前面的旋转轴先进行旋转时,不会影响排在后面顺序的轴初始状态的改变(因为世界坐标的缘故)。但是如果排在后面的旋转轴先旋转了,再旋转排在前面的旋转轴,就会导致前面旋转轴初始方向的改变。

欧拉角内旋

        欧拉角内旋就是使用本地坐标系,即初始三维坐标的x轴和y轴组成的平面就是MPU6050芯片上电时所处的平面。

        (重要!!!)在内旋的旋转过程中,因为已经规定了旋转顺序,正常来说就必须按照旋转轴的顺序进行旋转。在正常的内旋情况下,排在前面的旋转轴先进行旋转时,会影响排在后面顺序的轴初始状态的改变(后面的旋转轴会绕着排在前面的旋转轴旋转相同的旋转角度,并改变初始方向,后面的旋转轴根据前面旋转后得到的新的旋转轴再进行旋转)。如果排在后面的旋转轴先旋转了,再旋转排在前面的旋转轴,也会导致前面旋转轴初始方向的改变。

万向节死锁(重要!!)

        内旋:当我规定了以z-y-x顺序旋转时。如果y轴先旋转,并且刚好旋转了90°,(因为后面的旋转会影响前面轴初始态的缘故)就会导致z轴和x轴重合且方向相同,我再进行z轴或者x轴旋转,欧拉角x和z就会同时递增或者递减;如果y轴先旋转,并且刚好旋转了-90°,(因为后面的旋转会影响前面轴初始态的缘故)就会导致z轴和x轴重合且方向相反,我再进行z轴或者x轴旋转,欧拉角x和z就会同时一个递增一个递减

        外旋:当我规定了以z-y-x顺序旋转时。如果y轴先旋转,并且刚好旋转了-90°,(因为后面的旋转会影响前面轴初始态的缘故)就会导致z轴和x轴重合且方向相同,我再进行z轴或者x轴旋转,欧拉角x和z就会同时递增或者递减;如果y轴先旋转,并且刚好旋转了90°,(因为后面的旋转会影响前面轴初始态的缘故)就会导致z轴和x轴重合且方向相反,我再进行z轴或者x轴旋转,欧拉角x和z就会同时一个递增一个递减

        同理:规定了其他旋转顺序进行旋转时,只要在中间的旋转轴先旋转,并且刚好旋转了90°或-90°,就会发生万向节死锁。

关于欧拉角内旋和外旋问题可以通过Github上的开源项目rotation_master进行演示方便理解(感谢这位大神)

Release v20220112 · iwatake2222/rotation_master · GitHub

MPU6050缺陷

        MPU6050在没有外部磁力传感器的作用下时,芯片就没法获取地磁数据(地球磁力),所以就会导致欧拉角z在不断改变(上电初始化后,在使用一段时间后回到初始状态欧拉角z会有莫名其妙的角度,并且内旋外旋都存在这个问题),欧拉角z不断改变的结果就是:在三维旋转坐标中,x轴和y轴的初始方向的改变。

算法衍生

        虽然x轴和y轴的初始方向在不断改变,但他们所组成的xoy平面是不会改变的,所以在规定了一定旋转顺序旋转后的三维坐标各平面与初始xoy平面所构成的面面角就不会因为z轴(欧拉角z)的不确定性而发生改变,算法的构思适用于内旋和外旋,但是算法不同。

        面面角取值范围为0°—180°,可根据欧拉角的正负号判定面面角的正负号,就能给出旋转角度为-180°—180°,从而就能得出所有旋转状态返回的三个面面角组成的数组唯一性。(这里只给出了C/C++的正负号判断,Python重写很简单,但是我懒)

C/C++代码(外旋)

// 绕某旋转后点及初始轴
double *RodriguesRotate(double angle, double x1, double y1, double z1, double x2, double y2, double z2){

    double sin_angle = sin(angle * M_PI / 180.0);
    double cos_angle = cos(angle * M_PI / 180.0);
  
    double x = x1 * cos_angle + (y2 * z1 - z2 * y1) * sin_angle + x2 * (x2 * x1 + y2 * y1 + z2 * z1) * (1 - cos_angle);
    double y = y1 * cos_angle + (z2 * x1 - x2 * z1) * sin_angle + y2 * (x2 * x1 + y2 * y1 + z2 * z1) * (1 - cos_angle);
    double z = z1 * cos_angle + (x2 * y1 - y2 * x1) * sin_angle + z2 * (x2 * x1 + y2 * y1 + z2 * z1) * (1 - cos_angle);
    
    double *verts = new double [3];
    verts[0] = x;
    verts[1] = y;
    verts[2] = z;
    
    return verts;
}

// 过原点平面法向量计算
double *normal_vector(double x1,double y1,double z1,double x2,double y2,double z2){

    double a = (y1*z2)-(y2*z1);
    double b = (z1*x2)-(z2*x1);
    double c = (x1*y2)-(x2*y1);

    double *normal_vectors = new double [3];
    normal_vectors[0] = a;
    normal_vectors[1] = b;
    normal_vectors[2] = c;  
    
    return normal_vectors;
}

// 旋法向量与初始xoy平面法向量夹角
double dihedral_angle(double x, double y, double z){
    double angle = acos((x * 0 + y * 0 + z * 1) / sqrt(x * x + y * y + z * z)) * 180 / M_PI;
    return angle;
}



//主函数:
    
    Serial.print("欧拉角X : ");Serial.print(mpu6050.getAngleX());
    Serial.print("\t欧拉角Y : ");Serial.print(mpu6050.getAngleY());
    Serial.print("\t欧拉角Z : ");Serial.println(mpu6050.getAngleZ());

    // 定义初始点坐标
    double verts[4][3] = {
   {0, 0, 0}, {1, 0, 0}, {0, 1, 0}, {0, 0, 1}};

    // 计算X轴,Y轴旋转后初始坐标
    double *Sz_Y = RodriguesRotate(mpu6050.getAngleZ(),verts[2][0], verts[2][1], verts[2][2], verts[3][0], verts[3][1], verts[3][2]);
    double *Sz_X = RodriguesRotate(mpu6050.getAngleZ(), verts[1][0], verts[1][1], verts[1][2], verts[3][0], verts[3][1], verts[3][2]);
    double *Szy_X = RodriguesRotate(mpu6050.getAngleY(), Sz_X[0], Sz_X[1], Sz_X[2], Sz_Y[0], Sz_Y[1], Sz_Y[2]);

    // 计算旋转后点坐标
    double new_o[3] = {verts[0][0], verts[0][1], verts[0][2]};
    
    double *x_rz = RodriguesRotate(mpu6050.getAngleZ(), verts[1][0], verts[1][1], verts[1][2], verts[3][0], verts[3][1], verts[3][2]);
    double *x_ry = RodriguesRotate(mpu6050.getAngleY(), x_rz[0],x_rz[1],x_rz[2],Sz_Y[0],Sz_Y[1],Sz_Y[2]);
    double *new_x = RodriguesRotate(mpu6050.getAngleX(), x_ry[0],x_ry[1],x_ry[2],Szy_X[0],Szy_X[1],Szy_X[2]);
    if(!x_rz) delete(x_rz);
    if(!x_ry) delete(x_ry);

    double *y_rz = RodriguesRotate(mpu6050.getAngleZ(), verts[2][0], verts[2][1], verts[2][2], verts[3][0], verts[3][1], verts[3][2]);
    double *y_ry = RodriguesRotate(mpu6050.getAngleY(), y_rz[0],y_rz[1],y_rz[2],Sz_Y[0],Sz_Y[1],Sz_Y[2]);
    double *new_y = RodriguesRotate(mpu6050.getAngleX(), y_ry[0],y_ry[1],y_ry[2],Szy_X[0],Szy_X[1],Szy_X[2]);
    if(!y_rz) delete(y_rz);
    if(!y_ry) delete(y_ry);

    double *z_rz = RodriguesRotate(mpu6050.getAngleZ(), verts[3][0], verts[3][1], verts[3][2], verts[3][0], verts[3][1], verts[3][2]);
    double *z_ry = RodriguesRotate(mpu6050.getAngleY(), z_rz[0],z_rz[1],z_rz[2],Sz_Y[0],Sz_Y[1],Sz_Y[2]);
    double *new_z = RodriguesRotate(mpu6050.getAngleX(), z_ry[0],z_ry[1],z_ry[2],Szy_X[0],Szy_X[1],Szy_X[2]);
    if(!z_rz) delete(z_rz);
    if(!z_ry) delete(z_ry);

    if(!Sz_Y) delete(Sz_Y);
    if(!Sz_X) delete(Sz_X);
    if(!Szy_X) delete(Szy_X);

    // 旋转后的三维坐标系的点组成的三个面的法向量
    double *normal_vector_xoy = normal_vector(new_x[0], new_x[1], new_x[2], new_y[0], new_y[1], new_y[2]);
    double *normal_vector_xoz = normal_vector(new_x[0], new_x[1], new_x[2], new_z[0], new_z[1], new_z[2]);
    double *normal_vector_yoz = normal_vector(new_y[0], new_y[1], new_y[2], new_z[0], new_z[1], new_z[2]);
    if(!new_x) delete(new_x);
    if(!new_y) delete(new_y);
    if(!new_z) delete(new_z);

    // 法向量与初始xoy平面法向量夹角
    double dihedral_angle_xoy = dihedral_angle(normal_vector_xoy[0], normal_vector_xoy[1], normal_vector_xoy[2]);
    double dihedral_angle_xoz = dihedral_angle(normal_vector_xoz[0], normal_vector_xoz[1], normal_vector_xoz[2]);
    double dihedral_angle_yoz = dihedral_angle(normal_vector_yoz[0], normal_vector_yoz[1], normal_vector_yoz[2]);

    //范围:-180°<——>+180°
    if (normal_vector_yoz[2] >= 0) {
      Serial.print("XY与水平面夹角:");
      Serial.print(dihedral_angle_xoy);
    }
    else{
      Serial.print("XY与水平面夹角:");
      Serial.print(- dihedral_angle_xoy);
    }
    if (normal_vector_xoy[2] >= 0) {
      Serial.print("XZ与水平面夹角:");
      Serial.print(dihedral_angle_xoz);
    }
    else {
      Serial.print("XZ与水平面夹角:");
      Serial.print(- dihedral_angle_xoz);
    }
    if (normal_vector_xoz[2] >= 0) {
      Serial.print("YZ与水平面夹角:");
      Serial.print(dihedral_angle_yoz);
    }
    else{
      Serial.print("YZ与水平面夹角:");
      Serial.print(- dihedral_angle_yoz);
    }

    if(!normal_vector_xoy) delete(normal_vector_xoy);
    if(!normal_vector_xoz) delete(normal_vector_xoz);
    if(!normal_vector_yoz) delete(normal_vector_yoz);

Python代码(外旋)(使用numpy)

import math
import numpy as np

# 计算绕某轴旋转后的点及顺序后的旋转轴
def RodriguesRotate(angle, v, u):
    '''向量v绕向量u旋转角度θ,得到新的向量vert
    罗德里格斯旋转公式:v' = vcosθ + (u×v)sinθ + (u·v)u(1-cosθ)

    args:
        v:向量,维度为(3,)
        u:作为旋转轴的向量,维度为(3,)
        angle:旋转角度θ,此处默认为角度值
    returns:
        vert:旋转后得到的向量,维度为(3,)
    '''
    u = u / np.linalg.norm(u)  # 计算单位向量
    sin_angle = np.sin(angle * np.pi / 180)
    cos_angle = np.cos(angle * np.pi / 180)
    vert = v * cos_angle + np.cross(u, v) * sin_angle + np.dot(u, v) * u * (1 - cos_angle)
    verts = vert.tolist()
    return verts

# 计算旋转后三维坐标系的各平面法向量
def normal_vector(x1,y1,z1,x2,y2,z2,x3,y3,z3):

    a = (y2-y1)*(z3-z1)-(y3-y1)*(z2-z1)
    b = (z2-z1)*(x3-x1)-(z3-z1)*(x2-x1)
    c = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)
    verts = (a, b, c)
    return verts

# 计算旋转后三维坐标系的各平面与初始xoy平面夹角
def dihedral_angle(x, y, z):
    angle = math.acos((x * 0 + y * 0 + z * 1) / (x**2 + y**2 + z**2)**0.5) * 180 / math.pi
    return angle


def test(X, Y, Z):

    # 定义初始三维坐标系单位初始点坐标
    verts = [(0, 0, 0),(1, 0, 0), (0, 1, 0), (0, 0, 1)]

    # X轴,Y轴经旋转顺序后的初始向量坐标
    # 严格按照z-y-x旋转顺序进行计算
    Sz_Y = RodriguesRotate(Z, np.array(verts[2]), np.array(verts[3]))
    Sz_X = RodriguesRotate(Z, np.array(verts[1]), np.array(verts[3]))
    Szy_X = RodriguesRotate(Y, np.array(Sz_X), np.array(Sz_Y))
    print("y轴经过z轴旋转后状态:",Sz_Y)
    print("x轴经过z轴旋转后状态:",Sz_X)
    print("x轴经过z轴和y轴旋转后状态:",Szy_X)

    # 经旋转顺序后定义的单位点坐标
    # 严格按照z-y-x旋转顺序进行计算
    verts_z = [RodriguesRotate(Z, np.array(vert), np.array(verts[3])) for vert in verts]
    verts_zy = [RodriguesRotate(Y, np.array(vert), np.array(Sz_Y)) for vert in verts_z]
    verts_zyx = [RodriguesRotate(X, np.array(vert), np.array(Szy_X)) for vert in verts_zy]

    # 旋转后的三维坐标系的各个点组成的三个面
    xoy1 = [verts_zyx[0] + verts_zyx[1] + verts_zyx[2]]
    xoz1 = [verts_zyx[0] + verts_zyx[1] + verts_zyx[3]]
    yoz1 = [verts_zyx[0] + verts_zyx[2] + verts_zyx[3]]

    # 旋转后三维坐标系中三个平面的法向量
    normal_vector_xoy = [normal_vector(vert[0], vert[1], vert[2], vert[3], vert[4], vert[5], vert[6], vert[7], vert[8])
                         for vert in xoy1]
    normal_vector_xoz = [normal_vector(vert[0], vert[1], vert[2], vert[3], vert[4], vert[5], vert[6], vert[7], vert[8])
                         for vert in xoz1]
    normal_vector_yoz = [normal_vector(vert[0], vert[1], vert[2], vert[3], vert[4], vert[5], vert[6], vert[7], vert[8])
                         for vert in yoz1]

    # 法向量与初始xoy平面法向量(oz向量)夹角
    # 两平面法向量夹角就是面面角
    dihedral_angle_xoy = [dihedral_angle(vert[0], vert[1], vert[2]) for vert in normal_vector_xoy]
    dihedral_angle_xoz = [dihedral_angle(vert[0], vert[1], vert[2]) for vert in normal_vector_xoz]
    dihedral_angle_yoz = [dihedral_angle(vert[0], vert[1], vert[2]) for vert in normal_vector_yoz]
    print("旋转后三维坐标系中的xoy平面与初始xoy平面夹角:", dihedral_angle_xoy)
    print("旋转后三维坐标系中的xoz平面与初始xoy平面夹角:", dihedral_angle_xoz)
    print("旋转后三维坐标系中的yoz平面与初始xoy平面夹角:", dihedral_angle_yoz)

test(45,45,45) # 参数为欧拉角x,欧拉角y,欧拉角z

Python代码(外旋)(不使用numpy)

import math

# 计算绕某轴旋转后的点及顺序后的旋转轴
def RodriguesRotate(angle, x1, y1, z1, x2, y2, z2):

    sin_angle = math.sin(angle * math.pi / 180)
    cos_angle = math.cos(angle * math.pi / 180)

    x = x1 * cos_angle + (y2 * z1 - z2 * y1) * sin_angle + x2 * (x2 * x1 + y2 * y1 + z2 * z1) * (1 - cos_angle);
    y = y1 * cos_angle + (z2 * x1 - x2 * z1) * sin_angle + y2 * (x2 * x1 + y2 * y1 + z2 * z1) * (1 - cos_angle);
    z = z1 * cos_angle + (x2 * y1 - y2 * x1) * sin_angle + z2 * (x2 * x1 + y2 * y1 + z2 * z1) * (1 - cos_angle);
    verts = (x, y, z)
    return verts

# 计算旋转后三维坐标系的各平面法向量
def normal_vector(x1,y1,z1,x2,y2,z2,x3,y3,z3):

    a = (y2-y1)*(z3-z1)-(y3-y1)*(z2-z1)
    b = (z2-z1)*(x3-x1)-(z3-z1)*(x2-x1)
    c = (x2-x1)*(y3-y1)-(x3-x1)*(y2-y1)
    verts = (a, b, c)
    return verts

# 计算旋转后三维坐标系的各平面与初始xoy平面夹角
def dihedral_angle(x, y, z):
    angle = math.acos((x * 0 + y * 0 + z * 1) / (x**2 + y**2 + z**2)**0.5) * 180 / math.pi
    return angle


def test(X, Y, Z):

    # 定义初始三维坐标系单位初始点坐标
    verts = [(0, 0, 0),(1, 0, 0), (0, 1, 0), (0, 0, 1)]

    # 经旋转顺序后定义的单位点坐标
    # 严格按照z-y-x旋转顺序进行计算
    Sz_Y = RodriguesRotate(Z, verts[2][0], verts[2][1], verts[2][2], verts[3][0], verts[3][1], verts[3][2])
    Sz_X = RodriguesRotate(Z, verts[1][0], verts[1][1], verts[1][2], verts[3][0], verts[3][1], verts[3][2])
    Szy_X = RodriguesRotate(Y, Sz_X[0], Sz_X[1], Sz_X[2], Sz_Y[0], Sz_Y[1], Sz_Y[2])
    print("y轴经过z轴旋转后:", Sz_Y)
    print("x轴经过z轴旋转后:", Sz_X)
    print("x轴经过z轴和y轴旋转后:", Szy_X)

    # X轴,Y轴经旋转顺序后的初始向量坐标
    # 严格按照z-y-x旋转顺序进行计算
    verts_z = [RodriguesRotate(Z, vert[0], vert[1], vert[2], verts[3][0], verts[3][1], verts[3][2]) for vert in verts]
    verts_zy = [RodriguesRotate(Y, vert[0], vert[1], vert[2], Sz_Y[0], Sz_Y[1], Sz_Y[2]) for vert in verts_z]
    verts_zyx = [RodriguesRotate(X, vert[0], vert[1], vert[2], Szy_X[0], Szy_X[1], Szy_X[2]) for vert in verts_zy]

    # 旋转后的三维坐标系的各个点组成的三个面
    xoy1 = [verts_zyx[0] + verts_zyx[1] + verts_zyx[2]]
    xoz1 = [verts_zyx[0] + verts_zyx[1] + verts_zyx[3]]
    yoz1 = [verts_zyx[0] + verts_zyx[2] + verts_zyx[3]]

    # 旋转后三维坐标系中三个平面的法向量
    normal_vector_xoy = [normal_vector(vert[0], vert[1], vert[2], vert[3], vert[4], vert[5], vert[6], vert[7], vert[8])
                         for vert in xoy1]
    normal_vector_xoz = [normal_vector(vert[0], vert[1], vert[2], vert[3], vert[4], vert[5], vert[6], vert[7], vert[8])
                         for vert in xoz1]
    normal_vector_yoz = [normal_vector(vert[0], vert[1], vert[2], vert[3], vert[4], vert[5], vert[6], vert[7], vert[8])
                         for vert in yoz1]

    # 法向量与初始xoy平面法向量(oz向量)夹角
    # 两平面法向量夹角就是面面角
    dihedral_angle_xoy = [dihedral_angle(vert[0], vert[1], vert[2]) for vert in normal_vector_xoy]
    dihedral_angle_xoz = [dihedral_angle(vert[0], vert[1], vert[2]) for vert in normal_vector_xoz]
    dihedral_angle_yoz = [dihedral_angle(vert[0], vert[1], vert[2]) for vert in normal_vector_yoz]
    print("旋转后三维坐标系中的xoy平面与初始xoy平面夹角:", dihedral_angle_xoy)
    print("旋转后三维坐标系中的xoz平面与初始xoy平面夹角:", dihedral_angle_xoz)
    print("旋转后三维坐标系中的yoz平面与初始xoy平面夹角:", dihedral_angle_yoz)

test(45,45,45) # 参数为欧拉角x,欧拉角y,欧拉角z

运行结果

y轴经过z轴旋转后: (-0.7071067811865476, 0.7071067811865476, 0.0)
x轴经过z轴旋转后: (0.7071067811865476, 0.7071067811865476, 0.0)
x轴经过z轴和y轴旋转后: (0.5000000000000001, 0.5000000000000001, -0.7071067811865477)
旋转后三维坐标系中的xoy平面与初始xoy平面夹角: [60.00000000000001]
旋转后三维坐标系中的xoz平面与初始xoy平面夹角: [120.00000000000001]
旋转后三维坐标系中的yoz平面与初始xoy平面夹角: [135.0]

内旋算法参考:https://blog.csdn.net/weixin_49861340/article/details/131106922

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/weixin_49861340/article/details/131093279

智能推荐

命令行安装todesk_todesk命令行csdn-程序员宅基地

文章浏览阅读653次,点赞10次,收藏7次。要想通过命令行安装todesk,也是比较简单的。_todesk命令行csdn

如何开发一个个人微信小程序,微信小程序开发入门教程_微信小程序怎么开发自己的小程序-程序员宅基地

文章浏览阅读10w+次,点赞183次,收藏1.1k次。做任何程序开发要首先找到其官方文档,我们先来看看其有哪些官方文档。微信小程序开发文档链接为:https://mp.weixin.qq.com/debug/wxadoc/dev/index.html,如下图:这里就是做微信小程序开发的全部官方文档。知道了文档的位置,下面我们来介绍下如何做一个微信小程序开发:第一步:下载微信小程序开发者工具并安装,下载路径:https://mp.weix..._微信小程序怎么开发自己的小程序

前端解决浏览器直接打开图片URL,下载问题_前端想要通过url下载但是打开了网页-程序员宅基地

文章浏览阅读1w次,点赞3次,收藏7次。本周做的项目中有一个下载图片的功能,拿到后台返回的url,像文件一样,直接window.open,发现图片没有像文件一样被下载,而是重新打开了一个页面展示图片。然后我尝试了转成base64等方法也还是有跨域的问题。后来就想着自己把这个url,发送给Node,node转成数据流返回给我,我再下载。话不多说,上代码:vue前端代码: downZip (urls) { ..._前端想要通过url下载但是打开了网页

什么是内部类?成员内部类、静态内部类、局部内部类和匿名内部类的区别及作用?_成员内部类和局部内部类的区别-程序员宅基地

文章浏览阅读3.4k次,点赞8次,收藏42次。一、什么是内部类?or 内部类的概念内部类是定义在另一个类中的类;下面类TestB是类TestA的内部类。即内部类对象引用了实例化该内部对象的外围类对象。public class TestA{ class TestB {}}二、 为什么需要内部类?or 内部类有什么作用?1、 内部类方法可以访问该类定义所在的作用域中的数据,包括私有数据。2、内部类可以对同一个包中的其他类隐藏起来。3、 当想要定义一个回调函数且不想编写大量代码时,使用匿名内部类比较便捷。三、 内部类的分类成员内部_成员内部类和局部内部类的区别

分布式系统_分布式系统运维工具-程序员宅基地

文章浏览阅读118次。分布式系统要求拆分分布式思想的实质搭配要求分布式系统要求按照某些特定的规则将项目进行拆分。如果将一个项目的所有模板功能都写到一起,当某个模块出现问题时将直接导致整个服务器出现问题。拆分按照业务拆分为不同的服务器,有效的降低系统架构的耦合性在业务拆分的基础上可按照代码层级进行拆分(view、controller、service、pojo)分布式思想的实质分布式思想的实质是为了系统的..._分布式系统运维工具

用Exce分析l数据极简入门_exce l趋势分析数据量-程序员宅基地

文章浏览阅读174次。1.数据源准备2.数据处理step1:数据表处理应用函数:①VLOOKUP函数; ② CONCATENATE函数终表:step2:数据透视表统计分析(1) 透视表汇总不同渠道用户数, 金额(2)透视表汇总不同日期购买用户数,金额(3)透视表汇总不同用户购买订单数,金额step3:讲第二步结果可视化, 比如, 柱形图(1)不同渠道用户数, 金额(2)不同日期..._exce l趋势分析数据量

随便推点

SpringBoot实践(三十五):JVM信息分析_怎样查看springboot项目的jvm状态-程序员宅基地

文章浏览阅读902次。JVM分析可以也可以使用,那么什么时候用到jvm信息分析呢,一般生产测试环境,能够最大化将问题暴露,但是总有些问题只有生产运行很长时间后才会被发现,jvm分析经常用于运行了很久的系统有异常情况时的调优,比如堆内存本身分配不合理,新生代中eden比例太低等。_怎样查看springboot项目的jvm状态

基于springboot+vue的戒毒所人员管理系统 毕业设计-附源码251514_戒毒所管理系统-程序员宅基地

文章浏览阅读288次。戒毒所人员管理系统的开发是采用java语言,基于MVVM模式进行开发,采取MySQL作为后台数据的主要存储单元,采用Springboot框架实现了本系统的全部功能。戒毒所人员管理系统,具有戒毒人员管理、尿检管理、戒毒管理、治疗分类、社会跟踪等功能,本系统代码的复用率高,系统维护代价小,具有方便、灵活、高效等特征。_戒毒所管理系统

【LeetCode】面试题57 - II. 和为s的连续正数序列_leet code 和为s的正数序列 java-程序员宅基地

文章浏览阅读174次。来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof题目描述:输入一个正整数 target ,输出所有和为 target 的连续正整数序列(至少含有两个数)。序列内的数字由小到大排列,不同序列按照首个数字从小到大排列。示例 1:输入:target = 9..._leet code 和为s的正数序列 java

java spark的使用和配置_使用java调用spark注册进去的程序-程序员宅基地

文章浏览阅读3.3k次。前言spark在java使用比较少,多是scala的用法,我这里介绍一下我在项目中使用的代码配置详细算法的使用请点击我主页列表查看版本jar版本说明spark3.0.1scala2.12这个版本注意和spark版本对应,只是为了引jar包springboot版本2.3.2.RELEASEmaven<!-- spark --> <dependency> <gro_使用java调用spark注册进去的程序

汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用_uds协议栈 源代码-程序员宅基地

文章浏览阅读4.8k次。汽车零部件开发工具巨头V公司全套bootloader中UDS协议栈源代码,自己完成底层外设驱动开发后,集成即可使用,代码精简高效,大厂出品有量产保证。:139800617636213023darcy169_uds协议栈 源代码

AUTOSAR基础篇之OS(下)_autosar 定义了 5 种多核支持类型-程序员宅基地

文章浏览阅读4.6k次,点赞20次,收藏148次。AUTOSAR基础篇之OS(下)前言首先,请问大家几个小小的问题,你清楚:你知道多核OS在什么场景下使用吗?多核系统OS又是如何协同启动或者关闭的呢?AUTOSAR OS存在哪些功能安全等方面的要求呢?多核OS之间的启动关闭与单核相比又存在哪些异同呢?。。。。。。今天,我们来一起探索并回答这些问题。为了便于大家理解,以下是本文的主题大纲:[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JCXrdI0k-1636287756923)(https://gite_autosar 定义了 5 种多核支持类型

推荐文章

热门文章

相关标签