Hey guys,
So my team decided to switch to Java programming this year since we want to edge away from the basics of Labview. Everything’s going swell so far however we encountered an issue with the control scheme that our drive team is used to. Our drive team uses the gamepad in a fps-like sense. The left joystick is utilized to move the robot forward and backwards while the right joystick is used to rotate the robot. Much like an fps, the controller’s joysticks would be used in multiple directions to move the robot forward while turning a slight bit. Our programming team has worked tremendously hard on creating a formula to get this to work but we can’t seem to get it. Could you guys possibly help us at all? Thanks!
The simplest way to do that is:
rightPower = leftStickY - rightStickX
leftPower = leftStickY + rightStickX
For a slightly better version, see this method.
Could you elaborate on why you are edging away from LabVIEW? Just out of curiosity.
Correct me if I’m misunderstanding what you’re asking, but I think the arcade drive method in wpilibs RobotDrive class will do exactly what you want.
http://team2168.org/javadoc/edu/wpi/first/wpilibj/RobotDrive.html#arcadeDrive(double, double)
There’s some code examples here you could modify:
http://wpilib.screenstepslive.com/s/3120/m/7912/l/95588-getting-your-robot-to-drive-with-the-robotdrive-class
I’d type up an example, but I’m on my phone. Let us know if you need some more guidance.
Using the different methods in RobotDrive will be the easiest way to do it but what exactly you want to achieve with the right stick will dictate your code.
There is always confusion about what the right stick do.
arcadeDrive
public void arcadeDrive(double moveValue,
double rotateValue,
boolean squaredInputs)
Arcade drive implements single stick driving. This function lets you directly provide joystick values from any source.
Parameters:
moveValue - The value to use for forwards/backwards
rotateValue - The value to use for the rotate right/left
squaredInputs - If set, dereases the sensitivity at low speeds
In Arcade Drive, the right stick will rotate the robot even if the left stick is at mid stick. This is how our last driver likes to drive.
drive
public void drive(double outputMagnitude,
double curve)
Drive the motors at "speed" and "curve". The speed and curve are -1.0 to +1.0 values where 0.0 represents stopped and not turning. The algorithm for adding in the direction attempts to provide a constant turn radius for differing speeds. This function will most likely be used in an autonomous routine.
Parameters:
outputMagnitude - The forward component of the output magnitude to send to the motors.
curve - The rate of turn, constant for different forward speeds.
Myself, coming form remote control helicopter background, the left stick is the throttle and the right stick controls the turn rate. So if the left stick is at midstick nothing will happen even if you push the right stick completely over to the side. I can go full throttle with a very gentle curve by just moving the right stick a little bit or I can go very slow with an acute turn by moving the left stick only a little bit and the right stick bang to the side.
Attached the code for our 2 speed off season chassis using a logitech F310 gamepad as our controller. The left stick is the throttle and the right stick controls the turn rate. The inputs are squared to decrease the sensitivity at midstick(actually it is still very twitchy, may go cubed). If you decide to use arcadeDrive instead you don’t need to use the formula I have put in the code cause you can ask the input to be squared at the constructor level.
If you want more sophisticated way to do it like cheesy drive you can look at team 254’s code in Github.
/*----------------------------------------------------------------------------*/
/* Copyright (c) FIRST 2008. All Rights Reserved. */
/* Open Source Software - may be modified and shared by FRC teams. The code */
/* must be accompanied by the FIRST BSD license file in the root directory of */
/* the project. */
/*----------------------------------------------------------------------------*/
package edu.wpi.first.wpilibj.templates;
import edu.wpi.first.wpilibj.Compressor;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.SimpleRobot;
import edu.wpi.first.wpilibj.Solenoid;
import edu.wpi.first.wpilibj.Talon;
/**
* The VM is configured to automatically run this class, and to call the
* functions corresponding to each mode, as described in the SimpleRobot
* documentation. If you change the name of this class or the package after
* creating this project, you must also update the manifest file in the resource
* directory.
*/
public class RobotTemplate extends SimpleRobot {
private Talon rightMotor = new Talon(1);
private Talon leftMotor = new Talon (2);
private RobotDrive chassis = new RobotDrive(rightMotor,leftMotor);
private Joystick f310 = new Joystick(1);
private Compressor compressor = new Compressor(1,1);
private Solenoid shifterOne = new Solenoid(1);
private Solenoid shifterTwo = new Solenoid(2);
public RobotTemplate() {
compressor.start();
}
/**
* This function is called once each time the robot enters autonomous mode.
*/
public void autonomous() {
}
/**
* This function is called once each time the robot enters operator control.
*/
public void operatorControl() {
while (isOperatorControl() && isEnabled()) {
double rawleftY = f310.getRawAxis(2);
double rawrightX = f310.getRawAxis(4);
double leftY = rawleftY * rawleftY * rawleftY / Math.abs(rawleftY);
double rightX = rawrightX * rawrightX * rawrightX / Math.abs(rawrightX);
chassis.drive(leftY, rightX);
if (f310.getRawButton(2)) {
shifterOne.set(true);
shifterTwo.set(true);
} else if (f310.getRawButton(3)) {
shifterOne.set(false);
shifterTwo.set(false);
}
}
}
/**
* This function is called once each time the robot enters test mode.
*/
public void test() {
}
}
Hi! For our controllers, we use the left stick to control forward/backward, and right stick to control left/right movement. Is this something similar to what you want? A sample implementation of this could be something along the lines of
leftSpeed = y-x;
rightSpeed = y+x;
//y = Y axis of left joystick
//x = X axis of right joystick
If you have any other questions, please ask away!
Mr. Lim (Mentor of Jamie’s team) called it the Kaj Drive.
“Kaj refers to Kajeevan, a long-standing and well-decorated former driver for 188 who pushed hard for this drive layout as a grade 9 driver, and used it to great effect ever since.”
Here’s the code written by one of his student.
Note how Mr. Lim’s student decrease the midstick sensitivivty by using x^5:
//DRIVETRAIN--------------------------------------------------------------------------------------------
//kaj drive (max forward and back = 90%)
// (max left and right = 75%)
jagLeft.setX(-0.9 * (driverStick.getRawAxis(6) * driverStick.getRawAxis(6) * driverStick.getRawAxis(6) * driverStick.getRawAxis(6) * driverStick.getRawAxis(6))
+ 0.75 * (driverStick.getRawAxis(3) * driverStick.getRawAxis(3) * driverStick.getRawAxis(3) * driverStick.getRawAxis(3) * driverStick.getRawAxis(3)));
jagRight.setX(-0.9 * (driverStick.getRawAxis(6)* driverStick.getRawAxis(6) * driverStick.getRawAxis(6) * driverStick.getRawAxis(6) * driverStick.getRawAxis(6))
- 0.75 * (driverStick.getRawAxis(3) * driverStick.getRawAxis(3) * driverStick.getRawAxis(3)* driverStick.getRawAxis(3) * driverStick.getRawAxis(3)));
Yep, for Kaj Drive we usually cube it to smoothen the sensitivity. Another example of it is:
//Create variables for x, y, right speed and the left speed
double rightSpeed, leftSpeed, x, y;
//Set x and y to their axis values
x = driver.getRawAxis(InputConstants.rightXAxis);
y = driver.getRawAxis(InputConstants.leftYAxis);
//Drive Smoothing
//Set the left and rightspeed using x and y
leftSpeed = y - x;
rightSpeed = y + x;
//Set the left and right side of the drive
driveTrain.setLeftVBus(-leftSpeed);
driveTrain.setRightVBus(-rightSpeed);
If you have any questions about Kaj, ask away!