我看到了onPoseAvailable()回调和Tango.getPoseAtTime()之间的显著差异。我编写了一个测试程序,在onPoseAvailable()中,我记录了提交的姿态,并使用getPoseAtTime()请求姿态,使用之前的两个回调的时间戳。KEY_BOOLEAN_SMOOTH_POSE配置为false。下面是这样做的代码( 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]));
}
}下面是一个实际日志的摘录(为了清晰起见,我已经删除了记录的调用):
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)看看最后一个带有时间戳2733.062994的getPoseAtTime()条目。请注意,它的位置值与来自onPoseAvailable的姿态与相同的时间戳不匹配。这里有东西不对劲。
我确实认为,样条拟合的姿态不一定需要通过控制点,但我不认为这是一个可以接受的解释。首先,拥有一个为相同度量提供不同值的API没有多大意义。但除此之外,实际的数字并不支持这一猜想。
看看getPoseAtTime() Y值,0.460060。这超出了所有onPoseAvailable() Y值的Y范围,无论是在前后(实际上是在整个日志中)。没有一个合理的插值模型能产生这个值。
我想问题是这是怎么回事?这些姿势不一致,所以其中至少有一个是错误的(如果两者都错的话)。我猜onPoseAvailable()更有可能是正确的。
下面是两种姿态方法(纳什释放)的Y位置与时间的关系图(Nash释放),平板电脑固定在其码头上:

蓝线是onPoseAvailable()回调,红线是getPoseAtTime()轮询。这些结果有点奇怪。如果姿势完全不同,我预计轮询后的值会更平滑,因为它可以在投票时间前后使用样本的贡献进行过滤,而回调值要么未经过滤,要么只使用先前的样本进行过滤。但这并不是我们所看到的--被调查的价值似乎更加喧闹。
这是我上下移动平板电脑时捕捉到的类似的图表。轮询值仍然具有更高的频率,而且这两个信号的跟踪并不特别密切。

发布于 2015-12-02 17:15:33
谢谢rhashimoto指出这一点!
编辑
我必须编辑我的上一篇文章。我声称我在使用GetPoseAtTime而不是使用OnPoseAvailable回调时有一个更大的偏差。
正好相反。我在GetPoseAtTime上得到了更好的结果。
我在椅子上旋转360度,做了一次扫描。我开始在办公桌前停下来,就像你在照片中看到的那样。
扫描周期的开始和结束(单击它获得更高的分辨率)

上面的点云构成GetPoseAtTime,下面的点云由OnPoseAvailable回调构成。两人同时被捕。GetPoseAtTime的漂移是边际的,但是OnPoseAvailable回调的影响很大。
到目前为止,我发现的是GetPoseAtTime使用一个姿态图,如果检测到一个循环闭包,见本文就会纠正这些姿态。我测试了结果是否变得更好,如果我立即用一个可用的点云访问这个姿势,或者就在我合并所有点云的时候。
结果确实要好得多。到目前为止,我的经验是:
OnPoseAvailabe回调< GetPoseAtTime,扫描结束时有一个可用的点云< GetPoseAtTime
https://stackoverflow.com/questions/30144196
复制相似问题