Java

Customization Description: 
West Sound Academy - Introduction to Programming Robots with Java.
Overview: 

This course is intended to introduce the Java programming language to students using the EV3 (FLL), Tetrix (FTC) and RoboRio (FRC) robotics platforms. For EV3, the course moves the student away from block based robot programming to using a text based programming language. For Tetrix and RoboRio, the course will provide more instruction in Java itself, which is missing in existing materials. The course will teach a basic competency in Java with a focus on robotics applications. Robot construction will not be covered in any depth as it is assumed the student will have or acquire hardware building skills separately. The course is targeted to beginners and there are no prerequisites.

Get started using this course by clicking the first Unit and then the first Lesson. The Lesson content will be displayed and next/previous lesson buttons will appear at the bottom of each lesson making it easy to move between adjacent lessons.

Education Level: 
Overview: 
Learn about Interfaces which are definitions of the fields and methods implementing classes must expose.
Objectives: 

Understand Interfaces and be able to use them when appropriate.

Content: 

Just as a class is a description of an object, an Interface is a description of a class. An Interface defines the fields (variables) and methods that a class must provide (public access) to users of the class. The Interface does not define how a class derives the value of a field or the result of a method, only that a class that implements an Interface must expose that Interface's fields and methods. As such, the Interface defines a public facing API that the class must provide. Interfaces are also called Contracts, in that the Interface defines a contract or agreement (in terms of the fields and methods exposed) between a class and users of that class. Classes may extend only one (parent) class but classes may implement any number of interfaces.

One power of Interfaces is that any class that implements an Interface can be used where ever that Interface is defined as a required data type. This concept is best explained by an example.

A simplifed view of the PIDController class in the FRC library shows a constructor that takes two classes as input, a PIDSource object and a PIDOutput object. PIDSource and PIDOutput are both Interfaces. Digressing for a moment, a simplified PIDController needs two things to perform its function. An input or process control value that will be used by the PIDController to compute an output value, which must be sent to some other class for action. Now in many cases the input value will come from an encoder (counts) and the output value will go to a motor (power). You could define the PIDController class constructor as Public PIDController(Encoder enc, Motor motor). There are two problems with this. First, the PIDController class and the Encoder and Motor classes have not agreed on how data will pass between the Encoder and PIDController class and how data will pass between the PIDController and Motor class. The second issue is that the PIDController as defined will only work with Encoders and Motors. What if we wanted to use some other classes as the input and output objects? Interfaces solve both of these problems.

The simplified PIDController class constructor actually looks like this: Public PIDController(PIDSource source, PIDOutput output). PIDSource and PIDOutput are Interfaces and they define what fields and methods are required for any class that wants to act as a PID source or PID output object. These Interfaces define the contract between the PIDController class and any class wanting to act as a PID source data provider or a PID output data consumer. The example Interfaces look like this:

A class implementing the PIDSource Interface must provide a method defined as double pidGet(). That method must return the current input value to be used by the PIDController. Since any class passed into the PIDController constructor for input must implement the PIDSource Interface, the PIDController now knows what method to call on the source object reference variable to get the input value. For instance, the Encoder class implements PIDSource and as such must provide the method pidGet() along with its other methods. When pidGet() is called, the Encoder returns the current tick count. So an Encoder object can be passed to the PIDController constructor. But so can any other class that implements PIDSource. A class implementing the PIDSource Interface would look like this:

Any class that implements PIDOuput must provide the pidWrite(double value) method. That method when called, will take the passed value and perform some action with it. The PIDController knows that any class implementing PIDOutput will have  the pidWrite() method and so it knows how to send the output value it has calculated from the input, by calling the pidWrite method on the output object reference variable. A class implementing the PIDOutput Interface would look like this:

For instance, the Motor class implements PIDOutput and provides the pidWrite(double value) method and sets it's motor power from the value. So a Motor object can be passed to the PIDController constructor as an output object. But so can any other class that implements PIDOutput.

A simplified PIDController class would look like this:

An example of using these classes:

The key here is that the single implementation of the PIDController class can handle both the custom source and output classes as well as the standard encoder and motor classes.

Classes can implement more than one Interface along with any other fields or methods they wish. Interfaces are very powerful and allow a class expecting an Interface (like PIDController) to work with any number of other classes that implement that Interface.

Note that Interfaces only define the expected fields and methods to be exposed by the implementing class. The actual implementation (code) is contained in the class implementing the Interface.

Like many things in Java (and other languages), this is a basic introduction to Interfaces. There is a lot more to Interfaces which you can read about here. Here is a video on interfaces. This lesson should be enough to understand Interfaces and use them in your robot code.

 

Navigation:

Overview: 
Explore how the Singleton Design Pattern is used to simulate a static class.
Objectives: 

Understand the Singleton Design Pattern and how it is used.

Content: 

In a previous lesson, we discussed static variables and methods. Static variables and methods are available without an instance of their containing object and are shared with all other object instances that exist in your program. This is used for global variables and utility methods that don't really have the aspect of multiple instances that many objects do. We also said that Java does not support static classes. Lets explore the idea of static classes in more detail.

A static class would be useful when you will have only one instance of a class in existence at any time in your program. A robotics example might be a class that handles the teleop phase of the robot game. You really would not want to have more than one instance of your teleop class existing at the same time since the hardware interface can't be shared. So it would be nice to be able to define your teleop class as static.

Since you can't, you could define all variables and methods in your teleop class to be static and that would technically achieve the result you are looking for. However, it would still be possible to use the new keyword and create multiple instances of your teleop class. This would not make much sense as the fields and methods are static. However, you can disable the new keyword for a class by marking the class constructor private. Now you can't create instances of the teleop class with new and you have to access the class variables and methods using the class name. This will work but at the end of the day it is kind of messy and different than most classes you would write in Java.

A better alternative might be a regular class that is limited to a single instance and that single instance is shared when you ask for a new instance of that class. This can be done using the Singleton Design Pattern.

A quick note about design patterns. Design Patterns are coding techniques or design ideas shared by programmers across the world. Like code libraries, design patterns are idea or concept libraries. Singleton is a design pattern that describes a way to have a single instance object. This is how it works:

To create a Singleton class, you add a private class level static variable with the data type of the class itself. Next you mark the class constructor as private to disable the Java new keyword. Finally you add a method called (by convention) getInstance(). The getInstance() method checks to see if the static class variable is null, and if it is null, creates an instance of the class and stores the reference in the class variable and returns the reference to the caller. If the static class variable is not null, getInstance() returns the existing reference to the single existing instance of the class to the caller. In this way all callers to getInstance() get the same reference to the single instance of the class. The rest of the class can be written just like a normal class and the variables and methods are accessed via the instance reference in the calling class.

Here is an example of a singleton class:

Here is how this might be used:

Here we have 3 references to the singleton class but only one actual object instance has been created. Note that the variable instanceCount and method getInstanceCount() are coded and accessed just they would be in a normal class. This code would print out:

inst=1;req=3
inst=1;req=3
inst=1;req=3

Here is the example code in CodingPoint. Here is a video dicussing the Singleton pattern.

Singleton classes can be difficult to understand at first, but are very useful in Java programming and in robotics in particular.

 

Navigation:

Overview: 
Explore the concepts and details of using more than one Thread of execution in a program.
Objectives: 

Understand what Processes and Threads are and what it means to have multiple Threads active in Java program. Gain a basic understanding of how to use Threads.

 

Content: 

An executing Java program is called a Process. That process executes your instructions (program) sequentially following the path you created when you wrote your program. This single path is called a thread. As such, your program is only doing one activity (Java statement) at a time and working on one task (your programs list of statements) at a time. For most situations, this works fine. But there are times when you would like to have your program doing more than one thing at time. Using Java Threads it is possible to create additional threads or paths of execution that run in parallel with the main (or first) thread. The effect is that your program can be doing more than one thing (task) at a time. Doing robotics on our platforms you will not need additional threads (multi-threading) most of the time but there are some cases where multi-threading can be useful. Threads can be used to simplify the main path in your program or to perform repetitive tasks while the main thread is busy with something else, sleeping or waiting for some user action.

Like many aspects of programming in Java (and other languages), threads are simple in concept but potentially complex in implementation. There are several ways to do threading and multi-threading can create very interesting and hard to find bugs in your program. But it is possible to keep it simple and get benefit from multi-threading without getting into too much of the possible complexity. We are going to explore basic threading here and there will be example programs in each of the platform sections. It is probably best for you to go now to the section for your hardware platform and work through the examples until you come to the one on using Threads. Then return here to finish this lesson.

When creating a new thread of execution in a Java program, there are two ways to do it. You can use the runnable interface or you can extend the Thread class. We are only going to look at extending the Thread class.

When creating a new thread, the main thing we need to define is the code you want executed in that thread. When you create a new thread, you are telling the JVM here is a bit of code, start running it separately from the main thread and run it until the code path comes to an end. The thread code can have it's own private variables that exist only while the thread is running and the thread shares the class level variables of the class that creates the thread, assuming the thread class is an inner class. An inner class is a class within a class and doing threading with inner classes greatly simplifies things.

Lets look at a simple example:

Here the main thread prints the value of i every half second and the thread increments the value every second. You can see by the results of this code that the two threads run independently of each other.

The code we want to run in the thread is put in the run() method of the thread class. Threads are started with the start() method and stopped with the interrupt() method. When thread.interrupt() is called, the Thread class isInterrupted() method returns false. You should look for this to exit your thread code. If you happen to be in a blocking method when interrupted, sleep() in this case, the InterruptedException will be thrown. You normally just ignore that exception as it is just another signal to stop your thread code. The second catch statement catches and reports any errors that might occur in your code.

Here is this example in CodingPoint. Threads can be used in many ways and there are many methods on the Thread class for managing and coordinating threads. More complex threading is beyond the scope of this lesson and if you use threads it is best to keep it simple as shown here.

When doing multiple threads, you frequently need to share data between threads. Coordinating access to shared variables is called concurrency and is a complex and multi-faceted subject. Java contains many features to allow threads to coordinate write access to shared variables and objects by multiple thread. Again these features are beyond the scope of this lesson. To keep it simple and avoid concurrency issues, follow this rule: variables should only be updated by one thread. They can be read by several threads but only changed by one. In the above example, only the MyThread class changes the value of variable i.

Here is a simple tutorial and a video on multi-threading. Here is a more detailed tutorial including concurrency and here is the official Java documentation on threading.

 

 

Navigation:

Overview: 
Explore the concept of static fields and methods.
Objectives: 

Understand what static fields and methods are and how and when to use them.

Content: 

Normally, class members (variables and methods) are accessed via an instance reference. Leaving methods aside for the moment, this is because class variables exist separately for each instance of a class (created with the new keyword). If you have a variable x in a class and create two instances of the class, each instance will have its own x variable, access to which is by the instance reference. You also access methods via the instance reference. Here is an example:

The result:

theVar=3   theVar=7

Instance1 and instance2 refer to separate object instances of the class and as such each has its own theVar variable which has its own value. The variable is said to be an instance variable.

What if we would like to have a class level or global variable? One that is not specific to any instance of the class but exists as a single copy in memory at  the class level? We can do that with the static modifier. Marking a variable as static means there is only one copy of the variable for all class instances. The static variable is created when first accessed and persists as long as the program runs. Any instance of the class can access the static variable as it is shared among all instances of the class.

Since static variables are not accessed via an instance reference, you use the class name with a dot to access the variable.

You can also mark methods as static. This means the method does not need an instance reference to be called. The method is class level or global. Note that static methods can only access the static variables in the same class. Non-static or instance methods can access static and instance variables. Here is an example:

This example would print out:

instance count=0
instance count=3

The example uses a static variable to count how many instances of MyClass are created. We increment globalCount in the class constructor. This would make globalCount = 2 but to demonstrate static variable access, we directly increment globalCount to 3. We can do this since globalCount has public access. Note that the first output is zero because we called the static method which caused the static globalCount varible to be created and initialized, but we have not yet created any instances of the class. Note that the last statement would generate a compile error since we are accessing a non-static variable through a static (class name) reference.

Here is the example above on CodingGround. Fix the error and demonstrate the program.

Here are two videos (video1, video2) about static members. Here is a detailed discussion of static members.

Note: While classes can't normally be labelled static, an inner class, that is a class within a class, can be. We won't dicuss this as it is beyond the scope of this curriculum, but the use of the static keyword on the inner classes in our CodingGround examples is required when inner classes are defined in the same class as the main() method.

 

Navigation:

Overview: 
Explore logging or tracing of data by a Java program on a robot for later examination. This is a common technique to debug programs.
Objectives: 

Understand logging basic concepts.

 

Content: 

Logging, also called tracing, is the practice of recording debugging information from your program in a disk file for later examination. When logging, you place method calls in your program to call either the Java Logging system or helper methods in code provided by this course. As said in the last lesson, file output is a topic beyond the scope of this curriculum and the details of using the Java Logging system directly are as well. But, due the usefulness of logging in debugging robot programs, we are providing you with code to do logging for you. In each of the three sections on the FIRST robotic platforms, there will be a lesson on how to implement logging in your programs.

It is really pretty simple. You add a .java file containing the logging code to your project and then in your own code, you can call one of the logging methods provided by the logging code to record whatever information you think is useful to a file on the robot controller. You then use the appropriate utility program to pull that file back to your development PC where you can examine it. Each record in the log file contains the time of day, the class in your code where you called the log method and the source file and line number where that call is located. This makes it easy to go from the log file back to your code.

 

Navigation:

Overview: 
Short discussion of using data files and doing input/output in Java. As file I/O is rarely used in the robotics we are targeting, this is a minimal discussion.
Objectives: 

Understand how input/output with disk files fits into robotics programming and where to go for more information.

 

Content: 

Writing data to and reading data from disk files is a common activity for Java programs in many situations. However, file input/output (I/O) is rarely used in the programs created for robots on the platforms we are working with. As such, and given that file I/O is a large and complex topic, it is not going to be covered here. For those who are interested, here are some resources where you can learn more:

File I/O in Java is done with classes available in the java.io package. You can read about it here and many other places on the web. A newer package of I/O classes was released with Java 7 called java.nio.file and you can read the official documentation here.

 

Navigation:

Overview: 
Explore general topics related to using objects in Java programs.
Objectives: 

Understand additional basic concepts related to using objects in Java programs.

Content: 

Now we are going to look at some aspects of using objects in your code.

The first topic is access-modifiers. An access-modifier is one of the modifier keywords that can be specified before the word class when defining a class, before the Data Type when defining a variable and before the return Data Type when defining a method. We have been using public for access modifiers thus far. An access-modifier determines what access other classes have to the components of your class. There are several different access-modifier keywords but for robotics projects, public and private are sufficient. For classes, always use public. This means other classes can access your class.

When defining class level fields (recall that fields are the internal variables or ‘properties’ that an object may have), you can use public or private. For fields, public means other classes can access the field directly. Private means the field may only be accessed by code in your class. For robotics, fields can be public or private, but good programming practice says fields should be private, that is, only accessible outside your class through methods.

When defining methods, you can use public or private. For methods, public means other classes can call the method and private means the method can only be called by other methods in the same class. For robotics, methods can be either public or private as you think best. Private methods are those that support your class and don't really make sense to call from other classes. Here is a video about access control and here is more information about access control.

 

The next topic is object instance lifetime. When you create an object instance with the new keyword, a block of memory for the class variables is allocated in computer memory and a pointer to that memory location is placed in your object variable. The fact that there is a pointer to the instance in memory is recorded (called reference count). Any additional pointers to the same instance increment the reference count. As long as the reference count for an object instance is not zero, the instance will  be maintained in memory. When the reference count goes to zero, no one is using the instance and the JVM marks the memory as garbage and it will eventually be reclaimed by the system. The reference count is decremented whenever a variable pointing to an object instance is deleted (goes out of scope) or the value of the variable is changed to point to some other object instance or no instance all (null).

 

The next topic is variable scoping. Scoping describes the lifetime of variables you create in your program. When you define variables in a class at the class level, those variables will be allocated memory when a class instance is created with the new keyword. As long as the class instance is in use (reference count not zero), those fields will exist in memory. When a class instance is not being used anymore (marked for garbage collection), all of it's variables will have their memory released as part of that process.

Variables defined in methods (local) only have memory assigned to them when the method is executing. When a method starts, the local variables are allocated memory and retain it while the method runs. When the method ends, the memory is released. When a variable's memory is released because it's containing method or class ends it is called going out of scope.

 

Our next topic is the this keyword. The this keyword refers to the current instance of the containing object. The this keyword helps resolve ambiguity in naming within a class. In a constructor or method, if you use a variable or parameter name that is the same as a class field, the method local name hides the class field of the same name. The this keyword allows you to access the hidden name. Additionally, when calling a method which has a parameter which is a reference to the instance of the calling class, this allows you to pass the calling instance. Here is an an example of that:

This may seem a strange example but in reality there are many cases where a method in another class needs our own class instance as a parameter. Here is more information about the this keyword.

 

Navigation:

Overview: 
Explore the Java concept of class packages and using packages with the Import statement.
Objectives: 

Understand the Java concept of class packages and using packages with the Import statement.

Content: 

A real project, even robotics projects, can end up having many classes. You will likely need to use classes in libraries provided by FIRST or others. Finding the classes you need, controlling access to them and naming conflicts between your classes and library classes would be a problem. You may also want to organize a group of your classes into a library that can be reused with other projects or other robotics teams. Packages give us a way to group together related classes in a unique naming scheme and reference them from other classes.

Packages are intended to group related classes together and facilitate access control and prevent naming conflicts. Naming conflicts would occur if all the library classes you use and all of your classes were all grouped together, and there are library classes that have the same names as your own classes.

You create packages with the package statement placed at the start of your class files. The package statement has your package name (more on names later) and all classes with the same package name in your project are grouped into that package. All Java programs must have a package and If you don't use a package statement, your classes are grouped into the default "unnamed" package. It is good programming practice to at least put all of the classes in a project into the same directly named package. Here is more about packages.

The Java built-in library of classes is organized into the java package and there are many sub-packages organized by function. A name.name.name format is used to create a hierarchy within packages. Here is a detailed discussion of package naming.

While a specific package name format is not required there is a detailed convention used in package names. For robotics, you might want to use a name format like this:   

org.usfirst.<fll/ftc/frc>.teamnumber.projectname

or a simpler but perfectly valid one:

teamnumber.projectname

The first example locates your project package in relation to the world. Your package would not conflict with any other package if named like this. This is a nice convention but only important if your code can be integrated into other peoples projects and you plan to do so. The second example shows a simpler package structure that works fine for projects not shared with anyone else.

Packages organize classes we want to make use of in our own classes. So how do we access these other classes? The types (another name for classes) in a package are referred to as members. To access the members of a package you can specify the fully qualified package name when using classes, fields or methods or you can use the import statement. Using fully qualified package names can get pretty tedious. The import statement makes the package name known to the compiler so that when the compiler finds a class, field or method name it does not find in your code, it uses the imported packages to look for the name. This is called resolving the reference. Here is a discussion on using the import statement. Please read this discussion as it covers important details not discussed here.

Robot programs will import some number of Java packages and some number of packages from the robotics library provided for your hardware platform. You will see examples of this when you get to the unit covering your hardware platform.

Note that you do not see any imports or package name in the CodingGround examples. CodingGround uses the default package and is doing any needed imports for you behind the scenes.

Finally, many Java compilers and IDEs want to organize your source files (.java) into directories based on the package name(s) you use. Typically a directory hierarchy is created by IDEs that matches the package hierarchy when you create a package in an IDE. So the package name suggested above might have the directory hierarchy:

c:\projectname\src\org\usfirst\frc\team4450\projectname

or

c:\projectname\src\team4450\projectname

Note that project name is repeated because the projectname right after the c:\ is not part of the package, but is part of the project directory hierarchy.

Here is a summary discussion of packages and import. Here is a video on this topic.

One more important aspect of this topic. With import you tell Java what packages or classes within packages you want to use. But where does Java actually find that code to include in your program? When a programmer creates a library of classes, (a package) the deployment step for such a project is to create a .jar file. Jar means Java Archive and is a special zip file containing the byte code for the classes packaged into the jar file. You tell your IDE what jar files are available on your computer and then when you use an import statement, Java can locate the code to import in the jar files it knows about through your IDE. Typically, one part of an SDK is all of the jar files needed to develop your programs. Your robot platform SDK contains the jar files you need and automatically configures your IDE to know about them. At some point you may wish to use a package of classes not included in the robot SDK. You would download the jar file containing the package and tell your IDE about the jar file and then you can import members from the package.

 

Navigation:

Pages