While perusing 2337’s code (Thanks for publishing it!), I saw that they use a flat sequence in Begin. What are the relative merits of doing this? Does it end up executing faster with less thinking required of the scheduler?
Tim
While perusing 2337’s code (Thanks for publishing it!), I saw that they use a flat sequence in Begin. What are the relative merits of doing this? Does it end up executing faster with less thinking required of the scheduler?
Tim
If you give a link to the code, I can explain how the code would be compiled differently and would execute differently. But faster isn’t necessarily a good expectation.
Greg McKaskle
An image of the Begin.vi for reference
In the very first frame of the sequence structure they are initializing variables that will be used in the frames following. The first frame MUST finish executing completely before moving down the line, so they’re avoiding potential race conditions with the variable assignment.
This entire VI could have been condensed into a two frame sequence structure (like so) and wouldn’t have affected the end result. The reason that they split the sequence structure up further was for readability. Which in a graphical programming language like LabVIEW, goes a long way.
Can u add a link to the post where they have published it?
Here’s a link to hunt down the code (I hope):
http://www.chiefdelphi.com/forums/showthread.php?t=116908&highlight=2337+git+code
Thanks for the answers. I really needed to learn the variable initialization part, I think we got bit by not controlling that better last year.
Any other good insights Greg?
Well, since you ask …
I’m not sure I’d use the network variables for that purpose. They are meant for shared data across computers. Those aren’t local variables as previously stated. They will obviously work as a variable, but they are rather heavy to replace a constant and of course need something like the sequence to prevent a race condition.
There are many alternatives.
The first year, there was no refnum registry. You would allocate things in Begin, bundle them together, and pass them through the subVI as a parameter and into the other functions where the references would be indexed by name. The difficulty of creating or modifying a type and getting it to match with the various inputs and outputs suggested we do something simpler. But if you are ready to create clusters and/or typedefs, this would be the most commonly used solution by professionals.
The refnum registry, introduced in year two, stores the refnums in a named global location. It uses strings, to refer to the refnums for store and read operations. This is far simpler to understand, but it does allow for misspellings to cause a bug. But the misspelling will result in messages going to the DS Message box, so it is pretty easy to detect. And if your “misspelling” was to use front when you really meant back, that isn’t really a misspelling and none of the solutions will prevent that mistake.
If you would like to modify the refnum registry, you can add your own wrapper that takes in an enum instead of a string. You’ll create a typedef enum that contains all motor names. The store and read operations will then use the enum instead of the string, but adding a motor will mean updating the registry to know about the new motor name. Enums – enumerations – are really just numbers at runtime, but in your code you get to use a name for enhanced readability. LV enums are further restricted to be compact ordinals.
I’m not sure this was what you looking for, but that is my input on the code I was shown.
Greg McKaskle
The TechnoKats did exactly that this past season. We also created a vi full of global arrays that defined which cRIO resource was to be associated with each enum, and used for loops to Open each resource using the specified attributes. Adding a new motor meant adding it to the enum, then defining its PWM number (and its invert flag value) in the global array.
We started out by ignoring the refnum registry entirely, but that kept us from using Test mode.
Tim, just as John Sabath said, the intent of the flat sequence structure (besides avoiding a race condition) was readability, especially with younger programmers not familiar with LabVIEW.
Thanks for the feedback, Greg. We started using network variables because of how well they are organized and viewed in the Project Explorer, and because they simply seemed like a another type of global variable. Interestingly enough, we actually got the idea of using network variables to store refnum names from FRC68, in order to avoid the errors due to misspelling refnum names (when creating string constants, as the default code is set up to do), after they saw how we used network variables to share local robot state data across VI’s.
Our intent was always to be able to view all of those variables constantly - sharing them between computers - but accomplishing that in FRC means pushing them through the Dashboard, or manually using UDP or TCP packets, not actually utilizing the network variable itself (I assume).
I think that what Greg proposed - an enum (perhaps one for each type of refnum - motor, digital I/O, solenoid) would be the best way to evolve this system further. I think the ideal solution would be for LabVIEW to throw an error if refnum names were misspelled (similar to how in a text-based language, if variable names are misspelled, errors are thrown) - but I don’t know how that would be implemented in a visual language like LabVIEW, where most data flow isn’t named.
Sorry for the graveyard resurrection, but I thought some input from 2337 would be nice, even after the fact.
It would be very easy for the refnum get operation to return a runtime error, but not possible for a compile time error using a string. That is where the enum would help. Textual or visual, you’ll have the same difficulties here – strings aren’t sets.
The network variables are/were too heavy weight to be used in FRC. They were developed a number of years ago for industrial automation, and meant for exactly what you describe. They were used and still are used for monitoring or control machines to share status and set points with each other. But the memory the libraries needed pushed other things out. Additionally, they have a somewhat complicated set of options for quality and alarms. So we tried several times to get them to fit on the cRIO, and eventually put our eggs in the Smart Dashboard basket. It is the same concept, but with a much reduced feature set and implementation.
Greg McKaskle
Greg,
Thanks for the detailed answers. I always learn more than a couple thing when you post.
Using an enum to manage the motor references is going to be used by us. It is a great answer to constantly spell checking by hand when motor control goes wrong.
Thanks again to 2337 for going open kimono with their code and spurring me to learn some things. I am about to start another thread on something else I saw in there.
Tim