-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Datalogging Part 2, Custom Data
This tutorial shows how to customize the sample OpMode for FTC Datalogging.
This is Part 2 of a 4-part series on Datalogging. It presumes you completed Part 1, running the sample OpMode and charting its data.
Although aimed at OnBot Java users, these instructions allow Android Studio programmers to use the same Java code.
Datalogging can be made available to FTC Blocks users, by creating myBlocks in OnBot Java. MyBlocks are covered in a separate tutorial at the FTC Wiki here.
Many thanks to @Windwoes for developing this valuable tool.
Start by adding some physical devices to your 'robot'. For convenience, the sample OpMode used only internal or software data sources; the 'robot' was just a bare REV Hub.
This tutorial will log data from 5 basic devices, one for each of the 5 REV Hub port sections:
- DC Motor with encoder
- Conventional servo (not continuous rotation servo)
- REV touch sensor in Digital port
- REV potentiometer in Analog port
- REV color sensor in I2C port
You may connect only one or a few of these, based on availability -- this exercise simply shows how to customize any basic input.
Side note: a typical servo does not provide feedback (data) to the controller. A servo is included here because a user might want to chart its commanded position versus some other data source. In this example, the datalog field is grabberServo.getPosition()
which is simply the servo's last commanded position. Datalog users should think ahead to the desired chart, which might include robot inputs and outputs.
If you already have additional devices connected to the Hub, you may leave them in place.
In the DS app, or on the RC phone, open Configure Robot and add these datalogging devices. You may use the following names, or keep any existing configured names:
- DC Motor name: lifter
- Servo name: grabber
- Touch Sensor name: sensorTouch
- Potentiometer name: sensorPot
- Color Sensor name: sensorColor
Note that the REV Touch Sensor is an "n+1" device; configure it in the higher of two Digital port numbers marked on the Hub label. The REV Potentiometer is an "n" device; configure it as "Analog Input" in the lower of two marked Analog port numbers. Also note the REV Color Sensor V3 has its own device type listed.
When finished, save this as the active configuration.
ConceptDatalogger.java is the sample OpMode that the user runs from the Driver Station. It specifies and collects certain robot data to be logged and ultimately charted.
This Part 2 tutorial shows how to customize the sample OpMode, to collect other robot data.
After working on these or any other OBJ files, it's a good idea to right-click and Download them again to the laptop for safekeeping. This backup can be done periodically or at the end of your work session.
It's also helpful to right-click and Copy, Paste and Rename major revisions of edited files, to save previous/working versions under modified filenames such as v02, v03, etc.
The sample OpMode, and custom versions that you will create, use commands/methods provided in the Datalogger class. That class exists in a different Java file that is typically not edited by the user. Its inner workings are not covered in this tutorial series.
Connect the programming laptop to the Robot Controller device (Control Hub or RC phone) as usual.
In OnBot Java, right-click on ConceptDatalogger.java and choose Copy. Then right-click anywhere and choose Paste, then click OK; this creates a file named ConceptDatalogger_Copy.java.
Now right-click the copy, and choose Rename. Enter the name of your new OpMode: DatalogExample_v01.java. Click OK.
Click on this new filename to begin editing.
At line 28, change the OpMode display name from "Concept Datalogger 01" to "Datalog Example v01".
You will now set up the hardware devices, in this OpMode DatalogExample_v01.java.
First remove the hardware declarations used in the original sample (unless you are using one of these again). Find and delete the 2 separate lines for the voltage sensor, and the 5 separate lines for the IMU:
VoltageSensor battery;
battery = hardwareMap.voltageSensor.get("Control Hub");
BNO055IMU imu;
imu = hardwareMap.get(BNO055IMU.class, "imu");
BNO055IMU.Parameters parameters = new BNO055IMU.Parameters();
parameters.angleUnit = BNO055IMU.AngleUnit.DEGREES;
imu.initialize(parameters);
Replace those with declarations for your new hardware. First place the object instantiations after "public class" and before @Override:
Dcmotor lifterMotor;
Servo grabberServo;
TouchSensor myTouchSensor;
AnalogInput myPotSensor;
ColorSensor myColorSensor;
Now place the object assignments at the beginning of the "runOpMode()" section, using the device names (in quotes) from your Configuration file:
lifterMotor = hardwareMap.get(DcMotor.class, "lifter");
grabberServo = hardwareMap.get(Servo.class, "grabber");
myTouchSensor = hardwareMap.get(TouchSensor.class, "sensorTouch");
myPotSensor = hardwareMap.get(AnalogInput.class, "sensorPot");
myColorSensor = hardwareMap.get(ColorSensor.class, "sensorColor");
You may have noticed that OnBot Java automatically added the class import
statements for the 5 new hardware items:
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.Servo;
import com.qualcomm.robotcore.hardware.TouchSensor;
import com.qualcomm.robotcore.hardware.AnalogInput;
import com.qualcomm.robotcore.hardware.ColorSensor;
OnBot Java does not automatically remove unused import statements. If you deleted all IMU and VoltageSensor declarations (2+5 Java lines listed above), you may also delete the corresponding class imports:
import com.qualcomm.hardware.bosch.BNO055IMU;
import com.qualcomm.robotcore.hardware.VoltageSensor;
To create your custom datalog, the first step is declaring the data fields. These will be the columns of the CSV file and spreadsheet, after the automatic timestamp.
Near the end of this DatalogExample_v01.java OpMode, see the Datalog class definition. Here the previous fields were declared and labeled:
public Datalogger.GenericField opModeStatus = new Datalogger.GenericField("OpModeStatus");
public Datalogger.GenericField loopCounter = new Datalogger.GenericField("Loop Counter");
public Datalogger.GenericField yaw = new Datalogger.GenericField("Yaw");
public Datalogger.GenericField pitch = new Datalogger.GenericField("Pitch");
public Datalogger.GenericField roll = new Datalogger.GenericField("Roll");
public Datalogger.GenericField battery = new Datalogger.GenericField("Battery");
You can keep the first two data items if desired. They are generated by this OpMode's code, not by a hardware sensor. Replace or edit the remaining 4 items, using only the configured datalogging devices you added to the Hub. Your new list might read as follows:
public Datalogger.GenericField opModeStatus = new Datalogger.GenericField("OpModeStatus");
public Datalogger.GenericField loopCounter = new Datalogger.GenericField("Loop Counter");
public Datalogger.GenericField motorEncoder = new Datalogger.GenericField("Lifter Enc.");
public Datalogger.GenericField servoPosition = new Datalogger.GenericField("Grabber Pos.");
public Datalogger.GenericField touchPress = new Datalogger.GenericField("Touched");
public Datalogger.GenericField potValue = new Datalogger.GenericField("Pot. Value");
public Datalogger.GenericField totalLight = new Datalogger.GenericField("Total Light");
With the above edits, you have specified each data field name and its CSV column heading.
You did not need to research and specify the Java type of each data field. This will be handled automatically by the Datalogger.java
class.
Further down in the Datalog class definition, the method setFields()
gives the order that fields are arranged in the log file. This will be the order of columns in the CSV spreadsheet file.
The new version might read as follows, subject to the actual fields you defined above, and the order you prefer:
.setFields(
opModeStatus,
loopCounter,
motorEncoder,
servoPosition,
touchPress,
potValue,
totalLight
)
As the OpMode runs, collecting log data is done with the datalog
object, which is an instance of the Datalog class.
For the voltage sensor, a single value was assigned to datalog.battery
:
datalog.battery.set(battery.getVoltage());
For the IMU rotations, one value from the orientation
array was assigned to datalog.yaw
. Likewise for datalog.pitch
and datalog.roll
:
Orientation orientation = imu.getAngularOrientation();
datalog.yaw.set(orientation.firstAngle);
datalog.pitch.set(orientation.secondAngle);
datalog.roll.set(orientation.thirdAngle);
The above 1+4 lines can be deleted, along with the import statement for Orientation.
In this new OpMode, the added devices' data is logged as follows:
datalog.motorEncoder.set(lifterMotor.getCurrentPosition());
datalog.servoPosition.set("%.2f", grabberServo.getPosition());
datalog.touchPress.set(myTouchSensor.isPressed());
datalog.potValue.set("%.1f", myPotSensor.getVoltage());
datalog.totalLight.set(myColorSensor.alpha());
Just to illustrate, two of these data fields have been optionally formatted, using the same codes as used for telemetry. Here, the servo position will be logged with 2 decimal places, and the potentiometer voltage will be logged with 1 decimal place.
Such codes can be omitted. The Datalogger.java
class uses a default format of "%.3f" for data types float
and double
. The defaults can be edited in that file, if desired.
As noted far above, the servo method getPosition()
does not provide feedback from the servo device. It simply reports the servo's last commanded position.
The DC motor method getCurrentPosition()
does provide actual feedback from the motor encoder, if properly connected.
Finally, post the data to the log, with a timestamp. This is done with a single command; no editing is needed:
datalog.writeLine();
Not every field of the datalog must be collected/filled with each call to writeLine()
. Any non-collected field will be populated with its last value.
Between calls to writeLine()
, the order of collecting datalog fields does not matter. The data will be posted in the correct order, defined by the user in the setFields()
method.
The datalog receives the timestamp of the call to writeLine()
, not the time of collecting the data (e.g. datalog.motorEncoder.set()
).
Edit the telemetry section as desired. For example:
telemetry.addData("Lifter Motor Encoder", datalog.motorEncoder);
telemetry.addData("Grabber Position (commanded)", datalog.servoPosition);
telemetry.addData("Touched", datalog.touchPress);
telemetry.addData("Pot. Voltage", datalog.potValue);
telemetry.addData("Color Sensor Alpha (total light)", datalog.totalLight);
telemetry.update();
Again, all datalog fields are saved as text in the CSV file. Thus, Driver Station telemetry can display a logged value in its logged format only. See above for formatting numeric log values.
Numeric format codes do not apply for telemetry here, since the log values are no longer numeric. Not to worry, charting software interprets such values as numeric!
That's all the editing needed, to add the new devices.
Lastly, you could make the motor and servo move with simple gamepad input, inside the "for() loop".
lifterMotor.setPower(-gamepad1.left_stick_y);
grabberServo.setPosition(gamepad1.left_trigger);
Click the wrench icon "Build Everything". Correct any syntax errors noted, and repeat the build. Wait for confirmation, "Build Successful".
To compare with your own code developed above, click to see a complete DatalogExample_v01.java OpMode.
Time to test! On a paired Driver Station with gamepad, select the TeleOp OpMode listed as "Datalog Example v01". Touch INIT and Start. While observing the live telemetry on the DS screen, move and manipulate the robot's devices to generate data. Do this for about 20-30 seconds, then touch the square Stop button.
The datalog is now created, listed in OnBot Java with a Chrome browser refresh. Using the next steps from the Part 1 tutorial, here are sample charts using the new hardware:
After this is working well, you may continue to customize the OpMode for your needs. Work step-by-step, adding one feature at a time.
This example OpMode uses a "for() loop" with loop counter "i". This could be converted to the more common "while() loop", with various ways to end the loop.
Ultimately you could work this code into your existing Autonomous or TeleOp OpModes, or into test versions of those programs. Consider a Boolean toggle that turns datalogging on or off.
With each new major version, right-click and Copy, Paste and Rename, to save previous/working versions under modified filenames such as v02, v03, etc. It's also good to right-click and Download to the laptop periodically.
Excel and Google Sheets offer many more data evaluation features, beyond the scope of this tutorial. You are encouraged to learn and explore those features, ultimately providing a better understanding of robot performance. This may help you with troubleshooting, optimization and robot design.
As noted far above, you may want to datalog robot inputs and outputs, plotting them on X and Y axes. This may help identify cause and effect.
Datalogging can also be used to evaluate Vuforia and TensorFlow data from a camera. A "rogue" input or recognition might pass too quickly to observe with Driver Station telemetry, but Datalogging can display the actual events.
For example, TensorFlow Object Detection (TFOD) methods provide recognition labels, confidence values, and Bounding Box pixel coordinates. Combined with the automatic timestamps, this data could help troubleshoot and optimize the Autonomous programmed decision process:
- Was the Bounding Box suspiciously large?
- Was the first recognition "real"?
- Is the 10th consecutive recognition more trustworthy?
Teams using FTC Blocks and OnBot Java can use Datalogging to solve problems and improve robot performance. Teams using Android Studio can use all the same Java code described above.
FTC students will benefit from this valuable skill, widely used in professional fields such as engineering, scientific research, medicine, social media and marketing, business management, and many more.
You are encouraged to submit and describe other examples that worked for you.
===========
This is Part 2 of a 4-part series on FTC Datalogging.
Part 1 shows how to run a sample OpMode and chart its data.
Part 3 shows Android Studio users how to transfer datalog files from the RC device to a computer. (This isn't needed with OnBot Java, where datalogs appear on-screen for easy Download.)
Part 4 describes the inner workings of a different, much simpler Datalogging class. It's strictly a Java learning exercise, showing basic steps to log robot data on the RC device. It does not require familiarity with Parts 1 and 2.
Questions, comments and corrections to [email protected]
-
TensorFlow 2023-2024