简体   繁体   English

Project Tango onPoseAvailable()和getPoseAtTime()的差异

[英]Project Tango onPoseAvailable() and getPoseAtTime() discrepancies

I am seeing significant discrepancies between the poses from the onPoseAvailable() callback and Tango.getPoseAtTime() . 我看到onPoseAvailable()回调和Tango.getPoseAtTime()的姿势之间存在重大差异。 I wrote a test program where in onPoseAvailable() I logged the delivered pose and used getPoseAtTime() to request the pose using the timestamp from 2 callbacks earlier. 我编写了一个测试程序,其中在onPoseAvailable()我记录了所提供的姿势,并使用getPoseAtTime()使用来自2个回调的时间戳来请求姿势。 KEY_BOOLEAN_SMOOTH_POSE is configured false . KEY_BOOLEAN_SMOOTH_POSE配置为false Here is the code that does that (the timestamps_ member variable is a LinkedList<Double> ): 这是执行此操作的代码( timestamps_成员变量是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]));
   }
}

Here is an excerpt from an actual log (I have deinterleaved the logged calls for clarity): 这是实际日志的摘录(为清晰起见,我对记录的调用进行了去交织):

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)

Take a look at the last getPoseAtTime() entry, with timestamp 2733.062994. 看一下最后一个带有时间戳2733.062994的getPoseAtTime()条目。 Note that its position values do not match the pose from onPoseAvailable with the identical timestamp. 请注意,其位置值与具有相同时间戳记的onPoseAvailable中的姿势不匹配。 Something isn't right here. 这里不对劲。

I did consider that a spline fit of pose would not necessarily need to pass through the control points, but I don't think that is an acceptable explanation. 我确实认为,样条曲线的位姿拟合不一定需要通过控制点,但是我认为这不是可以接受的解释。 First of all it doesn't make a lot of sense to have an API that delivers different values for the same measurement. 首先,拥有一个为同一测量提供不同值的API并没有多大意义。 But in addition the actual numbers don't back that conjecture. 但除此之外,实际数字并不支持这一推测。

Look at the getPoseAtTime() Y value, 0.460060. 查看getPoseAtTime() Y值0.460060。 This is outside the Y range of all the onPoseAvailable() Y values, both before and after (over the entire log as a matter of fact). 这在所有onPoseAvailable() Y值的Y范围之前和之后(实际上是整个日志onPoseAvailable()都在Y范围之外。 No reasonable interpolation model can produce this value. 没有合理的插值模型可以产生该值。

I guess the question is what is going on here? 我想问题是这里发生了什么? The poses are inconsistent so at least one of them is wrong (if not both). 姿势不一致,因此至少其中之一是错误的(如果不是两个)。 My guess would be that the onPoseAvailable() is more likely to be correct. 我的猜测是onPoseAvailable()更可能是正确的。

Here is a graph of Y position versus time of the two pose methods (Nash release) with the tablet stationary in its dock: 这是将数位板固定在底座上时,两种姿势方法(Nash释放)的Y位置与时间的关系图:

在此处输入图片说明

The blue line is the onPoseAvailable() callback and the red line is the getPoseAtTime() polling. 蓝线是onPoseAvailable()回调,红线是getPoseAtTime()轮询。 These results are kind of strange. 这些结果有点奇怪。 If the poses are going to be different at all, I would expect that the polled value would be smoother because it could be filtered using contributions from samples before and after the poll time, while the callback value would either be unfiltered or filtered only using prior samples. 如果姿势完全不同,我希望轮询值会更平滑,因为可以使用轮询时间之前和之后的样本贡献来过滤轮询值,而回调值将不被过滤或仅使用之前的值进行过滤样品。 But that isn't what we see - the polled value appears much noisier. 但这不是我们所看到的-轮询的值看起来更嘈杂。

Here's a similar graph captured while I moved the tablet up and down. 这是我上下移动平板电脑时捕获的类似图形。 The polled value still has more high frequencies, and the two signals don't track particularly closely. 轮询的值仍然具有更高的频率,并且两个信号之间的跟踪并不特别紧密。

在此处输入图片说明

Thanks rhashimoto for pointing that out! 感谢rhashimoto指出这一点!

EDIT 编辑

I have to edit my previous post. 我必须编辑我以前的帖子。 I claimed that I had a greater drift while using GetPoseAtTime instead of the pose of the OnPoseAvailable callback. 我声称使用GetPoseAtTime而不是OnPoseAvailable回调的姿势时,漂移更大。

It's just the other way round. 反之亦然。 I get much better results with GetPoseAtTime. 使用GetPoseAtTime可以获得更好的结果。

I made a scan by spinning 360° on my chair. 我通过在椅子上旋转360°进行了扫描。 I started and stopped at my desk as you can see in the picture. 如您在图片中所见,我在办公桌前停下来。

start and end of the scanning cycle (click it for greater resolution) 扫描周期的开始和结束(单击以获得更高的分辨率) 扫描周期的开始和结束

The point clouds above use poses GetPoseAtTime and the point clouds below use pose by the OnPoseAvailable callback. 上方的点云使用GetPoseAtTime构成,下方的点云使用OnPoseAvailable回调构成。 Both captured at the same time. 两者同时捕获。 The drift with GetPoseAtTime is marginal, but with OnPoseAvailable callback really huge. GetPoseAtTime的漂移很小,但OnPoseAvailable回调的漂移确实很大。

What I found out so far is that GetPoseAtTime uses a pose graph and corrects the poses if a loop closure is detected see this article . 到目前为止,我发现,GetPoseAtTime使用姿势图并在检测到闭环时纠正姿势。 请参见本文 I tested if the results getting better, if I access the pose immediately with an available point cloud or just at the end while I'm merging all point clouds. 我测试了结果是否变好,是否立即使用可用的点云访问姿势或在合并所有点云时才访问姿势。

And indeed the result is way better. 结果的确更好。 So my experience so far is: 因此,到目前为止,我的经验是:

OnPoseAvailabe callback < GetPoseAtTime immediately with an available point cloud < GetPoseAtTime at the end of scanning 扫描结束时,OnPoseAvailabe回调<GetPoseAtTime立即具有可用点云<GetPoseAtTime

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM