经过数周的等待,我终于有了我的Project Tango。我的想法是创建一个可生成房间点云并将其导出到.xyz数据的应用程序。然后,我将使用.xyz文件在浏览器中显示点云!我从编译和调整Google github上的点云示例开始。

现在,我使用onXyzIjAvailable(TangoXyzIjData tangoXyzIjData)获取x y和z值的帧;要点。然后,将这些帧以Vector3的形式保存在PCLManager中。扫描完房间后,我只需使用以下命令将PCLManager中的所有Vector3写入.xyz文件:

OutputStream os = new FileOutputStream(file);
size = pointCloud.size();
for (int i = 0; i < size; i++) {
    String row = String.valueOf(pointCloud.get(i).x) + " "
               + String.valueOf(pointCloud.get(i).y) + " "
               + String.valueOf(pointCloud.get(i).z) + "\r\n";
    os.write(row.getBytes());
}
os.close();


一切正常,不是编译错误或崩溃。唯一似乎出错的是云中点的旋转或平移。当我查看点云时,一切都混乱了。尽管点数与记录的相同,但无法识别我扫描的区域。

这是否与我不将PoseData和XyzIjData一起使用有关?我对这个主题有点陌生,很难理解PoseData的确切功能。有人可以向我解释一下,并帮助我修复点云吗?

最佳答案

是的,您必须使用TangoPoseData

我猜您正确使用了TangoXyzIjData;但是通过这种方式获取的数据与设备的位置以及拍摄时设备的倾斜方式有关。

这是我解决这个问题的方法:
我从java_point_to_point_example开始。在此示例中,他们获得具有2个不同坐标系的2个不同点的坐标,然后将这些坐标写入基本坐标框架对。

首先,您必须设置您的exstrinsics,因此您将能够执行所需的所有转换。为此,我在mExstrinsics = setupExtrinsics(mTango)函数末尾调用setTangoListener()函数。这是代码(您也可以在上面链接的示例中找到该代码)。

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);
}


然后,当您到达Cloud点时,您必须对其进行“标准化”。使用您的exstrinsics非常简单:

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;
}


这应该足够了,现在您有了参考基准的点云。
如果您过度叠加了两个或多个这种“规范化”云,则可以获得房间的3D表示。

here解释了使用旋转矩阵执行此操作的另一种方法。

我的解决方案速度很慢(开发套件需要大约700ms的时间才能归一化约3000点的云),因此它不适合用于3D重建的实时应用程序。

我正在尝试使用NDK和JNI在C语言中使用Tango 3D重建库。该库有充分的文档记录,但是设置您的环境并开始使用JNI非常痛苦。 (事实上​​,我目前处于困境中)。

漂流


  当我打开设备时仍然存在问题。似乎点云散布很多。


我想你正在经历一些漂移。
仅当单独使用运动跟踪时,就会发生漂移:它由许多很小的误差构成,这些误差在估算姿势时会共同导致您相对于世界的姿势产生较大的误差。例如,如果您带上探戈设备,然后围成一个圆圈追踪您的TangoPoseData,然后在电子表格中绘制轨迹,或者您想要的任何东西,您会注意到平板电脑永远不会在他的起点返回,因为他在漂移远。
解决方案是使用区域学习。
如果您对此主题没有明确的想法,建议您观看Google I / O 2016的talk。它将涵盖很多要点,并为您提供了很好的介绍。

使用区域学习非常简单。
您只需在TangoPoseData.COORDINATE_FRAME_AREA_DESCRIPTION中更改参考基准即可。通过这种方式,您告诉您的探戈不要在启动应用程序时估算其姿势,而应估算该区域的某个固定点。
这是我的代码:

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才能使Tango使用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION键使用Area Learning。请记住,使用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);


使用这种技术,您将摆脱那些价差。

聚苯乙烯
在上面链接的“谈话”中,在22:35左右,它们向您展示如何将应用程序移植到Area Learning。在他们的示例中,他们使用TangoConfig.KEY_BOOLEAN_ENABLE_DRIFT_CORRECTION。此项不再存在(至少在Java API中)。请改用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION

09-28 09:38