【李群李代数】Sophus库中SE3类测试(附manif 与sophus 对比)

news2025/1/23 11:29:42

测试演示

8a45c63194599adc54a193876f84b280.png

测试结果

对Sophus库中SE3类进行一系列的测试,包括李群性质、原始数据访问、变异访问器、构造函数以及拟合等方面。在每个测试中,都会使用一些预设的数据进行操作,并通过SOPHUS_TEST_APPROX和SOPHUS_TEST_EQUAL等宏来检查操作结果是否符合预期。如果所有测试都通过,则整个程序会返回0,表示测试成功。如果有任何一个测试未通过,则程序会输出相应的错误信息。这是一种常见的单元测试策略,可以帮助开发者确保代码的正确性和稳定性。

se3测试源码:

#include <iostream>// 包含标准输入输出流库


#include <sophus/se3.hpp>// 包含Sophus库中的SE3类
#include "tests.hpp" // 包含测试头文件


// Explicit instantiate all class templates so that all member methods
// get compiled and for code coverage analysis.
// 显式实例化所有类模板,以便所有成员方法都被编译并进行代码覆盖率分析。
namespace Eigen {
template class Map<Sophus::SE3<double>>;// 实例化Map类模板,用于映射Sophus::SE3<double>类型
template class Map<Sophus::SE3<double> const>;// 实例化Map类模板,用于映射Sophus::SE3<double> const类型
}  // namespace Eigen


namespace Sophus {


template class SE3<double, Eigen::AutoAlign>;// 实例化SE3类模板,使用double类型和Eigen::AutoAlign对齐选项
template class SE3<float, Eigen::DontAlign>;// 实例化SE3类模板,使用float类型和Eigen::DontAlign对齐选项
#if SOPHUS_CERES
template class SE3<ceres::Jet<double, 3>>;  // 如果定义了SOPHUS_CERES,则实例化SE3类模板,使用ceres::Jet<double,
                                            // 3>类型
#endif


template <class Scalar>
class Tests {// 定义Tests类模板,用于测试
 public:
  using SE3Type = SE3<Scalar>;// 定义SE3Type类型别名,等价于SE3<Scalar>
  using SO3Type = SO3<Scalar>;// 定义SO3Type类型别名,等价于SO3<Scalar>
  using Point = typename SE3<Scalar>::Point;// 定义Point类型别名,等价于SE3<Scalar>::Point
  using Tangent = typename SE3<Scalar>::Tangent;// 定义Tangent类型别名,等价于SE3<Scalar>::Tangent
  Scalar const kPi = Constants<Scalar>::pi();// 定义常量kPi,等于pi的值


  Tests() {// 构造函数
    se3_vec_ = getTestSE3s<Scalar>();// 获取测试用的SE3对象向量


    Tangent tmp;// 定义临时变量tmp
    tmp << Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0);// 给tmp赋值
    tangent_vec_.push_back(tmp);// 将tmp添加到tangent_vec_向量中
    tmp << Scalar(1), Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0);
    tangent_vec_.push_back(tmp);
    tmp << Scalar(0), Scalar(1), Scalar(0), Scalar(1), Scalar(0), Scalar(0);
    tangent_vec_.push_back(tmp);
    tmp << Scalar(0), Scalar(-5), Scalar(10), Scalar(0), Scalar(0), Scalar(0);
    tangent_vec_.push_back(tmp);
    tmp << Scalar(-1), Scalar(1), Scalar(0), Scalar(0), Scalar(0), Scalar(1);
    tangent_vec_.push_back(tmp);
    tmp << Scalar(20), Scalar(-1), Scalar(0), Scalar(-1), Scalar(1), Scalar(0);
    tangent_vec_.push_back(tmp);
    tmp << Scalar(30), Scalar(5), Scalar(-1), Scalar(20), Scalar(-1), Scalar(0);
    tangent_vec_.push_back(tmp);


    point_vec_.push_back(Point(Scalar(1), Scalar(2), Scalar(4))); // 添加一个点到point_vec_向量中
    point_vec_.push_back(Point(Scalar(1), Scalar(-3), Scalar(0.5)));// 添加一个点到point_vec_向量中
    point_vec_.push_back(Point(Scalar(-5), Scalar(-6), Scalar(7)));// 添加一个点到point_vec_向量中
  }


  void runAll() {// 定义runAll函数,用于运行所有测试
    bool passed = testLieProperties();// 运行testLieProperties函数,测试李群性质
    passed &= testRawDataAcces();// 运行testRawDataAcces函数,测试原始数据访问
    passed &= testMutatingAccessors();// 运行testMutatingAccessors函数,测试变异访问器
    passed &= testConstructors();// 运行testConstructors函数,测试构造函数
    passed &= testFit();           // 运行testFit函数,测试拟合
    processTestResult(passed);// 处理测试结果
  }


 private:
  bool testLieProperties() {// 定义testLieProperties函数,用于测试李群性质
    // 创建LieGroupTests对象,用于测试SE3Type类型的李群性质
    LieGroupTests<SE3Type> tests(se3_vec_, tangent_vec_, point_vec_);
    return tests.doAllTestsPass();// 返回所有测试是否通过
  }


  bool testRawDataAcces() {// 定义testRawDataAcces函数,用于测试原始数据访问
    bool passed = true;// 定义passed变量,表示所有测试是否通过
    Eigen::Matrix<Scalar, 7, 1> raw;// 定义raw矩阵,用于存储原始数据
    raw << Scalar(0), Scalar(1), Scalar(0), Scalar(0), Scalar(1), Scalar(3),// 给raw矩阵赋值
        Scalar(2);
    Eigen::Map<SE3Type const> map_of_const_se3(raw.data());  // 创建map_of_const_se3对象,用于映射SE3Type
                                                             // const类型的数据
    // 测试map_of_const_se3对象的unit_quaternion()函数返回值的系数是否接近raw矩阵的前4个元素
    SOPHUS_TEST_APPROX(
        passed, map_of_const_se3.unit_quaternion().coeffs().eval(),
        raw.template head<4>().eval(), Constants<Scalar>::epsilon(), "");
    // 测试map_of_const_se3对象的translation()函数返回值是否接近raw矩阵的后3个元素
    SOPHUS_TEST_APPROX(passed, map_of_const_se3.translation().eval(),
                       raw.template tail<3>().eval(),
                       Constants<Scalar>::epsilon(), "");
    // 测试map_of_const_se3对象的unit_quaternion()函数返回值的系数的数据指针是否等于raw矩阵的数据指针
    SOPHUS_TEST_EQUAL(passed,
                      map_of_const_se3.unit_quaternion().coeffs().data(),
                      raw.data(), "");
    // 测试map_of_const_se3对象的translation()函数返回值的数据指针是否等于raw矩阵的数据指针加4
    SOPHUS_TEST_EQUAL(passed, map_of_const_se3.translation().data(),
                      raw.data() + 4, "");
    Eigen::Map<SE3Type const> const_shallow_copy = map_of_const_se3;// 创建const_shallow_copy对象,浅拷贝map_of_const_se3对象
    // 测试const_shallow_copy对象的unit_quaternion()函数返回值的系数是否等于map_of_const_se3对象的unit_quaternion()函数返回值的系数
    SOPHUS_TEST_EQUAL(passed,
                      const_shallow_copy.unit_quaternion().coeffs().eval(),
                      map_of_const_se3.unit_quaternion().coeffs().eval(), "");
    // 测试const_shallow_copy对象的translation()函数返回值是否等于map_of_const_se3对象的translation()函数返回值
    SOPHUS_TEST_EQUAL(passed, const_shallow_copy.translation().eval(),
                      map_of_const_se3.translation().eval(), "");


    Eigen::Matrix<Scalar, 7, 1> raw2;// 定义raw2矩阵,用于存储原始数据
    raw2 << Scalar(1), Scalar(0), Scalar(0), Scalar(0), Scalar(3), Scalar(2),
        Scalar(1);// 给raw2矩阵赋值
    Eigen::Map<SE3Type> map_of_se3(raw.data());// 创建map_of_se3对象,用于映射SE3Type类型的数据
    Eigen::Quaternion<Scalar> quat;// 创建quat四元数对象
    quat.coeffs() = raw2.template head<4>();// 给quat四元数对象的系数赋值
    map_of_se3.setQuaternion(quat);// 设置map_of_se3对象的四元数为quat
    map_of_se3.translation() = raw2.template tail<3>();// 设置map_of_se3对象的平移向量为raw2矩阵的后3个元素
     测试map_of_se3对象的unit_quaternion()函数返回值的系数是否接近raw2矩阵的前4个元素
    SOPHUS_TEST_APPROX(passed, map_of_se3.unit_quaternion().coeffs().eval(),
                       raw2.template head<4>().eval(),
                       Constants<Scalar>::epsilon(), "");
    // 测试map_of_se3对象的translation()函数返回值是否接近raw2矩阵的后3个元素
    SOPHUS_TEST_APPROX(passed, map_of_se3.translation().eval(),
                       raw2.template tail<3>().eval(),
                       Constants<Scalar>::epsilon(), "");
    // 测试map_of_se3对象的unit_quaternion()函数返回值的系数的数据指针是否等于raw矩阵的数据指针
    SOPHUS_TEST_EQUAL(passed, map_of_se3.unit_quaternion().coeffs().data(),
                      raw.data(), "");
    // 测试map_of_se3对象的translation()函数返回值的数据指针是否等于raw矩阵的数据指针加4
    SOPHUS_TEST_EQUAL(passed, map_of_se3.translation().data(), raw.data() + 4,
                      "");
    // 测试map_of_se3对象的unit_quaternion()函数返回值的系数的数据指针是否不等于quat四元数对象的系数的数据指针
    SOPHUS_TEST_NEQ(passed, map_of_se3.unit_quaternion().coeffs().data(),
                    quat.coeffs().data(), "");
    Eigen::Map<SE3Type> shallow_copy = map_of_se3;// 创建shallow_copy对象,浅拷贝map_of_se3对象
    // 测试shallow_copy对象的unit_quaternion()函数返回值的系数是否等于map_of_se3对象的unit_quaternion()函数返回值的系数
    SOPHUS_TEST_EQUAL(passed, shallow_copy.unit_quaternion().coeffs().eval(),
                      map_of_se3.unit_quaternion().coeffs().eval(), "");
    // 测试shallow_copy对象的translation()函数返回值是否等于map_of_se3对象的translation()函数返回值
    SOPHUS_TEST_EQUAL(passed, shallow_copy.translation().eval(),
                      map_of_se3.translation().eval(), "");
    Eigen::Map<SE3Type> const const_map_of_se3 = map_of_se3;// 创建const_map_of_se3对象,浅拷贝map_of_se3对象
    // 测试const_map_of_se3对象的unit_quaternion()函数返回值的系数是否等于map_of_se3对象的unit_quaternion()函数返回值的系数
    SOPHUS_TEST_EQUAL(passed,
                      const_map_of_se3.unit_quaternion().coeffs().eval(),
                      map_of_se3.unit_quaternion().coeffs().eval(), "");
    // 测试const_map_of_se3对象的translation()函数返回值是否等于map_of_se3对象的translation()函数返回值
    SOPHUS_TEST_EQUAL(passed, const_map_of_se3.translation().eval(),
                      map_of_se3.translation().eval(), "");
    // 创建const_se3常量对象,使用quat四元数和raw2矩阵的后三个元素初始化
    SE3Type const const_se3(quat, raw2.template tail<3>().eval());
    for (int i = 0; i < 7; ++i) {  // 循环遍历0到6
        // 测试const_se3常量对象的data()函数返回值第i个元素是否等于raw2矩阵第i个元素
      SOPHUS_TEST_EQUAL(passed, const_se3.data()[i], raw2.data()[i], "");
    }
    // 创建se3变量,使用quat四元数和raw2矩阵的后三个元素初始化
    SE3Type se3(quat, raw2.template tail<3>().eval());
    for (int i = 0; i < 7; ++i) {// 循环遍历0到6
        //  测试se3变量的data()函数返回值第i个元素是否等于raw2矩阵第i个元素
      SOPHUS_TEST_EQUAL(passed, se3.data()[i], raw2.data()[i], "");
    }


    for (int i = 0; i < 7; ++i) {  // 循环遍历0到6
      // 测试se3变量的data()函数返回值第i个元素是否等于raw矩阵第i个元素
      SOPHUS_TEST_EQUAL(passed, se3.data()[i], raw.data()[i], "");
    }
    SE3Type trans = SE3Type::transX(Scalar(0.2));// 创建trans变量,使用SE3Type::transX函数初始化,沿x轴平移0.2
    SOPHUS_TEST_APPROX(passed, trans.translation().x(), Scalar(0.2),
                       Constants<Scalar>::epsilon(), "");// 测试trans变量的translation()函数返回值的x分量是否接近0.2
    trans = SE3Type::transY(Scalar(0.7));// 使用SE3Type::transY函数初始化trans变量,沿y轴平移0.7
    SOPHUS_TEST_APPROX(passed, trans.translation().y(), Scalar(0.7),
                       Constants<Scalar>::epsilon(), "");// 测试trans变量的translation()函数返回值的y分量是否接近0.7
    trans = SE3Type::transZ(Scalar(-0.2));// 使用SE3Type::transZ函数初始化trans变量,沿z轴平移-0.2
    SOPHUS_TEST_APPROX(passed, trans.translation().z(), Scalar(-0.2),
                       Constants<Scalar>::epsilon(), "");// 测试trans变量的translation()函数返回值的z分量是否接近-0.2
    Tangent t;// 定义t变量,用于存储切向量
    t << Scalar(0), Scalar(0), Scalar(0), Scalar(0.2), Scalar(0), Scalar(0);// 给t变量赋值  运动螺旋[dx,dy,dz,wx,wy,wz]
    // 测试SE3Type::rotX函数返回值的矩阵是否等于SE3Type::exp函数返回值的矩阵
    SOPHUS_TEST_EQUAL(passed, SE3Type::rotX(Scalar(0.2)).matrix(),
                      SE3Type::exp(t).matrix(), "");
    t << Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(-0.2), Scalar(0); // 给t变量赋值
    SOPHUS_TEST_EQUAL(passed, SE3Type::rotY(Scalar(-0.2)).matrix(),
                      SE3Type::exp(t).matrix(), "");// 测试SE3Type::rotY函数返回值的矩阵是否等于SE3Type::exp函数返回值的矩阵
    t << Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(0), Scalar(1.1);
    SOPHUS_TEST_EQUAL(passed, SE3Type::rotZ(Scalar(1.1)).matrix(),
                      SE3Type::exp(t).matrix(), "");// 测试SE3Type::rotZ函数返回值的矩阵是否等于SE3Type::exp函数返回值的矩阵


    Eigen::Matrix<Scalar, 7, 1> data1, data2;// 定义data1和data2矩阵,用于存储数据
    data1 << Scalar(0), Scalar(1), Scalar(0), Scalar(0), Scalar(1), Scalar(2),
        Scalar(3);// 给data1矩阵赋值
    data1 << Scalar(0), Scalar(0), Scalar(1), Scalar(0), Scalar(3), Scalar(2),
        Scalar(1);  // 给data1矩阵赋值


    Eigen::Map<SE3Type> map1(data1.data()), map2(data2.data());// 创建map1和map2对象,分别映射data1和data2矩阵的数据


    // map -> map assignment
    map2 = map1;// 将map1对象赋值给map2对象
    // 测试map1对象的matrix()函数返回值是否等于map2对象的matrix()函数返回值
    SOPHUS_TEST_EQUAL(passed, map1.matrix(), map2.matrix(), "");


    // map -> type assignment
    SE3Type copy;// 创建copy变量
    copy = map1;// 将map1对象赋值给copy变量
    // 测试map1对象的matrix()函数返回值是否等于copy变量的matrix()函数返回值
    SOPHUS_TEST_EQUAL(passed, map1.matrix(), copy.matrix(), "");


    // type -> map assignment
    // 使用SE3Type::trans和SE3Type::rotZ函数初始化copy变量,沿x、y、z轴分别平移4、5、6,绕z轴旋转0.5
    copy = SE3Type::trans(Scalar(4), Scalar(5), Scalar(6)) *
           SE3Type::rotZ(Scalar(0.5));
    map1 = copy;// 将copy变量赋值给map1对象
    // 测试map1对象的matrix()函数返回值是否等于copy变量的matrix()函数返回值
    SOPHUS_TEST_EQUAL(passed, map1.matrix(), copy.matrix(), "");


    return passed;  // 返回所有测试是否通过
  }
  // 定义testMutatingAccessors函数,用于测试变异访问器
  bool testMutatingAccessors() {
    bool passed = true;// 定义passed变量,表示所有测试是否通过
    SE3Type se3;// 创建se3变量
    // 创建R变量,使用SO3Type::exp函数初始化,指数映射点 旋转矢量(0.2, 0.5, 0.0)
    SO3Type R(SO3Type::exp(Point(Scalar(0.2), Scalar(0.5), Scalar(0.0))));
    se3.setRotationMatrix(R.matrix());  // 设置se3变量的旋转矩阵为R变量的矩阵
    // 测试se3变量的rotationMatrix()函数返回值是否接近R变量的矩阵
    SOPHUS_TEST_APPROX(passed, se3.rotationMatrix(), R.matrix(),
                       Constants<Scalar>::epsilon(), "");


    return passed;// 返回所有测试是否通过
  }
  // 定义testConstructors函数,用于测试构造函数
  bool testConstructors() {
    bool passed = true;// 定义passed变量,表示所有测试是否通过
    // 创建I矩阵,初始化为单位矩阵
    Eigen::Matrix<Scalar, 4, 4> I = Eigen::Matrix<Scalar, 4, 4>::Identity();
    // 测试SE3Type默认构造函数返回值的矩阵是否等于I矩阵
    SOPHUS_TEST_EQUAL(passed, SE3Type().matrix(), I, "");


    SE3Type se3 = se3_vec_.front();//  获取se3_vec_向量的第一个元素赋值给se3变量
    Point translation = se3.translation();// 获取se3变量的translation()函数返回值赋值给translation变量
    SO3Type so3 = se3.so3();// 获取se3变量的so3()函数返回值赋值给so3变量
    // 测试SE3Type构造函数返回值的矩阵是否接近se3变量的矩阵
    SOPHUS_TEST_APPROX(passed, SE3Type(so3, translation).matrix(), se3.matrix(),
                       Constants<Scalar>::epsilon(), "");
    // 测试SE3Type构造函数返回值的矩阵是否接近se3变量的矩阵
    SOPHUS_TEST_APPROX(passed, SE3Type(so3.matrix(), translation).matrix(),
                       se3.matrix(), Constants<Scalar>::epsilon(), "");
    // 测试SE3Type构造函数返回值的矩阵是否接近se3变量的矩阵
    SOPHUS_TEST_APPROX(passed,
                       SE3Type(so3.unit_quaternion(), translation).matrix(),
                       se3.matrix(), Constants<Scalar>::epsilon(), "");
    // 测试SE3Type构造函数返回值的矩阵是否接近se3变量的矩阵
    SOPHUS_TEST_APPROX(passed, SE3Type(se3.matrix()).matrix(), se3.matrix(),
                       Constants<Scalar>::epsilon(), "");


    return passed;// 返回所有测试是否通过
  }


  template <class S = Scalar>
  enable_if_t<std::is_floating_point<S>::value, bool> testFit() {// 定义testFit函数模板,用于测试拟合,仅当S类型为浮点数类型时启用
    bool passed = true;// 定义passed变量,表示所有测试是否通过


    for (int i = 0; i < 100; ++i) {// 循环遍历0到99
      Matrix4<Scalar> T = Matrix4<Scalar>::Random();// 创建T矩阵,初始化为随机数
      //使用一些数值方法来计算一个最接近 T 的刚体变换矩阵。
      //这个刚体变换矩阵可以由一个旋转矩阵和一个平移向量构成,
      //这两个部分都可以从 T 矩阵中提取出来。然后,这个函数会使用这些信息来构造一个新的 SE3Type 对象并返回
      SE3Type se3 = SE3Type::fitToSE3(T);// 使用SE3Type::fitToSE3函数拟合T矩阵,赋值给se3变量
      SE3Type se3_2 = SE3Type::fitToSE3(se3.matrix());// 使用SE3Type::fitToSE3函数拟合se3变量的矩阵,赋值给se3_2变量
      // 测试se3和se2_2两个变量的矩阵是否接近
      SOPHUS_TEST_APPROX(passed, se3.matrix(), se3_2.matrix(),
                         Constants<Scalar>::epsilon(), "");
    }
    for (Scalar const angle :
         {Scalar(0.0), Scalar(0.1), Scalar(0.3), Scalar(-0.7)}) {// 循环遍历角度数组中的每个元素
      // 测试SE3Type::rotX函数返回值的angleX()函数返回值是否接近angle  
      SOPHUS_TEST_APPROX(passed, SE3Type::rotX(angle).angleX(), angle,
                         Constants<Scalar>::epsilon(), "");
      // 测试SE3Type::rotY函数返回值的angleY()函数返回值是否接近angle
      SOPHUS_TEST_APPROX(passed, SE3Type::rotY(angle).angleY(), angle,
                         Constants<Scalar>::epsilon(), "");
      // 测试SE3Type::rotZ函数返回值的angleZ()函数返回值是否接近angle
      SOPHUS_TEST_APPROX(passed, SE3Type::rotZ(angle).angleZ(), angle,
                         Constants<Scalar>::epsilon(), "");
    }
    return passed;// 返回所有测试是否通过
  }


  template <class S = Scalar>
  enable_if_t<!std::is_floating_point<S>::value, bool> testFit() {// 定义testFit函数模板,用于测试拟合,仅当S类型不为浮点数类型时启用
    return true;// 直接返回true
  }


  std::vector<SE3Type, Eigen::aligned_allocator<SE3Type>> se3_vec_;// 定义se3_vec_向量,用于存储SE3Type类型的对象
  std::vector<Tangent, Eigen::aligned_allocator<Tangent>> tangent_vec_;// 定义tangent_vec_向量,用于存储Tangent类型的对象
  std::vector<Point, Eigen::aligned_allocator<Point>> point_vec_;// 定义point_vec_向量,用于存储Point类型的对象
};


int test_se3() {// 定义test_se3函数,用于测试SE3类
  using std::cerr;
  using std::endl;


  cerr << "Test SE3" << endl << endl;
  cerr << "Double tests: " << endl;
  Tests<double>().runAll();// 运行所有double类型的测试
  cerr << "Float tests: " << endl;
  Tests<float>().runAll();// 运行所有float类型的测试


#if SOPHUS_CERES
  cerr << "ceres::Jet<double, 3> tests: " << endl;
  Tests<ceres::Jet<double, 3>>().runAll();// 运行所有ceres::Jet<double, 3>类型的测试
#endif


  return 0;
}
}  // namespace Sophus


int main() { return Sophus::test_se3(); }// 主函数,运行Sophus命名空间下的test_se3函数,并返回其返回值

测试代码的目的:

  1. 测试代码主要是为了验证sophus库中的算法实现是否正确。开发者通过编写测试用例,来确保各种算法场景下的输出结果与预期一致。

  2. 测试代码也可以用于回归测试。当sophus库有更新时,可以运行测试代码,验证更新后算法的输出是否与之前一致,防止引入新的bug。

  3. 测试代码可以作为使用sophus库的示例代码。通过查看测试代码,用户可以更快地理解如何正确使用sophus库中的接口。

  4. 编写测试代码是良好的编码习惯。充分的测试可以提高代码质量,降低出错概率。维护测试代码也可以让开发者更好地理解自己编写的代码。

  5. 开源项目提供测试代码,可以让用户对代码质量更有信心,也方便其他开发者为项目编写新的测试用例。

  6. 自动化测试框架也可以通过运行测试代码,帮助开发者进行持续集成和部署。

sophus vs manif :

73587e3ccdf83d57ebbe6fa7e652be15.png

1d1c30e6c823c47ce56c1ee3a8082c2b.png

14fb10bec6c99d815b5cefe611833c12.png

9e8bd7716d6da0e7149be9bd50c1fd42.png

参考网址:
1. https://juejin.cn/post/7067858653339975688

Sophus源码逐行解读 ( 结合视觉SLAM十四讲的概念 )

2. https://juejin.cn/post/7075761513113321479 

Lie Group Foundations

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

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

相关文章

2023应届生java面试搞笑之一:CAS口误说成开心锁-笑坏面试官

源于&#xff1a;XX网&#xff0c;如果冒犯&#xff0c;表示歉意 面试官&#xff1a;什么是CAS 我&#xff1a;这个简单&#xff0c;开心锁 面试官&#xff1a;WTF&#xff1f; 我&#xff1a;一脸自信&#xff0c;对&#xff0c;就是这个 面试官&#xff1a;哈哈大笑&#xff…

opencv入门-Opencv原理以及Opencv-Python安装

图像的表示 1&#xff0c;位数 计算机采用0/1编码的系统&#xff0c;数字图像也是0/1来记录信息&#xff0c;图像都是8位数图像&#xff0c;包含0~255灰度&#xff0c; 其中0代表最黑&#xff0c;1代表最白 3&#xff0c; 4&#xff0c;OpenCV部署方法 安装OpenCV之前…

AUTOSAR规范与ECU软件开发(实践篇)7.10MCAL模块配置方法及常用接口函数介绍之Base与Resource的配置

目录 1、前言 2 、Base与Resource模块 1、前言 本例程的硬件平台为MPC5744P开发板&#xff0c;主要配置MPC5744P的mcal的每个模块的配置&#xff0c;如要配置NXP的MCU之S32k324的例程请参考&#xff1a; 2 、Base与Resource模块 Base与Resource这两个模块与具体功能无关&…

什么是 Web 应用程序安全测试?

Web 应用程序安全测试是一种严格的实践&#xff0c;旨在识别、分析和纠正基于 Web 的应用程序中的漏洞。 此过程涉及使用一套全面的工具和方法来评估 Web 应用程序的安全性和完整性。它包括渗透测试、漏洞评估和代码审查等实践。 Web 应用程序安全测试的主要目标是阻止潜在的…

Linux 学习笔记(1)——系统基本配置与开关机命令

目录 0、起步 0-1&#xff09;命令使用指引 0-2&#xff09;查看历史的命令记录 0-3&#xff09;清空窗口内容 0-4&#xff09;获取本机的内网 IP 地址 0-5&#xff09;获取本机的公网ip地址 0-6&#xff09;在window的命令行窗口中远程连接linux 0-7&#xff09;修改系…

[Linux]套接字通信

摘于https://subingwen.cn,作者:苏丙榅 侵删 文章目录 1. 套接字-socket1.1 概念1.2 网络协议1.3 socket编程1.3.1 字节序1.3.2 IP地址转换1.3.3 sockaddr 数据结构1.3.4 套接字函数 1.4 TCP通信流程1.4.1 服务器端通信流程1.4.2 客户端的通信流程 1.5 扩展阅读1.5.1 初始化套…

Cocos独立游戏开发框架中的日志模块:Bug无所遁形

引言 本系列是《8年主程手把手打造Cocos独立游戏开发框架》&#xff0c;欢迎大家关注分享收藏订阅。 在Cocos独立游戏开发框架中&#xff0c;一个强大的日志模块是不可或缺的组成部分。日志不仅仅是记录应用程序的运行状态&#xff0c;还可以用于故障排除、性能监测和安全审计…

获取并修改图像中的像素点

实现原理 我们可以通过行和列的坐标值获取该像素点的像素值。对于BGR图像&#xff0c;它返回一个蓝&#xff0c;绿&#xff0c;红值的数组。对于灰度图像&#xff0c;仅返回相应的强度值。使用相同的方法对像素值进行修改。 import numpy as np import cv2 as cv import matp…

Python语音识别处理详解

概要 人们对智能语音助手的需求不断提高&#xff0c;语音识别技术也随之迅速发展。在这篇文章中&#xff0c;我们将介绍如何使用Python的SpeechRecognition和pydub等库来实现语音识别和处理&#xff0c;从而打造属于自己的智能语音助手。 1. 什么是语音识别&#xff1f; 语音…

超图嵌入论文阅读1:对偶机制非均匀超网络嵌入

超图嵌入论文阅读1&#xff1a;对偶机制非均匀超网络嵌入 原文&#xff1a;Nonuniform Hyper-Network Embedding with Dual Mechanism ——TOIS&#xff08;一区 CCF-A&#xff09; 背景 超边&#xff1a;每条边可以连接不确定数量的顶点 我们关注超网络的两个属性&#xff1…

【Locomotor运动模块】瞬移

文章目录 一、原理二、两种类型1、Instant(立刻)2、Dash&#xff08;猛冲&#xff09; 三、瞬移区域、瞬移点1、瞬移区域2、瞬移点 一、原理 抛物线指针选择好目标位置&#xff0c;然后告诉瞬移预设体&#xff1a;你想法把游戏区域弄到目标位置来 解释&#xff1a;抛物线指针选…

阿里云对象存储oss-文件上传过程详解(两种方式)

阿里云对象存储oss-文件上传过程详解{两种方式} 方式一(最新代码,时间:2023/8/27)(1)如何配置系统变量(2)完整代码 方式二(跟黑马最新教程同代码)(1)在复制下来的代码中(2)完整代码 方式一(最新代码,时间:2023/8/27) 问题:需要配置系统变量才能够使用 (1)如何配置系统变量 以wi…

wxWidgets从空项目开始Hello World

前文回顾 接上篇&#xff0c;已经是在CodeBlocks20.03配置了wxWidgets3.0.5&#xff0c;并且能够通过项目创建导航创建一个新的工程&#xff0c;并且成功运行。 那么上一个是通过CodeBlocks的模板创建的&#xff0c;一进去就已经是2个头文件2个cpp文件&#xff0c;总是感觉缺…

网络安全(黑客)自学路线,了解什么是黑客

谈起黑客&#xff0c;可能各位都会想到&#xff1a;盗号&#xff0c;其实不尽然&#xff1b;黑客是一群喜爱研究技术的群体&#xff0c;在黑客圈中&#xff0c;一般分为三大圈&#xff1a;娱乐圈 技术圈 职业圈。 娱乐圈&#xff1a;主要是初中生和高中生较多&#xff0c;玩网恋…

C++ struct 笔记(超级详细)

今日碎碎念&#xff1a;我在学C语言时经常用到结构体struct&#xff0c;之后在写C程序时遇到在struct中定义构造函数和成员函数的情况&#xff0c;这在c语言中是从未遇到过的&#xff0c;觉得奇怪&#xff0c;想到之前并没有真正系统学习C里的struct&#xff0c;有必要今天详细…

7.6 递归求学生年龄

有5个学生坐在一起&#xff0c;问第五个学生多少岁&#xff0c;他说比第四个学生大两岁。问第四个学生的岁数&#xff0c;他说比第三个学生大2岁。问第三个学生&#xff0c;又说比第二个学生大2岁。问第二个学生&#xff0c;说比第一个学生大2岁。最后问第一个学生&#xff0c;…

Unity中Shader的遮罩的实现

文章目录 前言一、遮罩效果的实现主要是使用对应的纹理实现的&#xff0c;在属性中暴露对应的遮罩纹理&#xff0c;对其进行采样后&#xff0c;最后相乘输出即可二、如果需要像和主要纹理一样流动&#xff0c;则需要使用和_Time篇一样的方法实现流动即可 前言 Unity中Shader的…

TBOX开发需求说明

TBOX功能需求&#xff1a; 支持4G上网功能&#xff0c;可获取外网IP&#xff0c;可和云端平台连通支持路由功能&#xff0c;支持计算平台、网关和云端平台建立网络连接支持USB转网口&#xff0c;智能座舱会通过USB连接AG35建立网络连接&#xff08;类似IVI通过USB口连接TBOX&a…

AAC处理码流分析工具(三十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

安装kali虚拟机镜像的坑

1.0 安装虚拟机镜像成功之后&#xff0c;只有光标&#xff0c;没有界面 在VMware上安装kali linux环境时&#xff0c;根据提示操作完成后&#xff0c;开启虚拟机&#xff0c;屏幕黑屏&#xff0c;左上角有一个光标在闪&#xff0c;一直开不了机。 出现问题的原因&#xff0c;…