# Running Your First App :::{caution} This section is only relevant to users who are working within the Cobra repository. Downstream users will need to write their own apps to run. For help on building your own apps, see [The Exercises](./exercises.md) ::: In the `pntos-cobra-apps/src/pntos/apps/` directory, there are several off-the-shelf {term}`apps ` of increasing complexity assembled from off-the-shelf {term}`Cobra` plugins that serve to demonstrate {term}`Cobra` and the development process for you to build your own {term}`apps `. This page serves as an introduction to running an arbitrary {term}`Cobra` {term}`app `. For more details on any particular app, refer to the corresponding page in the {ref}`tutorial-apps` section of the docs. ## Running an App A {term}`Cobra` app consists of a Python script containing all plugin imports, config, and code needed to start a particular instance of a {term}`Cobra` implementation. The core {term}`Cobra` plugin set contains a [Transport plugin](./plugins/transport_plugin.md) that retrieves {term}`ASPN` messages from an [LCM](https://github.com/lcm-proj/lcm) relay. This allows pntOS to ingest data either from sensors sending ASPN measurements live, or (in the case of the tutorial apps) from an LCM log file replaying data over the relay. These instructions will walk you through starting a generic app, spinning up the LCM relay, and playing back a log file to feed data into pntOS. ### Activate Virtual Environment These instructions assume an active virtual environment as outlined in the [](./installation.md). If you currently have that virtual environment activated, skip to [](#select-and-run-an-app). If you have not yet created a Python virtual environment for the [Cobra repository](https://github.com/is4s/cobra), follow the instructions in [](./installation.md) then go to [](#select-and-run-an-app). If you have created the virtual environment but it is not currently activated, run the below command from the root directory to enter the virtual environment. The command varies depending on your shell: ```{include} snippets/activate_venv.md ``` ### Select and Run an App The available apps can be found in each subfolder of the `{workspace-root}/pntos-cobra-apps/src/pntos/apps` directory. If this is your first time with {term}`Cobra`, starting with the `pos_ins` app is recommended. The available off-the-shelf apps are in the {ref}`tutorial-apps` section of these docs. `````{tab-set} ````{tab-item} POS INS Tutorial App :sync: pos-ins-tutorial For documentation specifically explaining this app, see [](./apps/pos_ins.md). ### Run the POS INS Tutorial App To run this app, run this command from the root workspace directory (with the Python virtual environment activated): ```shell cobra_tutorial_pos_ins_app ``` Once the app is started, it will immediately start processing messages from the input log, with a progress bar tracking the percentage of messages that have been processed. Once the entire input log has been processed, the app will automatically shut down. For tutorial apps, a UI plugin for LCM log plotting is initiated on shutdown. You should see something like the following terminal output, followed by a set of plots displaying the results: ```text [17/07/2026 11:51:39] [LoggingPlugin] [INFO] using hard-coded global logging level INFO [17/07/2026 11:51:39] [OrchestrationPlugin] [INFO] Aligned filter at 1747680879.539799929s [17/07/2026 11:51:39] [ControllerPlugin] [INFO] Press Ctrl + C at any time to shut down pntOS... [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/vn-100/imu with a timestamp of 1747680879.539799690s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/ins-d/pva with a timestamp of 1747680879.543048859s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/simulated/velocity with a timestamp of 1747680879.543048859s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/simulated/directiontoknownfeature with a timestamp of 1747680879.543048859s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/position with a timestamp of 1747680880.300589800s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/velocity with a timestamp of 1747680880.300589800s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/pva with a timestamp of 1747680880.300589800s [17/07/2026 11:51:39] [TransportPlugin] [INFO] Found new channel /sensor/bmp388/baro_pressure with a timestamp of 1747680880.328312635s 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 474M/474M [00:17<00:00, 26.7MB/s] [17/07/2026 11:51:57] [TransportPlugin] [INFO] Done processing LCM log. [17/07/2026 11:51:57] [ControllerPlugin] [INFO] Shutting down all plugins... [17/07/2026 11:51:57] [TransportPlugin] [INFO] Shutdown plugin for Cobra Tutorial LCM Log Transport Plugin. Reading measurements from log... 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 476M/476M [00:05<00:00, 82.9MB/s] [17/07/2026 11:52:04] [UiPlugin] [INFO] Plotting results. This may take a while... [17/07/2026 11:52:11] [UiPlugin] [INFO] Plots saved to pntos_output. Close all windows to continue shutdown. ``` The results from the tutorial app will be displayed in separate windows. To continue with the shutdown, simply close all the plotting windows. ```{note} The UI plotting plugin is only used in tutorial apps. However, most apps record the pntOS solution to `pntos_output.log` by default for plotting or further processing. For information on how to plot the pntOS solution from a log file, see [](#view-results-from-a-log-file). ``` ```` ````{tab-item} POS INS Velocity Tutorial App :sync: vel-app For documentation specifically explaining this app, see [](./apps/pos_vel_ins.md). ### Run the Position and Velocity Update App To run this app, run this command from the root workspace directory (with the Python virtual environment activated): ```shell cobra_tutorial_pos_vel_ins_app ``` Once the app is started, it will immediately start processing messages from the input log, with a progress bar tracking the percentage of messages that have been processed. Once the entire input log has been processed, the app will automatically shut down. For tutorial apps, a UI plugin for LCM log plotting is initiated on shutdown. You should see something like the following terminal output, followed by a set of plots displaying the results: ```text [17/07/2026 11:58:37] [LoggingPlugin] [INFO] using hard-coded global logging level INFO [17/07/2026 11:58:37] [OrchestrationPlugin] [INFO] Aligned filter at 1747680879.539799929s [17/07/2026 11:58:37] [ControllerPlugin] [INFO] Press Ctrl + C at any time to shut down pntOS... [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/vn-100/imu with a timestamp of 1747680879.539799690s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/ins-d/pva with a timestamp of 1747680879.543048859s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/simulated/velocity with a timestamp of 1747680879.543048859s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/simulated/directiontoknownfeature with a timestamp of 1747680879.543048859s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/position with a timestamp of 1747680880.300589800s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/velocity with a timestamp of 1747680880.300589800s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/pva with a timestamp of 1747680880.300589800s [17/07/2026 11:58:37] [TransportPlugin] [INFO] Found new channel /sensor/bmp388/baro_pressure with a timestamp of 1747680880.328312635s 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 474M/474M [00:20<00:00, 22.8MB/s] [17/07/2026 11:58:58] [TransportPlugin] [INFO] Done processing LCM log. [17/07/2026 11:58:58] [ControllerPlugin] [INFO] Shutting down all plugins... [17/07/2026 11:58:58] [TransportPlugin] [INFO] Shutdown plugin for Cobra Tutorial LCM Log Transport Plugin. Reading measurements from log... 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 476M/476M [00:05<00:00, 81.1MB/s] [17/07/2026 11:59:05] [UiPlugin] [INFO] Plotting results. This may take a while... [17/07/2026 11:59:12] [UiPlugin] [INFO] Plots saved to pntos_output. Close all windows to continue shutdown. ``` The results from the tutorial app will be displayed in separate windows. To continue with the shutdown, simply close all the plotting windows. ```{note} The UI plotting plugin is only used in tutorial apps. However, most apps record the pntOS solution to `pntos_output.log` by default for plotting or further processing. For information on how to plot the pntOS solution from a log file, see [](#view-results-from-a-log-file). ``` ```` ````{tab-item} POS INS Standard App :sync: pos-ins-standard For documentation specifically explaining this app, see [](./apps/pos_ins_standard.md). ### Run the POS INS Standard App To run this app, run this command from the root workspace directory (with the Python virtual environment activated): ```shell cobra_standard_pos_ins_app ``` Once the app is started, it will immediately start processing messages from the input log, with a progress bar tracking the percentage of messages that have been processed. Once the entire input log has been processed, the app will automatically shutdown and you should see something like the following in the terminal: ```text [17/07/2026 12:08:15] [LoggingPlugin] [INFO] using hard-coded global logging level INFO [17/07/2026 12:08:15] [ControllerPlugin] [INFO] Press Ctrl + C at any time to shut down pntOS... [17/07/2026 12:08:15] [TransportPlugin] [INFO] LCM log reader is running. [17/07/2026 12:08:15] [TransportPlugin] [INFO] Found new channel /sensor/vn-100/imu with a timestamp of 1747680879.539799690s [17/07/2026 12:08:15] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/position with a timestamp of 1747680880.300589800s [17/07/2026 12:08:15] [OrchestrationPlugin] [INFO] Aligned filter at 1747680889.549539804s 100%|██████████████████████████████████████████████████████████████████████████████████████████████████████████▉| 474M/474M [00:11<00:00, 40.9MB/s] [17/07/2026 12:08:27] [TransportPlugin] [INFO] Done processing LCM log. [17/07/2026 12:08:27] [ControllerPlugin] [INFO] Shutting down all plugins... [17/07/2026 12:08:27] [TransportPlugin] [INFO] Shutdown plugin for Cobra LCM Log Transport Plugin. [17/07/2026 12:08:27] [LoggingPlugin] [INFO] Logging plugin shut down correctly. ``` The pntOS solution will be recorded to `pntos_output.log`. For information on how to plot the pntOS solution from a log file, see [](#view-results-from-a-log-file). ```` ````{tab-item} LCM Relay App :sync: lcm-relay The LCM Relay App is similar to the POS INS Standard App, but uses a different transport plugin that requires the user to separately spin up an LCM relay, and manually record the output log file. The purpose of this app is to support real-time use cases where pntOS may ingest sensor data over the network, and broadcast a live solution. To run this app, follow the steps below: ```{warning} The following commands each require separate terminals. Be sure to activate the virtual environment for each terminal as described in [](#activate-virtual-environment) before running these commands. ``` ### Start a Local TCP Server In order to feed messages into the transport plugin from an LCM log file, we need to first start a local TCP server (located in the virtual environment) in a new terminal: ```shell java -classpath $VIRTUAL_ENV/lib/python3.*/site-packages/share/java/lcm.jar lcm.lcm.TCPService ``` ### Play LCM Log File The `pntos-python-datasets-lcm` package installs a script to find the installed data and start playing it back: ```shell play-lcm-dataset ``` ```{note} If you would like to see what the above command is doing or would like to know where the dataset exists on the disk, you can run the command with a `-v` verbose flag: play-lcm-dataset -v Running the above will print out the exact command the script executes before executing it. ``` This should open the LCM LogPlayer GUI with a play button. You should see the following channels: - /sensor/bmp388/baro_pressure - /sensor/ins-d/pva - /sensor/simulated/directiontoknownfeature - /sensor/simulated/velocity - /sensor/ublox-ZED-F9T/position - /sensor/ublox-ZED-F9T/pva - /sensor/ublox-ZED-F9T/velocity - /sensor/vn-100/imu ### Record Output If you wish to record the pntOS solutions that are published by the LCM transport plugin, start the lcm-logger: ```{warning} You must delete or rename any existing `pntos_output.log` files before running this command. ``` ```shell lcm-logger --lcm-url=tcpq:// pntos_output.log ``` This process will listen to any messages transmitted over LCM and record them to `pntos_output.log`. Alternatively, to just see the solution printed to the terminal, set the logging level to `DEBUG` when initializing the {py:obj}`pntos.cobra.StandardLoggingPlugin`. ### Run the LCM Relay App Finally, to start the LCM Relay App run the following command in a new terminal: ```shell cobra_standard_lcm_relay_app ``` This will spin up pntOS and it is ready to start processing messages. To produce solutions, simply push the `play` button in the LogPlayer to start the datastream. You should see something similar to the following: ```text [17/07/2026 12:20:49] [LoggingPlugin] [INFO] using hard-coded global logging level INFO [17/07/2026 12:20:49] [ControllerPlugin] [INFO] Press Ctrl + C at any time to shut down pntOS... LCM tcpq: connecting... [17/07/2026 12:20:49] [TransportPlugin] [INFO] LCM message handler is running. [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/vn-100/imu with a timestamp of 1747680879.539799690s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/ins-d/pva with a timestamp of 1747680879.543048859s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/simulated/velocity with a timestamp of 1747680879.543048859s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/simulated/directiontoknownfeature with a timestamp of 1747680879.543048859s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/position with a timestamp of 1747680880.300589800s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/velocity with a timestamp of 1747680880.300589800s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/ublox-ZED-F9T/pva with a timestamp of 1747680880.300589800s [17/07/2026 12:20:51] [TransportPlugin] [INFO] Found new channel /sensor/bmp388/baro_pressure with a timestamp of 1747680880.328312635s [17/07/2026 12:21:01] [OrchestrationPlugin] [INFO] Aligned filter at 1747680889.549539804s ``` Unlike the other apps, there will be no progess bar displayed in the console. The LogPlayer will have a progress bar where you can track the progress of the log file. Once it is done processing, you may press `Ctrl + C` to shutdown pntOS. ```{note} You may click the `>>` button in the LogPlayer GUI to speed up the playback. However, if the data is played too fast, pntOS may not be able to provide solutions at the requested rate. In this case, you will want to wait for pntOS to process all messages before shutting down. To know when pntOS is done processing data, you can observe the terminal output where the `lcm-logger` command was run (see [](#record-output)), which will print summary statements at 1 second intervals until no more traffic is observed on the network bus. ``` ```` ````{tab-item} All Other Apps :sync: all-other-apps pntOS includes several other off-the-shelf apps that are not mentioned on this page. Each app is categorized as a `dummy`, `tutorial`, `standard`, or `advanced` app where each type showcases certain capabilities and features of pntOS from low to high complexity. Any other apps not mentioned here may be run with the following command: ```shell cobra_{app-type}_{app-name}_app ``` This is the general format of the app command-line entry points, where you would replace `{app-type}` with the app's designated type, and replace `{app-name}` with the name of the Python script of the actual app. If you are running in the source project directory, you can also run the apps directly using the executable Python files, located in `{workspace-root}/pntos-cobra-apps/src/pntos/apps`. ```` ````` ### View Results from a Log File To view the plots of the results from a log file run: ```shell postprocessing/plot_results.py pntos_output.log ``` This should display the pntOS results in individual windows and save the plots to the `{workspace-root}/pntos_output` directory. ```{tip} Included in the source code is a convenience script that will run an app, process an example log file, and plot the results all via a single command. It will work on any of the existing apps that produce a PVA solution from the example LCM or ROS logs. To use it, simply run: postprocessing/run_app_and_record_data.py Where `` should be replaced with the path to the app you want to run. ```