Mixing Joystick Values for mecanum wheels

We are preparing for the possibility of installing mecanum wheels on our robot this year and as a proccess are trying to figure out how to mix three joystick values into a working motor signal…

X is what controls your left/right movement.
y is what controls your up/down movement.
and Z is supposed to control the robot’s spin around the Z axis.

we have nailed the combo for X and Y but i’m still lacking the Z integration…


m1/-------------\m2
    |-------------|
    |-------------|
    |-------------|
    |-------------|
    |-------------|
    |-------------|
m3\-------------/m4

m1=y+x-127
m4=y+x-127

m2=y-x+127
m3=y-x+127

any ideas on how to integrate the Z axis so that when stationary the robot can be controlled to turn around itself but can still be turned while moving in a straight line (i realize that the form would be a circle of sorts)

later on i hope to tackle moving on a straight line in relation to the field while all the while turning, so that the effect is somewhat like an ice puck, turning around itself while still moving in a straight line)

but first thing first… any idea how to integrate the Z axis control?

Thanks,
-Leav

Most of the time, when a team wants to get that Z axis going, they use a second joystick. Three-axis gameport joysticks are next to impossible to find (or, once found, are of sketchy quality).

This following code does exactly what you want, but it does not use a gyro. The robot control is relative to the current position of the robot. It might not be as easy to drive as an absolute position omni/mecanum drive, but it is still very intuitive and easy to control.

Here is the code I used for my Vex Holonomic Drive. The motors (when looking onto the top of the robot) were numbers exactly as they would for a mathmatical quadrants. The RF, LF, LR, and RR refer to Right Front, Left Front, Left Rear, and Right Rear wheels respectively. This code can be adaped for possible use in FRC, although you might have to tweak the input by 127. The Vex Transmitter sends 0 - 255 signal, and I think (but am not 100% sure) that some FRC joysticks send -127 - 127 signal.

Here is the variable mapping:

LF / ---- \ RF
LR \ ---- / RR

And here is the PWM port mapping:

2 / ---- \ 1
3 \ ---- / 4

And finally, here is the code:

#include "Main.h"

void main ( void )
{
      while ( 1 )
      {
            // Get Data 
            leftx = GetRxInput ( 1 , 4 ) ;
            lefty = GetRxInput ( 1 , 3 ) ;
            rightx = GetRxInput ( 1 , 1 ) ;
            leftx = leftx / 2 ;
            lefty = lefty / 2 ;
            spin = rightx / 2 ;
            // Drive Code 
            LF = RR = lefty - leftx + 127 ;
            RF = LR = 255 - lefty - leftx ;
            RR = 255 - RR ; // Reverse Direction
            LR = 255 - LR ; // Reverse Direction
            // Spin Code 
            RF = RF - spin + 63 ;
            RR = RR - spin + 63 ;
            LF = LF - spin + 63 ;
            LR = LR - spin + 63 ;
            // Check for values out of range 
            if ( LF < 0 )
            {
                  LF = 0 ;
            }
            else if ( LF > 255 )
            {
                  LF = 255 ;
            }
            if ( RF < 0 )
            {
                  RF = 0 ;
            }
            else if ( RF > 255 )
            {
                  RF = 255 ;
            }
            if ( RR < 0 )
            {
                  RR = 0 ;
            }
            else if ( RR > 255 )
            {
                  RR = 255 ;
            }
            if ( LR < 0 )
            {
                  LR = 0 ;
            }
            else if ( LR > 255 )
            {
                  LR = 255 ;
            }
            // Set Motors 
            SetMotor ( 1 , RF ) ;
            SetMotor ( 2 , LF ) ;
            SetMotor ( 3 , LR ) ;
            SetMotor ( 4 , RR ) ;
      }
}

And here is that code in action:

~15 Mb - Windows Media Video - http://www.team228.org/index/multimedia/vex-holonomic-drive.wmv

Wow! Thats probably the coolest VEX bot I’ve ever seen. Looks like you were
owning at savage soccer. Its to bad VEX doesn’t have a gyro looks like it may
have helped keep the robot going strait. I’m defiantly going to try this code with
the FRC robot.

thanks, that looks great and just what i need!
I have a couple of questions though:

1)what does

GetRxInput ( 1 , 4 ) ;

do?
I assumed that it get’s the forth axis position information from joystick 1
and so on for

GetRxInput ( 1 , 1) ;

and

GetRxInput ( 1 , 3 ) ;

.
i’m assuming a RC like radio control… am i right?

2)Why did you cut all the joystick values in half?


            leftx = leftx / 2 ;
            lefty = lefty / 2 ;
            spin = rightx / 2 ;

3)something doesn’t make sense:
let’s say that the joystick is full forward with no spin


            leftx = GetRxInput ( 1 , 4 )  ----->=127 ;
            lefty = GetRxInput ( 1 , 3 ) ------>=256;
            rightx = GetRxInput ( 1 , 1 )  ----->=127;

then:


            leftx = leftx / 2 = 63;
            lefty = lefty / 2 = 127 ;
            spin = rightx / 2 = 63 ;

right?
and then:


            LF = RR = lefty - leftx + 127 = 127-63+127=193 ;
            RF = LR = 255 - lefty - leftx = 255-127-63=63;
            RR = 255 - RR = 63;// Reverse Direction
            LR = 255 - LR = 193  ; // Reverse Direction

and then:


            RF = RF - spin + 63 = 63-63+63=63 ;
            RR = RR - spin + 63 = 63-63+63=63;
            LF = LF - spin + 63 = 193-63+63=193;
            LR = LR - spin + 63 = 193-63+63=193;

so you end up with:


            RF=63 ;
            RR=63;
            LF=193;
            LR=193;

which would in my opinion induce spin on your robot (both right wheels goinf forward and both left wheels going back) while the stick is forward (assuming that vex motors use the same 0=full_backwards 127=stop and 256=full_forward configuration) as the FRC bots.

also, with full forward the motors only get up to 193 max 63 min values… (instead of 255 max and 0 min…) is this intentional?

would you mind clearing this up for me? :confused:

Thanks!
-Leav

This is the format for GetRxInput for Vex

GetRxInput ( Controller # , Channel # );

For FRC its:

GetOIAInput (Port # , Joystick Axis # );

Just a note that that is only if you use easyC or WPILib (I think atleast).

artdutra04, would you mind clearing up my confusion?

Okay, I’m going as fast as I can! :wink:

Some of this code is specific to EasyC for Vex, but it should only take slight tweaking to get this code to work for in EasyC for FRC. :slight_smile:

GetRxInput ( 1 , 4 ) ;
GetRxInput ( 1 , 3 ) ;
GetRxInput ( 1 , 1 ) ;

The GetRxInput() command gets the signal coming in from the Vex transmitter. The first number is the Rx Port, and the second number is the channel. So GetRxInput ( 1 , 4 ) ; is getting the signal from RX Port 1, Channel 4. On the Vex Transmitter, here are how the channels are laid out:

Left Joystick, X-Axis: Channel 4
Left Joystick, Y-Axis: Channel 3
Right Joystick, X-Axis: Channel 1
Right Joystick, X-Axis: Channel 2

I am using the left joystick (both axis) to control the forward/reverse/left/right/diagonal movement, and the X-Axis on the right joystick to control the spin. There are also two additional channels (channels 5 and 6) on the Vex transmitter that are controlled via the push buttons on the back of the transmitter, but they weren’t used for anything here.

2)Why did you cut all the joystick values in half?


            leftx = leftx / 2 ;
            lefty = lefty / 2 ;
            spin = rightx / 2 ;

The way the signals are mixed here is that they are added or subtracted from 127 (neutral). Since the Vex Transmitter joystick values range from 0 - 255, using the operation RF = LR = 127 + 255 - 0 ; would result in variable overflow, which wraps the PWM signal around to 0, and causes the motors to act weird, and causes lots of headaches… :rolleyes: This ensures that the variables will never overflow the 0 or 255 limit on the PWM signal.

3)something doesn’t make sense:
let’s say that the joystick is full forward with no spin


            leftx = GetRxInput ( 1 , 4 )  ----->=127 ;
            lefty = GetRxInput ( 1 , 3 ) ------>=256;
            rightx = GetRxInput ( 1 , 1 )  ----->=127;

then:


            leftx = leftx / 2 = 63;
            lefty = lefty / 2 = 127 ;
            spin = rightx / 2 = 63 ;

right?
and then:


            LF = RR = lefty - leftx + 127 = 127-63+127=193 ;
            RF = LR = 255 - lefty - leftx = 255-127-63=63;
            RR = 255 - RR = 63;// Reverse Direction
            LR = 255 - LR = 193  ; // Reverse Direction

and then:


            RF = RF - spin + 63 = 63-63+63=63 ;
            RR = RR - spin + 63 = 63-63+63=63;
            LF = LF - spin + 63 = 193-63+63=193;
            LR = LR - spin + 63 = 193-63+63=193;

so you end up with:


            RF=63 ;
            RR=63;
            LF=193;
            LR=193;

This is correct, and will work exactly as planned. The robot will drive forward. Remember, when you have two motors, with each facing in opposite directions (such as the two transmissions on a tank-drive robot), you must spin the motors in opposite directions to get the robot to drive forward. If you sent the same 255 signal to both transmissions, both transmissions would spin clockwise (or counter-clockwise, depending on the tranny). The robot would then spin in circles with a zero turn radius.

And yes, without doing an exponential curve to the values, you will only get half the PWM strength going through this algorithm when you are traveling orthogonally. This is because when you are traveling diagonally, the values going to two of the corner motors are full speed (0 and 255), while the other two corners don’t move at all (both are 127). For example, to go to the “Northeast” or travel towards “2 o’ clock” relative to the front of the robot, the PWM signal to the motors will be:

255* / --- \ 127
127  \ --- / 0*
  • These may be reversed depending on the rotation of the motor.

There are other ways of doing this that will get you the full range of values. By the way, the range is 0-255.

I made up some mixing equations for an omni drive that I was making, but its outputs aren’t the wheel setup that you have, so they would have to be revised.

One suggestion that might help to get you in the right direction is to first map out your stuff for going forward/backward and left right.

Then, consider turning as an override so that you have one speed that each wheel wants to go in the desired x-y direction and the value of how much you want to turn and scale down the effect of the x-y motion as the desired turn gets sharper.
Assume X, Y, and Z are your inputs, Z being rotation. I beleive your final product will look something like:

n=abs(z-127)/128;

LF=Z+n( (X-Y); //and adjust this for each of your wheels

Technical note, 255 may be ok, but is also used in the packet header. If you have strange problems with victors not responding or PWMs not changing, try changing that maximum to 254. (I don’t remember off-hand any instances where this was the case.)