Version 1.0-0 | 11-04-25
Currently, the only graphical editor is CTLedit, written in Snap!, and the only Java code generator is CTL2Java, written in Python. This manual will cover each program, with a focus towards less obvious aspects, and how to use the two programs together.
Key notes
To get started
Click the green flag. You will be presented with a few prompts, including which season these controls are for and the visual layout of the controller. Once you have completed these and all the buttons appear, the program is ready to use. Since you have this Manual, you can simply close the Help display that appears by clicking on the question mark button in the lower right.
Editing Controls
Every element visible on the controller can be mapped. The 4 D-Pad buttons are separate. The joysticks themselves represent the stick click buttons, and the axis buttons below them represent the 2 axes.
When you click a control, the information on the right side of the screen changes. Click the gray Set button to the right of an item to edit it. The last item has a gray Add button to add another set of these fields for when a Modifier button is held. (To create a Modifier button, set the type of a button to Modifier.) Only those Actions which are for your selected Season and have been enabled in the Library Manager will be shown.
If you set a button to a fake Axis or an axis to a fake Button, you will have to edit these from their respective menus, which are covered in the next section.
Green Flag Menu
When you click on the Green Flag, all the controls disappear! Not to worry, Redraw will return you to normal operation. This option is also useful when something in the program gets a little out of whack.
Reset will erase your current project and start a new one, running you through the introductory prompts again. It will confirm with you before doing this.
Export is how you save your work. This will show 2 lists: Gamepad1 and Gamepad2. (If you didn’t map anything on gamepad2, you don’t need to export that one.) Right-click on each list and click “Export”. This should download a .json file that you can give to CTL2Java.
Other CTLedit Features
There are 6 controls in the bottom-left corner. We will step through them from left to right.
First is the UI Font Size slider. This changes the size of all the colorful text (all text drawn with pen blocks), but unfortunately does not change the size of the menus or Ask dialogs. Still, the default here is admittedly small, so increase this if you have trouble reading things.
Next is the Move/Edit toggle. Move mode lets you change where controls are placed visually, while Edit mode lets you map the controls. While in Move mode, you can either drag and drop controls, or you can click on one to have it follow your mouse cursor until you press the spacebar.
Next is the Gamepad toggle. Click this to switch between editing gamepad1 and gamepad2.
Next is the Library Manager. This shows all the available Action Libraries and which ones are valid for the selected Season. You may enable or disable valid Libraries. It will check the Base dependencies of Extension Action Libraries. This is mostly just useful for de-cluttering your Action mapping menus.
Finally we reach the Fake Buttons menu, followed by the Fake Axes menu. If you set a Button’s type as Axis, for example, this maps that Axis as a fake Button. It is treated as a new fake Button, and you must select it from the Fake Buttons menu to map a Button Type and Action to it. Merging two Axes also creates a new Fake Axis that you must edit from the Fake Axes menu.
Key Notes
To Get Started
There are 2 interface options for CTL2Java: run it on the command line with ctl2java.py, or run gui.py for a simple TkInter GUI. We will explain the command line options here. The GUI is just a different way to set the same arguments, so the same understanding is required either way.
ctl2java.py --help (or -h if you’re feeling lazy) will briefly explain each argument, but this manual will go into further depth.
Arguments
[Required*] -if1 INFILE --infile1 INFILE
The mapping file for gamepad1. INFILE should be the path to a .json file from CTLedit. This can either be a full file path, or just the path relative to ctl2java.py.
*This argument is actually Optional, but I’m guessing that most use cases want to load mappings from a file rather than stdin. If you want to get them from stdin (gamepad1 only!), then leave this argument blank.
[Optional] -if2 INFILE --infile2 INFILE
The mapping file for gamepad2. If you didn’t map anything on gamepad2, you don’t need this.
[Required*] -of OUTFILE --outfile OUTFILE
Technically this is the name of the output Class. Do not include the “.java” file extension. If you want your control scheme to be, for example, the “Indy23” class, and thus the “Indy23.java” file, then OUTFILE should be “Indy23”.
*This argument is actually Optional, but I’m guessing that most use cases want the generated code to go to a file rather than stdout. If you want to pipe it through something else first, then leave this argument blank.
[Optional] -op OUTPACKAGE –outpackage OUTPACKAGE
This is the Java package that the output file will be part of. For example, if the generated Scheme is to live in TeamCode, OUTPACKAGE should be “org.firstinspires.ftc.teamcode”. But this example is a bit contrived - TeamCode is actually the default if this argument is not given.
[Optional] -dt DRIVETYPE --drivetype DRIVETYPE
DRIVETYPE can be either “Indy” or “Fieldy”.
“Indy” is for independent Robot-oriented Drive, Turn, and Strafe axes. If you turn the robot, then pressing Forward makes it go in its new facing direction.
“Fieldy” is for Field-oriented Drive and Strafe axes. After turning the robot, pressing Forward makes it go the same direction it did before, not its new facing direction.
If this argument is not set, “Indy” is used.
[Optional] -d –debug
This enables additional debugging information, primarily useful to CTL2Java developers and also a good idea to send along with a bug report. (Speaking of, if you do find a bug, please open a GitHub issue, and send the output from your attempts with this debug info. enabled. Thanks!) Setting this option has no effect on the generated controls scheme.
[Optional] -f --verify
This tells CTL2Java to perform its initial steps of verifying the integrity of the mapping files but not to continue further than that and actually generate the control scheme. You probably won’t need this unless you’re developing another front-end like CTLedit.
[Optional] -ver --version
Print program version then exit. This exits immediately after that and does not generate a scheme, even if other arguments are set!
CTL2Java on GitHub
This project is hosted on GitHub. You may notice it’s a personal project, so I maintain it as I have time. One of the things I don’t really have time for is thorough and varied bug-testing, so ifwhen you find bug(s) while using this program, please open a GitHub issue about it. I would appreciate if you could send the following with it:
And then I’ll fix the bug, release a new patch, and admit to whatever embarrassing mistake I made this time. Your support here is greatly appreciated - thank you!