Java

Overview: 
Explore some of the advanced data types available with Java.
Overview: 
Explore how Java converts between different data types.
Objectives: 

Understand Java's data conversion features which are called Casting.

Content: 

Java provides the ability to convert from one data type to another within a set of rules. Some conversions are made automatically and some you have to explicitly request.

Here is a discussion of converting between primitive data types.

Here is a discussion of converting between reference (object) data types.

Here is a video about casting.

 

Navigation:

Overview: 
Explore basic variable collections in Java.
Objectives: 

Understand basic collections, what they are, how they work and how to use them.

Content: 

A Collection is an object that stores lists of other objects allowing the group of stored objects to be manipulated in many powerful ways. A Collection may sound like an array or ArrayList and while a Collection is quite different than an array, ArrayList is in fact one implementation of the Collection concept. Java has a large number of specific implementations of the Collection concept you can use. Here are the most commonly used types of Collection:

  • set - A list of objects with no duplicates.
  • list - A list of objects duplicates allowed. (ArrayList is an implementation of the list general type)
  • map - A list of objects with key values (no duplicates).
  • queue - A list of objects with features that support sequential processing of the elements.

Within each type, there are a number of actual implementations you can use. Each implementation has specific features or performance aspects that you consider when choosing an implementation to use for your programs. Here is an example:

This prints out:
second string
third string
first string
The example creates a Set of String objects stored in a HashSet implementation. A HashSet is a high performance Set but does not guarantee any particular order when retrieving elements from the Set. Note that since this is a Set, the second attempt to add "first string" to the collection is ignored since there is already a duplicate element in the Set.
 
Collections have methods for adding, deleting and retrieving elements and much more. One useful feature of Collections is the Iterator. An Iterator is an object you can retrieve from the Collection that provides methods for navigating and modifying the list. Using an Iterator you can move forward and backward on a Collection using next and previous. Note the for keyword in the example. The Java for keyword understands Iterators and supports using them to access Collection elements.  Here we we are saying do a for loop for all of the elements in mySet, type the elements as String and give me access to each element through the variable s.
 
Here is an example of a List type Collection:

This prints out:
new first string                                                                                                                                       
first string                                                                                                                                           
second string                                                                                                                                          
third string
second string
--------------------
second string
third string
second string
first string
new first string

Here we create a List type Collection using the ArrayList implementation and add some elements. Note we added an element using an index (position) and it inserted the element at that location, moving all subsequent elements up. The ArrayList allows us to add a duplicate element. Finally we use the Iterator type ListIterator (a specialized Iterator for List collections) to manually list the elements in forward order and then reverse order. Note that the ListIterator to go in reverse order is created with it's starting position set to the last element in the list by using the list length field to identify the last element's position.

Due to the many types of Collections and the many implementations of the types of Collections, Collections can seem daunting and overly complex. Collections are very powerful tools for manipulating data sets but most cases can be handled by the ArrayList Collection type.

Here is a video on the ArrayList Collection type. Here is a detailed discussion of Collections starting with an introduction and moving through the specific implementations of the various Collection types.

Here is the example code in CodingGround. Add code to the example to use the iterator for myList to locate the element containing "third string" and remove it from the list. Print out the modified myList to confirm the removal.

 

Navigation:

Overview: 
Explore variable arrays in Java.
Objectives: 

Understand what arrays are and how to use them.

Content: 

An array is a special object used to store a list of variables of the same data type. An array is defined like this:

This statement defines and then creates an array of 3 integer variables (or elements) which will be addressed as a list. The new keyword defines the size of the array. We can then put values in the array and access them with an index value (position) in the array. Arrays are indexed starting at zero:

Note that we can initialize array values with the new keyword:

Arrays may have more than one dimension:

For loops are especially useful in processing arrays:

This will print out:

row 0 col 0 = 5
row 0 col 1 = 10
row 1 col 0 = 15
row 1 col 1 = 20

Notice the array has a built-in field called length that tells the size of the array.

Arrays are fixed in their dimensions once created so the array size can't be changed. If you need dynamic array sizing, that is, you want to change the size of the array as your program proceeds, you can use a class called an ArrayList. The ArrayList is defined in the java.util package. An ArrayList has methods that allow you to add and remove elements on the fly:

String s will contain "A different String object". Why? Because when we removed element zero, the rest of the elements shifted down.

ArrayLists have a number of methods you can use to manipulate the array. Note that the ArrayList can only contain object instance references (no primitives). Also note that when we created the ArrayList, we specified the type of object that would be contained in the ArrayList.

The for statement has a special case called for-each that applies to arrays and collections (next lesson). This special for statement will automatically provide each element in an array to your code in the for statement or block:

ArrayList is just one of many types of Lists (called Collections) available in the Java API.

Here is a video about single dimension Arrays. Here is a video about multi-dimension Arrays. Here is a detailed discussion of Arrays.

Here is the example code on CodingGround. Add code to the example to add up all the elements in array x1 using a for loop and print the result. Add another for loop to print the strings in ArrayList a1.

 

Navigation:

Overview: 
Explore Java enum (enumerations) class.
Objectives: 

Understand Java enum class and how to use it.

Content: 

Lots of times when programming we need to assign constant values to track the various states of a data item. For example, in a program we have an integer variable that indicates the day of the week. We can define a convention where the integer value zero is assigned to mean Sunday, the value of 1 to mean Monday, 2 to mean Tuesday and so on. When coding our program we have to remember that 2 means Tuesday. This tracking of numeric values and what they mean for various variables can get cumbersome and error prone in more complex programs. Another way to track the values associated with various states of a variable is with enums.

An enum or enumeration, is a special data type (an object) defined by Java. It is a list of constant numeric values known at compile time by names. When a variable of the enum type is created it is assigned one of it's pre-defined constant value names and can only have one of it's constant names as its value at a time. Because they represent constants, the names assigned are by convention in upper case. Here is an example:

Internally, Sunday is assigned a value of zero by the compiler, Monday a value of 1 and so on. The key concept is using names instead of constant values, so instead of having to remember what 1 or 6 or whatever some number means in the context of some variable, you use a name. Using names improves readability and reliability of code by making things more obvious. So how do we use enums? Here are some examples:

Here we created a variable day of enum type DayOfWeek and set it to TUESDAY. We can then use day in various ways. enums are best used to represent a fixed set of constants, like day of week, planets of the solar system, menu choices, any list of constants whose values are all known at compile time. Internally by default, each enum name is assigned a constant integer value starting at zero, but in the simple enum case, we don't care as we want to use the names not the numbers. Data types other than integers may be used (see below).
 
To make things more interesting, remember that an enum is a special form of a class. Therefore it can have fields and methods. By default, enum variables don't tell you their underlying constant value, only the name the variable is set to. We can extend the enum in the above example to track and return the underlying constant value of the enum to demonstrate extending the enum with fields and methods:

Here we added an int field to the enum and defined a constructor to set the value of the field. We also added a method to get the day number and made the field public so we can access it directly. Note that when using a constructor, we are required to explicitly define the constants for each name. Note in this example the numeric values assigned to the enum names are not in sequence. They don't have to be.
 
You can assign any primitive or String constant value you wish to the names and you can have more that one data value for each name. However, when you want to use a constant value other than integer or have more that one constant value associated with a name, you must use a constructor to define the data types. See the detailed discussion for more about this.
 
Enums are very useful in their basic form and given that they have the full capability of classes, they can be extended to be very powerful as in the Planets example in the detailed discussion.
 
Here is a video about enums. Here is a detailed discussion of enums.
 
Here is the example code in CodingGround for you to experiment with. Complete both enums for a full 7 days and test. After the next lesson on Arrays, return here and modify the example to print out a list of all of the values in the enums. You will need to view the video above to see how.
 

Navigation:

Overview: 
Explore Java classes for basic numeric data types.
Objectives: 

Understand what the Number classes are and how they are used, including the concepts of boxing and unboxing.

Content: 

We explored Java's primitive data types in an earlier lesson. While we use primitive numeric data types directly most of the time, there are times when we need to treat a numeric primitive as an object. For this reason Java provides the Number Classes. There is a subclass of Number for each numeric primitive:

  • Byte (byte)
  • Integer (int)
  • Short (short)
  • Long (long)
  • Double (double)
  • Float (float)

These classes wrap the primitive data type in an object. Often the compiler wraps the primitive for you. If you use a primitive where an object is expected, the compiler "boxes" the primitive in its wrapper class for you. If you use a Number object where a primitive is expected the compiler will convert or "unbox" the object into the primitive value.

There are three main reasons why you would want to use a Number object instead of the corresponding primitive type:

  • As an argument of a method that expects an object.
  • To use constants defined by the class, such as MIN_VALUE and MAX_VALUE, that provide the upper and lower bounds of the data type.
  • To use class methods for converting values to and from other primitive types, for converting to and from strings, and for converting between number systems (decimal, octal, hexadecimal, binary).

The last item is the most common reason.  The Number classes provide many methods for converting, parsing and otherwise manipulating numbers. Many of the methods are static, meaning you can use them without an actual instance of a Number class. A typical use is converting (parsing) a string of digits into a Number object or the primitive type. The various methods can be quite useful.

You can also use instances of Number classes just like you would a primitive type. Here is an example showing an Integer variable being used just like a primitive int and also showing one of the static methods of Integer to convert a String to an integer value:

Lets look at what is happening in the example. First we create an Integer object and set it's value to 3. Then we perform a math operation on that Integer object. To do this, Java unboxes the Integer object i to a primitive integer and adds 2 to it. The statement returns the primitive integer value 5 and Java sees that we want to put a primitive 5 into the Integer object i and so Java boxes the primitive integer back into an Integer object, which now contains 5 as it's value.

Next we print out the value of the Integer object i. Java sees we are using i like a primitive value and so unboxes the Integer object to a primitive value which println() knows how to handle. We also see that since i is an Integer object, we can use the methods defined for the Integer object, one of which is toString() which returns a string representation of the numeric value. The println() function sees a string and knows how to handle it.

Next we use a static method of the Integer class, parsetInt(n), to parse a string of digits into an int value and store that int value into a primitive int variable. You can see that the methods of the Integer object can be used to work with both primitive int values and Integer objects.

Finally we print the value of the primitive int j. Again, println() knows how to handle primitive int values so the first j is no problem. However, the next display of j tries to use the toString() method. This will fail since the variable j is a primitive int, which does not have methods.

Here is this example on CodingGround. Compile to see the error generated by Java when you try to use a method on a primitive data type variable. Fix the problem and get the program to run.

Here is a detailed discussion of the Number Classes.

 

Navigation:

Overview: 
Explore more detailed information about the Modern Robotics Core Device Interface module, the Core Device Discovery utility and sensor device access using the I2C interface. This lesson only applies if you are using MR controller modules. REV Hub users should skip this lesson.
Objectives: 

Gain advanced knowledge of the Modern Robotics Core Device Interface and accessing I2C based sensors over the CDI and using the Core Device Discovery utility to configure I2C devices.

Content: 

The Modern Robotics Core Device Interface Module is used to connect devices, typically sensors, to the robot control system. There are several different connection protocol options available: digital, analog and I2C. A number of the Modern Robotics sensors use I2C and typically, if you only have one sensor of a specific type, you can ignore the I2C details and let the FTC SDK object for the sensor communication using default parameters. But if for instance you wanted to have 2 color sensors on a robot, you have to move beyond the defaults and perform I2C address configuration so that the two color sensors are not both using the default I2C address assigned to sensors at the factory. Configuring the I2C addresses requires using a utility program called Core Device Discovery.

Here is a detailed discussion of the Core Device Interface.

This lesson at Modern Robotics Education delves into this topic in detail. Follow the lesson, watch the videos and when you are done you will be ready to handle I2C addressing.

 

Navigation:

Overview: 
Explore multi-threading by looking at an example.
Objectives: 

Understand how a multi-threaded OpMode works by looking at an example.

Content: 

If you have not read the lesson on multi-threading in the Advanced Topics unit, do so before continuing.

We are going to look at a simple example of multi-threading (also called multi-tasking). We are going to take the Tank Drive exercise and modify it to have the driving part of the code run in a new thread. The idea is that the main thread can focus on other tasks, perhaps more important or complex and the simple driving code can be in a thread, executing separately from the main thread and just taking care of driving. Create a new class called DriveTankMT and put the following code in it:

The first thing to notice is the use of a private inner (nested) class DriveThread, that extends java.Thread. That class will hold all of the thread specific code, which in the simple case, is just the run() method. Our code to handle driving is in the run() method. We use an inner class because it is simpler and makes accessing the members of the main class easier. Here is more on inner classes.

In the main class at start up we create an instance of the driving thread class and use that instance reference variable to control the thread. Control is pretty simple, when we want to start driving we call the start() method on the thread class and when we want driving to stop we call the interrupt() method on the thread class. While running, the DriveThread class handles the mapping of joystick input to motor power settings and you can see the main thread goes about other business.

In this example, the variables leftY and rightY are shared between the main thread and the driving thread. To reduce concurrency problems, only the driving thread sets the values of leftY and rightY. The main thread only reads from these variables. If high accuracy were needed, we would put the volatile modifier on the definition of leftY and rightY. This is adequate for simple situations. More complex data sharing between threads and a more detailed exploration of concurrency is beyond the scope of this lesson but you can read more about threads and concurrency here.

 

Navigation:

Overview: 
Explore adding logging of debugging information to a file on the controller phone and then pulling that file back to the PC for examination.
Objectives: 

Add the provided logging utility source code to your project and then understand how to use logging in your programs.

Content: 

We are now going to take a look at logging (also called tracing) as a tool to debug our robot programs. Logging is recording useful information from the robot program to a disk file on the controller device. You can then download that file to your PC and examine it. It can be very useful to record information while your robot is running during a match so you can look at it afterwards and see what took place. If you have not read the general lesson on Logging, you should do that now.

To get started, we need to get the provided logging code into your robot controller project. In the teamcode package, create a new class called Logging. Click here to open the logging class code. Copy the code and paste it into the new Logging class you just created. This adds the logging class to your project and makes it available for use in your OpModes.

Now we are going to copy the DriveCircleTouch example and add logging to it. Create a new class in the teamcode package called DriveCircleLogging. Copy the code below into that class.

Now lets discuss the changes made to implement logging. We added a constructor method to this class and in that method call Logging.Setup(). This initializes the logging system. We then write a message to the log file with the Logging.log() method. We then added other messages recording the progress of the OpMmode.

The logging class will write the messages to a file called Logging.txt in the top directory of the controller device. You can use ADB (Android Debug Bridge) to download that file from the device. Open the terminal window at the bottom of Android Studio. Copy and paste this command into the terminal window and press enter:

ZTE: adb pull //storage/sdcard0/Logging.txt c:\temp\robot_logging.txt
MOTO G: adb pull sdcard/Logging.txt c:\temp\robot_logging.txt
Control Hub: adb pull sdcard/Logging.txt c:\temp\robot_logging.txt

This will pull the file from the device into the PC directory specified. You can then view the file with Notepad.

Run the program 3 times, once letting it run the 5 seconds and stop on timeout. Then  run again and press the touch button before the 5 seconds passes. Last, run it and click the Stop button on the Driver Station before time runs out. Then pull the Logging.txt file back to your PC and take a look. It should look like this:

<0>02:43:46:360 DriveCircleLogging.<init>(DriveCircleLogging.java:25): Starting Drive Circle Logging
<1>02:43:46:377 DriveCircleLogging.runOpMode(DriveCircleLogging.java:41): waiting for start
<1>02:43:47:286 DriveCircleLogging.runOpMode(DriveCircleLogging.java:49): running
<1>02:43:53:299 DriveCircleLogging.runOpMode(DriveCircleLogging.java:68): timeout
<1>02:43:53:301 DriveCircleLogging.runOpMode(DriveCircleLogging.java:81): out of while loop
<1>02:43:53:312 DriveCircleLogging.runOpMode(DriveCircleLogging.java:91): stopFlag=true, i=3, d=3.750000
<1>02:43:53:314 DriveCircleLogging.runOpMode(DriveCircleLogging.java:93): done
<0>02:43:54:647 ========================================================================
<0>02:43:54:650 DriveCircleLogging.<init>(DriveCircleLogging.java:25): Starting Drive Circle Logging
<2>02:43:54:662 DriveCircleLogging.runOpMode(DriveCircleLogging.java:41): waiting for start
<2>02:43:55:305 DriveCircleLogging.runOpMode(DriveCircleLogging.java:49): running
<2>02:43:57:456 DriveCircleLogging.runOpMode(DriveCircleLogging.java:74): button touched
<2>02:43:57:464 DriveCircleLogging.runOpMode(DriveCircleLogging.java:81): out of while loop
<2>02:43:57:480 DriveCircleLogging.runOpMode(DriveCircleLogging.java:91): stopFlag=true, i=3, d=3.750000
<2>02:43:57:483 DriveCircleLogging.runOpMode(DriveCircleLogging.java:93): done

Note the log message that uses format specifiers to merge variable data into the log message. You can read more about formatting here.

 

Navigation:

Pages