Project Roadmap - MontclairRobotics/PowerUp GitHub Wiki

I'm just trying to get the ball rolling. Consider this to be a "mockument" of the real design document.

Basic Design Philosophies:

(for now in no particular order)

Hardware Configuration Class:

In order to support consistency across multiple versions code being developed, as well as, providing a single place to coordinate all physical/electrical configurations a hardware configuration class will be created. This class contains:

enums for each port type (CAN device id's, PWM ports, Digital I/O ports, etc.)

enums are used to provide strongly typed values that can be enumerated in single location making it easy to check for duplicates. Any other form that provides a strongly typed easily sequenced values would be acceptable.

Higher level objects that are completely hardware dependent.

For example, in a Sprocket project, the Motor, Module, and DriveModule definitions could exist here. The notable exception should be any binding between devices that could vary from different robot programs/versions using the same physical robot.

Sprocket:

(Just taking a position here, feel free to disagree.) The program will be based on the Sprocket framework. Wherever appropriate Sprocket tools will be used to develop and "wire" components. Where needed Sprocket will be extended and/or functionality will be replaced. These extensions should be segregated to make it easy to reuse and/or transfer into Sprocket.

Robot Class:

The class Robot is deployed to hardware. To handle multiple version of robot functionality in the master branch, the Robot class should be an empty class which extends some other class containing the implementation to be used.

Ontogeny recapitulates phylogeny:

The code structure should, where possible, follow the robot's structure. Physical modules that operate independently as a unit can be modeled, programmed, and controlled independently as units. This can be done by writing controller classes that manage the modules. For example, on our Steamworks robot, opening and closing the Gear manipulator operates independently of the climbing mechanism. The Gear manipulator has logic and feedback involving two motors and four switch that can be encapsulated into a "set and forget" control scheme that provides abstracted inputs/outputs. This same abstracted interface can be used by the teleop and autonomous routines. The request could be Gear.Request.Open, Gear.Request.Close, or Gear.Request.Nil and the feedback could be Gear.Status.Open, Gear.Status.Closing, Gear.Status.Closed, or Gear.Status.Opening. Often these controllers can be implemented as state machines. Of course this approach can be nested and continuing with this example each of the two jaws of the Gear manipulator can be abstracted with a controller class containing a state machine of its own leaving the Gear manipulator controller class to manage the coordination of the two jaw controller classes.

Who's the Boss:

Code that controls the robot should be able to connect to autonomous and teleop code via the same interface. So the drivetrain code should run the same way and be controlled the same way regardless of whether an autonomous or teleop routine is running. This may sound simple and obvious but is often not done. It requires that information gathering/decision making processes be isolated from execution processes.

The answer is 6. Now just figure out the units:

Control requests should be expressed using the most complete convenient real-world units. Drive speed can be expressed as a fraction of unity (0-1). But if encoders exist on a suitable (non-slip) drivetrain, speed could be expressed as feet/second. In isolation this might seem like a minor change, but it implies not just the existance, but the use of feedback control. Additionally, another function might request the drivetrain to travel some distance. It would be in keeping with this approach that the distance also be expressed in feet (possibly with a max speed in feet/second). It may be that while the drivetrain uses a consistent set of units. A manipulator might use another like inches instead of feet. As long as the devices are fully independent this should be okay, but if they work together, then common units would be preferable.

Init Heavy, Run Light

Robot control code must run quickly and efficiently, but writing that code should also be quick, easy, and reliable. These two ideas are somewhat in conflict. Usually what makes code easy to craft is a hierarchy of dynamic tools that are largely data driven and use long chains of nested lookup functions and the like. In cases where the results of these calls won't change for the duration of the run, they should be resolved during construction/init routines with the results saved and used in recurring update routines. This allows for simple construction and efficient use. Moreover the work done to "convert" from the easy to use init to efficient to use data is done once at a time that is less efficiency critical.

Now just write it.