此代码间歇性地工作。它在一个小型微控制器上运行。即使重新启动处理器,它也能正常工作,但是如果我更改了部分代码,它就会中断。这让我觉得它是某种指针错误或内存损坏。发生的是坐标,p_res.pos.x有时读取为0(不正确的值)和96(正确的值)传递给write_circle_outlined。在大多数情况下,似乎是正确的。如果有人能发现任何明显错误的信息,请指出来!
int demo_game()
{
long int d;
int x, y;
struct WorldCamera p_viewer;
struct Point3D_LLA p_subj;
struct Point2D_CalcRes p_res;
p_viewer.hfov = 27;
p_viewer.vfov = 32;
p_viewer.width = 192;
p_viewer.height = 128;
p_viewer.p.lat = 51.26f;
p_viewer.p.lon = -1.0862f;
p_viewer.p.alt = 100.0f;
p_subj.lat = 51.20f;
p_subj.lon = -1.0862f;
p_subj.alt = 100.0f;
while(1)
{
fill_buffer(draw_buffer_mask, 0x0000);
fill_buffer(draw_buffer_level, 0xffff);
compute_3d_transform(&p_viewer, &p_subj, &p_res, 10000.0f);
x = p_res.pos.x;
y = p_res.pos.y;
write_circle_outlined(x, y, 1.0f / p_res.est_dist, 0, 0, 0, 1);
p_viewer.p.lat -= 0.0001f;
//p_viewer.p.alt -= 0.00001f;
d = 20000;
while(d--);
}
return 1;
}
compute_3d_transform的代码是:
void compute_3d_transform(struct WorldCamera *p_viewer, struct Point3D_LLA *p_subj, struct Point2D_CalcRes *res, float cliph)
{
// Estimate the distance to the waypoint. This isn't intended to replace
// proper lat/lon distance algorithms, but provides a general indication
// of how far away our subject is from the camera. It works accurately for
// short distances of less than 1km, but doesn't give distances in any
// meaningful unit (lat/lon distance?)
res->est_dist = hypot2(p_viewer->p.lat - p_subj->lat, p_viewer->p.lon - p_subj->lon);
// Save precious cycles if outside of visible world.
if(res->est_dist > cliph)
goto quick_exit;
// Compute the horizontal angle to the point.
// atan2(y,x) so atan2(lon,lat) and not atan2(lat,lon)!
res->h_angle = RAD2DEG(angle_dist(atan2(p_viewer->p.lon - p_subj->lon, p_viewer->p.lat - p_subj->lat), p_viewer->yaw));
res->small_dist = res->est_dist * 0.0025f; // by trial and error this works well.
// Using the estimated distance and altitude delta we can calculate
// the vertical angle.
res->v_angle = RAD2DEG(atan2(p_viewer->p.alt - p_subj->alt, res->est_dist));
// Normalize the results to fit in the field of view of the camera if
// the point is visible. If they are outside of (0,hfov] or (0,vfov]
// then the point is not visible.
res->h_angle += p_viewer->hfov / 2;
res->v_angle += p_viewer->vfov / 2;
// Set flags.
if(res->h_angle < 0 || res->h_angle > p_viewer->hfov)
res->flags |= X_OVER;
if(res->v_angle < 0 || res->v_angle > p_viewer->vfov)
res->flags |= Y_OVER;
res->pos.x = (res->h_angle / p_viewer->hfov) * p_viewer->width;
res->pos.y = (res->v_angle / p_viewer->vfov) * p_viewer->height;
return;
quick_exit:
res->flags |= X_OVER | Y_OVER;
return;
}
结果的结构:
typedef struct Point2D_Pixel { unsigned int x, y; };
// Structure for storing calculated results (from camera transforms.)
typedef struct Point2D_CalcRes
{
struct Point2D_Pixel pos;
float h_angle, v_angle, est_dist, small_dist;
int flags;
};
代码是我的开源项目的一部分,因此可以在这里发布大量代码。
答案 0 :(得分:4)
我看到你的一些计算取决于p_viewer->yaw
,但我没有看到p_viewer->yaw
的任何初始化。这是你的问题吗?
答案 1 :(得分:2)
一些看似粗略的事情:
您可以从compute_3d_transform
返回,而无需设置p_res
/ res
中的多个字段,但来电者从不检查此情况。
您始终从res->flags
读取而不先将其初始化。
答案 2 :(得分:1)
当我用C程序中,我会用一个分而治之为这类问题调试技术来尝试隔离有问题的操作(注意症状是否改变,因为加入调试代码,其指示悬空的指针类型错误)。
基本上,开始与其中值是已知的良好的第一行(和证明它的是在该行一贯良好)。然后确定它在哪里是坏的。然后约。在两点之间插入一个测试,看看它是不是很糟糕。如果不是,然后将中间点和已知不良位置之间的测试半途而废,如果它是坏的,然后插入中间点和已知良好的位置之间的中途测试,等等。
如果识别的行本身是一个函数调用,则可以在该被调用的函数中重复此过程,依此类推。
使用这种方法时,最大限度地减少添加的代码量和人为的“噪音”非常重要,这可能会造成时间变化。
如果您没有(或不能使用)交互式调试器,或者在使用交互式调试器时没有显示问题,请使用此项。
答案 3 :(得分:1)
每当输出不同时,它可能意味着某些值未初始化,结果取决于变量中存在的垃圾值。牢记这一点,我寻找未初始化的变量。结构p_res未初始化。
if(res->est_dist > cliph)
goto quick_exit;
这意味着条件可能会变为真或假,具体取决于res-&gt; est_dist中存储的垃圾值。当if条件变为true时,它直接转到quick_exit标签并且不更新p_res.pos.x。如果条件结果为假,则更新。