The producer consumer is a standard LabVIEW architecture which allows for the separation of the code that is creating data or instruction from the code that is logging that data or putting those instructions to action.
Its primary use is for large scale applications where recording every bit of data is important, but in FRC we often times care more about the most current data or instructions, so while a true producer consumer is implemented using a queue, it is advisable to use an fgv or global variable.
One reason to use this is to separate the code that is deciding what needs to be done (reading the joysticks) and implementing (setting the actuators).
Why not put it all in one place?
The more code there is in a single vi, the harder it is to maintain (correct an issue, update, or add to).
Don't parallel loops cause lag? They can, if not implemented correctly. It is worth noting that the standard architecture utilizes several parallel loops. (The main loop running Teleop, the loop in the vision code, the loops in periodic tasks, ... etc.). To avoid having one loop hog the cpu, put a wait in it (wait (ms).vi). Even a wait of 0 milliseconds will free the cpu to perform other tasks (like running other loops).
For this example, we will implement a robot that has a linear actuator using a PID and encoder.
Initializing the necessary items.
Here, the joystick is read, and depending on which button is pushed (if any), the value in the global variable is updated.
Here the state is read from the global variable and used to create an encoder set point. Based on that set point and what the encoder currently reads, the motor is set.
This tutorial shows how just a little bit of separating code can make all of the pieces seem simpler and much easier to understand. Also, if the actuator needed to go through sequences, it could do so without affecting how often the joysticks values are read or affecting the drive loop. For an additional architecture to consider for sequences, look at our state machine tutorial. These two pieces work well together, allowing the driver to update the instructions at any instant, and when the sequence is ready, it can check for the latest update in the variable.