Directional change in joystick

KPollock

Member
Hey, everyone. Hope you're doing well.

Just putting this message out there to seek some help and guidance. Is there a good source to learning how to use atan/ atan2. What I'm seeking here is trying to learn how to rotate the x/y value of an analog joystick. Or if there is another way to do it, I'm all ears to learn. I'm using a teensy board if that's relevant.

Thanks in advance, ready to learn!
 
Rotation is done with a rotation matrix,
[ cos (a), sin (a) ]
[ -sin (a), cos (a) ] - use matrix multiplication of the rotation matrix with the coords as a column vector to get the rotated colum vector. And a is the angle in radians.

atan2 is used to determine the angle of something that's already rotated, as in
a = atan2(y, x)

You can also use complex numbers to do rotation, as in

z_rot = z e^(ia).
where z = x + iy, a is the angle in radians, and i is sqrt(-1)
 
I'll expand on MarkT's post above, starting from the very basics, so that everyone can follow. (Also, MarkT, your rotation matrix is transposed wrt. standard right-handed coordinate system and column vectors: it's usually the upper right sine that is negated, not the lower left one. It only affects the rotation direction, the same way as negating the angle in radians or degrees.)

Code:
c = cos(radians) = cos(degrees · π / 180)
s = sin(radians) = sin(degrees · π / 180)

atan2(s, c) = atan2(R·s, R·c) = radians,  radians · 180 / π = degrees
where R is any nonzero real number (can be even negative).

    ⎡ x ⎤        ⎡ x'⎤       ⎡ c  -s ⎤
v = ⎢   ⎥,  v' = ⎢   ⎥,  R = ⎢       ⎥
    ⎣ y ⎦        ⎣ y'⎦       ⎣ s   c ⎦

             ⎡ x'⎤   ⎡ c  -s ⎤ ⎡ x ⎤
v' = R v  ⇔  ⎢   ⎥ = ⎢       ⎥ ⎢   ⎥
             ⎣ y'⎦   ⎣ s   c ⎦ ⎣ y ⎦

             ⎧ x' = c x - s y
          ⇔  ⎨
             ⎩ y' = s x + c y
The prime ' is just one way to differentiate variables. It just means that x and x' are separate variables, as are y and y'. We could just as well call these oldx, newx, oldy, and newy, but the prime notation is more common and therefore useful to know, making these formulae easier to read.

Zero angle is towards positive x axis, 90° = π/2 is towards positive y axis, ±180° = ±π is towards negative x axis, and -90° = +270° = 3π/2 = -π/2 is towards negative y axis. Thus, positive angles rotate from positive x axis to positive y axis.

No rotation is trivial: c=1 and s=0, which leads to x'=x and y'=y, no change.

Rotation by multiples of 90° are trivial, because one of c and s is zero and the other is +1 or -1.

Rotation by 45° has c=s=√½≃0.7071067812. Additional multiples of 90° (the other diagonal directions) only change the signs.

To add scaling, you can multiply both c and s by the same positive real number. If it is less than 1, it will shorten the result compared to the original; if it is greater than 1, it will lengthen the result compared to original.
 
My apologies for the delayed replies. It's hard getting here now since I've got a 1 year old. Thank you all for your feedback so far. It's still confusing as to how I'll implement it, but that's the challenge I'm looking for. Thank you for your inputs.
 
Hey, from what I've gathered. If all I'm doing is an offset of the joystick. I wouldn't need atan/ atan2 is this correct? I simply want to rotate the joystick say 12 degrees to the left. Because I would be rotating everything, every angle would remain the same.
 
Hey, everyone. Lots of learning coming from me. I've been working on a project using atan2. While I've learned a lot so far, there is still so much to continue to learn. I've been able to figure out offsets, changing values etc. What is stumping me right now is having a joystick rotate as I change the values using theta to rotate a vector. Correct me if I'm saying that incorrectly. What I'm trying to accomplish is having the joystick x/y value also rotate as the vector rotates. Does that make sense?

Code:
#include <math.h>

// Pin definitions
const int joystickXPin = A9;  // X-axis
const int joystickYPin = A8;  // Y-axis

// Function to rotate a vector (x, y) counterclockwise by angle theta (in radians)
void rotateVector(float &x, float &y, float theta) {
    float cosTheta = cos(theta);
    float sinTheta = sin(theta);

    float xNew = x * cosTheta - y * sinTheta;
    float yNew = x * sinTheta + y * cosTheta;

    x = xNew;
    y = yNew;
}

void setup() {
  Serial.begin(9600);
  Joystick.useManualSend(true);

  // Example vector
  float x = 1.0;
  float y = 0.0;
  float theta = PI / 4; // 45 degrees in radians

  Serial.print("Original Vector: (");
  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.println(")");

  // Rotate the vector
  rotateVector(x, y, theta);

  Serial.print("Rotated Vector: (");
  Serial.print(x);
  Serial.print(", ");
  Serial.print(y);
  Serial.println(")");
}

void loop() {
  // Read joystick values
  int xValue = analogRead(joystickXPin);
  int yValue = analogRead(joystickYPin);

  Joystick.X(xValue);
  Joystick.Y(yValue);

  // Normalize values to a range of -1 to 1
  float xNew = map(xValue, 0, 1023, -1, 1);
  float yNew = map(yValue, 0, 1023, -1, 1);

  // Calculate angle in radians
  float angle = atan2(yNew, xNew);  // Returns angle in radians

  // Convert radians to degrees
  float angleDegrees = angle * (180.0 / PI);

  // Print results
  Serial.print("X: ");
  Serial.print(xNew);
  Serial.print(" | Y: ");
  Serial.print(yNew);
  Serial.print(" | Angle: ");
  Serial.println(angleDegrees);

  Joystick.send_now();

  // Small delay
  delay(100);
}
 
Back
Top