8

我看到onPoseAvailable()回调和Tango.getPoseAtTime(). 我编写了一个测试程序,在其中onPoseAvailable()记录了传递的姿势,并使用getPoseAtTime()之前 2 个回调的时间戳来请求姿势。KEY_BOOLEAN_SMOOTH_POSE已配置false。这是执行此操作的代码(timestamps_成员变量是 a LinkedList<Double>):

@Override
public void onPoseAvailable(TangoPoseData poseData) {
   if (poseData != null && poseData.statusCode == TangoPoseData.POSE_VALID) {
      Log.v("bug",
         String.format("onPoseAvailable t: %f, base: %d,  target %d, p: (%f, %f, %f)",
            poseData.timestamp,
            poseData.baseFrame,
            poseData.targetFrame,
            poseData.translation[0], poseData.translation[1], poseData.translation[2]));
      timestamps_.add(poseData.timestamp);
      if (timestamps_.size() > 3)
         timestamps_.remove();
   }

   if (timestamps_.isEmpty())
      return;

   TangoCoordinateFramePair framePair = new TangoCoordinateFramePair(
      TangoPoseData.COORDINATE_FRAME_START_OF_SERVICE,
      TangoPoseData.COORDINATE_FRAME_DEVICE);
   poseData = tango_.getPoseAtTime(timestamps_.getFirst(), framePair);
   if (poseData != null && poseData.statusCode == TangoPoseData.POSE_VALID) {
      Log.v("bug",
         String.format("getPoseAtTime t: %f, base: %d,  target %d, p: (%f, %f, %f)",
            poseData.timestamp,
            poseData.baseFrame,
            poseData.targetFrame,
            poseData.translation[0], poseData.translation[1], poseData.translation[2]));
   }
}

这是实际日志的摘录(为了清楚起见,我对记录的调用进行了去交错处理):

onPoseAvailable t: 2732.762486, base: 2,  target 4, p: (0.280245, 0.412468, 0.562201)
onPoseAvailable t: 2732.802553, base: 2,  target 4, p: (0.296951, 0.420919, 0.599938)
onPoseAvailable t: 2732.852638, base: 2,  target 4, p: (0.317444, 0.429809, 0.646445)
onPoseAvailable t: 2732.882689, base: 2,  target 4, p: (0.330845, 0.434106, 0.676810)
onPoseAvailable t: 2732.932774, base: 2,  target 4, p: (0.350995, 0.439777, 0.723639)
onPoseAvailable t: 2732.962825, base: 2,  target 4, p: (0.363319, 0.442731, 0.754508)
onPoseAvailable t: 2732.992875, base: 2,  target 4, p: (0.373911, 0.445289, 0.784786)
onPoseAvailable t: 2733.032943, base: 2,  target 4, p: (0.387709, 0.448182, 0.822682)
onPoseAvailable t: 2733.062994, base: 2,  target 4, p: (0.398502, 0.450481, 0.852662)
onPoseAvailable t: 2733.073011, base: 2,  target 4, p: (0.401869, 0.451084, 0.862530)
onPoseAvailable t: 2733.103062, base: 2,  target 4, p: (0.411136, 0.452486, 0.890441)

getPoseAtTime t: 2732.712401, base: 2,  target 4, p: (0.269301, 0.410911, 0.549182)
getPoseAtTime t: 2732.732435, base: 2,  target 4, p: (0.277217, 0.415130, 0.567040)
getPoseAtTime t: 2732.762486, base: 2,  target 4, p: (0.288928, 0.421914, 0.595162)
getPoseAtTime t: 2732.802553, base: 2,  target 4, p: (0.305241, 0.429648, 0.632158)
getPoseAtTime t: 2732.852638, base: 2,  target 4, p: (0.324359, 0.437655, 0.680300)
getPoseAtTime t: 2732.882689, base: 2,  target 4, p: (0.332997, 0.442538, 0.712727)
getPoseAtTime t: 2732.932774, base: 2,  target 4, p: (0.353665, 0.447269, 0.759725)
getPoseAtTime t: 2732.962825, base: 2,  target 4, p: (0.369174, 0.451645, 0.790263)
getPoseAtTime t: 2732.992875, base: 2,  target 4, p: (0.382584, 0.454754, 0.819555)
getPoseAtTime t: 2733.032943, base: 2,  target 4, p: (0.396857, 0.456922, 0.856626)
getPoseAtTime t: 2733.062994, base: 2,  target 4, p: (0.409672, 0.460060, 0.888748)

看看最后一个getPoseAtTime()条目,时间戳为 2733.062994。onPoseAvailable请注意,它的位置值与具有相同时间戳的姿势不​​匹配。这里有些不对劲。

我确实认为样条拟合姿势不一定需要通过控制点,但我认为这不是一个可以接受的解释。首先,拥有一个为相同测量提供不同值的 API 没有多大意义。但除此之外,实际数字并不支持该猜想。

查看getPoseAtTime()Y 值,0.460060。这在之前和之后的所有 Y 值的 Y 范围之外onPoseAvailable()(事实上,在整个日志中)。没有合理的插值模型可以产生这个值。

我想问题是这里发生了什么?姿势不一致,因此至少其中一个是错误的(如果不是两个)。我的猜测onPoseAvailable()是更有可能是正确的。

这是两种姿势方法(Nash 释放)的 Y 位置与时间的关系图,其中平板电脑在其底座中静止:

在此处输入图像描述

蓝线是onPoseAvailable()回调,红线是getPoseAtTime()轮询。这些结果有点奇怪。如果姿势完全不同,我希望轮询值会更平滑,因为它可以在轮询时间之前和之后使用来自样本的贡献进行过滤,而回调值将未过滤或仅使用先验过滤样品。但这不是我们所看到的 - 轮询值看起来更嘈杂。

这是我上下移动平板电脑时捕获的类似图表。轮询值仍然具有更高的频率,并且两个信号的跟踪不是特别紧密。

在此处输入图像描述

4

1 回答 1

4

感谢 rhashimoto 指出这一点!

编辑

我必须编辑我以前的帖子。我声称在使用 GetPoseAtTime 而不是 OnPoseAvailable 回调的姿势时,我的漂移更大。

这只是反过来。使用 GetPoseAtTime 可以获得更好的结果。

我在椅子上旋转 360° 进行了扫描。正如你在图片中看到的那样,我开始和停止在我的办公桌前。

扫描周期的开始和结束(单击它以获得更大的分辨率) 扫描周期的开始和结束

上面的点云使用姿势 GetPoseAtTime,下面的点云使用 OnPoseAvailable 回调的姿势。两人同时被抓获。GetPoseAtTime 的漂移是微不足道的,但 OnPoseAvailable 回调真的很大。

到目前为止,我发现 GetPoseAtTime 使用姿势图并在检测到闭环时纠正姿势,请参阅这篇文章。我测试了结果是否变得更好,我是否立即使用可用的点云访问姿势,或者在我合并所有点云时仅在最后访问。

事实上,结果要好得多。所以到目前为止我的经验是:

OnPoseAvailabe 回调 < GetPoseAtTime 立即使用可用的点云 < GetPoseAtTime 在扫描结束时

于 2015-12-02T17:15:33.367 回答