Tetrix

Overview: 
Learn about timing issues in robotics programming.
Objectives: 

Understand the speed of program execution on a robot and what that means for your program. Understand how to write code that does not fail due to timing issues.

Content: 

When programming robots (or any other real-time system), it is very important to understand how the speed realm of the robot differs from your own. When we look at our robot program, we see the while loop that we use to perform the read-environment/make-decision/act repeating pattern. We tend to think of this loop as happening slowly or at least as we might think of going through these operations.

The reality is that the robot will execute the while loop in our program thousands of times per second. The robot operates much faster than you think. This can lead to bugs in your programs in some situations.

Consider the example code below. The purpose of the program is to perform two actions controlled by the gamepad buttons. The program will count each time your press button A and on each press of button B, toggle a boolean variable from true to false. Download the program in Android Studio and test it on your robot.

So what happened? When you pressed the A button the immediate result is the program counted hundreds or thousands of button presses. Why? Because while the A button press seemed to you to be quick, on the program's time scale the button was down for many repeats of the while loop, and it counted each loop. Same for the B button. The setting of the boolean value bButton seems erratic and definately not a toggle each time the button is pressed. Again, due to the fact that your idea of a button press and the program's idea of a button press are quite different.

What do we do about this? We have to write code to handle this situation and convert the many button presses seen by the while loop into one logical press and act only when the one logical press happends. Here is the example program modified to handle the timing problems:

Download this program into Android studio and try it out. You should see the button presses now handled correctly.

The use of the variables aButtonPressed and bButtonPressed to track the state of the button is called latching.

In the earlier lesson Using Servos, we observed that the code that moved the arm up and down was susceptible to the timing issue discussed in this lesson. Even though you momentarily pushed the button to make the robot arm move up or down, the arm would keep moving after button release and it was hard to move the arm with any precision. Here is an example of how the code that handles moving the arm in response to button presses could be rewritten to move the arm a constant fixed amount for each quick button press and move the arm a longer distance for a long button press. Try it out:

 

Navigation:

Overview: 
Explore programming Servos.
Objectives: 

Understand Servos and how to program them.

Content: 

Now lets look at using servos to control robot functions. The wheel motors we used in the previous exercises simply run at whatever power level they are set at. Servos are different in that they have a defined range of motion and you control them by setting the location in that range you want the servo to move to. Once in that position, servos resist movement. Servos are typically used for arms and grippers.

Servo positions range from 0 to 1 representing 100% of the servo's range of motion. When you build your robot, you will have to experimentally determine how the position values map to the arm and gripper servos in terms up up/down and open/closed.

Note that there are also continuous servos which run just like regular motors. You set the power and direction and the servo runs in that mode until set to something different.

In this exercise, we will have three servos on our robot, one will raise and lower an arm. In our hardware configuration we name this servo "arm_servo". At the end of the arm is a simple gripper which is opened and closed by a second servo named "grip_servo". The third servo is a continuous servo named "cont_servo". We use buttons on the controller to move the servos. Lets extend our Tank Drive example to operate these servos:

Copy and paste this code into a new OpMode called DriveWithGripper and demonstrate servo control on your robot.
 
We operate the regular servos by adding or subtracting a small amount to the servo position when a gamepad button is depressed. We have to montior the position and not go over or under the servo min/max. For the continuous servo we just set the power with appropriate sign to rotate the servo in response to the left and right D-pad buttons.
 
Note that the increment and decrement of the servo position variables show the two different ways to add or subtract with a numeric variable.
 
Here is more information about servos on the Modern Robotics website.
 
When you test this code you will see that displaying double or float values may result in a very large number  being displayed due to the nature of these data types in Java. By default, if a double or float has places right of the decimal point, all of those places will be displayed. We can trim that down using the format function of the String class. Here we call String.format(formatstring, variable) where the format string tells Java we will be displaying a floating point number and we only want to show 2 places right of the decimal point. You can comment out the original lines and uncomment the lines with String.format() to see how this works. Finally, addData() has built in support for formatting the message so you don't have to use String.format(). Try all 3 ways. Here is a detailed discussion of formatting variables into strings for output.
 
You will likely (depends on the robot) observe that the arm continues moving after you release the buttons that make it go up and down. This is caused by the difference between human and robot perception of time and how that affects our program. We will explore this issue and how to fix it in the Timing Considerations lesson.
 

Navigation:

Overview: 
Explore the use of encoders to create feedback control of motors.
Objectives: 

Understand how to use encoders to better control motors by measuring their operation.

Content: 

So far we have been controlling the distance the robot travels with elapsed time. A more accurate way to control movement is with encoders. Encoders attach to or are integrated into the drive motors and count the revolutions of the motor shaft either optically or magnetically. The DcMotor object has support for using encoder counts to control how long the motor will run when turned on. In the example code we will run forward for 5000 encoder counts and stop. Then we will run backwards to zero encoder counts to the starting point. You will need to add encoders to both of the drive motors. Note that encoders don't count revolutions directly but count partial rotations to allow you to process small movements. A US Digital E4P encoder (in the Tetrix kit) will report 1440 counts for one revolution of the motor shaft. Each type of encoder will have a different counts per revolution value so you need to consult the specs for each encoder you use to determine the number of counts per revolution (if needed for your application).

We set the target position of 5000 encoder counts. Nothing happens until we set the power level on the motors, then they start running and will run until the encoder count reaches 5000 and then stop on thier own. Note we still need to set power to zero when the movement is done.

Our code needs to wait while the motors are running to the target position. The example shows two ways to do that, one watching the DcMotor.isBusy() function (true while motor has not reached the target) and the other compares the current motor position to the target position. You could also determine the amount of time needed to complete the movement and wait for that time to pass. In either case, since we selected the motor run mode as RUN_TO_POSITION, the motor will stop on it's own with brakes on.

Run mode RUN_WITH_ENCODER does not stop on it's own. You have to manage that yourself. RUN_WITH_ENCODER tries to run the motor at a constant speed, which is a percentage of the max speed of the motor. You set the percentage just as you do with percentage of power using the setPower() function. When you set a power level, the speed of the motor will be influenced by the battery power level and will slow down as power fades. When you set a speed level, the motor will adjust it's power to maintain a constant speed, to the extent there is battery power available to accomplish that.

If your program calls for you to run your motors without using encoders after you use encoders, you must set the motors to run without encoders using the enum DcMotor.RunMode.RUN_WITHOUT_ENCODER. Running without encoders just means the motor will take no automatic action, but the encoder is still counting. As shown in the example, you can monitor encoder counts yourself and decide when stop instead of having the motor do it automatically. Having the motor stop automatically is more accurate.

Create a new class called DriveWithEncoder and copy/paste the example code. Demonstrate your program using encoder counts.

In practice, you can determine the number of encoder counts needed to complete a movement experimentally by displaying the counts reported by the motors and manually moving/driving the robot through the movement. You can also measure the number of encoder counts that translate to actual distance in inches or feet and then set your movement in those units, converting to counts. The number of counts to a unit of distance will be a function of wheel size and the gears used between the motor shaft and wheel shaft. Modify the example to move a selected distance in feet. Make the code that converts distance into counts into a function that can be reused.

Here is more information about encoders on the Modern Robotics website.

Here is a quiz on using encoders.

 

 

Navigation:

Overview: 
Explore using the Touch Sensor device to gather information about the robot's environment.
Objectives: 

Understand how to use the Touch  Sensor to gather information about the robot's environment.

Content: 

Lets look a using sensors by starting with the simple touch sensor. This is simply a button that can be used to signal your code that something has happened by pushing the button. We will add a REV Robotics Touch Sensor to the robot and plug it into digital port 0-1 on the Expansion Hub. We modify our controller phone configuration to identify digital port 1 as a  Rev Touch Sensor and name it touch_sensor. Why did we use port 1 instead of 0? It has to do with the way the ports are wired. More about that here.

We will take the earlier DriveCircle exercise and modify it to use the touch sensor to determine when to stop driving:

Copy and paste this code into a new OpMode class called DriveCircleTouch and demonstrate your robot driving in a circle. It should keep driving until you press the touch sensor button or 5 seconds pass. Note the use of the while loop to run the robot while watching for 5 seconds to pass and also watching for the touch sensor button press. The TouchSensor isPressed() function returns false when not pressed and true when pressed. For us to continue to run while not pressed, we invert the result of the isPressed() function by preceeding it with the ! (invert) operator.

When using the REV Robotics touch sensor, you can also access the sensor as a generic digital (input) device. Go into the controller configuration and change the touch_sensor device type from REV Touch Sensor to Digital Device. Here is the above code sample modified to use the REV sensor configured as a digital input:

Connecting the touch sensor as a digital input or some other digital device to the REV Hub has some nuances. Be sure to read the discussion here.

 

Navigation:

Overview: 
Explore an example program that uses the Xbox controller to drive in Arcade (one joystick) mode.
Objectives: 

Understand driving under joystick control using one joystick to control both motors (Arcade mode).

Content: 

Lets look at another style of motor control (driving) called arcade. In arcade mode, a single joystick controls both forward/backward motion but also left and right. This allows the robot to be driven with one finger, typically the thumb.

In arcade mode, the joystick y axis controls the forward and reverse motion of the robot. You will need to set both motors to the power level indicated by the y axis deflection. That controls forward and backward motion. So how do we turn? We use the x axis (side to side) deflection to cause the motors to run at different speeds by adding the x value to one motor power level and subtracting the x value from the other motor power level. Here is the code:

Here we are using the x and y axis deflection values from the right joystick only. We combine the x and y values to get the motor power setting. Again, which side is added to and which is subtracted from is determined by your motor gearing which determines the rotation direction of the motor. In our test case negative y axis values make the motors turn in the direction that yields forward motion. Since the joystick x axis returns negative values for left deflection, for a left turn (for example) we subtract the x value from the left motor (minus a minus) yielding a positive value for the left motor (backward) and add a negative yielding a negative value for the right motor (forward). If no y deflection is present, the left motor turns backward and the right forward and the robot spins left. When you add some y deflection the spin turns into an arc.

Arcade driving is more complex to understand and program and more difficult to operate but may make sense for some robots and some drivers.

This sample and the previous one introduces the idle() method which is part of the super class LinearOpMode. When you program a loop as we have here, it is possible and likely for that loop to run without interruption, monopolizing the phone cpu and causing other parts of the robot controller application, like the part that communicates with the driver station phone for example, to be starved for cpu time and not function. The idle() method interrupts your loop momentarily and allows the other classes in the robot controller app to get some cpu time to perform thier functions before resuming your loop.

Copy and paste this code into a new class called DriveArcade, compile and demonstrate arcade mode driving.

 

Navigation:

Overview: 
Explore driving the robot with two joysticks (Tank mode) on a controller.
Objectives: 

Understand Tank mode driving and using input from two joysticks to drive the robot.

Content: 

Now lets look at a teleop example. Here we will use the joysticks on one of the Xbox controllers to drive the robot. We will use tank style driving. In tank mode each joystick controls the motor on one side of the robot. Moving the joystick forward or backward will cause the motor on the corresponding side of the robot to turn in that direction and the power level will be determined by how much the joystick is moved off of center. In this mode, to drive straight you have to move each joystick the same amount. Varying the deflection of the joysticks causes the robot to turn. Here is the code:

Here we are using the built-in reference variable for the left gamepad. We are interested in the y axis which is forward and backward.The joysticks return negative values when pushed forward and positive when pushed backward, in the range -1 to +1 with zero being no deflection or centered. Our test robot uses positive power values to move forward so we need reverse the sign of the y joystick axis by multiplying the value by -1.

We also introduce an object in the FTC SDK API, Range. This static object (don't need an instance, just the class name) exposes a number of generic functions useful in robot control. Another useful static class is Math in the Java library. This class provides a large number of computation support methods accessed by using the name Math.

Since the motor power level ranges from -1 to +1, we will use the Range.clip() function to apply those limits to the right and left stick values to make sure the input never exceeds the allowed power values. While the values returned from the joystick should never actually exceed the motor power limits, it is good practice to be sure your input values match the range of values accepted by the function you are calling.

Finally, we use the built-in function opModeIsActive() to determine when we should stop the driving loop and exit the program. This function returns true when the OpMode is running and false when stopped.

Copy and paste this code into a new class called DriveTank, compile and demonstrate tank mode driving.

 

Navigation:

Overview: 
Instructions on deploying code to the robot controller over WiFi instead of USB cable.
Objectives: 

Understand how to deploy code over WiFi.

Content: 

If you are using OnBot, you can skip this lesson as you already know how to do this. AS users, read on!

As you have no doubt learned, deploying code with a USB cable is time consuming and puts a lot of wear on the controller device USB connectors. When you are developing actual robot code, you will be doing this a lot. There is a better way.

You can deploy your code over a WiFi network instead of using a cable. This is much quicker and puts no wear on the controller device.

Here are the instructions on how to do it using a cell phone over WiFi Direct. Instructions for the Control Hub are below.

We will use the Android Debug Bridge (adb) app running on the phone and configure it to provide communication between the phone and your PC over WiFi. Normally, you would open the terminal window (bottom of the AS screen) and issue commands to ADB to get this running. We will create three AS External Tools to make the process easier.

Android Studio allows for the creation of External Tools, which will appear in the main window’s Tools / ExternalTools menu. These tools can do just about anything, and they can easily be used to run adb commands on the click of a button.

In Android Studio, open the main settings panel:

  • On Mac OS, click “Android Studio”, then “Preferences…” (or simply press the hotkey “⌘,”).
  • On Windows, click “File”, then “Settings…”.

In the settings panel:

  1. Expand the “Tools” item
  2. Click “External Tools” to open the External Tools list. The list is normally empty.
  3. For each of the following tools below, click the [+] button, and fill in the provided fields (leaving all others unchanged). Once each tool screen is filled-in, click “OK” to save. (Note: The “Program” field is the same, so the value can be cut and pasted to avoid re-typing.)
  4. Once all tools have been added, click the main settings panel’s “OK” button to save.

“Enable ADB over TCP/IP”

Field Value
Name: Enable ADB over TCP/IP
Program: $ModuleSdkPath$\platform-tools\adb.exe
Parameters: tcpip 5555

“Connect to ADB over WiFi Direct”

Field Value
Name: Connect to ADB over WiFi Direct
Program: $ModuleSdkPath$\platform-tools\adb.exe
Parameters: connect 192.168.49.1:5555

“Disconnect ADB”

Field Value
Name: Disconnect ADB
Program: $ModuleSdkPath$\platform-tools\adb.exe
Parameters: disconnect

With this done, you attach the phone to the PC with the USB cable. When the PC has recognized the phone, run the Enable ADB over TCP/IP external tool (Tools pull down menu->External Tools). When the command file has completed, disconnect the USB cable. You need to do this step with the USB cable each time you reboot the phone. Note: when running these external tool commands, you must have a Java source file in your project open and selected for editing (cursor in that file) when you execute the external tool.

On the controller app go to the settings menu and select Program & Manage. On the next screen you will see the name of the network created by the phone, something like DIRECT-xy-1234-RC. On your development PC, connect to that network name and use the network pass code displayed on the phone. Select to Automatically Connect so the PC will remember the pass code on future connections. The name of the WiFi Direct network should not change unless you change the name of the controller phone. Now run the Connect to ADB over WiFi Direct external tool in AS. This connects your PC to the phone over WiFi Direct. The connection will remain until you disconnect from the phone's network.

Now, when you compile in AS, the networked controller phone will be available as a deployment target. Compiled code will be sent to the phone over the network connection. 

Note: while connected to the phone's WiFi, your connection to the internet will not be available. You will need to switch networks when you need Internet access. If you do wish switch to another connection, run the Disconnect ADB tool before switching. When you switch back to the phone WiFi network, you will need to run the Connect to ADB over WiFi Direct tool again to reestablish the connection between AS and the phone. Also, a reminder that the first time you connect to the RC phone from any PC, you will be prompted on the phone to accept the PC's RSA Security Key before the first connection will be completed.

Note: If you do not disconnect adb before switching to away from the phone network, when you switch back to the phone network, and try to compile, in the window where you select the phone for deployment, it may be marked as [OFFLINE] and won't allow deployment. When this happens run the Disconnect ABD tool then run the Connect to ADB tool again and that should fix it.

Note: you can add the three external tools to the tool bar above the editing area. This left to you to figure out how, but to get started, right click on the tool bar.


Here are the instructions on how to do it using a Control Hub over WiFi.

We will use the Android Debug Bridge (adb) app which automatically runs on the hub to provide communication between the hub and your PC over WiFi. Normally, you would open the terminal window (bottom of the AS screen) and issue commands to ADB to get this running. We will create two AS External Tools to make the process easier.

Android Studio allows for the creation of External Tools, which will appear in the main window’s Tools / ExternalTools menu. These tools can do just about anything, and they can easily be used to run adb commands on the click of a button.

In Android Studio, open the main settings panel:

  • On Mac OS, click “Android Studio”, then “Preferences…” (or simply press the hotkey “⌘,”).
  • On Windows, click “File”, then “Settings…”.

In the settings panel:

  1. Expand the “Tools” item
  2. Click “External Tools” to open the External Tools list. The list is normally empty.
  3. For each of the following tools below, click the [+] button, and fill in the provided fields (leaving all others unchanged). Once each tool screen is filled-in, click “OK” to save. (Note: The “Program” field is the same, so the value can be cut and pasted to avoid re-typing.)
  4. Once all tools have been added, click the main settings panel’s “OK” button to save.

“Connect to ADB over WiFi”

Field Value
Name: Connect to ADB over WiFi 
Program: $ModuleSdkPath$\platform-tools\adb.exe
Parameters: connect 192.168.43.1:5555

“Disconnect ADB”

Field Value
Name: Disconnect ADB
Program: $ModuleSdkPath$\platform-tools\adb.exe
Parameters: disconnect

With this done, connect your PC to the Control Hub over WiFi. When the PC has connected to the hub, run the Connect to ADB over WiFi external tool (Tools pull down menu->External Tools). When the command file has completed you are ready to use AS. The connection will remain until you disconnect from the hub's network. Note: when running these external tool commands, you must have a java source file in your project open with the cursor in that file when you execute the external tool.

Now, when you compile in AS, the networked Control Hub will be available as a deployment target. Compiled code will be sent to the hub over the network connection. 

Note: while connected to the hub WiFi, your connection to the internet will not be available. You will need to switch networks when you need Internet access. If you do wish switch to another connection, run the Disconnect ADB tool before switching. When you switch back to the hub WiFi network, you will need to run the Connect to ADB over WiFi tool again to reestablish the connection between AS and the hub.

Note: If you do not disconnect adb before switching to away from the hub network, when you switch back to the hub network, and try to compile, in the window where you select the hub for deployment, it may be marked as [OFFLINE] and won't allow deployment. When this happens you will need to power the hub off and back on and reconnect.

Note: you can add the two external tools to the tool bar above the editing area. This left to you to figure out how, but to get started, right click on the tool bar.

 

Navigation:

Overview: 
Explore making a robot drive in a circle.
Objectives: 

Understand how to make curved turns.

Content: 

Now lets look at an example that drives the robot in a circle. The key idea here is that if you drive the motors in the same direction but at different power levels (speeds) the robot will drive in an arc and if it runs long enough that arc becomes a circle. Here is the code:

Copy and paste this code into a new class called DriveCircle and demonstrate your robot driving in a circle. You will need to adjust the power levels and sleep time to complete the circle. The power levels and time will depend on the motor placement and gearing of your robot.

 

Navigation:

Overview: 
Explore how to make turns in robot code by programming the robot to drive in a square pattern.
Objectives: 

Understand how to make the robot turn right angles and how to use time delays.

Content: 
Now lets expand on the previous example. This OpMode shows changing direction, use of a for loop and time delays to drive in a square pattern by programming only two of the moves needed (drive straight then turn).

Note that the robot steers or changes direction by varying the motor power being applied to each side. If the motors are not turning at the same power level in the same direction, the robot will turn. This is called skid steering.
 
Copy and paste this code into a new class called DriveSquare and demonstrate your robot driving in a square. You may need to adjust the sleep times to get accurate 90 degree turns to complete the square. Note that because of the use of the for loop and the code design that moves forward then turns for each of the four parts of the square, the robot will turn one extra time. An exercise for you is to modify the program to eliminate the extra turn.
 

Navigation:

Overview: 
Explore example code that shows how to drive a robot forward and then stop.
Objectives: 

Understand basic motor control and work through an exercise in actually programming a robot.

Content: 

So lets do some actual robot programming. Assuming you have constructed a simple robot chassis with two DC motors driving two wheels, one on the left and one on the right side of the robot, we will also assume you have configured the controller phone for this hardware and named the motors left_motor and right_motor. Given all this, we can write a simple LinearOpMode to drive the robot forward for 2 seconds and then stop:

When we construct a robot, there will  be one end of the robot that is naturally the "front". Motor power is expressed as -1.0 to +1.0 (0 being no power), with - turning the motor in one direction and + in the other. We have decided for our robot that + power should move the robot in the forward direction. So we set both motor power levels to some + value and observe the motion of the robot. One motor will turn in the correct direction for forward movement and the other motor will turn opposite of what it should. For the motor turning the wrong way (on our robot it is the left one) we will reverese it. We use the method call:

 leftMotor.setDirection(DCMotor.Direction.REVERSE).

Now the robot moves forward with both motors when given a + power value. You must do this exercise with each robot you build as the gearing you use may change which motor should be reversed. Note that the reason we have to reverse one motor is because the motors are mounted (typically) on opposite sides of the robot. If they both turn the same direction the robot will spin around instead of move forward.

Note the use of the enum data type exposed by the DCMotor class: Direction.REVERSE. We could have figured out what constant value to use here to indicate reverse direction but the enum makes it very easy to set the correct value. You can see the other choices by typing a period right after Direction which causes AS to show you the available choices.

Note the use of the sleep() method. This causes your program to wait (block or delay) for the number of milliseconds specified. 1000 milliseconds equals 1 second. The power settings on your motors will remain in effect during the wait.
 
Note that after each call to telemetry.addData(), we call telemetry.update(). Update sends any preceeding data queued with the addData method to the Driver Station. In Linear OpModes you must call telemetry.update() to send telemetry data to the DS. In regular OpModes, this update is done automatically when the loop() or init_loop() methods end.

Ok! Let's make this happen:

If you are using OnBot, click the + sign in the left navigation pane to create a new Java file called DriveForward. Use the default location.
 
If you are using Android Studio, go into the ftc_app-master project. Locate the org.firstinspires.ftc.teamcode package node under TeamCode\java in the project navigation pane. Right click on package to open it. Right click on any item below the package (like the readme file) and select New, then Java Class. Give the class the name DriveForward. This will create the new class file in the package folder. Double click that new class file to open it in the editor window.
 
Now note that the clickable link view raw appears in the lower right corner of the example source code displays, as you see above. You can click on it to display the source code by itself. This makes it easier to select and copy the code (click the back arrow to return to the lesson). Do this and copy all the exercise code and paste it into the new class file replacing all of the existing contents. The code is now in OnBot or Android Studio in the file DriveForward.java and ready for you to compile.

The OpMode is registered with the FtcRobotContoller app with the @Autonomous annotation before the class name. This categorizes the OpMode as Autonomous and puts it in a group called "Exercises". You can un-comment the @Disabled annotation to remove the OpMode from the list of OpModes that appear on the Driver Station without having to remove the class from the project.

Note the annotation @Overrides on the runOpMode() function. This tells the Java compiler that we intended to have this runOpMode() function replace the function with the same name in the base OpMode class.
 
Now, for OnBot, you can click the Build All (wrench) button (lower right). This will compile all of your code and if there are no errors, you can look at the OpMode list on the driver station app. You should see DriveForward in the OpMode list. Select it as the current OpMode. Press Init and then press Start to test your program. Your robot should drive forward for 2 seconds and then stop. You should see the telemetry messages at the bottom of the driver station app.

For Android Studio, unplug your controller device from the robot and plug it into your PC. When the device is recognized click the green arrow button (top center of the AS menu bar). This will launch the compile and deployment process. You will be prompted to select your device on a list of deployment targets and approve the download of the program. Two notes: the downloaded program is called an APK in Android parlance, and the first compile you do after starting AS make take some time whereas subsequent compiles should be quick. When the download has completed, the new controller app on your device should restart.

Now plug the controller device back into the robot. When the controller and driver station devices have connected and the controller has connected to the robot hardware, you can look at the OpMode list on the driver station app. You should see DriveForward in the OpMode list. Select it as the current OpMode. Press Init and then press Start to test your program. Your robot should drive forward for 2 seconds and then stop. You should see the telemetry messages at the bottom of the driver station app.

You can now experiment with different power settings and directions and different amounts of time by changing the program, compiling and deploying to the robot.

Note that in addition to the Java and FTC SDK documentation mentioned earlier, if you have questions about a class or method, and you are using AS, you can place the cursor over the name of an instance of that class or method, click, then press ctrl-q. This will open a window that will contain any documentation available for the selected item. You can see a list of available fields and methods for a class by typing the name of the class (or instance variable) followed by a dot. The list will be displayed and you can arrow up and down to view any available documentation for the selected item. With an item highlighted, pressing enter will add the field or method name to your code after the dot.
 

Navigation:

Pages