是的,你必须使用TangoPoseData。
我猜你正确使用了TangoXyzIjData;但是您以这种方式获得的数据与设备的位置以及拍摄时设备的倾斜方式有关。
我是这样解决这个问题的:
我从java_point_to_point_example开始。在此示例中,他们使用 2 个不同的坐标系获得 2 个不同点的坐标,然后将这些坐标写入基本坐标系对。
首先,您必须设置您的外参,这样您就可以执行您需要的所有转换。为此,我在 setTangoListener() 函数的末尾调用 mExstrinsics = setupExtrinsics(mTango) 函数。这是代码(您也可以在我上面链接的示例中找到)。
private DeviceExtrinsics setupExtrinsics(Tango mTango) {
//camera to IMU tranform
TangoCoordinateFramePair framePair = new TangoCoordinateFramePair();
framePair.baseFrame = TangoPoseData.COORDINATE_FRAME_IMU;
framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_COLOR;
TangoPoseData imu_T_rgb = mTango.getPoseAtTime(0.0,framePair);
//IMU to device transform
framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_DEVICE;
TangoPoseData imu_T_device = mTango.getPoseAtTime(0.0,framePair);
//IMU to depth transform
framePair.targetFrame = TangoPoseData.COORDINATE_FRAME_CAMERA_DEPTH;
TangoPoseData imu_T_depth = mTango.getPoseAtTime(0.0,framePair);
return new DeviceExtrinsics(imu_T_device,imu_T_rgb,imu_T_depth);
}
然后,当您获得点云时,您必须对其进行“标准化”。使用你的 extrinsics 非常简单:
public ArrayList<Vector3> normalize(TangoXyzIjData cloud, TangoPoseData cameraPose, DeviceExtrinsics extrinsics) {
ArrayList<Vector3> normalizedCloud = new ArrayList<>();
TangoPoseData camera_T_imu = ScenePoseCalculator.matrixToTangoPose(extrinsics.getDeviceTDepthCamera());
while (cloud.xyz.hasRemaining()) {
Vector3 rotatedV = ScenePoseCalculator.getPointInEngineFrame(
new Vector3(cloud.xyz.get(),cloud.xyz.get(),cloud.xyz.get()),
camera_T_imu,
cameraPose
);
normalizedCloud.add(rotatedV);
}
return normalizedCloud;
}
这应该足够了,现在你有一个点云 wrt 你的基本参考框架。
如果您过度叠加两个或更多这种“标准化”云,您可以获得房间的 3D 表示。
还有另一种使用旋转矩阵的方法,解释了here。
我的解决方案非常慢(开发工具包大约需要 700 毫秒来标准化约 3000 个点的云),因此它不适合用于 3D 重建的实时应用程序。
Atm 我正在尝试使用 NDK 和 JNI 在 C 中使用 Tango 3D Reconstruction Library。该库有很好的文档记录,但设置环境并开始使用 JNI 非常痛苦。 (事实上,我现在被困住了)。
漂流
当我用设备转身时仍然有问题。看来点云散开了很多。
我猜你正在经历一些漂流。
当您单独使用 Motion Tracking 时会发生漂移:它包含在估计您的 Pose 时的许多非常小的错误,这些错误加在一起会导致您相对于世界的姿势出现很大错误.例如,如果你带着你的探戈设备绕着一个圆圈走,追踪你的TangoPoseData,然后你在电子表格或任何你想要的东西中画出你的轨迹,你会注意到平板电脑永远不会回到他的起点,因为他在漂流离开。
解决方案是使用区域学习。
如果您对此主题没有明确的想法,我建议您观看 Google I/O 2016 上的 talk。它将涵盖很多要点并给您一个很好的介绍。
使用区域学习非常简单。
您只需在TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION 中更改您的基本参考框架。通过这种方式,你告诉你的 Tango 估计他的姿势,而不是你启动应用程序时的位置,而是该区域的某个固定点。
这是我的代码:
private static final ArrayList<TangoCoordinateFramePair> FRAME_PAIRS =
new ArrayList<TangoCoordinateFramePair>();
{
FRAME_PAIRS.add(new TangoCoordinateFramePair(
TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION,
TangoPoseData.COORDINATE_FRAME_DEVICE
));
}
现在您可以像往常一样使用这个FRAME_PAIRS。
然后您必须修改您的TangoConfig 以使用密钥TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION 发布Tango 以使用区域学习。请记住,当使用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION 时,您不能使用学习模式和加载 ADF(区域描述文件)。
所以你不能使用:
-
TangoConfig.KEY_BOOLEAN_LEARNINGMODE
-
TangoConfig.KEY_STRING_AREADESCRIPTION
这是我在我的应用程序中初始化TangoConfig 的方式:
TangoConfig config = tango.getConfig(TangoConfig.CONFIG_TYPE_DEFAULT);
//Turning depth sensor on.
config.putBoolean(TangoConfig.KEY_BOOLEAN_DEPTH, true);
//Turning motiontracking on.
config.putBoolean(TangoConfig.KEY_BOOLEAN_MOTIONTRACKING,true);
//If tango gets stuck he tries to autorecover himself.
config.putBoolean(TangoConfig.KEY_BOOLEAN_AUTORECOVERY,true);
//Tango tries to store and remember places and rooms,
//this is used to reduce drifting.
config.putBoolean(TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION,true);
//Turns the color camera on.
config.putBoolean(TangoConfig.KEY_BOOLEAN_COLORCAMERA, true);
使用这种技术,您将摆脱这些价差。
PS
在上面链接的谈话中,大约在 22:35,他们向您展示了如何将您的应用程序移植到 Area Learning。在他们的示例中,他们使用 TangoConfig.KEY_BOOLEAN_ENABLE_DRIFT_CORRECTION。该密钥不再存在(至少在 Java API 中)。请改用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION。