从Project Tango

时间:2016-07-07 10:55:31

标签: android google-project-tango point-clouds

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

现在我使用onXyzIjAvailable(TangoXyzIjData tangoXyzIjData)来获取x y和z值的帧;要点。然后我以Vector3的形式将这些帧保存在PCLManager中。在我完成扫描房间后,我使用以下方法将所有Vector3从PCLManager写入.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究竟做了什么。有人可以向我解释并帮我修复点云吗?

1 个答案:

答案 0 :(得分:3)

是的,您必须使用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时,你必须&#34;标准化&#34;它。使用你的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;
}

这应该足够了,现在你有一个基于参考框架的点云。 如果你过度使用了这两个或更多的&#34;标准化&#34;云,您可以获得房间的3D表示。

还有另一种方法可以使用旋转矩阵,here解释。

我的解决方案非常慢(开发工具包需要大约700毫秒来规范化大约3000点的云),因此它不适合用于3D重建的实时应用。

Atm我尝试使用NDK和JNI在C中使用Tango 3D重建库。该库已有详细记录,但设置环境并开始使用JNI非常痛苦。 (事实上​​,我现在被困住了。)

漂移

  

当我转动设备时仍然存在问题。点云似乎扩散了很多。

我猜你正在经历一些漂移 当您单独使用运动跟踪时会发生漂移:它会在估算您的姿势时出现很多非常小的错误,这些错误会导致相对于世界的姿势出现重大错误。例如,如果您使用探戈装置并且走一圈跟踪您的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
在上面链接的Talk i中,在22:35左右,它们向您展示了如何将应用程序移植到区域学习。在他们的示例中,他们使用 TangoConfig.KEY_BOOLEAN_ENABLE_DRIFT_CORRECTION 。此密钥不再存在(至少在Java API中)。请改用TangoConfig.KEY_BOOLEAN_DRIFT_CORRECTION