Hello! I’m writing a bunch of sample programmes to use as examples for teaching new programmers, and I’m currently working on PID. I know there’s a PID class, but I would prefer to write my own as I have the capability. The PID loops I know of utilize time a lot, and tend to be a bit eccentric, so I was thinking of creating them in a separate thread (using the Task class). The thing I want to know is how fast threads execute. Is it 50Hz like the periodic methods or is it more akin to the discontinued continuous methods? Thanks!
It would be akin to the continuous methods, though a little bit faster, I would suspect.
You’re likely to have an unfun time splitting out something like a PID controller to a separate thread- and for no benefit. In my experience, PID doesn’t take any resources- or not enough to cause lag. I’ve ran a few PID loops (Of my own making- not the builtin class.) concurrently through the TeleopPeriodic functions, with no problems… what PID algorithms are you using that take lots of resources?
A couple suggestions - first one is to look at the PID class source code from WPIlib. They do actually spawn a Task for monitoring. The second thought is that you can write your own and your own task and if you’re looking to limit the frequency with which it loops, simply use Wait() appropriately. If you’d like a Task base class, my team has a nice one called JankyTask where you can base your class on it and simply write your ‘Run()’ function and it will get called by the base class after a 2ms loop delay when it is running.
Testjig is at: https://github.com/bobwolff68/FRCTeam1967/tree/master/code/JankyTaskTestjig
And the base class itself is: https://github.com/bobwolff68/FRCTeam1967/blob/master/code/include/jankyTask.h and: https://github.com/bobwolff68/FRCTeam1967/blob/master/code/classes/jankyTask.cpp
multi-threading can lead to all kinds of subtle errors. I would recommend not using it in examples for novice programmers without sufficient context. If you have to ask how fast a task executes, I question whether you can write sufficient examples.
1000% agree - I setup the tasks (or the framework) and show the students how it works. In 10 years only 3 students really “got it” enough to make wise changes to the framework. Most years the students fill in each task as if it were a standalone program - still amazing efforts by a 14-18 year old.
I taught classes for Wind River, Montavista and others for many years. Not all degreed professionals really get how a real-time multi-tasking environment works. Once you start talking about RMA methods, scheduling theory etc it is not just secondary students that get lost. This is (one of) the most difficult application programming environments.
Ouch. At the time I wrote the question, I didn’t have access to the robot or the development environment, and was just hoping someone could tell me off the top of their head. I’ve since had access and figured it out on my own. We’re only using it to isolate separate instances of our PID loops (for demonstration purposes), and our programming mentor and I deemed it’s speed more than sufficient. We tested it using robot from last year and encoders to test running four consecutive loops on each of the independent drive motors (on blocks; not for driving purposes but to allow us to check and graph the speeds with a tachometer). I’ll put up some graphs to show our results when I get the pictures off of the camera.
That will be interesting to see. I think the point that persons in this thread are making is that “how fast is a task” is a verrrrry relative question. For example, I could code a simple task that ran in a tight loop and set the priority as great as possible (0 using the VxWorks native API or 99 using the Posix API). The speed of your task would be limited (only) by the throughput of the CPU, the nature of your code (does it all fit in cache, is it optimized etc) and what is going on in interrupt context. Of course nothing else in task context would ever run.
The real question (I think) is if we run at a priority that does not interfere with the operating system (exception handling, log messages etc) or the NI and WPI infrastructure (loaded when we image the robots, saftey and DS comms etc), what sort of performance might one expect. But even this measurement is relative - you might have a complex multi-tasking application where you are concerned about meeting periodic deadlines.
The “professional” way to handle this general question is to analyse all the code running on the robot. Google “rate monotonic analysis” - it is a widely used algorithm. The beauty of VxWorks (as opposed to Windoze) is if the analysis says you can meet all your timing parameters, the operating system will guarantee the performance. Make sense?
Of course in FIRST such an analysis might be impractical. So we run as many PID classes as we can, optimize the vision processing and pray. FIRST 1296 moved the vision processing to a Rasberry Pi and find that the cRIO can do most anything you ask if properly coded. In real-time programming there are a few time killers that programmers forgot most often - formatted print statements, memory allocation and long spinlocks can kill you. For this reason do NOT output stuff to the console in your normal (non-debug) modes of operation, allocate your memory as the robot powers up in an initialization phase and use proper operating system primitives (like mutual exclusion semaphores) to protect shared code or hardware. Also beware of C++ and Java - try to use constructors and templates that allocate memory up front and do not free and allocate memory in critical regions of your code.
HTH