In past years my team has written our vision code in c++ and deployed to a jetson tx1. This year though ive decided to switch things up a bit and try out using kotlin for our vision(so that way everything uses gradle and I have to worry less about cross compilation) and were using a jetson nano. So far just the opencv interface is nice and its all well but two things have made me almost rethink my choice
GPIO/CAN on jvm just doesnt seem to work, we’ve talked about trying to unify all out external processes to talk can to the roborio but there doesnt seem to be any good librarys for it in java/kotlin. I looked into pi4j and ktgpio, pi4j seems the most promising it just doesnt natively support CAN meaning we’d basically have to make a CAN interface ourselves. Im personally not too caught up on this though
Since im not seeing us getting the CAN idea working this year(nor do I see mucj benefit from it) Ive been looking at some serialization/rpc libraries. In the past when we tried to use network tables we found it very slow and inconsistent, so this year during the c++ implementation I tried using msgpack and found it was awesome. My question is, msgpack does support java, but would I be better off using gRPC, sticking with msgpack and raw udp, or has network tables finally caught up?
Depending on what exactly you intend to do with vision, writing your own solution may be overkill. If all you want is vision targets, the limelight or a raspberry pi with photonvision works really well. If you want to track the cargo, photonvision still works quite well, but a solution like what you are doing begins to seem a bit more reasonable.
If you really want a fancy recognition system, you may want to look into axon (docs at: Axon — FIRST Robotics Competition documentation). It runs on the raspberry pi image and passes data back over network tables.
Developing your own vision solution can be done. Honestly, I don’t know how to do it. But just consider that maybe you are adding more complexity than is needed for what you are doing.
While the default periodic flush rate is fairly slow (10 Hz) and asynchronous, NetworkTables has very consistent low latency (e.g. 1us range) if you flush (NetworkTableInstance.getDefault().flush()) immediately after updating the values you’re sending. This is the approach used by Limelight and PhotonVision and it works very well.
I’d suggest only doing stuff yourself that’s your core competency. There’s way too much stuff to do in a season.
The Not Invented Here mindset reminds me of when I played Pokemon Gold as a kid without knowing saves were a thing. You get really good at the start of the game, but don’t make any long-term progress between play sessions. In FRC, this is analogous to getting really good at basic FRC stuff every year, but having to start over when the person maintaining your custom framework graduates.
You can think of past libraries or COTS solutions as progress saves. Whether those progress saves are deemed necessary to remain competitive (a loaded word with different definitions for different teams) is a separate question. Some teams don’t care about competitiveness altogether, which is fine if that’s a conscious choice.
Knowing how to apply canned solutions effectively to get something done, and when one is warranted, is a useful skill as well.
Why switch from C++ to Kotlin? That seems like it adds more middleware. That means there’s less opportunities for students to learn, especially about how programming languages work. To make this experience as educational as possible for your students, I would recommend going over with them how programming languages work, namely the different syntax and functionality choices they make. As the final step in this, your students can attain and develop skills in creating programming languages, skills that can drive their careers. You should give your students OCaml - Lexer and parser generators (ocamllex, ocamlyacc) as a reference manual on how industry leaders use lexers and parsers. They can use this to create their own programming language.
Keep in mind, CAN can have a non-deterministic latency associated with other messages on the bus. The FRC addressing scheme prevents you from fully defining message priority.
We did a UDP scheme between a coprocessor and the roboRIO back in 2017. Data communication worked well, and was quite robust.
Peter’s got the right answer though for 2022 - NT has the right stuff built in to do inter-processor communication. We’ve used it for the past two years under the scheme he described, and it’s the lowest setup/maintenance effort.