forked from PX4/PX4-Autopilot
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: (slightly) better course example code
- Loading branch information
Showing
17 changed files
with
312 additions
and
171 deletions.
There are no files selected for viewing
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
menuconfig MODULES_COURSE | ||
bool "course" | ||
default n | ||
rsource "*/Kconfig" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# This tells PX4 that this directory contains a module. | ||
# It is also possible to add a library or a test. (But we will not cover that in this course.) | ||
px4_add_module( | ||
# This is the name of the module. It is common to use the following format: | ||
# (It is possible to have one extra level of submodules, like we have here.) | ||
# MODULE <namespace>__<module_name> | ||
MODULE modules__course__hello_world | ||
|
||
# This is the name of the main function of the module. | ||
# This means that there must be a function with this name, postfixed with "_main" somewhere in the source code. | ||
# E.g. if this is "hello_world", there must be a function called "hello_world_main". | ||
MAIN hello_world | ||
|
||
# This is a list of source code files that are part of the module and should be built. | ||
# The source files are relative to the directory of this CMakeLists.txt file. | ||
SRCS | ||
hello_world.cpp | ||
) | ||
|
||
# To see the full list of options, see the file `cmake/px4_add_module.cmake` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
menuconfig MODULES_COURSE_HELLO_WORLD | ||
depends on MODULES_COURSE | ||
bool "hello" | ||
default y | ||
---help-- - | ||
Enable the simple hello world module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Hello, world! | ||
|
||
This is one of the smallest possible programs for PX4. | ||
|
||
Notice how we have four different files in this module : | ||
- `Kconfig` | ||
- `CMakeLists.txt` | ||
- `hello_world.cpp` | ||
- `hello_world.h` | ||
|
||
|
||
## Kconfig | ||
The `Kconfig` file is the configuration file for the module. It tells the build system that this module exists. We can also add configuration options here. | ||
For this simple module, the only configuration option is whether the module is enabled or not. | ||
The options we define in the `Kconfig` file are available in the `make <build target> boardconfig` menu. | ||
|
||
## CMakeLists | ||
The `CMakeLists.txt` file is the build script for the module. It tells the build system how to build the module. | ||
See the comments in the file for more information. | ||
|
||
## hello_world.cpp | ||
This is the main source file for the module. Right now, it contains only a main function. | ||
|
||
## hello_world.h | ||
This is the header file for the module. It contains the function prototype for the `hello_world` function. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
#include <px4_platform_common/log.h> | ||
#include <stdio.h> | ||
|
||
#include <uORB/topics/tune_control.h> | ||
|
||
#include "hello_world.h" | ||
|
||
using namespace time_literals; | ||
|
||
void play_note(int frequency = 440, int duration = 250_ms, int volume = 20) | ||
{ | ||
// The tune_control topic is used to play tunes or individual notes on the buzzer | ||
tune_control_s tune{}; | ||
|
||
tune.timestamp = hrt_absolute_time(); // Must be set to the current time | ||
tune.tune_id = 0; // Indicates a custom note | ||
tune.frequency = frequency; | ||
tune.volume = volume; | ||
tune.duration = duration; | ||
|
||
// Publish the tune_control message | ||
orb_advertise(ORB_ID(tune_control), &tune); | ||
} | ||
|
||
int hello_world_main(int argc, char *argv[]) | ||
{ | ||
PX4_INFO("Hello, World!"); | ||
// TODO: Play a note | ||
return 0; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
# pragma once | ||
|
||
// The main function must be declared as extern "C" to prevent name mangling. | ||
// Basically, this is so that a C program can call this function, even though it is written in C++. | ||
extern "C" __EXPORT int hello_world_main(int argc, char *argv[]); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
px4_add_module ( | ||
MODULE modules__course__task_module | ||
MAIN task_module | ||
SRCS | ||
px4_course_task_module.cpp | ||
MODULE_CONFIG | ||
module.yaml | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
menuconfig MODULES_COURSE_TASK_MODULE | ||
depends on MODULES_COURSE | ||
bool "task_module" | ||
default y | ||
---help--- | ||
Enable the Ascend PX4 course module |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
module_name: PX4 Course, Thread Example | ||
|
||
parameters: | ||
- group: PX4 Course | ||
definitions: | ||
COURSE_HI_NUM: | ||
description: | ||
short: How many times to greet | ||
long: | | ||
When running the thread example, the program will say Hello" this many times :) | ||
type: int32 | ||
min: 1 | ||
max: 20 | ||
default: 2 | ||
COURSE_HI_LONG: | ||
description: | ||
short: Long greeting | ||
long: | | ||
If set to false, the program will only say "Hi!". | ||
If set to true, the program will say "Hello, PX4 Course!" instead. | ||
type: boolean | ||
default: false |
142 changes: 142 additions & 0 deletions
142
src/modules/course/task_module/px4_course_task_module.cpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,142 @@ | ||
#include <cstdio> | ||
|
||
#include "px4_course_task_module.h" | ||
#define MIN(X,Y) ((X) < (Y) ? (X) : (Y)) | ||
|
||
using namespace time_literals; | ||
|
||
int TaskModule::print_usage(const char *reason) | ||
{ | ||
printf("usage: task_module {start|stop|status}\n"); | ||
return 0; | ||
} | ||
|
||
int TaskModule::task_spawn(int argc, char *argv[]) | ||
{ | ||
_task_id = px4_task_spawn_cmd("module", | ||
SCHED_DEFAULT, | ||
SCHED_PRIORITY_DEFAULT, | ||
1024, | ||
(px4_main_t)&run_trampoline, | ||
(char *const *)argv); | ||
|
||
if (_task_id < 0) { | ||
_task_id = -1; | ||
return -errno; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
/* | ||
* We can use this function to implement custom commands for our module. | ||
* I.e. things other than the standard start/stop/status/print_usage. | ||
*/ | ||
int TaskModule::custom_command(int argc, char *argv[]) | ||
{ | ||
printf("User ran command \"%s\" with arguments \"", argv[0]); | ||
|
||
for (int i = 1; i < argc; ++i) { | ||
printf("%s ", argv[i]); | ||
} | ||
|
||
printf("\"\n"); | ||
return 1; | ||
} | ||
|
||
/* | ||
* This function is called from the new thread that is created for the module. | ||
* It should create an instance of the module and return it. | ||
* It can also parse the arguments passed to the module, and use them to configure the module. | ||
* You don't need to modify this function. | ||
*/ | ||
TaskModule *TaskModule::instantiate(int argc, char *argv[]) | ||
{ | ||
TaskModule *instance = new TaskModule(); | ||
|
||
if (instance == nullptr) { | ||
PX4_ERR("alloc failed"); | ||
} | ||
|
||
return instance; | ||
} | ||
|
||
/* | ||
* Constructor for the TaskModule class. | ||
*/ | ||
TaskModule::TaskModule() | ||
: ModuleParams(nullptr) | ||
{ | ||
} | ||
|
||
void TaskModule::greet(uint32_t num_greetings, bool long_greeting) | ||
{ | ||
constexpr const char *short_greeting_str = "Hi!"; | ||
constexpr const char *long_greeting_str = "Hello, PX4 course!"; | ||
|
||
for (uint32_t i = 0; i < num_greetings; i++) { | ||
printf("%s\n", long_greeting ? long_greeting_str : short_greeting_str); | ||
} | ||
} | ||
|
||
void TaskModule::sound_alert() | ||
{ | ||
tune_control_s tune{}; | ||
tune.tune_override = true; | ||
tune.timestamp = hrt_absolute_time(); | ||
tune.tune_id = 0; | ||
tune.frequency = 2000; | ||
tune.volume = 20; | ||
tune.duration = 150_ms; | ||
|
||
_tune_control_pub.publish(tune); | ||
|
||
} | ||
|
||
/* | ||
* The run function is called when the module is started. | ||
* This is where the main logic of the module should be. | ||
* Notice that the function should return when should_exit() returns true. | ||
*/ | ||
void TaskModule::run() | ||
{ | ||
// NB! Most time related functions in PX4 are in microseconds, not milliseconds! | ||
// By using time_literals we can convert to microseconds easily, like below. | ||
uint64_t greet_interval = 10_s; | ||
hrt_abstime last_greet{0}; | ||
|
||
while (!should_exit()) { | ||
// Check for parameter updates. Maybe the greet interval has changed. | ||
if (_parameter_update_sub.updated()) { | ||
// clear update so that updated() returns false next time | ||
parameter_update_s update; | ||
_parameter_update_sub.copy(&update); | ||
|
||
// Update parameters from storage | ||
// This is provided by the ModuleParams class we inherit from | ||
updateParams(); | ||
} | ||
|
||
auto time_since_last_greet = hrt_elapsed_time(&last_greet); | ||
|
||
if (time_since_last_greet >= greet_interval) { | ||
greet(_param_course_hi_num.get(), _param_course_hi_long.get()); | ||
last_greet = hrt_absolute_time(); | ||
} | ||
|
||
// TODO: Check for acceleration updates and sound alarm if | ||
// the acceleration is above a certain value | ||
|
||
// Sleep for 0.1 second or until the next greet time | ||
px4_usleep(MIN(100_ms, greet_interval - time_since_last_greet)); | ||
} | ||
|
||
} | ||
|
||
/* | ||
* You don't need to change this function, it just calls main in the class. | ||
*/ | ||
extern "C" __EXPORT int task_module_main(int argc, char *argv[]) | ||
{ | ||
return TaskModule::main(argc, argv); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
#pragma once | ||
|
||
#include <px4_platform_common/module.h> | ||
#include <px4_platform_common/module_params.h> | ||
#include <uORB/SubscriptionInterval.hpp> | ||
#include <uORB/Publication.hpp> | ||
#include <uORB/topics/parameter_update.h> | ||
#include <uORB/topics/vehicle_acceleration.h> | ||
#include <uORB/topics/tune_control.h> | ||
|
||
using namespace time_literals; | ||
extern "C" __EXPORT int task_module_main(int argc, char *argv[]); | ||
|
||
// Note that the TaskModule inherits from the ModuleBase, which gives us some useful features | ||
|
||
class TaskModule : public ModuleBase<TaskModule>, public ModuleParams | ||
{ | ||
public: | ||
TaskModule(); | ||
|
||
virtual ~TaskModule() = default; | ||
|
||
// All classes that inherit from ModuleBase and run in their own thread | ||
// must implement the funtions below. | ||
static int task_spawn(int argc, char *argv[]); | ||
static TaskModule *instantiate(int argc, char *argv[]); | ||
static int custom_command(int argc, char *argv[]); | ||
static int print_usage(const char *reason = nullptr); | ||
void run() override; | ||
|
||
private: | ||
void greet(uint32_t num_greetings, bool long_greeting); | ||
void sound_alert(); | ||
|
||
DEFINE_PARAMETERS( | ||
(ParamInt<px4::params::COURSE_HI_NUM>) _param_course_hi_num, | ||
(ParamBool<px4::params::COURSE_HI_LONG>) _param_course_hi_long | ||
) | ||
|
||
// Subscriptions | ||
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s}; | ||
uORB::SubscriptionInterval _vehicle_acceleration_sub{ORB_ID(vehicle_acceleration), 100_ms}; | ||
uORB::Publication<tune_control_s> _tune_control_pub{ORB_ID(tune_control)}; | ||
}; |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
Oops, something went wrong.