- CMAKE配置
cmake_minimum_required(VERSION 3.16)
project(FridayLibrary)
set(CMAKE_CXX_STANDARD 14)
SET(BOOST_INCLUDE_DIR C:/Program\ Files/PCL\ 1.11.0/3rdParty/Boost/include)
SET(BOOST_LIBRARY_DIR C:/Program\ Files/PCL\ 1.11.0/3rdParty/Boost/lib)
set(PLC_ROOT C:/Program\ Files/PCL\ 1.11.0)
set(PLC_INCLUDE_DIR C:/Program\ Files/PCL\ 1.11.0/include)
set(PLC_LIBRARY_DIR C:/Program\ Files/PCL\ 1.11.0/lib)
find_package(PCL REQUIRED)
if(PCL_FOUND)
message ("PCL found")
else()
message (FATAL_ERROR "Cannot find PCL")
endif(PCL_FOUND)
include_directories(${PLC_INCLUDE_DIR} ${BOOST_INCLUDE_DIR})
link_directories(${PLC_LIBRARY_DIR} ${BOOST_LIBRARY_DIR})
add_library(FridayLibrary SHARED library.cpp library.h)
target_link_libraries( FridayLibrary PRIVATE
${PCL_LIBRARIES}
${BOOST_LIBRARIES}
)
- PCL + C++
pcl::PointCloud<pcl::PointXYZ>::Ptr srcCloud(new pcl::PointCloud<pcl::PointXYZ>());
pcl::PointCloud<pcl::PointXYZ>::Ptr dstCloud(new pcl::PointCloud<pcl::PointXYZ>());
srcCloud->width = 12;
srcCloud->height = 1;
srcCloud->is_dense = false;
srcCloud->resize(srcCloud->width * srcCloud->height);
dstCloud->width = 12;
dstCloud->height = 1;
dstCloud->is_dense = false;
dstCloud->resize(dstCloud->width * dstCloud->height);
srcCloud->points[0].x = 0.0625075, srcCloud->points[0].y = 0.0341182, srcCloud->points[0].z = -0.0291991;
srcCloud->points[1].x = 0.0466103, srcCloud->points[1].y = 0.0437115, srcCloud->points[1].z = 0.0275582;
srcCloud->points[2].x = 0.0702050, srcCloud->points[2].y = 0.0316673, srcCloud->points[2].z = -0.0269043;
srcCloud->points[3].x = 0.0527458, srcCloud->points[3].y = 0.0392645, srcCloud->points[3].z = 0.0298687;
srcCloud->points[4].x = 0.0670084, srcCloud->points[4].y = 0.0275866, srcCloud->points[4].z = -0.0272287;
srcCloud->points[5].x = 0.0514137, srcCloud->points[5].y = 0.0382540, srcCloud->points[5].z = 0.029152;
srcCloud->points[6].x = 0.0575101, srcCloud->points[6].y = 0.0254605, srcCloud->points[6].z = -0.0302174;
srcCloud->points[7].x = 0.0535772, srcCloud->points[7].y = 0.0332998, srcCloud->points[7].z = -0.0328697;
srcCloud->points[8].x = 0.0383195, srcCloud->points[8].y = 0.0486851, srcCloud->points[8].z = 0.0244912;
srcCloud->points[9].x = 0.0560232, srcCloud->points[9].y = 0.0385878, srcCloud->points[9].z = -0.0330957;
srcCloud->points[10].x = 0.0660206, srcCloud->points[10].y = 0.0425857, srcCloud->points[10].z = -0.0297611;
srcCloud->points[11].x = 0.0489257, srcCloud->points[11].y = 0.053031, srcCloud->points[11].z = 0.0257074;
dstCloud->points[0].x = 5.299e-06, dstCloud->points[0].y = -7.164e-06, dstCloud->points[0].z = -0.0300047;
dstCloud->points[1].x = 5.299e-06, dstCloud->points[1].y = -7.164e-06, dstCloud->points[1].z = 0.0300047;
dstCloud->points[2].x = 0.00883181, dstCloud->points[2].y = 0.00174854, dstCloud->points[2].z = -0.0300047;
dstCloud->points[3].x = 0.0088318, dstCloud->points[3].y = -0.00176288, dstCloud->points[3].z = 0.0300047;
dstCloud->points[4].x = 0.00831968, dstCloud->points[4].y = -0.00345109, dstCloud->points[4].z = -0.0300047;
dstCloud->points[5].x = 0.00831968, dstCloud->points[5].y = -0.00345111, dstCloud->points[5].z = 0.0300047;
dstCloud->points[6].x = 5.297e-06, dstCloud->points[6].y = -0.00900659, dstCloud->points[6].z = -0.0300047;
dstCloud->points[7].x = -0.00747745, dstCloud->points[7].y = -0.00500697, dstCloud->points[7].z = -0.0300047;
dstCloud->points[8].x = -0.00899412, dstCloud->points[8].y = -7.2e-06, dstCloud->points[8].z = 0.0300047;
dstCloud->points[9].x = -0.00882121, dstCloud->points[9].y = 0.00174855, dstCloud->points[9].z = -0.0300047;
dstCloud->points[10].x = -0.00175039, dstCloud->points[10].y = 0.00881934, dstCloud->points[10].z = -0.0300047;
dstCloud->points[11].x = -0.00175046, dstCloud->points[11].y = 0.00881932, dstCloud->points[11].z = 0.0300047;
//利用SVD方法求解变换矩阵
pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> TESVD;
pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ>::Matrix4 transformation2;
TESVD.estimateRigidTransformation(*srcCloud, *dstCloud, transformation2);
//输出变换矩阵信息
std::cout << "The Estimated Rotation and translation matrices (using getTransformation function) are : \n" << std::endl;
printf("\n");
printf(" | %6.3f %6.3f %6.3f | \n", transformation2(0, 0), transformation2(0, 1), transformation2(0, 2));
printf("R = | %6.3f %6.3f %6.3f | \n", transformation2(1, 0), transformation2(1, 1), transformation2(1, 2));
printf(" | %6.3f %6.3f %6.3f | \n", transformation2(2, 0), transformation2(2, 1), transformation2(2, 2));
printf("\n");
printf("t = < %0.3f, %0.3f, %0.3f >\n", transformation2(0, 3), transformation2(1, 3), transformation2(2, 3));
//rpyMatrix();
Eigen::Matrix3d rotation_matrix;
rotation_matrix(0, 0) = transformation2(0, 0);
rotation_matrix(0, 1) = transformation2(0, 1);
rotation_matrix(0, 2) = transformation2(0, 2);
rotation_matrix(1, 0) = transformation2(1, 0);
rotation_matrix(1, 1) = transformation2(1, 1);
rotation_matrix(1, 2) = transformation2(1, 2);
rotation_matrix(2, 0) = transformation2(2, 0);
rotation_matrix(2, 1) = transformation2(2, 1);
rotation_matrix(2, 2) = transformation2(2, 2);
auto eulerAngle = rotation_matrix.eulerAngles(0, 1, 2);
std::cout << eulerAngle * 180 / 3.14 << std::endl;
- C# 封装
头文件
#ifndef FRIDAYLIBRARY_LIBRARY_H
#define FRIDAYLIBRARY_LIBRARY_H
#include <pcl/io/pcd_io.h>
#include <pcl/point_types.h>
#include <pcl/sample_consensus/ransac.h>
#include <pcl/sample_consensus/sac_model_plane.h>
#include <pcl/visualization/pcl_visualizer.h>
#include <boost/thread/thread.hpp>
#include <pcl/point_cloud.h>
#include <pcl/registration/transformation_estimation_svd.h>
#include <vector>
#ifdef __DLL_BUILD
#define DLL_EXPORT __declspec(dllexport)
#else
#define DLL_EXPORT __declspec(dllimport)
#endif
#ifdef __cplusplus
extern "C" {
#endif
/// <summary>
/// 通过对应点获取目标点云在原始点云坐标空间下的姿态
/// </summary>
/// <param name="p_src_x">原始点云的X坐标</param>
/// <param name="p_src_y">原始点云的Y坐标</param>
/// <param name="p_src_z">原始点云的Z坐标</param>
/// <param name="p_dst_x">目标点云的X坐标</param>
/// <param name="p_dst_y">目标点云的Y坐标</param>
/// <param name="p_dst_z">目标点云的Z坐标</param>
/// <param name="length">点云个数</param>
/// <param name="pose">返回的姿态[X, Y, Z, RX, RY, RZ ]</param>
DLL_EXPORT void get_plane_pose( const float* p_src_x,
const float* p_src_y,
const float* p_src_z,
const float* p_dst_x,
const float* p_dst_y,
const float* p_dst_z,
const size_t length, float* pose);
#ifdef __cplusplus
}
#endif
#endif //FRIDAYLIBRARY_LIBRARY_H
源文件
#define __DLL_BUILD
#include "library.h"
/// <summary>
/// 通过对应点获取目标点云在原始点云坐标空间下的姿态
/// </summary>
/// <param name="p_src_x">原始点云的X坐标</param>
/// <param name="p_src_y">原始点云的Y坐标</param>
/// <param name="p_src_z">原始点云的Z坐标</param>
/// <param name="p_dst_x">目标点云的X坐标</param>
/// <param name="p_dst_y">目标点云的Y坐标</param>
/// <param name="p_dst_z">目标点云的Z坐标</param>
/// <param name="length">点云个数</param>
/// <param name="pose">返回的姿态[X, Y, Z, RX, RY, RZ ]</param>
void get_plane_pose(const float* p_src_x,
const float* p_src_y,
const float* p_src_z,
const float* p_dst_x,
const float* p_dst_y,
const float* p_dst_z,
const size_t length, float* pose)
{
pcl::PointCloud<pcl::PointXYZ>::Ptr src_cloud(new pcl::PointCloud<pcl::PointXYZ>());
pcl::PointCloud<pcl::PointXYZ>::Ptr dst_cloud(new pcl::PointCloud<pcl::PointXYZ>());
src_cloud->width = length;
src_cloud->height = 1;
src_cloud->is_dense = false;
src_cloud->resize(src_cloud->width * src_cloud->height);
dst_cloud->width = length;
dst_cloud->height = 1;
dst_cloud->is_dense = false;
dst_cloud->resize(dst_cloud->width * dst_cloud->height);
for (size_t i = 0; i < length; i++)
{
src_cloud->points[i].x = p_src_x[i];
src_cloud->points[i].y = p_src_y[i];
src_cloud->points[i].z = p_src_z[i];
dst_cloud->points[i].x = p_dst_x[i];
dst_cloud->points[i].y = p_dst_y[i];
dst_cloud->points[i].z = p_dst_z[i];
}
const pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ> estimation_svd;
pcl::registration::TransformationEstimationSVD<pcl::PointXYZ, pcl::PointXYZ>::Matrix4 transformation_matrix;
estimation_svd.estimateRigidTransformation(*src_cloud, *dst_cloud, transformation_matrix);
Eigen::Matrix3d rotation_matrix;
rotation_matrix(0, 0) = transformation_matrix(0, 0);
rotation_matrix(0, 1) = transformation_matrix(0, 1);
rotation_matrix(0, 2) = transformation_matrix(0, 2);
rotation_matrix(1, 0) = transformation_matrix(1, 0);
rotation_matrix(1, 1) = transformation_matrix(1, 1);
rotation_matrix(1, 2) = transformation_matrix(1, 2);
rotation_matrix(2, 0) = transformation_matrix(2, 0);
rotation_matrix(2, 1) = transformation_matrix(2, 1);
rotation_matrix(2, 2) = transformation_matrix(2, 2);
const auto euler_angles = rotation_matrix.eulerAngles(0, 1, 2) * 180 / 3.1415926f;
pose[0] = transformation_matrix(0, 3);
pose[1] = transformation_matrix(1, 3);
pose[2] = transformation_matrix(2, 3);
pose[3] = static_cast<float>(euler_angles[0]);
pose[4] = static_cast<float>(euler_angles[1]);
pose[5] = static_cast<float>(euler_angles[2]);
}
C# 调用
using System;
using System.IO;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
internal class Program
{
public struct Buffer
{
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 128)]
public byte[] DstAddr;
}
[DllImport("./FridayLibrary", CallingConvention = CallingConvention.Cdecl, EntryPoint = "get_plane_pose")]
internal static extern void GetPose(float[] srcX, float[] srcY, float[] srcZ, float[] dstX, float[] dstY, float[] dstZ, int length, ref Buffer buf);
static void Main(string[] args)
{
var srcX = new float[]
{
0.0625075f, 0.0466103f, 0.0702050f, 0.0527458f, 0.0670084f, 0.0514137f, 0.0575101f, 0.0535772f, 0.0383195f, 0.0560232f, 0.0660206f, 0.0489257f
};
var srcY = new float[]
{
0.0341182f, 0.0437115f, 0.0316673f, 0.0392645f, 0.0275866f, 0.0382540f, 0.0254605f, 0.0332998f, 0.0486851f, 0.0385878f, 0.0425857f, 0.053031f
};
var srcZ = new float[]
{
-0.0291991f, 0.0275582f, -0.0269043f, 0.0298687f, -0.0272287f, 0.029152f, -0.0302174f, -0.0328697f, 0.0244912f, -0.0330957f, -0.0297611f, 0.0257074f
};
var dstX = new float[]
{
5.299e-06f, 5.299e-06f, 0.00883181f, 0.0088318f, 0.00831968f, 0.00831968f, 5.297e-06f, -0.00747745f, -0.00899412f, -0.00882121f, -0.00175039f, -0.00175046f
};
var dstY = new float[]
{
-7.164e-06f, -7.164e-06f, 0.00174854f, -0.00176288f, -0.00345109f, -0.00345111f, -0.00900659f, -0.00500697f, -7.2e-06f, 0.00174855f, 0.00881934f, 0.00881932f
};
var dstZ = new float[]
{
-0.0300047f, 0.0300047f, -0.0300047f, 0.0300047f, -0.0300047f, 0.0300047f, -0.0300047f, -0.0300047f, 0.0300047f, -0.0300047f, -0.0300047f, 0.0300047f
};
GetPose(srcX, srcY, srcZ,dstX,dstY,dstZ,9,ref buf);
using (var stream = new MemoryStream(buf.DstAddr))
{
using (var reader = new BinaryReader(stream))
{
var tx = reader.ReadSingle();
var ty = reader.ReadSingle();
var tz = reader.ReadSingle();
var rx = reader.ReadSingle();
var ry = reader.ReadSingle();
var rz = reader.ReadSingle();
Console.WriteLine($"{tx}, {ty}, {tz}, {rx}, {ry}, {rz}");
}
}
Console.ReadKey();
}
}
}