当前位置: 首页 > news >正文

跟着Open3D学C++

前置声明

  • 在很多头文件中有很多这样的代码,参考PointCloud.h
namespace open3d {namespace camera {
class PinholeCameraIntrinsic;
}namespace geometry {class Image;
class RGBDImage;
class TriangleMesh;
class VoxelGrid;
}
}
  • 直接声明其他类型避免在当前头文件中包含这些类型的头文件,减少代码之间的耦合,以及大大的减少编译时间。
  • 缺点就是没包含头文件这些类只能用来声明,不能进行实例化。通常用作函数声明或者使用智能指针进行声明,使用较为受限。
static std::shared_ptr<PointCloud> CreateFromDepthImage(const Image &depth,const camera::PinholeCameraIntrinsic &intrinsic, // 作为函数声明的参数const Eigen::Matrix4d &extrinsic = Eigen::Matrix4d::Identity(),double depth_scale = 1000.0,double depth_trunc = 1000.0,int stride = 1,bool project_valid_depth_only = true);

面试考点:基类需要为虚函数

  • 便于继承的类进行资源释放,参考Geometry.h
class Geometry {
public:virtual ~Geometry() {}
};class Geometry3D : public Geometry {
public:~Geometry3D() override {}
}class PointCloud : public Geometry3D {~PointCloud() override {}
}

限定作用域的枚举

  • 主要是防止命名空间被污染,和cpp尽可能少使用宏的动机一样
enum class GeometryType {/// Unspecified geometry type.Unspecified = 0,/// PointCloudPointCloud = 1,/// VoxelGridVoxelGrid = 2,/// OctreeOctree = 3,/// LineSetLineSet = 4,/// MeshBaseMeshBase = 5,/// TriangleMeshTriangleMesh = 6,/// HalfEdgeTriangleMeshHalfEdgeTriangleMesh = 7,/// ImageImage = 8,/// RGBDImageRGBDImage = 9,/// TetraMeshTetraMesh = 10,/// OrientedBoundingBoxOrientedBoundingBox = 11,/// AxisAlignedBoundingBoxAxisAlignedBoundingBox = 12,
};

函数传参尽量使用const&

  • 参数传递使用引用可减少拷贝构造,尤其是对于复杂类型的参数
  • 任何时候能用const尽量用const,参考effective cpp第三条
PointCloud(const std::vector<Eigen::Vector3d> &points): Geometry3D(Geometry::GeometryType::PointCloud), points_(points) {}

构造函数列表初始化

  • 相比在构造函数中赋值,初始化列表可以在成员变量初始化的时候直接赋值,而不是初始化之后再赋值
PointCloud(const std::vector<Eigen::Vector3d> &points): Geometry3D(Geometry::GeometryType::PointCloud), points_(points) {}

运算符重载

  • 这一点较为普通,很多基础数据类型都会重载常见的运算符
PointCloud &PointCloud::operator+=(const PointCloud &cloud);

最大值最小值的使用

  • 使用cpp风格std::numeric_limits::max()
if (voxel_size * std::numeric_limits<int>::max() <(voxel_max_bound - voxel_min_bound).maxCoeff()) {utility::LogError("[VoxelDownSample] voxel_size is too small.");
}

随机数的使用

  • 比C语言的rand要更好用
std::random_device rd;
std::mt19937 prng(rd());
std::shuffle(indices.begin(), indices.end(), prng);

tuple的使用

  • 使用起来像python风格
  • 有看到规范说多个变量相同类型相同含义最好还是用vector,不同含义不同类型用struct,用tuple会出现返回值含义不清楚的问题,大家怎么看?
  • 但是比起struct还要单独建立一个类,tuple简直使用起来太方便了。
// 声明
std::tuple<Tensor, Tensor, Tensor> NanoFlannIndex::SearchRadius(const Tensor &query_points, const Tensor &radii, bool sort) const;
// 调用
auto [indices, distances, neighbors_row_splits] = NanoFlannIndex::SearchRadius(query_points, radii, sort);

omp加速

  • 大家可以去了解一下,简单的只需要在for循环外加一条omp指令就可以实现多线程加速
#pragma omp parallel for schedule(static) \num_threads(utility::EstimateMaxThreads())for (int i = 0; i < int(points_.size()); i++) {std::vector<int> tmp_indices;std::vector<double> dist;size_t nb_neighbors = kdtree.SearchRadius(points_[i], search_radius,tmp_indices, dist);mask[i] = (nb_neighbors > nb_points);}
  • 也可以封装起来使用更方便
template <typename func_t>
void ParallelFor(const Device& device, int64_t n, const func_t& func) {if (device.GetType() != Device::DeviceType::CPU) {utility::LogError("ParallelFor for CPU cannot run on device {}.",device.ToString());}if (n == 0) {return;}#pragma omp parallel for num_threads(utility::EstimateMaxThreads())for (int64_t i = 0; i < n; ++i) {func(i);}
}
  • tbb也使用较多,可以更深入的控制
// Parallel search.
tbb::parallel_for(tbb::blocked_range<size_t>(0, num_query_points),[&](const tbb::blocked_range<size_t> &r) {std::vector<std::pair<index_t, scalar_t>> ret_matches;for (size_t i = r.begin(); i != r.end(); ++i) {scalar_t radius = radii[i].Item<scalar_t>();scalar_t radius_squared = radius * radius;size_t num_results = holder->index_->radiusSearch(query_points[i].GetDataPtr<scalar_t>(),radius_squared, ret_matches, params);ret_matches.resize(num_results);std::vector<index_t> single_indices;std::vector<scalar_t> single_distances;for (auto it = ret_matches.begin();it < ret_matches.end(); it++) {single_indices.push_back(it->first);single_distances.push_back(it->second);}batch_indices[i] = single_indices;batch_distances[i] = single_distances;}});

参数使用类进行封装

  • 调用更加清晰明了
class ICPConvergenceCriteria {
public:/// \brief Parameterized Constructor.////// \param relative_fitness If relative change (difference) of fitness score/// is lower than relative_fitness, the iteration stops. \param/// relative_rmse If relative change (difference) of inliner RMSE score is/// lower than relative_rmse, the iteration stops. \param max_iteration/// Maximum iteration before iteration stops.ICPConvergenceCriteria(double relative_fitness = 1e-6,double relative_rmse = 1e-6,int max_iteration = 30): relative_fitness_(relative_fitness),relative_rmse_(relative_rmse),max_iteration_(max_iteration) {}~ICPConvergenceCriteria() {}public:/// If relative change (difference) of fitness score is lower than/// `relative_fitness`, the iteration stops.double relative_fitness_;/// If relative change (difference) of inliner RMSE score is lower than/// `relative_rmse`, the iteration stops.double relative_rmse_;/// Maximum iteration before iteration stops.int max_iteration_;
};auto result = pipelines::registration::RegistrationColoredICP(*source_down, *target_down, 0.07, trans,pipelines::registration::TransformationEstimationForColoredICP(),pipelines::registration::ICPConvergenceCriteria(1e-6, 1e-6,iterations[i]));
  • 对比PCL的ICP算法,open3d的不是类,而只是一个函数,使用参数类更加方便。用类和用函数实现大家怎么看?
  • cpp20对于成员变量有更好的方式
// cpp20初始化赋值时可指定成员变量名,更加清晰
struct Temp{int a = 0;int b = 0;
};auto temp = Temp{.a = 1, .b = 2};
Temp temp1{.b = 3};

http://www.mrgr.cn/news/48635.html

相关文章:

  • (亲测可行)ubuntu下载安装c++版opencv4.7.0和4.5.0 安装opencv4.5.0报错及解决方法
  • 嵌入式系统中常见的存储器
  • npm install进度卡在 idealTree:node_global: sill idealTree buildDeps
  • 如何使用ssm实现班级同学录网站
  • 机器学习——自动化机器学习(AutoML)
  • 【Web开发】第一弹:HTML表格基础与应用实例
  • 每日一练:两个字符串的最小ASCLL删除和
  • python根据端口查询出pid号是多少
  • GRS、GOTS、OCS、BCI、RDS的区别
  • ElasticSearch+Kibana 8.1.0安装部署
  • webm格式怎么转换成mp4?这几种方法可以轻松完成视频转换!
  • 基于Arduino的花瓶
  • mig IP核的学习
  • 前端开发攻略---前端ocr图片文字提取功能
  • WHAT - OpenAPI 规范和开放 API
  • 最全Python爬虫教程,学会你也是大师了!
  • 柯桥学日语日常口语入门教学当日本人说「すごいね」时,该怎么回?
  • 系统缺失mfc140.dll的修复方法,有效修复错误mfc140.dll详细步骤
  • sed删除每行末尾的空格或制表符
  • MES管理系统提升智能工厂四大核心能力