New to Java: HELP!

We are a 2nd year team and are trying to make the switch to Java. We are using our robot from last year to practice, but have yet to be able to get the robot to move with Java.

We have looked/followed the tutorials from FIRST, flashed our bridge, and the benchtop test tutorial code seems to download to the Rio from eclipse, but no movement.

We have 4 motors using SPARK controllers and are using a Logitech Extreme 3D joystick. I’m thinking the problem is that we haven’t declared the SPARK controllers in the code, but I am not sure, nor am I sure how to do that.

I did find this site: http://first.wpi.edu/FRC/roborio/beta/docs/java/edu/wpi/first/wpilibj/Spark.html
That discusses the SPARK controller, but I am not sure how to import the class, or how to put it into the code to make it run.

Secondly, once we download the code (assuming everything is correct) do we have to do anything to make it run? Once we get the “build successful” message in Eclipse should we simply be able to hit the joystick and the bot move?

Here is the code we have:


package org.usfirst.frc.team6302.robot;

import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;

/**
 * The VM is configured to automatically run this class, and to call the
 * functions corresponding to each mode, as described in the IterativeRobot
 * 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 Robot extends IterativeRobot {
	RobotDrive myRobot = new RobotDrive(0, 1);
	Joystick stick = new Joystick(0);
	Timer timer = new Timer();

	/**
	 * This function is run when the robot is first started up and should be
	 * used for any initialization code.
	 */
	@Override
	public void robotInit() {
	}

	/**
	 * This function is run once each time the robot enters autonomous mode
	 */
	@Override
	public void autonomousInit() {
		timer.reset();
		timer.start();
	}

	/**
	 * This function is called periodically during autonomous
	 */
	@Override
	public void autonomousPeriodic() {
		// Drive for 2 seconds
		if (timer.get() < 2.0) {
			myRobot.drive(-0.5, 0.0); // drive forwards half speed
		} else {
			myRobot.drive(0.0, 0.0); // stop robot
		}
	}

	/**
	 * This function is called once each time the robot enters tele-operated
	 * mode
	 */
	@Override
	public void teleopInit() {
	}

	/**
	 * This function is called periodically during operator control
	 */
	@Override
	public void teleopPeriodic() {
		myRobot.arcadeDrive(stick);
	}

	/**
	 * This function is called periodically during test mode
	 */
	@Override
	public void testPeriodic() {
		LiveWindow.run();
	}
}

Any help will be great!

For your first question: read the javadoc for RobotDrive. Also, don’t use RobotDrive; it’s deprecated. Use DifferentialDrive.

You have to enable the robot for the robot to move. When the robot is enabled, it will (as per the method names) loop whatever code is in either autonomousPeriodic() or teleopPeriodic() depending on what mode you have selected in driver station.

After you get the robot code loaded, you will need to let the robot boot, and connect to it and enable through the driver station as with any of the other robot languages.

As it appears you have a fairly standard drive train style, I suggest using the arcade drive software directly from ScreenStepsLive to begin, make sure THAT works with no changes other than things like port numbers, and make incremental changes from there.

After posting the code I continued working and figured out the Spark issue (I think).

package org.usfirst.frc.team6302.robot;

import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.Spark;
/**
 * The VM is configured to automatically run this class, and to call the
 * functions corresponding to each mode, as described in the IterativeRobot
 * 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 Robot extends IterativeRobot {
	RobotDrive myRobot;
	Spark frontLeft, frontRight, rearLeft, rearRight;
		Joystick left, right;
	Timer timer = new Timer();

	/**
	 * This function is run when the robot is first started up and should be
	 * used for any initialization code.
	 */
	@Override
	public void robotInit() {
		frontLeft = new Spark(0);
		frontRight = new Spark(1);
		rearLeft = new Spark(4);
		rearRight = new Spark(5);
		left = new Joystick(1);
		right = new Joystick (0);
	}
	
	/**
	 * This function is run once each time the robot enters autonomous mode
	 */
	@Override
	public void autonomousInit() {
		timer.reset();
		timer.start();
	}

	/**
	 * This function is called periodically during autonomous
	 */
	@Override
	public void autonomousPeriodic() {
		// Drive for 2 seconds
		if (timer.get() < 2.0) {
			myRobot.drive(-0.5, 0.0); // drive forwards half speed
		} else {
			myRobot.drive(0.0, 0.0); // stop robot
		}
	}

	/**
	 * This function is called once each time the robot enters tele-operated
	 * mode
	 */
	@Override
	public void teleopInit() {
		frontLeft = new Spark(0);
		frontRight = new Spark(1);
		rearLeft = new Spark(4);
		rearRight = new Spark(5);
		}

	public void operatorControl() {
		while (isOperatorControl() && isEnabled()) {
			myRobot.tankDrive(left, right);
			Timer.delay(0.01);
		}
		
	}

	/**
	 * This function is called periodically during test mode
	 */
	@Override
	public void testPeriodic() {
		LiveWindow.run();
	}
}

When I enable the teleop from the driver station I get an error saying there is no code. I have a screenshot of the console but I am not sure how to share it here.

Oblarg: How would using DifferentialDrive change the code I have?

If you are successfully deploying code but the robot still claims there is no code, the code is most likely crashing on startup. There should be an error in the console that indicates what line of the code is causing the crash.

Oblarg: How would using DifferentialDrive change the code I have?

It’s a different class altogether, so the constructor and methods you call will be different and possibly have slightly different functionality. Details can be found in the javadoc.

You are correct that you need to create Spark classes for each motor. However, you need to pass them into the RobotDrive constructor. In the robotInit function add:

	
myRobot = new RobotDrive(frontLeft, rearLeft, frontRight, rearRight);

You also need comment out or remove the lines inside teleopInit. No need to create the Spark controllers again.

	
	@Override
	public void teleopInit() {
		frontLeft = new Spark(0);
		frontRight = new Spark(1);
		rearLeft = new Spark(4);
		rearRight = new Spark(5);
		}

FYI, in your previous code without the Spark classes, you used the following constructor for RobotDrive:

	
RobotDrive myRobot = new RobotDrive(0, 1);

This constructor automatically instances Talon controllers which will not work with Spark controllers.

Did you have a compile error when downloading? Check the output console in Eclipse to make sure it was a successful build and download.

DifferentialDrive is the replacement class for RobotDrive in the beta version of the wpilib. Unless you have downloaded and installed the beta version this will not be available and you should use RobotDrive.

Hrm, indeed. Perhaps something should be done so that the beta javadoc is not the first thing that appears when one does a google search on “wpilib robotdrive?”

Here is the link to the release JavaDocs for WPILib: http://first.wpi.edu/FRC/roborio/release/docs/java/

Secondly, once we download the code (assuming everything is correct) do we have to do anything to make it run? Once we get the “build successful” message in Eclipse should we simply be able to hit the joystick and the bot move?

When you see “build successful”, your code has not yet been downloaded to the robot. It has been built (i.e., it has compiled and linked), but it’s still on your computer/laptop. To deploy your code to the robot, you have to select “WPILib Java Deploy” from the “Run As” button on the Eclipse toolbar. After that you should be able to see in the Driver Station that your robot has code. You can then use the Driver Station to enable (i.e., run) your code – autonomous, teleop or an entire simulated practice round.

Ok, we made some changes and we got the program to deploy and run from the driver station (yay). However, now when we push the joysticks forward they run one motor on each side. (If we push right joystick it runs a motor on the right and the left, and vice versa)

How do you tell which motor will be controlled by which joystick?

Here is our latest code:

package org.usfirst.frc.team6302.robot;

import edu.wpi.first.wpilibj.IterativeRobot;
import edu.wpi.first.wpilibj.Joystick;
import edu.wpi.first.wpilibj.RobotDrive;
import edu.wpi.first.wpilibj.Timer;
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
import edu.wpi.first.wpilibj.Spark;
/**
 * The VM is configured to automatically run this class, and to call the
 * functions corresponding to each mode, as described in the IterativeRobot
 * 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 Robot extends IterativeRobot {
	//Defines the variables as members of our Robot class
	RobotDrive myRobot;
	Spark frontLeft  = new Spark(0);
	Spark rearLeft = new Spark(1);
	Spark frontRight=  new Spark(2);
	Spark rearRight =  new Spark(3);
     Joystick leftStick, rightStick;
	Timer timer;
	
	// Initializes the variables in the RobotInit method, this method is called when the robot is initializing
	public void robotInit() {
		myRobot= new RobotDrive(frontLeft, frontRight, rearLeft, rearRight);
		leftStick = new Joystick (0);
		rightStick = new Joystick (1);
		timer = new Timer ();
		

	}
	public void autonomousInit() {
		timer.reset();
		timer.start();
	}
	public void autonomousPeriodic() {
		if (timer.get() < 2.0) {
			myRobot.drive(-0.5,  0.0);
		} else {
			myRobot.drive(0.0, 0.0);
		}
	}
	public void teleopInit() {}
	
	public void teleopPeriodic() {
		myRobot.tankDrive(leftStick,  rightStick);
	}
	public void testPeriodic () {
		LiveWindow.run();
	}
	
	
	
}


You can find the answer to this question by reading the WPILib Java documents (linked above) on RobotDrive, the class you are calling to drive your robot around. In general, this is the right place to look for these sorts of questions.

The problem is how you declared RobotDrive. You declared FrontLeft, FrontRight, RearLeft, RearRight in that order. If you are declaring 4 motors for your robot drive, you want both of your left motors first, then both of your right motors. If you declare RobotDrive with FrontLeft, RearLeft, FrontRight, RearRight, you will probably get what you are looking for.

When you call tankDrive in the manner that you did, on an instance of RobotDrive with 4 motors, it will drive the first two declared motors with the left stick, and the second two declared motors with the right stick.

Thank you all for the help, we now have the robot driving correctly. I have 1 more question however.

I have figured out how to limit the speed of the motors by multiplying the joystick x and y values by a number <1, but what I would like to do is have a button that, while held, would limit the speed, but when released would run full speed.

I looked in the javaDocs and saw the buttons and joystickbuttons classes, but I am not sure how to get the button to run robot at half speed.

One simple way to accomplish this would be to have a variable (let’s call it speedConstant) which you set to a value based on the state of the button. If the button is pressed, you set it to 0.5, otherwise you set it to 1. Then when you call your tank drive method, you can pass in your joystick values multiplied by this constant, and it will always work regardless of the button state.

Since Java code in FRC loops iteratively, you basically never want to use a while loop or anything of the sort, as it will prevent the rest of the code from running while you’re stuck in it. So don’t think “run this code while this condition exists”, think “if this condition exists at this time, do this, otherwise do that”.

I don’t want to be discouraging, but I think you should probably step away from robot code for the moment and work through some java tutorials.

The questions you’re asking indicate that you don’t really understand how the code you’re writing works, and if that’s the case it is very much in your interest to get a firm grasp on fundamental programming concepts before continuing further.

I understand the drive to get something working as soon as possible, but robot programming is not something that can be done in a step-by-step manner. The tutorials exist to give you a basic idea of how the WPILib framework functions, but this is contingent on your understanding of the programming concepts that it uses; they do not exist to teach someone unfamiliar with programming how to program a robot.

I agree with working through the tutorials. We were trying to get the robot driving to show off for open house, and were wanting to control the speed to make it more drivable for the kids. The button was an “extra” anyway.

I thought someone had posted a link to some tutorials in here, but I can’t find them. What are some you would recommend?

I recommend oracle’s java tutorials, particularly if you already know how to program.