Lesson 09: Mechanum Drive Math and Coding

Description:

This page outlines the mathematical ideas behind driver control for Mechanum (Straffer) drive robots. There are three stages:

First: Take the deltaX and deltaY (X axis and Y axis) from a Control paddle and convert to a vector that represents the magnitude (speed) of the robot and the theta (direction) you want the robot to travel

Second: Take the X value from another Control paddle and use that to control the direction of the Robot.

Third: Take the values from the vector and use the formula (image below) to calculate the wheel power

Process:

  1. Compute Vector [Magnitude, Theta] as shown in Math below: (You can get the values from the gamepad with code like:

double xValue = gamepad1.left_stick_x;
double yValue = gamepad1.left_stick_y;

2. Get the robot turn direction from the Right Joystick x:

double turnValue = gamepad1.right_stick_x;

3. Use the above values to calculate the motor values for the leftFront, leftRear, rightFront, rightRear motors. The general math is shown below:


4. Once you calculate V0, V1, V2, and V3. Assign those to the motors leftFront, leftRear, rightFront, rightRear. You may have to experiment to get the correct wheel assignments. Sample code for Quad Driver Control is below. You will need to complete.


/*

Copyright (c) 2016 Robert Atkinson


All rights reserved.


Modified by michaudc 2021

*/

package org.firstinspires.ftc.teamcode;


import com.qualcomm.robotcore.eventloop.opmode.OpMode;

import com.qualcomm.robotcore.eventloop.opmode.TeleOp;

import com.qualcomm.robotcore.hardware.DcMotor;

import com.qualcomm.robotcore.util.Range;


/**

* This file provides basic Telop driving for a Pushbot robot.

* The code is structured as an Iterative OpMode

*

* This OpMode uses the common Pushbot hardware class to define the devices on the robot.

* All device access is managed through the HardwarePushbot class.

*

* This particular OpMode executes a basic Tank Drive Teleop for a PushBot

* It raises and lowers the claw using the Gampad Y and A buttons respectively.

* It also opens and closes the claws slowly using the left and right Bumper buttons.

*

* Use Android Studios to Copy this Class, and Paste it into your team's code folder with a new name.

* Remove or comment out the @Disabled line to add this opmode to the Driver Station OpMode list

*/


@TeleOp(name="MaristBot2021: Teleop Quad 2021", group="Training")

//@Disabled

public class TeleopTank_Quad_2021 extends OpMode {


/* Declare OpMode members. */

MaristBaseRobot2021_Quad robot = new MaristBaseRobot2021_Quad();

// use the class created to define a Robot's hardware

// could also use HardwarePushbotMatrix class.

double clawOffset = 0.0 ; // Servo mid position

final double CLAW_SPEED = 0.02 ; // sets rate to move servo



/*

* Code to run ONCE when the driver hits INIT

*/

@Override

public void init() {

/* Initialize the hardware variables.

* The init() method of the hardware class does all the work here

*/

robot.init(hardwareMap);


// Send telemetry message to signify robot waiting;

telemetry.addData("Say", "Robot Ready"); //


// Set to Run without Encoder for Tele Operated

robot.leftFront.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);

robot.rightFront.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);

robot.leftRear.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);

robot.rightRear.setMode(DcMotor.RunMode.RUN_WITHOUT_ENCODER);


}


/*

* Code to run REPEATEDLY after the driver hits INIT, but before they hit PLAY

*/

@Override

public void init_loop() {

}


/*

* Code to run ONCE when the driver hits PLAY

*/

@Override

public void start() {

}


/*

* Code to run REPEATEDLY after the driver hits PLAY but before they hit STOP

*/

@Override

public void loop() {

// Declare variables needed

double xValue;

double yValue;

double turnValue;


// Get Values from Joysticks

// TODO: You finish


// Do the Math!

// TODO: You finish


// Assign to Drive Wheels

// TODO: You Finish


// Use gamepad left & right Bumpers to open and close the claw

if (gamepad1.right_bumper)

clawOffset += CLAW_SPEED;

else if (gamepad1.left_bumper)

clawOffset -= CLAW_SPEED;


// Move both servos to new position. Assume servos are mirror image of each other.

clawOffset = Range.clip(clawOffset, -0.5, 0.5);

robot.leftHand.setPosition(robot.MID_SERVO + clawOffset);

robot.rightHand.setPosition(robot.MID_SERVO - clawOffset);


// Use gamepad buttons to move the arm up (Y) and down (A)

// Commented out for now

/*

if (gamepad1.y)

robot.rightArm.setPower(robot.ARM_UP_POWER);

else if (gamepad1.a)

robot.rightArm.setPower(robot.ARM_DOWN_POWER);

else

robot.rightArm.setPower(0.0);

*/


/*


// Control Arm with Right and Left Triggers

double armMotorPower = gamepad1.right_trigger - gamepad1.left_trigger;

// Limit Power to -0.4 to 0.4

if (armMotorPower > 0.4) {

armMotorPower = 0.4;

}


if (armMotorPower < -0.4) {

armMotorPower = -0.4;

}


robot.leftArm.setPower(armMotorPower);


*/


// Send telemetry message to signify robot running;

telemetry.addData("claw", "Offset = %.2f", clawOffset);

telemetry.addData("left", "%.2f", left);

telemetry.addData("right", "%.2f", right);

}


/*

* Code to run ONCE after the driver hits STOP

*/

@Override

public void stop() {

}


}


Additional Source Code files can be found at:

https://nebomusic.net/ftc/Base_Code_2021_V1/