I was wondering if someone could help me understand how to use the robot characterization (from a second level concept). Maybe I’m confusing some of these topics with the simulation libraries, especially the arm and elevator. Yes, I already read the latest 2022 documentation coming out from WpiLib. (and maybe some of this could go to WpiLib documentation to help other teams)
Like I have some questions:
What is the difference between an arm, elevator, and general mechanism? Or how to I tell what mechanism to use? Maybe I can provide example mechanisms, and someone could categorize them:
a) Ball basket pivot motor. (think 2020 Everybot front ball hopper from team 118, guessing arm)
b) Long lead screw (like most 3d printer z-axis) to lift the robot (guessing elevator)
c) A scissor jack lift to reach higher (I’m guessing elevator also, but might be weird since I believe the lift motion is not linear (maybe only the force is not linear))
d) A horizontal grabber (think WCP Greyt Roller Claw, although that looks pneumatic; I think this has to be general linear flywheel mechanism to not consider gravity)
How do you characterize mechanisms? The directions seem to be written to only characterize drivetrains.
For example, our basket like A above has a limited amount of range. It started about 5* past vertical in starting configuration, and the bottom is about flat (so ~95* range), and needed to be about 75* up to score. How does the characterization know where gravity is relative to the mechanism so that it can calculate Kcos (the gravity coefficient). Do I need to tell SysId somewhere?
Maybe for an elevator, it’s easier, because you can start it in the middle of travel, but I’m guessing we need forward direction up and backwards direction down for gravity to calculated correctly.
Back to the arm, is that the assumption also, that forward is up against gravity and backwards is down?
A partial answer: The characterization process outlined by these docs assume you have a working model. This model is always going to be some rule describing how your input voltage affects the way your measurements (typically encoder data) evolve. The characterizer here takes in a model and a dataset and attempts to fit constants which would make your model most closely match the dataset. Often, your model doesn’t have to be “perfect,” but a good-enough model will get your output voltage close enough on open-loop that your closed-loop parameters don’t have to do much work.
Pretty much every motor model used for controls often ends up being of the form V = k_1 \dot x + k_2 \ddot x + \text{other terms based on system dynamics}.
For your estimates:
“A” could be best characterized as an arm. The key aspect of an arm is that it experiences a torque proportional to the cosine of its angle from horizontal - hence the cosine term in the equation.
“B” could be best characterized as an elevator since you have a load from gravity, as well as static friction.
“C” could be approximated as an elevator if you stay in the range where the load on your motor remains constant, but it’s important to note that the force is nonlinear, and also not cosine-proportional like in the arm example. You would need to look at the forces on the system and compute what the eventual load on the motor is if you want an accurate characterization.
“D” sounds like the sort of thing that’s best estimated by a flywheel, there aren’t (at least in a spherical-cows model) any external loads on the system, so you just have to overcome the inertia.
Overall, you’re 4 for 4 on understanding which characterizations are which.
I won’t comment on the code here since I’m far from an expert on WPILib, but I will give a very rough outline of a general-purpose algorithmic approach one might take:
Characterize your system according to an equation of the form V = k_1 f_1(x) + k_2 f_2(x) + \cdots k_n f_n(x), where each k_i is some unknown constant.
Do some experimentation, and collect lots of data where you log the values of V as well as f_1(x), f_2(x), \cdots f_n(x) at many different time intervals.
Plot your data and make sure to check that it matches the model you expected - you can’t really get anything useful out of the next step unless you’re sure of this.
Formulate a least-squares regression model (Your favorite spreadsheet editor can probably do this if you don’t want to code it yourself or find a library) which will find values of k_1, k_2 \cdots k_n which would best-fit your observed data.
Using the method described above, you’ll get the best results when the data you observe covers the domain of what you expect to see in real life. For instance, if you have an elevator model, you could collect all your data while moving upward, but you would get much better results if you collected data moving upward and downward at both different speeds and accelerations.
The reason overall to use characterization is that it lets you figure out what your voltage output should be based on the state of the system you want to be in. For instance: if I know my elevator has a velocity of 1 inch/sec, and I want the acceleration to be 2 inches/sec^2, I can then go solve for the value of V I need to make that acceleration happen. Typically, this approach is used in tandem with PID or some other closed loop.
Out of curiosity, what’s your end goal for characterizing those types of mechanisms? It seems like for most of them, a simple p controller would work just fine. If the non-linear element is small relative, there isn’t much reason to make things complex by compensating for it.
To be honest, I’m not 100% sure what I’m looking for either, it was half an exploration on what features WpiLib has, and half to see if it could have helped our issues we had this season. It was also to point out that the instructions for characterizing seem lacking beyond drivetrains.
The problem I was investigating was our basket design from 2020/21. It was similar to the Everybot 118 intake/score. The issue we had was to hold it up during driving to protect it and score. Since we had to hold it at a 75* angle to score, the PID loop we tried had issues. For example, if you spin the robot in circles, centrifugal force swings the basket out far enough that it would be too low to score anymore, and the motor had to drive it back to position. A P-only controller doesn’t really work for this basket since gravity helps down, but not on the way up, you need a LOT more P to bring it up. We also burned up a couple motors there as the PID loop was trying to hold it in position while it swings around.
Now, I will say, the issue could have been fixed other ways. I keep thinking I never checked if that motor was in brake mode, and that would have certainly helped. We were fighting our encoder a little, since wherever you started was considered the zero position, and we never recalibrated it at teleopInit since it has to be in starting position then (a CanCoder or potentiometer would be better here to store absolute position)… We also could have changed the gearbox to be a higher ratio or add idle gears to stop backlash and sagging (not a mechanical person). It sure seems like the feed forward term the robot characterization tool would calculate would help the gravity part of the mechanism, but I don’t have the robot at home to try it.
Just trying to figure out how to solve a mechanical problem in software again
I’m not sure that characterization would help in this situation. The additional motor output from compensating for the angle would make it more likely to burn the motor out rather then less likely. A better solution would be change the gearing or the motor.
You are more advanced than our 2020 “arm” which just had a couple rugged limit switches with open loop driving to that point. It also swings out when you rotate quickly. But usually the operator could compensate, though. And it did have break mode on a heftier sport gearbox.
Ignoring that, these tools are still in their infancy and so I think the number that have fully implemented mechanisms like elevators or arms are quite low and there will be a need for more documentation to bring those along for less savvy folks. It isn’t a replacement for other simpler controls but is just another tool for it. I remember spending in 2019 spending 2 weeks to get am arm like mechanism with controls like we wanted with encoders and 2018 we had a another more complex limit switch setup that never really worked well enough for the operator to give up manual control.
Drivetrains are a high priority to improve auto driving precision more than anything. The shooting flywheel was a nice easy to implement process with the state space controls implemented. I think there will be much more elevator and arm stuff if it is important in the game this year which is somewhat likely, otherwise it get better explained by trying it and asking lots of questions in the process, then getting that into a doc for others to follow through.
A friendly reminder that frc-docs is open source and community-maintained, and if there’s documentation you’d like to see you can open a github issue or, better, write a pull request!
I fully agree with sending back our feedback to the documentation team, I just think they want us to know what we are talking about first before contributing. (I guess we could put in open issues too to say what could be improved)
Honestly, I think I want to go to the new Sysid tool team first and ask for either:
Source code generation again so we can tweak stuff like initialization in hand code first. (like I can set up the proper initial angle for the mechanism when it starts, or the known issue with swerve modules where they won’t initialize and keep them zeroed while it does it’s forward/backward tests. I do like their new JSON initialization technique though.) The older frc-characterization project allowed code generation and changes. (and then allows the code to be run in simulation also so the virtual robot could be characterized if you want)
The format of the network tables they expect so we could just populate the tables and motor commands with proper data ourselves.
In response to 1. This is actually a design decision to move away from Java projects as the timing issues related to JVM garbage collection actually ruins a lot of teams characterization data. C++ timing is much more stable and usable.
Now we technically could’ve moved to C++ generatable projects, but given a tiny minority of FRC teams are C++, it would not have been much of a benefit and more error prone than anything.
With a lot of teams investigating swerve, we are looking into things regarding Swerve support in SysID for the future.
For swerve teams, is the telemetry format compatible with how 2910 did their characterization? It seems they used a different format of telemetry than frc-characterization, I was thinking perhaps they found a new format that worked for them: