ControllerPlugin

Summary

The ControllerPlugin is responsible for invoking plugin startup logic, choosing the concurrency model, and coordinating any platform-independent plugin activity. It is the conceptual main function of a pntOS-Python App.

General Plugin Description

We’ll introduce the ControllerPlugin by first considering the general construction of a pntOS-Python App, which is the means by which a user creates and starts a pntOS-Python system. Every implementation of a pntOS-Python App follows the same general flow:

  1. Set up plugin configuration.

  2. Instantiate a ControllerPlugin.

  3. Instantiate any additional plugins.

  4. Start up the controller plugin by calling the controller.init_plugin function.

  5. Start up the rest of the plugins by passing them to the controller via controller.take_control.

  6. Eventually shut the system down using controller.shutdown_plugin.

Aside from selecting the initial batch of plugins to use and setting up any required configuration, all direct interaction is with the ControllerPlugin. Thus, the ControllerPlugin, and more specifically its take_control function, could be considered the on button of the pntOS-Python API. Once given control, it is the ControllerPlugin's responsibility to organize and initialize all the other plugins with the basics they need to run. This typically includes:

  1. Ensuring a registry is available through a RegistryPlugin, which allows all plugins have access to their initial configuration.

  2. Providing Mediators to all other plugins via their init_plugin function, through which plugins can access the registry and broadcast messages out through the transport plugin(s).

  3. Calling any specialized plugin startup functions, such as OrchestrationPlugin.init_orchestration_plugin and TransportPlugin.start_listening.

  4. Implementing the concurrency model (single threaded, multithreaded etc.).

  5. Buffering and sorting of incoming data.

  6. Defining default system outputs, through controller-initiated calls to Mediator.request_solutions or Mediator.broadcast_aspn_message.

More information on plugin requirements may be found in the plugin’s API documentation.

ControllerPlugin API

As with all the other plugins, the ControllerPlugin inherits functions from the CommonPlugin parent class. However, ControllerPlugin implementations of these functions have special requirements:

  1. init_plugin(): Since the ControllerPlugin is the one responsible for creation of the Mediator, it should not receive a Mediator instance via init_plugin().

  2. shutdown_plugin(): Most plugins need only to worry about performing their own shutdown requirements, but as the ControllerPlugin manages all other plugins, calling its shutdown_plugin() method should trigger an orderly shutdown of all other plugins.

Those aside, the controller API has only one additional function:

65    @abstractmethod
66    def take_control(
67        self,
68        plugins: list[CommonPlugin],
69        plugin_resources_locations: list[str | None] | None = None,
70        initial_config: str | None = None,
71    ) -> None:

This function is used to run a specific instantiation of the pntOS-Python API. In fact, the entirety of a App is simply setting up the arguments for this function.

ControllerPlugin Implementations

As of this writing Cobra has two ControllerPlugin implementations, the StandardControllerPlugin and the BuscatControllerPlugin.

StandardControllerPlugin

As the base-level example, it uses a single-threaded concurrency model and leans very hard on the StandardMediator implementation to support communication- essentially attaching a core set of plugins to the StandardMediator to implement its callback functionality. The StandardMediator routes incoming data to, and extracts solutions from a single The OrchestrationPlugin, supporting sensor fusion.

Note that this plugin does not currently support PlatformIntegrationPlugins and it assumes that each TransportPlugin it receives has a non-blocking start_listening function (i.e. they manage their own thread).

BuscatControllerPlugin

The BuscatControllerPlugin is a specialized controller that does not support full sensor fusion as the StandardControllerPlugin does. Rather, it works with a subset of plugins to enable the combination of data streams and/or conversion of any transport-supported data format to any other.

Comparison

Below is a table illustrating the plugins supported by each of the above ControllerPlugins:

Plugin

Standard supports

Buscat supports

pntos.api.ControllerPlugin

0

0

pntos.api.FusionPlugin

1+

0

pntos.api.FusionStrategyPlugin

1+

0

pntos.api.InertialPlugin

1+

0

pntos.api.InitializationPlugin

1+

0

pntos.api.LoggingPlugin

1

1

pntos.api.OrchestrationPlugin

1

0

pntos.api.PlatformIntegrationPlugin

0

0

pntos.api.PreprocessorPlugin

0+

0

pntos.api.RegistryPlugin

1

1

pntos.api.StateModelingPlugin

0+

0

pntos.api.TransportPlugin

1+

1+

pntos.api.UiPlugin

0+*

0+*

pntos.api.UtilityPlugin

0+

0

Note

In the above table

  1. A numerical entry indicates the controller requires at least the specified number of that plugin type.

  2. A + indicates more than the listed number is supported but not required.

  3. * for UI plugins only, this means an arbitrary number is supported, but only 1 instance may have a UiPlugin.requires_main_thread return of True.