I have been working for too long on the business applications it seems... And graduated too long ago perhaps :) Recently i have been tasked writing a small simulation of robotics using C (although this question is more math/algorithm than C) where i have two units (tank-bots) starting at an X and Y coordinate on a playfield.
Now there are keys on a panel to rotate them, and a key to move them forwards. I am now facing a minor brain meltdown on the translation from degrees of rotation to the next X,Y coord to move to in the cartesian playfield.
Due to limitations in HW only fixed point is available for the actual movement, but calculations can be done by float values.
I wrote the following code just from memory just now:
/* 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);
Unfortunately it seems my brain is not really refreshed on polar coordinate math and geometry after all these years on writing pure biz software, so it seems to not work as intended.
For instance if rotationAngle is 180, instead the next x/y is to the left, causing the bot to topple over :)
What i want is a movement scheme similiar to the old Micro Machines games if you remember where the next point would be in front of where the object is facing, so it moves (speed) number of steps there.
Can someone suggest where i'm going wrong here...
Also, if there is a smoother way of doing this in C than the pure mathematical attempt that i just wrote (badly at that), give me a hint.
EDIT:
Tried to add :
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));
according to answer below as 0 degrees is indeed the positive Y-axis. But this also gives incorrect results. Now movement for 180 degrees starting point is upwards to the left. At 180 degrees should be movement along the negative Y axis.
Some more code:
Init of _tank struct -
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;
The rotation degree is just a number (fixed integer), and i wrap it around as according to the circle @ 360 degrees, like so -
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;
}
One key for rotating clockwise, one for counter clockwise.
The rotation works, but the movement does not, as described...
Results of debug run:
Initial state (no movement due to 0 speed) -
radians = -2.3561945
x = 400
y = 150
speed = 0
After movement (speed > 0) -
radians = -2.3561945 (the same since i only press the move button)
x = 399
y = 149
speed = 2
This seems odd. The X coord should not change at all if the rotation is 180 degrees from the initial origin right? Only the Y should change, and in the opposite direction. I would translate the change instead to if speed is 2, vector length should be 2 so change would be 2 steps in the direction the object is facing, so y = y + 2 and x = x + 0 for 180 degree rotation on the object?
I feel like i'm getting there :)
Further EDIT:
Seems to be ALMOST correct along the lines of what i need for the playfield if i do this:
radians = (_tanks[0].rotationAngle - 90) * (M_PI / 180);
Note -90...
Still when speed is lowered it seems to glitch but at least it moves in the right direction.
radians
is going to be a number between 0 and 2PI, i.e. 0 to 6.28. Therefore radians must be a float. – user3386109double
sinceM_PI
is one. – Tommyradians
. Anint
value isn't going to work very well, as @user3386109 already noted. If you can't single-step, addprintf()
statements to see what the values are during the computation. When you know what the values are it will help you figure out why the code isn't doing what you expect. – steveha