首页 文章

C程序,从旋转度获得笛卡尔坐标

提问于
浏览
3

我在工作应用程序上工作的时间太长了......而且很久以前就毕业了:)最近我一直在编写一个使用C的小型机器人模拟(虽然这个问题比C更算数学/算法)我有两个单位(坦克机器人)从比赛场地的X和Y坐标开始 .

现在,面板上有按键可以旋转它们,还有一个按键可以向前移动它们 . 我现在面临着从旋转度到下一个X,Y坐标转换到笛卡尔游戏区域的轻微脑崩溃 .

由于HW的限制,只有固定点可用于实际运动,但计算可以通过浮点值来完成 .

我刚刚从内存中编写了以下代码:

/* Recalculate to radians */

int radians;



/* Use sin and cos to get a vector (new x and y coords). Translate from polar to   
   cartesian coordinates */
radians = (int) _tanks[0].rotationAngle * (M_PI / 180);
_tanks[0].x += _tanks[0].speed * cos(radians);
_tanks[0].y += _tanks[0].speed * sin(radians);

radians = (int) _tanks[1].rotationAngle * (M_PI / 180);
_tanks[1].x += _tanks[1].speed * cos(radians);
_tanks[1].y += _tanks[1].speed * sin(radians);

不幸的是,在编写纯商业软件这些年后,似乎我的大脑在极坐标数学和几何上并没有真正刷新,所以它似乎无法按预期工作 .

例如,如果rotationAngle是180,那么下一个x / y就在左边,导致机器人翻倒:)

我想要的是一个与旧的Micro Machines游戏类似的运动方案,如果你还记得下一个点在物体面对面的位置,那么它会移动(速度)那里的步数 .

有人可以建议我在哪里错了...

另外,如果在C语言中使用更简单的方法比我刚刚编写的纯数学尝试(严重的那样),请给我一个提示 .

编辑:

试图添加:

float radians;


 radians = (45 - _tanks[0].rotationAngle) * (M_PI / 180);
 _tanks[0].x += (int) (_tanks[0].speed * cos(radians));
 _tanks[0].y += (int) (_tanks[0].speed * sin(radians));

根据下面的答案,0度确实是正Y轴 . 但这也给出了不正确的结果 . 现在180度起点的移动向左移动 . 在180度应沿负Y轴移动 .

更多代码:

初始_tank结构 -

tanks[0].acc = 0;
tanks[0].dec = 0;
tanks[0].rotationAngle = 180;
tanks[0].speed = 0;
tanks[0].x = 400;
tanks[0].y = 150;
tanks[0].turretRotationAngle = 180;

旋转度只是一个数字(固定整数),我根据圆圈@ 360度包裹它,就像这样 -

switch(direction) {
case 0:
    tank->rotationAngle -= degrees;
    if(tank->rotationAngle < 1) {
        tank->rotationAngle = 360;
    }
break;
case 1:
    tank->rotationAngle += degrees;
        if(tank->rotationAngle > 360) {
        tank->rotationAngle = 0;
    }
break;

}

顺时针旋转一键,逆时针旋转一键 .

旋转工作,但运动没有,如上所述......

调试运行结果:

初始状态(由于0速度没有移动) -

radians = -2.3561945
x = 400
y = 150 
speed = 0

移动后(速度> 0) -

radians = -2.3561945 (the same since i only press the move button)
x = 399
y = 149 
speed = 2

这看起来很奇怪 . 如果旋转距离初始原点180度,X坐标根本不应该改变?只有Y应该改变,而相反的方向 . 我会将变化转换为如果速度为2,矢量长度应为2,那么变化将是对象面向的方向的2步,因此y = y 2和x = x 0对象的180度旋转?

我觉得我到了那里:)

进一步编辑:

如果我这样做,似乎沿着我需要的游戏场几乎是正确的:

radians = (_tanks[0].rotationAngle - 90) * (M_PI / 180);

注意-90 ...

当速度降低时,似乎仍然出现故障,但至少它会向正确的方向移动 .

2 回答

  • 4

    例如,如果rotationAngle是180,那么下一个x / y就在左边,导致机器人翻倒:)

    是的,这就是你的代码所做的:你的代码是正确的,除了上面提到的 int radians 问题,前提是0°是正x轴,90°是正y轴,180°是负x -axis,270°(或-90°)是负y轴 .

    我猜这相反,你想要0°成为正y轴吗?并且 - 你想要90°是正x轴(所以你的角度围绕圆顺时针顺时针进行),还是负x轴(所以它们逆时针进行)?对于前一个(顺时针)情况,只需将 _tanks[...].rotationAngle 更改为 (90 - _tanks[...].rotationAngle) (在45°线附近为"flip");对于后者(逆时针)的情况,只需将其更改为 (_tanks[...].rotationAngle + 90) (至"rotate",它关于原点90°) .

  • 1

    @ruakh和@ user3386109很好地讨论了角度单位和阶段的问题 .

    另外,对于“在C中执行此操作的更平滑方式”,还要考虑:

    • 使用 round() ,否则代码会引入偏差 . (假设 _tanks[1].x 是某个整数)
    double radians = _tanks[0].rotationAngle * (M_PI / 180);
    _tanks[0].x += (int) round(_tanks[0].speed * cos(radians));
    
    • 使用 float 而不是 double 作为额外的精度,不需要更长的计算时间 .
    float radians = _tanks[0].rotationAngle * (float)((M_PI / 180));
    _tanks[0].x += (int) roundf(_tanks[0].speed * cosf(radians));  // note function names
    
    • 如果处理时间有限,整数查找表可以与360 int 缩放的正弦和余弦值一起使用,而不是所有浮点数学 .
    _tanks[0].x += (_tanks[0].speed * LUT_cos[_tanks[0].rotationAngle])/scale;
    

相关问题