What's the difference between robotInit() and constructor in SimpleRobot?

Is there any functional difference between the robotInit() method and a constructor for a class extending SimpleRobot? I read the description in the API for robotInit() and it look likes it’s supposed to do the exact same thing as a constructor.

My code works fine with just using the constructor, but my compilation messages keep recommending I provide robotInit() and disabled() methods so I was just curious.

The robotInit() will be ran once when the robot first turns on. I put in commands to initialize settings to separate it from the actual objects (victors and sensors.) It is really just there if you need to run something at startup.

That’s what the constructor is for. You can just run whatever functions you want to start at robot boot in the constructor. From what I can tell, there is no difference.

Alex Brinister

Look inside of IterativeRobot to understand exactly the difference. The constructor is called before any init stuff in startCompetition().

1 Like

The constructor is called before any init stuff in startCompetition().

So what is the point of robotInit()?

Alex Brinister

Like I said, it serves a different function than the constructor. It’s called when you are basically guaranteed that all WPILIBJ stuff will work. The constructor is a bit iffy on that point. An example would be Preferences. There is a bug that anything called before robotInit() (well actually anything called before Preferences is done initialising, but in practicality it’s before robotInit()) where writing to files will cause a File Close IOException. It’s usually much safer to assume nothing will function properly until robotInit().

That being said, we don’t do that. We construct everything in the constructor and it works completely fine. If anything is wrong with your initialising, try moving it to robotInit(), but otherwise the constructor is a more elegant solution (if you wanted to use the code somewhere that doesn’t call robotInit() - or in Java SE).

In the software industry, things like init() and postInit() are used to remove circular dependencies. This is often the case during display startup – the data that drives the display can’t be displayed until the data processors are up. So one would register a listener in the data processors, and that listener would call display.postInit().

There’s also an issue in Java where overwritten functions still call the parent’s implementation in the parent’s constructor while constructing the child object. That’s why, if you call an internal method from a constructor that method should be private or final. Here’s some more info. An outside class which then call the robotInit() method fixes this issue.

The language isn’t specified, so that’s the best I got :wink:

There are some reasons to prefer doing initialization in robotInit() instead of the constructor for FRC, but at the end of the day the difference is minor.

First, some background on how a Java program runs on the cRIO. We are using J2ME (not J2SE as on a desktop PC), and the main type of app we run is called a MIDlet. MIDlets are basically a common way to start, pause, and stop Java applications on mobile devices. If you look at the WPIlib code, RobotBase (which is the Parent of IterativeRobot and SimpleRobot) extends MIDlet.

MIDlets basically have three methods that define them: startApp(), pauseApp(), and destroyApp(). These three methods do exactly what they sound like: startApp() kicks off your program, pauseApp() causes it to enter a paused state (after which startApp() would be called again to resume), and destroyApp() kills it. In FRC we never use the pause/resume functionality.

So we already hit on one key difference between the constructor and startApp() - startApp() can be called more than once if the MIDlet is paused and resumed. As a result the developer should make sure you don’t re-allocate resources that were not freed up during the call do pauseApp(). Again, in FRC it doesn’t matter because we never pause.

A second difference is that the MIDlet always has access to the user’s display during startApp(), but not necessarily during the call to the constructor. Remember, J2ME was designed for phones and similar devices - obviously we don’t have a display.

robotInit() is called during startApp() by IterativeRobot/SimpleRobot. The built-in boilerplate code in RobotBase and IterativeRobot/SimpleRobot does a couple of things for you before it calls robotInit(). First, it sets a couple of diagnostics flags that let the driver station/FMS know that your robot is alive and booting up. Second, it wraps the call to robotInit() in a catch all block - if you throw an exception in robotInit(), the catch block will print out a stack trace for you. This is very helpful - definitely better than just watching your code die with no diagnostics.

1 Like