This year, I was a programming mentor in a robot building competition for high school students. Specifically, one of 11 mentors assisting 40 high-schoolers of the Park Hill Trobots team in the FIRST Robotics Competition.
In this blog, I discuss key lessons I learned as a programming mentor of high school students building a Java-based robot that could run, climb, balance, aim, and release projectiles.
(Want to see what we made? Check it out here.)
About The FIRST Competition
The FIRST (For Inspiration and Recognition of Science and Technology) Robotics Competition is an annual event open to high schoolers 14-18 years old.
It challenges teams to solve a common problem (which changes every year) using a standard “kit of parts” and a common set of rules. Teams explore possible career paths as they work together to design, build, and program robots that compete against other teams. Here’s a video describing the 2020 challenge we sought to overcome.
Keyhole Software is a sponsor, and other Keyhole team members have donated their time to the next generations of STEM professionals. (Check out Jonny Hackett’s Building Soft Skills Through Robotics post).
I had been involved with the team for 3 years.
- The first year I joined late and mostly wrangled students.
- In the second year, I put my programming experience to work and helped with a scouting application to allow our team to collect data on other teams. We give credit to that app for helping us select the right teams for our alliance to help us win the Iowa Regional and getting a trip to the world championship in Houston.
- After that year, our programming mentor moved away and that position fell to me.
In all previous seasons, our robot had been programmed in LabView, a language with which I had no experience. For this season, we switched to Java. It was a much better fit; I have more than 20 years of Java experience, the high school taught some Java classes, and the students wanted Java.
Lesson 1: Real-time control systems are different than business systems
When programming in a business system, it generally goes like this:
- There is some type of user input,
- I either retrieve, manipulate, or store that data,
- and results are displayed to the user.
That is a gross simplification of course, but what is common is that I have control through the entire request. Not much changed unless I changed it.
With the robot, however, while I was responding to an event, the robot kept on keeping on— motors kept spinning, the robot kept moving, and things kept changing.
Programming The Robot
For the computer brain, the WPILibrary is used. It has a control loop that executes once every 20ms. Different systems get their default code called, and events (based on inputs, controllers or sensors) could be fired. The big mistake I made was implementing looping behavior in control loop events.
Our goal was to visually target an element on the field when the driver pressed a controller button, so we coded an event and mapped it to the button. Then, based on how far off the target was to the left or right, we turned the robot.
At first, we implemented this as a while
loop where we looped until the target was within our targeting threshold. Unfortunately, with this route, we got all kinds of motor safety errors and other systems stopped responding.
We found out that the problem was caused because we tied up the control loop. Initially, it didn’t seem like it would cause a big delay to take a quarter or so of a second to turn. However, since it was expecting to completely update every system once every 20ms, in actuality, it was a huge delay.
So,
while (Math.abs(getAngleOfError()) >= LimelightConstants.TURN_TO_TARGET_TOLERANCE && hasTarget()){ turn = getAngleOfError()*0.1; if (Math.abs(turn) < min){ turn = turn > 0 ? min:-min; } drivetrain.tankDriveVolts(turn, -turn); }
became:
if(Math.abs(getAngleOfError()) >= LimelightConstants.TURN_TO_TARGET_TOLERANCE && hasTarget()){ turn = getAngleOfError()*0.1; if (Math.abs(turn) < min){ turn = turn > 0 ? min:-min; } drivetrain.tankDriveVolts(turn, -turn); } else { //This prevents errors on the console from not updated drive train. drivetrain.tankDriveVolts(0, 0); }
Since I had no experience in control systems and the student programmers had no experience with the Java library, it took us a couple of days to figure out that we needed to change the event from when the button is pressed to while the button is held. Then, the control loop would run the loop for us.
Our while
not targeted changed to if
not targeted.
We needed to break the habit of trying to control the loop and realize that the loop was there for us.
Lesson 2: It is a teaching role
The students I worked with had a variety of programming experience. We had students fully capable of coding a complete piece of robot functionality on their own and others that needed quite a bit of hands-on guidance and instruction.
To be honest, I wasn’t quite ready for this kind of range of skill levels. I didn’t realize at first that I needed to teach the concept of useful names. For instance, turning
NetworkTableInstance.getDefault().getTable("limelight").getEntry("tx").getDouble(0.0);
Into
private NetworkTable table = NetworkTableInstance.getDefault().getTable("limelight"); private NetworkTableEntry tx = table.getEntry("tx");public NetworkTableEntry getTx() { return tx; } public double getAngleOfError(){ //+1 is a fudge factor cor camera mounting return getTx().getDouble(0.0) + 1.5; }
I had to shift my thinking, and realize that my position involved teaching everything from basic skills I take for granted to more complicated things. As a coach, my job is to help each of my students grow their skills, and that growth looks different for every kid.
Lesson 3: It is a managing role
Unsurprisingly, giving large tasks to high school students is not very productive. Breaking the large task into smaller pieces and giving it to them as a list works much better.
Seems simple enough, but the process of breaking the programming tasks into small enough tasks was, in some cases, more time consuming than writing the code myself. It was stressful because the deadlines in FRC are competition dates. They aren’t arbitrary. As we experience in our professional jobs, code releases cannot be delayed. We needed working code on time.
For example, one task, “Encoder Limit on Climber Extension,” became …
- Define
ClimberConstant
forEXTENSION_LIMIT
, this value will be determined when we get the bot - Add
Method
to climber to reset theextensionMotor
encoder(extensionMotor.setSelectedSensorPosition(0)
; - Call the
climber.resetEncoder
method fromRobot.teleopInit
- in
Climber.extend
and an if statement around the set calls that are there ifextensionMotor.getSelectedSensorPosition() <
; Extension limit call the sets that are there else callclimber.hold
Another part of my role as coach and manager was dealing with deadlines. I found that students didn’t communicate much when their task list wasn’t going well. I had to continually ask for updates and check in with them to make sure they didn’t need help.
We implemented a scrum board, which was some help. However, even with the board, I sometimes didn’t know a student was having trouble completing the task until I expected it to be done.
My solution was more conversation about tasks and smaller task breakouts. At times, getting the information was sometimes like pulling teeth. I suppose no one wants to admit when they are having issues, but as a programmer, raising visibility to problems is a crucial skill.
Lesson 4: It is a programming role
FRC is not entirely student-built bots. It is accepted and encouraged that mentors lead and work with the students. Unlike some high school competitions, the adults have some direct effect on the competition. Some parts were manufactured by mentors, and some code was written by mentors.
When I came to the role, I didn’t think I would need to write much code, just slice up the functionality, handoff pieces, answer questions, and help troubleshoot. What I quickly learned was that since a lot of the things were new to me as well. I needed to do them first before I could teach them or hand them out. This, unfortunately, created delays in getting work to students, and it meant more of the robot’s final code ended up being mine than I wanted.
Hopefully next time, with the lessons I’ve learned, I can hand more code and do less.
Wrap Up
The build season for FRC can be very time consuming and all-encompassing, but I enjoy it and teaching the students a lot. I will probably continue to be the programming mentor even after my children graduate and are no longer on the team.
After all the lessons learned, we did produce one heck of a bot.
If you would like to get involved, here are some resources:
- FIRST Robotics Competition
- KC FIRST – Kansas City area FIRST community
- Competition Resources
- Find a FIRST near you
- Volunteer with FIRST