How to fix left and right being inverted on xbox controller joystick - Java

My team is using a xbox 360 controller to control our robot this year. The right joystick controls forward and backwards, up and down. The left joystick controls left and right but moving the joystick to the right moves the robot left and vice versa. Left and right is inverted essentially.
We are using Java with Victor Spx Motor Controllers.

I’ve tried switching pretty much everything I can think of in the code. I already inverted the motor controllers. I switched the pwm cables around and the values in the code but all that does is mess it up even more.
Here it is though. I’m not certain if it’s a software or hardware issue.
`/----------------------------------------------------------------------------/
/* Copyright © 2017-2019 FIRST. 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 frc.robot;

//import edu.wpi.first.wpilibj.Spark;
import edu.wpi.first.wpilibj.SpeedControllerGroup;
import edu.wpi.first.wpilibj.TimedRobot;
import edu.wpi.first.wpilibj.Victor;
import edu.wpi.first.wpilibj.VictorSP;
import edu.wpi.first.wpilibj.PWMVictorSPX;
import edu.wpi.first.wpilibj.XboxController;
import edu.wpi.first.wpilibj.GenericHID.Hand;
import edu.wpi.first.wpilibj.XboxController.Button;
import edu.wpi.first.wpilibj.XboxController.Axis;
import edu.wpi.first.wpilibj.drive.DifferentialDrive;
import edu.wpi.first.wpilibj2.command.Command;
import edu.wpi.first.wpilibj2.command.CommandScheduler;
import edu.wpi.first.wpilibj.PWMVictorSPX;

/**

  • The VM is configured to automatically run this class, and to call the functions corresponding to
  • each mode, as described in the TimedRobot documentation. If you change the name of this class or
  • the package after creating this project, you must also update the build.gradle file in the
  • project.
    */
    public class Robot extends TimedRobot {
    private Command m_autonomousCommand;

private RobotContainer m_robotContainer;

PWMVictorSPX vict0 = new PWMVictorSPX(9);// right motor
PWMVictorSPX vict1 = new PWMVictorSPX(8);// right motor
PWMVictorSPX vict2 = new PWMVictorSPX(7);// left motor
PWMVictorSPX vict3 = new PWMVictorSPX(6);// left motor

SpeedControllerGroup left = new SpeedControllerGroup(vict2, vict3);
SpeedControllerGroup right= new SpeedControllerGroup(vict0, vict1);

DifferentialDrive robot = new DifferentialDrive(left, right);
XboxController controller = new XboxController(0);
// XboxController Axis = new Axis(0);

/**

  • This function is run when the robot is first started up and should be used for any

  • initialization code.
    */
    @Override
    public void robotInit() {
    // Instantiate our RobotContainer. This will perform all our button bindings, and put our
    // autonomous chooser on the dashboard.
    m_robotContainer = new RobotContainer();

    vict0.setInverted(true);
    vict1.setInverted(true);
    vict2.setInverted(true);
    vict3.setInverted(true);
    }

/**

  • This function is called every robot packet, no matter the mode. Use this for items like
  • diagnostics that you want ran during disabled, autonomous, teleoperated and test.
  • This runs after the mode specific periodic functions, but before

  • LiveWindow and SmartDashboard integrated updating.
    */
    @Override
    public void robotPeriodic() {
    // Runs the Scheduler. This is responsible for polling buttons, adding newly-scheduled
    // commands, running already-scheduled commands, removing finished or interrupted commands,
    // and running subsystem periodic() methods. This must be called from the robot’s periodic
    // block in order for anything in the Command-based framework to work.
    CommandScheduler.getInstance().run();
    }

/**

  • This function is called once each time the robot enters Disabled mode.
    */
    @Override
    public void disabledInit() {
    }

@Override
public void disabledPeriodic() {
}

/**

  • This autonomous runs the autonomous command selected by your {@link RobotContainer} class.
    */
    @Override
    public void autonomousInit() {
    m_autonomousCommand = m_robotContainer.getAutonomousCommand();
// schedule the autonomous command (example)
if (m_autonomousCommand != null) {
  m_autonomousCommand.schedule();
}

}

/**

  • This function is called periodically during autonomous.
    */
    @Override
    public void autonomousPeriodic() {
    }

@Override
public void teleopInit() {
// This makes sure that the autonomous stops running when
// teleop starts running. If you want the autonomous to
// continue until interrupted by another command, remove
// this line or comment it out.
if (m_autonomousCommand != null) {
m_autonomousCommand.cancel();
}
}

/**

  • This function is called periodically during operator control.
    */
    @Override
    public void teleopPeriodic() {
    CommandScheduler.getInstance().run();
//int LEFT_STICK_X = 0;

double x = .75;
robot.arcadeDrive(x * controller.getY(Hand.kRight), x * controller.getX(Hand.kLeft), false);

}

@Override
public void testInit() {
// Cancels all running commands at the start of test mode.
CommandScheduler.getInstance().cancelAll();
}

/**

  • This function is called periodically during test mode.
    */
    @Override
    public void testPeriodic() {
    CommandScheduler.getInstance().run();
//int LEFT_STICK_X = 0;

double x = .75;
robot.arcadeDrive(x * controller.getY(Hand.kRight), x * controller.getX(Hand.kLeft), false);

}
}`

One easy way is to invert the x axis.

robot.arcadeDrive(x * controller.getY(Hand.kRight), - x * controller.getX(Hand.kLeft), false)

Why are you multiplying the joystick axes by 0.75? This limits the speed to 75%, but limits the power by 75%^

1 Like

Open driver station on the controller tab (the one with the USB iconography) and watch what happens with the axis values as you move the joysticks. You can see the bar graph move as you move the controllers joysticks around. The middle is 0, full left is -1, and full right is 1.

The Y axis on xbox controllers are inverted (up means -1, down means 1) and the X axis on the controllers is natural (left means -1 and right means 1).

So the simple solution is to get everything back in phase with each other, disable inversion on the motor controllers, make sure the PWM cables are plugged in the way they should be etc. Then, after everything is put back together, test out in isolation what you’re wanting to do. For example, since you are arcade driving, I assume you want up on the left joystick to move the robot forward. First things first (the way we do it) is to invert the joystick value.

double left = controller.getY(Hand.kRight) * -1;

That will make that inverted value positive as you move the stick forward. Then, with a positive value being sent to the motor controllers, observe your motor controllers. Are they outputting positive or negative? Never used Victors, but CTRE’s Talons blink green for positive, red for negative. For us the goal is to get green blinking to equate to forward motion on both sides of the robot. With the controller value positive, then you can think about inverting the motors on one side or the other to get that working.

Good luck.