Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何从立方体的最大和最小坐标值计算四元数?_C++_Ros_Quaternions_Vertex - Fatal编程技术网

C++ 如何从立方体的最大和最小坐标值计算四元数?

C++ 如何从立方体的最大和最小坐标值计算四元数?,c++,ros,quaternions,vertex,C++,Ros,Quaternions,Vertex,我在创建立方体(ROS中检测到的对象的边界框)的方向时遇到了一些问题。我知道最大和最小坐标值(xmin,xmax,ymin,ymax,zmin,zmax)。因此,我可以很容易地找到对象边界框(立方体)的顶点,它们是 [xmin ymin zmin; xmax ymin zmin; xmax ymax zmin; xmin ymax zmin; xmin ymin zmax; xmax ymin zmax; xmax ymax zmax; xmin ymax zmax]

我在创建立方体(ROS中检测到的对象的边界框)的方向时遇到了一些问题。我知道最大和最小坐标值(xmin,xmax,ymin,ymax,zmin,zmax)。因此,我可以很容易地找到对象边界框(立方体)的顶点,它们是

[xmin ymin zmin; 
 xmax ymin zmin; 
 xmax ymax zmin; 
 xmin ymax zmin;
 xmin ymin zmax; 
 xmax ymin zmax; 
 xmax ymax zmax;
 xmin ymax zmax]
现在,如何从这些顶点创建四元数以获得边界框的方向?我知道四元数是由4个数字组成的集合,[x y z w],以如下方式表示旋转:

// RotationAngle is in radians
x = RotationAxis.x * sin(RotationAngle / 2)
y = RotationAxis.y * sin(RotationAngle / 2)
z = RotationAxis.z * sin(RotationAngle / 2)
w = cos(RotationAngle / 2)
当知道对象的顶点(在我的例子中是立方体或三维矩形)时,如何获得旋转轴和旋转角?
感谢您使用最小值和最大值创建边界框的方式,它将生成与x、y和z轴对齐的边界框。因此,它没有任何旋转,它的四元数是[0,0,0,1]

如果知道哪个顶点与立方体/矩形的哪个角相关,则获取随机定向立方体或矩形的旋转矩阵并不复杂。然后,您可以只使用两条垂直边作为对象坐标系中的x轴和y轴。规格化这些向量后,可以通过构建x和y向量的叉积在对象帧中创建z轴。3x3旋转矩阵的列是以下三个向量:

    | x_0  y_0  z_0 |
R = | x_1  y_1  z_1 |
    | x_2  y_2  z_2 |
您可以在internet上搜索资源,从旋转矩阵中获取旋转轴和四元数

对于一般对象,如果在对象坐标系中有两个垂直轴上的点的顶点,则可以使用相同的方法。如果不知道顶点在对象帧中的corespondig点,则会变得更复杂。如果顶点均匀地覆盖对象(例如,来自3D摄影机或激光扫描的顶点),则可以使用主成分分析来查找顶点的主轴。这些轴构成旋转矩阵的列(确保主轴构成右手fram,即旋转矩阵的确定值为+1)

如果这些方法也不适用于您,您可以在点云(例如:点云库)的上下文中搜索姿势估计方法。

(我不知道ROS是什么,但这里是对您的问题的抽象讨论。)

首先,“旋转”从“从”状态开始,到“到”状态结束。您知道“到”状态,但必须指定“从”状态。假设长方体以默认状态开始,一个角点位于(0,0,0),另一个角点位于(1,1,1)

此默认框状态与最终框状态类似,是“轴对齐”框。现在,长方体可能已旋转90度、180度或270度,但如果长方体的不同面彼此不明显,这可能无关紧要。此场景将进行0度旋转,表示此旋转的四元数通常计算为(0,0,0,1)。您仍然需要缩放和平移(计算起来也很简单)才能从默认状态到BB,但不需要旋转

现在,如果这些面实际上是不同的,那么我们确实会有一个旋转。让我们称之为“轴对齐旋转”或AAR,它可以将默认框转换为24种不同状态中的任意一种。这样想:旋转轴可以是任意方向上的6个基向量中的任意一个(+x,-x,+y,-y,+z,-z),角度可以是0、90、180或270度(6*4是24!)

每种情况,当你这样想的时候,都完全定义了一个旋转四元数,这是很容易构造的。然后,问题就变成了找到24个旋转中的一个

我可以为此想出两个心理模型:或者为你的盒子选择一个“正面”和一个“顶部”的面,并找出它们在“到”状态下的最终位置(6个位置为“正面”,4个位置为“顶部”);或者你可以选择一个“原点”顶点和一个“邻居”顶点,并找到它们的最终位置(8个位置为“原点”,3个位置为“邻居”)在任何一种情况下,您都可能会有一个用于预计算四元数的24条目表,您将根据“旋转”从中进行选择。

用于提取OBB的代码(来自教程):

pcl::MomentOfInertiaEstimation <pcl::PointXYZ> feature_extractor;
feature_extractor.setInputCloud (cloud);
feature_extractor.compute ();

pcl::PointXYZ min_point_OBB;
pcl::PointXYZ max_point_OBB;
pcl::PointXYZ position_OBB;
Eigen::Matrix3f rotational_matrix_OBB;
Eigen::Vector3f major_vector, middle_vector, minor_vector;
Eigen::Vector3f mass_center;

feature_extractor.getOBB (min_point_OBB, max_point_OBB, position_OBB, rotational_matrix_OBB);
feature_extractor.getEigenVectors (major_vector, middle_vector, minor_vector);
feature_extractor.getMassCenter (mass_center);

但是如果我知道8个顶点,我就可以创建立方体。这个立方体必须有一定的方向。如何获得旋转矩阵,以及如何知道哪个顶点与立方体/矩形的哪个角相关。如果您使用问题中提到的8个顶点创建立方体,其边将平行于x、y和z轴。在没有任何进一步的信息或约束的情况下,任何旋转(即作为旋转矩阵的单位矩阵)都不如将立方体的边转换为平行于x、y和z轴的任何其他旋转。正如在另一个答案中提到的,您有几个旋转导致类似的结果(一个边沿平行于x、y和z轴的立方体)。因此,额外的约束或假设可以帮助您缩小范围。但是你没有提到任何这样的约束,但是我知道立方体的8个角点(x,y,z)。所以它必须有方向性。正确,知道任何立方体的8个角坐标点,从那里可以找到它的方向。我说的对吗?立方体有一个方向(单位矩阵也是旋转的)。问题是,方向不是唯一的:旋转是从初始位置到最终位置转换的一部分。如果您不知道立方体的初始方向,则不清楚要选择24种可能的旋转方式中的哪一种。那么,您为什么对轴对齐边界框的方向感兴趣呢?我使用ZED深度相机。那么我可以应用主成分分析来找到顶点的主轴吗?那么如何得到顶点的主轴呢。?在那之后你能得到旋转矩阵吗?但在PCA教程中,我有大值、中值、小值;然后,艾根:
Eigen::Vector3f p1 (min_point_OBB.x, min_point_OBB.y, min_point_OBB.z);
Eigen::Vector3f p2 (min_point_OBB.x, min_point_OBB.y, max_point_OBB.z);
Eigen::Vector3f p3 (max_point_OBB.x, min_point_OBB.y, max_point_OBB.z);
Eigen::Vector3f p4 (max_point_OBB.x, min_point_OBB.y, min_point_OBB.z);
Eigen::Vector3f p5 (min_point_OBB.x, max_point_OBB.y, min_point_OBB.z);
Eigen::Vector3f p6 (min_point_OBB.x, max_point_OBB.y, max_point_OBB.z);
Eigen::Vector3f p7 (max_point_OBB.x, max_point_OBB.y, max_point_OBB.z);
Eigen::Vector3f p8 (max_point_OBB.x, max_point_OBB.y, min_point_OBB.z);

p1 = rotational_matrix_OBB * p1 + position;
p2 = rotational_matrix_OBB * p2 + position;
p3 = rotational_matrix_OBB * p3 + position;
p4 = rotational_matrix_OBB * p4 + position;
p5 = rotational_matrix_OBB * p5 + position;
p6 = rotational_matrix_OBB * p6 + position;
p7 = rotational_matrix_OBB * p7 + position;
p8 = rotational_matrix_OBB * p8 + position