Network tables already initialized error

I am very new to programming the Robot in Java (last 1 week). I have the robot in LabVIEW right now however it is much more complicated to do certain tasks like switching camera feeds and vision tracking. However, I am just using general Java programming that I have learned over the last year and I am still having issues. The robot code successfully deploys but does not run properly. I get the error that Network Tables have already been initialized when it runs the Robot.java class file. I am extending it to use the IterativeRobot. I have not initialized NetworkTables anywhere else that I am aware of.

I have attached the errors from the console to pastebin here: https://pastebin.com/GMVJng0d

Our robot code can be viewed on github. I am using the development-testR branch: https://github.com/FRC2518/2017Bot3/tree/development-testR

As a side note, I am using InteliJ Ultimate 2017.1 on Windows using the FRC plugin for it.

Anyone who can take a look and see what I am missing and maybe offer any advice on how to improve the code or tell me something that would not work would be appreciated. We have a competition starting tomorrow and I would like to be able to have vision tracking and camera switching. If not I will be stuck with my current LabVIEW code.

Thank you,
Brandan Schmitz
FRC Team 2518 - Spartan Robotics

I have seen this one before and it can be a bit mysterious. This exception is happening while the constructor chain of your Robot class and its base classes is being run. The issue is that the RobotBase class expects to be the one to initialize the network tables and it sees them as already initialized. One could well argue that this is a bug in RobotBase and/or NetworkTables but that is another discussion. What it sees is that some other code that ran earlier has already initialized the network tables.

New FRC Java programmers can find this quite strange since you have been told that the construction of your Robot class and the call to its robotInit() method is the first thing that happens in your code, so how could have the network tables already been initialized? Because, that is not the first code of yours that gets executed. Because of how Java static and instance initialization works (and this is a complicated subject), other code you write can execute first. In fact, you have this in your Robot class.

public static final GearGrabber gearGrabber = new GearGrabber();
public static final RobotLifter robotLifter = new RobotLifter();
public static final DriveTrain driveTrain = new DriveTrain();
public static final Cameras cameras = new Cameras();

These static fields will be initialized at first class reference. Which is before your constructor runs. You generally want to avoid statics in your Robot class for this reason. BTW, in your particular case, I believe it is the construction or your Cameras subsystem that is initializing the network tables before the construction of Robot because Cameras has this initialization:

private UsbCamera frontCamera = CameraServer.getInstance().startAutomaticCapture(0);

which will subsequently initialize the network tables (this is what bit us too).

So, change those four declarations to not be static and it should work.

public final GearGrabber gearGrabber = new GearGrabber();
public final RobotLifter robotLifter = new RobotLifter();
public final DriveTrain driveTrain = new DriveTrain();
public final Cameras cameras = new Cameras();

Note that it will not work because those fields will be initialized after your constructor runs. They will actually be initialized before your Robot constructor runs. However, they will be initialized after your base class instance fields are initialized and the base class constructors run. This means the RobotBase constructor will run before the Cameras subsystem is constructed and RobotBase will be happy.

However, you probably had them as public static for a reason and I suspect other parts of your code reference them directly. In fact, I can see that your command do just this. This will have to change.

Only one instance of your Robot class will be created and you can hold a reference to it and then your commands can get to these fields via this saved reference. The one and only static field in your Robot class should be this one:

	public static Robot INSTANCE;

And then in robotInit() set it like this:

	INSTANCE = this;

And then in your command, reference a subsystem like this:

	requires(Robot.INSTANCE.driveTrain);

This is the way it is typically done in FRC although it makes me shudder a bit each time I see it. It works for these small systems but there are more robust ways to manage this is larger systems.

I hope this helps,
Steve

Thank you Steve, that makes things a lot clearer. I like your explanations as well, it helps me understand it. It makes sense that the camera would do that, considering is stores stuff to the network tables. In the ssh log that I access, the roboRIO did seem to stop when it got to the point of initializing the cameras. I have changed my code and will be testing it tomorrow morning.

I was just using the default template that is included in the example projects in Eclipse. I suppose they gotta leave something for people to figure out. :stuck_out_tongue:

Thank you,
Brandan Schmitz
FRC Team 2518 - Spartan Robotics