Programming Mecanum Wheels - 4 Victors

Okay, so I’ve been working on testing my code on a practice bot and need help. I’m using an Attack 3 Joystick (I have 2 ) and a robot with 4 mecanum wheels, each with 4 victors.

Problem is: I have the sample code for a 2 motor robot and am having trouble creating a 4 motor drivetrain and using mecanum wheels.

I create the drive system by doing this:

RobotDrive *myRobot;
Joystick stick;

then

myRobot = new Robotdrive(1,2,3,4);
stick = new Joystick(1);

then under operator control I write,

myRobot->MecanumDrive_Cartesian(stick->GetX(),stick->GetY(),stick->
getTwist());

Except this isn’t working. Do I need to declare something specific for the victors or logitech attack 3 joystick? And am I assigning the one joystick to control the whole robotdrive? I really need some help, anything would be appreciated at this point.

Thank you in advance!

just a couple things jumping out at me…

  1. Joystick stick should be declared as a pointer, like so:
Joystick *stick;
  1. The Attack3 joysticks do not have a 3rd(Twist) axis. In order to properly handle this, you could use a different joystick with a 3rd axis, use an axis(x or y) from a 2nd joystick, or wire up your own potentiometer or other device to read rotation.

Okay thank you. Would I have to declare the Victors then too, or does WPI’s API handle that? Thank you for any help.

By default, the RobotDrive class will instantiate Jaguars as its motor controllers. If you are using Victors you need to explicitly instantiating them yourself and use the following constructor instead:

RobotDrive(SpeedController *frontLeftMotor,
           SpeedController *rearLeftMotor,
           SpeedController *frontRightMotor,
           SpeedController *rearRightMotor);

In other words:


class MyRobot: public SimpleRobot
{
    Victor leftFrontMotor;
    Victor leftRearMotor;
    Victor rightFrontMotor;
    Victor rightRearMotor;
    RobotDrive drive;
 
    MyRobot():
        leftFrontMotor(1),
        leftRearMotor(2),
        rightFrontMotor(3),
        rightRearMotor(4),
        drive(&leftFrontMotor, &leftRearMotor, &rightFrontMotor, &rightRearMotor)
    {
    }
    ....
}

Okay so here is where I stand, don’t have a chance to test it on the practice bot today but will tomorrow. Anyone got any advice on the program and is there anything essential I should add or do to this program? Not totally sure how to do the twist part for the Mecanum wheels using an Attack3 joystick…

Here it is:

#include "WPILib.h"
class RobotDemo : public SimpleRobot
{
	RobotDrive *drive;
	
	Victor *leftFrontMotor;
	Victor *leftRearMotor;
	Victor *rightFrontMotor;
	Victor *rightRearMotor;
	
	Joystick *Attack1;
	Joystick *Attack2;
	
public:
	RobotDemo(void)
	{		
		drive = new RobotDrive(leftFrontMotor,leftRearMotor,rightFrontMotor,rightRearMotor);	
		Attack1 = new Joystick(1);		
		Attack2 = new Joystick(2);
		GetWatchdog().SetExpiration(0.1); 
		drive->SetExpiration(0.1);
	}
	void Autonomous(void)
	{
	}
	void OperatorControl(void)
	{
		GetWatchdog().SetEnabled(true);
		drive->SetSafetyEnabled(true);
		while (IsOperatorControl())
		{
			drive->MecanumDrive_Cartesian(Attack1->GetX(),Attack1->GetY(),Attack2->GetTwist());
			Wait(0.005);				
		}
	}
};

START_ROBOT_CLASS(RobotDemo);

No, your code just declared four Victor pointers but you did not instantiate them. Regarding the Attack3 joystick, can’t help you on that since I am not familiar with it.

#include "WPILib.h"
class RobotDemo : public SimpleRobot
{
    Victor *leftFrontMotor;
    Victor *leftRearMotor;
    Victor *rightFrontMotor;
    Victor *rightRearMotor;
    RobotDrive *drive;
 
    Joystick *Attack1;
    Joystick *Attack2;
 
public:
    RobotDemo(void)
    {
        leftFrontMotor = new Victor(1);
        leftRearMotor = new Victor(2);
        rightFrontMotor = new Victor(3);
        rightRearMotor = new Victor(4);
        drive = new RobotDrive(leftFrontMotor,leftRearMotor,rightFrontMotor,rightRearMotor);    
        Attack1 = new Joystick(1);        
        Attack2 = new Joystick(2);
        GetWatchdog().SetExpiration(0.1); 
        drive->SetExpiration(0.1);
    }
    void Autonomous(void)
    {
    }
    void OperatorControl(void)
    {
        GetWatchdog().SetEnabled(true);
        drive->SetSafetyEnabled(true);
        while (IsOperatorControl())
        {
            drive->MecanumDrive_Cartesian(Attack1->GetX(),Attack1->GetY(),Attack2->GetTwist());
            Wait(0.005);                
        }
    }
};
 
START_ROBOT_CLASS(RobotDemo);

Oh wait my bad - forgot to do that…thank you. And do you know if I should program anything to handle switching between operator control and autonomous - or will this program automatically handle that during competition?

I am not sure if I understand your question. The Field Management System will dictate what mode (autonomous or teleop) the robot is in and will call either Autonomous or OperatorControl methods of your robot code. So you don’t need to write any code to “switch mode”. However, you do need to write code for both the Autonomous and OperatorControl functions.

Ah, was just wondering how each part of the game is handled. And last question (I promise!) - if I have lets say a jaguar powering a belt that moves the ball, how could I go about programming that? I’m lost on how to control motors that does not involve the wheels.

Thank you in advance.

How do you control the Jaguar? By PWM or by CAN bus. Let me assume you are using PWM. Then it would look something like this:


Jaguar *beltMotor;
...
beltMotor = new Jaguar(1);  //assuming PWM channel 1
...
beltMotor->Set(1.0);  //turning one way full speed
beltMotor->Set(-1.0); //turning the other way full speed
beltMotor->Set(0.0);  //stop

Okay thank you!

You require the second joystick because each Attack3 only has 2 axes, but you need 3. So you will use the X- and Y-axis of Attack1 for moving straight(front/back and sideways), and the X-axis of Attack2 to do rotation. the getTwist method does nothing with Attack3 joysticks because they don’t have the 3rd(or Twist) axis.


	void OperatorControl(void)
	{
		GetWatchdog().SetEnabled(true);
		drive->SetSafetyEnabled(true);
		while (IsOperatorControl())
		{
			drive->MecanumDrive_Cartesian(Attack1->GetX(),Attack1->GetY(),Attack2->GetX());
			Wait(0.005);				
		}
	}

Alright, thank you! However, I was sure everything was ready to go but now im getting a watchdog not fed error. I feed the watchdog but its not working. Does anyone know how to fix this?

#include "WPILib.h"
class RobotDemo : public SimpleRobot
{	
    Victor *leftFrontMotor;
    Victor *leftRearMotor;
    Victor *rightFrontMotor;
    Victor *rightRearMotor;

    RobotDrive *drive; // Drive system for the robot
 
    Joystick *Attack1; // Plugged into USB port 1
    Joystick *Attack2; // Plugged into USB port 2
    
    Jaguar *beltMotor; // Slides the cart for the basketballs
    Jaguar *angleMotor; // Changes the angle for the basketball shooter
    Jaguar *bshooter; // Moves the belt to shoot the basketball (Must be able to go forward and backward)

public:
    RobotDemo(void)
    {

    	//Initialize the four Victors to power the Mecanum wheels
    	leftFrontMotor = new Victor(1); 
        leftRearMotor = new Victor(2);
        rightFrontMotor = new Victor(3);
        rightRearMotor = new Victor(4);

        //Initialize the drive system
        drive = new RobotDrive(leftFrontMotor,leftRearMotor,rightFrontMotor,rightRearMotor);  

        //Initialize the two joysticks used to control the robot
        //Define joysticks being used at USB port #1 and USB port #2 on the Driver's Station
        Attack1 = new Joystick(1);        
        Attack2 = new Joystick(2);

        //Initialize Jaguars for the various Robot's functions
        beltMotor = new Jaguar(5);
        angleMotor = new Jaguar(6);
        bshooter = new Jaguar(7);

        
        Watchdog().SetExpiration(0.1);
        drive->SetExpiration(0.1);
        drive->SetSafetyEnabled(false);

        printf("Object Initialization is a success!");
    }

    void Autonomous(void)
    {
    	while (IsAutonomous() && IsEnabled()) {
    		Watchdog().SetEnabled(false);
    	}
    }
    void OperatorControl(void)
    {
    	//Enable Watchdog  which is responsible for handling robot failure
    	Watchdog().SetEnabled(true);
        drive->SetSafetyEnabled(true);

        //Enter the loop where robot can be controlled manually

        while (IsOperatorControl())
        {
        	Watchdog().Feed();
        	printf("The Operator Controlled period has begun!");
            //Use Attack3 joysticks to drive the robot 
            drive->MecanumDrive_Cartesian(Attack1->GetX(),Attack1->GetY(),Attack2->GetX());
            Wait(0.001);                
        }
    }
}; 
START_ROBOT_CLASS(RobotDemo);

Anyone know how to fix this watchdog not fed error? I really need help badly right now and have spent 2 hours trying to figure it out…

Move the printf function outside the while loop, right now it gets called so often it might screw up the timing.

HTH

okay ill give it a shot, thanks!