We have been using a similar architecture for the past few years, with a few improvements this year. Everything is written in LabVIEW, and follows common programming practices for LabVIEW.
-All mechanisms are organized into subsystem controllers, each containing a high-level VI with a while loop running at a certain frequency (most run every 20ms). A few subsystems run multiple loops at different speeds and priorities.
-All subsystem controller VI's set the thread priority and execution system for that subsystem. We organize them logically, but since all threads are important, we generally set them all to above-normal or high.
-There is one thread which is not timed to a fixed period, but to the Ocurrance coming from Start Communication (it's timed to the radio packets). This is called "MainTask" and contains the standard Robot Main while loop and the HMI system.
-The standard RobotMain loop contains the logic to enter and exit autonomous (by starting/stopping AutonomousThread.vi), and the HMI system which reads joystick inputs and generates high-level responses.
-The Autonomous system is exactly the code we used last year and released
here. We wrote many new script commands to fit this year's game and robot design, but the architecture and script system is the same.
-New for this year is a "signal manager", which manages timestamped binary signals. We use these to indicate boolean events, and corresponding "signal traps" tell a subsystem when new signals are sent, which is very useful for communicating between asynchronous systems.
-Data communication happens between data storage VI's - Most are set as Subroutine priority for execution speed reasons, and store bundles of data between asynchronous tasks. A subset of data storage VI's are state storage VI's - They store the commanded state of a mechanism. A commanded state is enumerated in a strict type def, and the state storage VI's allow systems to write a new state, read the current state, and also manages resetting the state to an uninitialized or manual state when entering enabled.
-Most VI's listen for SIGENABLED and react to being enabled, but none react to entering or exiting autonomous mode (we don't even have a signal for it, or really store that state anywhere). The autonomous command system has wrapper command VI's which allow setting states through the script system.
-The only exception to all of this is the drive motors - There is a set of VI's which records the drive state, which sets who controls the drive motors. They are set like a normal system during teleop, but autonomous routines directly command the drive motors, since autonomous drive actions are completely different from teleop drive actions.