PX4编写自己的队列任务并执行

参考链接:PX4 User Guide - Development - Applicaiton/Module Template

一、基于话题订阅决定运行频率

  1. Firmware/src/modules 下新建文件夹 mc_self_check,并在里面添加 MulticopterSelfCheck.cppMulticopterSelfCheck.hppCMakeLists.txt 三个文件。
  2. 按照官方给的模板,也参考PX4源文件 Firmware/src/modules/mc_att_control 中的文件写法,三个文件内容分别如下

MulticopterSelfCheck.hpp

#pragma once

#include <drivers/drv_hrt.h>
#include <lib/perf/perf_counter.h>
#include <lib/systemlib/mavlink_log.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/defines.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <matrix/matrix/math.hpp>
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/manual_control_switches.h>
#include <uORB/topics/vehicle_local_position.h>
#include <uORB/topics/vehicle_attitude.h>

using namespace time_literals;

class MulticopterSelfCheck :
	public ModuleBase<MulticopterSelfCheck>,
	public ModuleParams,
	public px4::WorkItem
{
public:
	MulticopterSelfCheck();
	~MulticopterSelfCheck() override;

	bool init();
	static int task_spawn(int argc, char *argv[]);
	static int custom_command(int argc, char *argv[]);
	static int print_usage(const char *reason = nullptr);
private:
	hrt_abstime	_time_stamp_last_loop{0};

	void Run() override;
	perf_counter_t _loop_perf;
	uORB::SubscriptionCallbackWorkItem _local_pos_sub{this, ORB_ID(vehicle_local_position)};
	uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
	uORB::Subscription _manual_control_switches_sub{ORB_ID(manual_control_switches)};
};

MulticopterSelfCheck.cpp

#include "MulticopterSelfCheck.hpp"
#include <stdio.h>

MulticopterSelfCheck::MulticopterSelfCheck():
	ModuleParams(nullptr),
	WorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl),
	_loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle"))
{
}

MulticopterSelfCheck::~MulticopterSelfCheck()
{
	perf_free(_loop_perf);
}

bool MulticopterSelfCheck::init()
{
	if (!_local_pos_sub.registerCallback()) {
		PX4_ERR("vehicle_local_position callback registration failed!");
		return false;
	}
	return true;
}


void MulticopterSelfCheck::Run()
{
	if (should_exit()){
		_local_pos_sub.unregisterCallback();
		exit_and_cleanup();
		return;
	}

	perf_begin(_loop_perf);

	vehicle_local_position_s local_pos;
	if (_local_pos_sub.update(&local_pos)) {
		const hrt_abstime time_stamp_now = local_pos.timestamp;
		const float dt = math::constrain(((time_stamp_now - _time_stamp_last_loop) * 1e-6f), 0.002f, 0.04f);
		_time_stamp_last_loop = time_stamp_now;

		printf("dt = %f\r\n", (double)dt);
	}
	perf_end(_loop_perf);
}

int MulticopterSelfCheck::task_spawn(int argc, char *argv[])
{
	MulticopterSelfCheck *instance = new MulticopterSelfCheck();

	if (instance) {
		_object.store(instance);
		_task_id = task_id_is_work_queue;

		if (instance->init()) {
			return PX4_OK;
		}

	} else {
		PX4_ERR("alloc failed");
	}
	delete instance;
	_object.store(nullptr);
	_task_id = -1;

	return PX4_ERROR;
}

int MulticopterSelfCheck::custom_command(int argc, char *argv[])
{
	return print_usage("unknown command");
}

int MulticopterSelfCheck::print_usage(const char *reason)
{
	if (reason) {
		PX4_WARN("%s\n", reason);
	}

	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
### Description
Self check.
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("mc_self_check", "check");
	PRINT_MODULE_USAGE_COMMAND("start");
	PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
	return 0;
}

extern "C" __EXPORT int mc_self_check_main(int argc, char *argv[])
{
	return MulticopterSelfCheck::main(argc, argv);
}

CMakeLists.txt

px4_add_module(
	MODULE modules__mc_self_check
	MAIN mc_self_check
	COMPILE_FLAGS
		${MAX_CUSTOM_OPT_LEVEL}
	SRCS
		MulticopterSelfCheck.cpp
		MulticopterSelfCheck.hpp
	DEPENDS
		px4_work_queue
	)
  1. 添加编译指令
    Firmware/boards/px4/sitl/default.cmake 下的 px4_add_board 函数的 MODULES 后加上 mc_self_check

一些版本的PX4需要 Kconfig 文件,并且使用指令进行配置编译项。Kconfig例子如下

menuconfig MODULES_MC_SELF_CHECK
	bool "self_check"
	default n
	---help---
		Enable support for self_check

menuconfig USER_MC_SELF_CHECK
	bool "mc_self_check running as userspace module"
	default y
	depends on BOARD_PROTECTED && MODULES_MC_SELF_CHECK
	---help---
		Put self_check in userspace memory

指令为

make px4_sitl_default boardconfig

随后选择需要编译的文件。

  1. 添加启动命令
    Firmware/ROMFS/px4fmu_common/init.d/rc.mc_apps 最后加上 mc_self_check start

  2. 编译运行
    先清除编译,否则可能会报错。依次执行以下指令

make clean
make px4_sitl_default gazebo

最终可见如下输出

在这里插入图片描述
该输出是在 Multicopter.cpp/MulticopterSelfCheck::Run() 中编写的。

二、定时执行任务

如果要定时执行,修改代码如下

MulticopterSelfCheck.hpp

/**
 * Multicopter self-check.
 */

#pragma once

#include <drivers/drv_hrt.h>
#include <lib/perf/perf_counter.h>
#include <lib/systemlib/mavlink_log.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/defines.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/posix.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>

#include <matrix/matrix/math.hpp>
#include <uORB/Publication.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/manual_control_switches.h>
#include <uORB/topics/vehicle_local_position.h>
#include <uORB/topics/vehicle_attitude.h>

using namespace time_literals;

class MulticopterSelfCheck :
	public ModuleBase<MulticopterSelfCheck>,
	public ModuleParams,
	//public px4::WorkItem
	public px4::ScheduledWorkItem  // different
{
public:
	MulticopterSelfCheck();
	~MulticopterSelfCheck() override;

	bool init();
	static int task_spawn(int argc, char *argv[]);
	static int custom_command(int argc, char *argv[]);
	static int print_usage(const char *reason = nullptr);

private:
	hrt_abstime	_time_stamp_last_loop{0};

	void Run() override;
	perf_counter_t _loop_perf;

	uORB::SubscriptionCallbackWorkItem _local_pos_sub{this, ORB_ID(vehicle_local_position)};
	uORB::Subscription _vehicle_attitude_sub{ORB_ID(vehicle_attitude)};
	uORB::Subscription _manual_control_switches_sub{ORB_ID(manual_control_switches)};
};

MulticopterSelfCheck.cpp

#include "MulticopterSelfCheck.hpp"


MulticopterSelfCheck::MulticopterSelfCheck():
	ModuleParams(nullptr),
	//WorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl),
	ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::rate_ctrl), // different
	_loop_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": cycle"))
{

}

MulticopterSelfCheck::~MulticopterSelfCheck()
{
	perf_free(_loop_perf);
}


bool MulticopterSelfCheck::init()
{
	// if (!_local_pos_sub.registerCallback()) {
	// 	PX4_ERR("vehicle_local_position callback registration failed!");
	// 	return false;
	// }
	ScheduleOnInterval(50000_us); // different
	return true;
}


void MulticopterSelfCheck::Run()
{
	if (should_exit()){
		_local_pos_sub.unregisterCallback();
		exit_and_cleanup();
		return;
	}

	perf_begin(_loop_perf);

	const hrt_abstime time_stamp_now = hrt_absolute_time();
	const float dt = (time_stamp_now - _time_stamp_last_loop) * 1e-6f;
	_time_stamp_last_loop = time_stamp_now;

	printf("dt = %f\r\n", (double)dt);

	perf_end(_loop_perf);
}

int MulticopterSelfCheck::task_spawn(int argc, char *argv[])
{
	MulticopterSelfCheck *instance = new MulticopterSelfCheck();

	if (instance) {
		_object.store(instance);
		_task_id = task_id_is_work_queue;

		if (instance->init()) {
			return PX4_OK;
		}

	} else {
		PX4_ERR("alloc failed");
	}
	delete instance;
	_object.store(nullptr);
	_task_id = -1;

	return PX4_ERROR;
}

int MulticopterSelfCheck::custom_command(int argc, char *argv[])
{
	return print_usage("unknown command");
}

int MulticopterSelfCheck::print_usage(const char *reason)
{
	if (reason) {
		PX4_WARN("%s\n", reason);
	}

	PRINT_MODULE_DESCRIPTION(
		R"DESCR_STR(
### Description
Self check.
)DESCR_STR");

	PRINT_MODULE_USAGE_NAME("mc_self_check", "check");
	PRINT_MODULE_USAGE_COMMAND("start");
	PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
	return 0;
}

extern "C" __EXPORT int mc_self_check_main(int argc, char *argv[])
{
	return MulticopterSelfCheck::main(argc, argv);
}

init() 中决定运行频率,此时是50000us=50ms,运行结果如下

在这里插入图片描述
并不是精确度50ms=0.05s,这主要是由于该循环也有一定调用周期,好像是250Hz=4ms,因此很难刚好总在0.05s。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大强强小强强

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值