说明: 我使用的PointLLA构造函数只通过Latitude和Longitude,但我从未明确将内部Altitude成员变量设置为0. Rookie错误......
原始问题: 我的代码中有一个错误,我有一段非常可怕的时间。我正在计算单个点和矩形角之间的距离。在这种情况下,该点以矩形为中心,因此我应该得到四个相等的距离。我得到三个相等的距离,一个几乎相等的距离值是不一致的(每次运行都不同)。
如果我有几个关键的调试语句(几乎只是一个std :: cout调用)明确打印出每个矩形角的位置,我得到距离的预期值,并且不一致性消失。这是相关的代码:
// calculate the minimum and maximum distance to
// camEye within the available lat/lon bounds
Vec3 viewBoundsNE; convLLAToECEF(PointLLA(maxLat,maxLon),viewBoundsNE);
Vec3 viewBoundsNW; convLLAToECEF(PointLLA(maxLat,minLon),viewBoundsNW);
Vec3 viewBoundsSW; convLLAToECEF(PointLLA(minLat,minLon),viewBoundsSW);
Vec3 viewBoundsSE; convLLAToECEF(PointLLA(minLat,maxLon),viewBoundsSE);
// begin comment this block out, and buggy output
OSRDEBUG << "INFO: NE (" << viewBoundsNE.x
<< " " << viewBoundsNE.y
<< " " << viewBoundsNE.z << ")";
OSRDEBUG << "INFO: NW (" << viewBoundsNW.x
<< " " << viewBoundsNW.y
<< " " << viewBoundsNW.z << ")";
OSRDEBUG << "INFO: SE (" << viewBoundsSW.x
<< " " << viewBoundsSW.y
<< " " << viewBoundsSW.z << ")";
OSRDEBUG << "INFO: SW (" << viewBoundsSE.x
<< " " << viewBoundsSE.y
<< " " << viewBoundsSE.z << ")";
// --------------- end
// to get the maximum distance, find the maxima
// of the distances to each corner of the bounding box
double distToNE = camEye.DistanceTo(viewBoundsNE);
double distToNW = camEye.DistanceTo(viewBoundsNW); // <-- inconsistent
double distToSE = camEye.DistanceTo(viewBoundsSE);
double distToSW = camEye.DistanceTo(viewBoundsSW);
std::cout << "INFO: distToNE: " << distToNE << std::endl;
std::cout << "INFO: distToNW: " << distToNW << std::endl; // <-- inconsistent
std::cout << "INFO: distToSE: " << distToSE << std::endl;
std::cout << "INFO: distToSW: " << distToSW << std::endl;
double maxDistToViewBounds = distToNE;
if(distToNW > maxDistToViewBounds)
{ maxDistToViewBounds = distToNW; }
if(distToSE > maxDistToViewBounds)
{ maxDistToViewBounds = distToSE; }
if(distToSW > maxDistToViewBounds)
{ maxDistToViewBounds = distToSW; }
OSRDEBUG << "INFO: maxDistToViewBounds: " << maxDistToViewBounds;
因此,如果我运行上面显示的代码,我将得到如下输出:
INFO: NE (6378137 104.12492 78.289415)
INFO: NW (6378137 -104.12492 78.289415)
INFO: SE (6378137 -104.12492 -78.289415)
INFO: SW (6378137 104.12492 -78.289415)
INFO: distToNE: 462.71851
INFO: distToNW: 462.71851
INFO: distToSE: 462.71851
INFO: distToSW: 462.71851
INFO: maxDistToViewBounds: 462.71851
完全符合预期。请注意,所有distTo *值都相同。我可以一遍又一遍地运行程序,我会得到完全相同的输出。但是现在,如果我在上面的代码中注释掉我注意到的块,我会得到类似的结果:
INFO: distToNE: 462.71851
INFO: distToNW: 463.85601
INFO: distToSE: 462.71851
INFO: distToSW: 462.71851
INFO: maxDistToViewBounds: 463.85601
每次运行都会稍微改变一下。为什么要分散而不是其他价值?我不知道。再运行几次:
463.06218
462.79352
462.76194
462.74772
463.09787
464.04648
那么......这里发生了什么?我尝试清理/重建我的项目,看看是否有一些奇怪的事情发生但它没有帮助。我正在使用GCC 4.6.3和x86目标。
编辑:添加相关功能的定义。
void MapRenderer::convLLAToECEF(const PointLLA &pointLLA, Vec3 &pointECEF)
{
// conversion formula from...
// hxxp://www.microem.ru/pages/u_blox/tech/dataconvert/GPS.G1-X-00006.pdf
// remember to convert deg->rad
double sinLat = sin(pointLLA.lat * K_PI/180.0f);
double sinLon = sin(pointLLA.lon * K_PI/180.0f);
double cosLat = cos(pointLLA.lat * K_PI/180.0f);
double cosLon = cos(pointLLA.lon * K_PI/180.0f);
// v = radius of curvature (meters)
double v = ELL_SEMI_MAJOR / (sqrt(1-(ELL_ECC_EXP2*sinLat*sinLat)));
pointECEF.x = (v + pointLLA.alt) * cosLat * cosLon;
pointECEF.y = (v + pointLLA.alt) * cosLat * sinLon;
pointECEF.z = ((1-ELL_ECC_EXP2)*v + pointLLA.alt)*sinLat;
}
// and from the Vec3 class defn
inline double DistanceTo(Vec3 const &otherVec) const
{
return sqrt((x-otherVec.x)*(x-otherVec.x) +
(y-otherVec.y)*(y-otherVec.y) +
(z-otherVec.z)*(z-otherVec.z));
}
答案 0 :(得分:5)
不一致的输出表明您在代码中的某处使用了未初始化的变量,或者您有一些内存错误(访问已删除的内存,双重删除内存等)。我没有看到你粘贴的代码中发生过这些事情,但是还有许多其他代码被调用。
Vec3构造函数是否将所有成员变量初始化为零(或某些已知状态)?如果没有,那么这样做,看看是否有帮助。如果它们已经初始化,请仔细查看convLLAToECEF和PointLLA以查看是否有任何变量未初始化或者是否存在任何内存错误。
答案 1 :(得分:0)
在我看来,DistanceTo
函数在某种程度上被窃听。如果你无法解决问题,请尝试一下,并报告回来。
camEye
来排除该类中的有状态。答案 2 :(得分:0)
尽管我讨厌它,你是否在调试器中逐步完成了它?我通常倾向于基于stdout的调试,但似乎它有所帮助。除此之外,你有一些令人讨厌的踢腿的副作用。
我的猜测是,你希望(当然正确地)所有四个值相同的事实是在某处掩盖“NW / SW / NE / SE”错字。我要做的第一件事是将你在这里拥有的块隔离到它自己的函数(它采用框和点坐标),然后用几个不同位置的点运行它。我认为这个错误很可能会在那时迅速暴露出来。
答案 3 :(得分:0)
如果您有调试语句,请查看问题是否重现,但在输出后移动它们。然后,调试语句可以帮助确定是Vec3
对象是否已损坏,或者是从中进行计算。
其他想法:在valgrind
下运行代码。
分解反汇编输出。