Omni Wheel Drive

Hi we are a new team this is our first competition and we have been having trouble programming our omni-wheel drive. We have been using this code

#pragma config(Motor,  port1,           LR,            tmotorVex393_HBridge, openLoop, reversed)
#pragma config(Motor,  port2,           FR,            tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port3,           BR,            tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port8,           BL,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port9,           FL,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port10,          LL,            tmotorVex393_HBridge, openLoop)
#pragma platform(VEX)
#pragma competitionControl(Competition) //Competition Control and Duration Settings
#pragma autonomousDuration(20)
#pragma userControlDuration(120)
#include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!

void pre_auton()
{

}

task autonomous()
{
	AutonomousCodePlaceholderForTesting();  // Remove this function call once you have "real" code.
}

task usercontrol()
{
	while (true)
	{ 
		// control omni wheel drive with joysticks
		startMotor(FR, vexRT[Ch2] - vexRT[Ch1] - vexRT[Ch3]);
		startMotor(BR, vexRT[Ch2] + vexRT[Ch1] - vexRT[Ch3]);
		startMotor(BL, vexRT[Ch2] - vexRT[Ch1] + vexRT[Ch3]);
		startMotor(FL, vexRT[Ch2] + vexRT[Ch1] + vexRT[Ch3]);
	}
}

But it gets really jerky and wierd when we try to go full speed. please help

The (middle in your case, but usually last) set, Ch1 (which I assume to be rotation) needs to be all negatives or all positives, but usually all negatives.

I was the first here to write this code, and the source of where most people learned to control a holonomic in this particular way.
I published the code and a tutorial to go along with said code a few years ago on these forums and more recently I revamped the support material here.

The newer tutorial has example code which is known good (the old one did too but you had to read through 15 pages of posts to find it):

// Cody's ROBOTC X Holonomic Code
// =======================
// Usage:	Drive code for "X" Holonomic drive
// License:	Public Domain, use at your own risk.
//
//  ROBOT SEEN FROM ABOVE
//
//        ♦ FRONT ♦
//      ♦           ♦
//    ♦  FL       FR  ♦
//            ↑
//           ←X→
//            ↓
//    ♦  BL       BR  ♦
//      ♦           ♦
//        ♦       ♦  

// Controller 1/2, Stick L/R, Axis X/Y
#define C1LX vexRT[Ch4]
#define C1LY vexRT[Ch3]
#define C1RX vexRT[Ch1]

task main() {

	while(true) {
	
		// Y component, X component, Rotation
		motor[FL] = -C1LY - C1LX - C1RX;
		motor[FR] =  C1LY - C1LX - C1RX;
		motor[BR] =  C1LY + C1LX - C1RX;
		motor[BL] = -C1LY + C1LX - C1RX;

		// Motor values can only be updated every 20ms
		wait10Msec(2);

	}

}

Ch2 is forward and backward
Ch1 is left and right
Ch3 is rotation

it works at slow speeds

Ch3 is a Y axis of the left stick, you don’t want to use that for rotation, you want one of the X axes.

Ah I have my control on the left stick and rotation on the right. Sounds like you want the opposite.

That’s interesting, so let’s do it…

// Cody's ROBOTC X Holonomic Code - Inverted Sticks
// =======================
// Usage:	Drive code for "X" Holonomic drive
// License:	Public Domain, use at your own risk.
//
//  ROBOT SEEN FROM ABOVE
//
//        ♦ FRONT ♦
//      ♦           ♦
//    ♦  FL       FR  ♦
//            ↑
//           ←X→
//            ↓
//    ♦  BL       BR  ♦
//      ♦           ♦
//        ♦       ♦  

// Controller 1/2, Stick L/R, Axis X/Y
#define C1LX vexRT[Ch4]
#define C1LY vexRT[Ch3]

#define C1RX vexRT[Ch1]
#define C1RY vexRT[Ch2]

task main() {

	while(true) {
	
		// Y component, X component, Rotation
		motor[FL] = -C1RY - C1RX - C1LX;
		motor[FR] =  C1RY - C1RX - C1LX;
		motor[BR] =  C1RY + C1RX - C1LX;
		motor[BL] = -C1RY + C1RX - C1LX;

		// Motor values can only be updated every 20ms
		wait10Msec(2);

	}

}

If the #define statements confuse you, you can write it like so…

// Cody's ROBOTC X Holonomic Code - Inverted Sticks
// =======================
// Usage:	Drive code for "X" Holonomic drive
// License:	Public Domain, use at your own risk.
//
//  ROBOT SEEN FROM ABOVE
//
//        ♦ FRONT ♦
//      ♦           ♦
//    ♦  FL       FR  ♦
//            ↑
//           ←X→
//            ↓
//    ♦  BL       BR  ♦
//      ♦           ♦
//        ♦       ♦  

task main() {

	while(true) {
	
		// Y component, X component, Rotation
		motor[FL] = -vexRT[Ch2] - vexRT[Ch1] - vexRT[Ch4];
		motor[FR] =  vexRT[Ch2] - vexRT[Ch1] - vexRT[Ch4];
		motor[BR] =  vexRT[Ch2] + vexRT[Ch1] - vexRT[Ch4];
		motor[BL] = -vexRT[Ch2] + vexRT[Ch1] - vexRT[Ch4];

		// Motor values can only be updated every 20ms
		wait10Msec(2);

	}

}

will this code eliminate the jerky stuff that keeps happening? here is what i did with that code.


#pragma config(Motor,  port1,           LR,            tmotorVex393_HBridge, openLoop, reversed)
#pragma config(Motor,  port2,           FR,            tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port3,           BR,            tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port8,           BL,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port9,           FL,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port10,          LL,            tmotorVex393_HBridge, openLoop)
#pragma platform(VEX)
#pragma competitionControl(Competition) //Competition Control and Duration Settings
#pragma autonomousDuration(20)
#pragma userControlDuration(120)
#include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!
#define joy3 vexRT[Ch3]
#define joy1 vexRT[Ch1]
#define joy2 vexRT[Ch2]

void pre_auton()
{

}

task autonomous()
{
	AutonomousCodePlaceholderForTesting();  // Remove this function call once you have "real" code.
}

task usercontrol()
{
	while (true)
	{ 
		// control omni wheel drive with joysticks
		startMotor(FR, joy2 - joy1 - joy3);
		startMotor(BR, joy2 + joy1 - joy3);
		startMotor(BL, joy2 - joy1 + joy3);
		startMotor(FL, joy2 + joy1 + joy3);
		wait10Msec(2);
	}
}

why do you do


motor[FL] = -C1RY - C1RX - C1LX;

this negative in C1RY?

I would recommend not using natural language, just because it is a bit funkier than regular C.

how do i switch to regular c

I’m not on my PC currently, but when you change compiler mode from IQ to Cortex, you should be able to unselect the check mark on that menu next to “Natural Language”.

I am not with my robot but will this code work without making the robot jerk around when i go full speed?


#pragma config(Motor,  port1,           LR,            tmotorVex393_HBridge, openLoop, reversed)
#pragma config(Motor,  port2,           FR,            tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port3,           BR,            tmotorVex393_MC29, openLoop, reversed)
#pragma config(Motor,  port8,           BL,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port9,           FL,            tmotorVex393_MC29, openLoop)
#pragma config(Motor,  port10,          LL,            tmotorVex393_HBridge, openLoop)
#pragma platform(VEX)
#pragma competitionControl(Competition) //Competition Control and Duration Settings
#pragma autonomousDuration(20)
#pragma userControlDuration(120)
#include "Vex_Competition_Includes.c"   //Main competition background code...do not modify!
#define joy3 vexRT[Ch3]
#define joy1 vexRT[Ch1]
#define joy2 vexRT[Ch2]

void pre_auton()
{

}

task autonomous()
{
	AutonomousCodePlaceholderForTesting();  // Remove this function call once you have "real" code.
}

task usercontrol()
{
	while (true)
	{
		// control omni wheel drive with joysticks
		motor[FR] = joy2 - joy1 - joy3;
		motor[BR] = joy2 + joy1 - joy3;
		motor[BL] = joy2 - joy1 + joy3;
		motor[FL] = joy2 + joy1 + joy3;
	}
}

It really depends, I have tested Cody’s code with my robot and mine hasn’t jerked about. But I can’t speak for your specific robot…

Just to confirm, if you just use i.e. the sample programs (you can use a normal tank drive code on an X-Drive, it just won’t strafe), it works fine.

Just so we can eliminate any chance it is something physical on the robot or with the motors/cortex.

Program it like a tank drive with either a set of buttons or an x channel on on of the joysticks being strafing. Much easier to both program and drive. MUCH easier.

I think that’s an awful way to drive a holo.

I won’t bother defending my position, you can program your holo in whatever way you want but I that’s not what I would do.

Why don’t people just put in the sample mecanum code? It works with holonomic drives… its the same principle… instead of the rollers being 45degrees to the wheel they are 45degrees to the robot. it will work like a charm, you just have to make sure that your motors are all running in the right directions.