How to Write a PX4 Module: Step-by-Step Guide
To write a
PX4 module, create a C++ class inheriting from ModuleBase, implement required methods like task_spawn and run, and register the module in the build system. This module runs as a separate task in the PX4 autopilot environment.Syntax
A PX4 module is a C++ class that inherits from ModuleBase. It must implement static methods like task_spawn to start the module and print_usage to show help. The run method contains the main loop logic.
Key parts:
- task_spawn: Starts the module task.
- run: Main execution loop.
- print_usage: Shows usage info.
- ModuleBase: Base class for PX4 modules.
c++
#include <px4_platform_common/module.h> class MyModule : public ModuleBase<MyModule> { public: static int task_spawn(int argc, char *argv[]) { MyModule *instance = new MyModule(); if (instance) { _object.store(instance); _task_id = task_id_is_work_queue; instance->run(); return 0; } return -1; } static int print_usage(const char *reason = nullptr) { if (reason) { PX4_WARN("%s", reason); } PX4_INFO("Usage: my_module {start|stop|status}"); return 0; } void run() { PX4_INFO("MyModule running"); // Main loop here } private: MyModule() = default; };
Example
This example shows a simple PX4 module that prints a message once and exits. It demonstrates how to define the module class, implement task_spawn, and run the module.
c++
#include <px4_platform_common/module.h> class HelloModule : public ModuleBase<HelloModule> { public: static int task_spawn(int argc, char *argv[]) { HelloModule *instance = new HelloModule(); if (instance) { _object.store(instance); _task_id = task_id_is_work_queue; instance->run(); return 0; } return -1; } static int print_usage(const char *reason = nullptr) { if (reason) { PX4_WARN("%s", reason); } PX4_INFO("Usage: hello_module {start|stop|status}"); return 0; } void run() { PX4_INFO("Hello from PX4 module!"); } private: HelloModule() = default; }; extern "C" __EXPORT int hello_module_main(int argc, char *argv[]) { return HelloModule::main(argc, argv); }
Output
Hello from PX4 module!
Common Pitfalls
Common mistakes when writing PX4 modules include:
- Not properly registering the module with
extern "C" __EXPORTfunction, so PX4 cannot start it. - Forgetting to implement
task_spawnorrunmethods, causing the module to not run. - Not handling task cleanup or exit conditions, which can cause resource leaks.
- Using blocking calls inside
runwithout yielding, which can freeze the autopilot.
c++
// Wrong: Missing extern "C" export class BadModule : public ModuleBase<BadModule> { public: void run() { PX4_INFO("BadModule running"); } }; // Right: Proper export and main extern "C" __EXPORT int bad_module_main(int argc, char *argv[]) { return BadModule::main(argc, argv); }
Quick Reference
Summary tips for PX4 module development:
- Always inherit from
ModuleBasetemplate. - Implement
task_spawn,run, andprint_usage. - Export the main function with
extern "C" __EXPORT. - Use PX4 logging macros like
PX4_INFOfor output. - Keep
runnon-blocking or use sleep/yield properly.
Key Takeaways
PX4 modules are C++ classes inheriting from ModuleBase with specific static methods.
Implement task_spawn to start the module and run for main logic.
Always export the main function with extern "C" __EXPORT for PX4 to recognize the module.
Avoid blocking calls in run to keep the autopilot responsive.
Use PX4 logging macros for clear debug output.