PX4源码分析16:mc_att_control模块讲解,未完待续...

打开mc_att_control.h文件,我们可以看到主要由两个模块组成,一个是声明全局函数,另一个是声明一个类,如下所示:

extern "C" __EXPORT int mc_att_control_main(int argc, char *argv[]);
class MulticopterAttitudeControl : --- { --- };

声明全局函数的目的是告诉编译器,此处为mc_att_control模块的入口;
声明类的目的是为上述的全局函数提供服务。
我们跳到入口函数的实现部分,可以看到里面只有一行代码,即调用main()函数并返回“返回值”。

int mc_att_control_main(int argc, char *argv[])
{
	return MulticopterAttitudeControl::main(argc, argv);
}

实际上MulticopterAttitudeControl这个类中并没有定义main()函数,但是它继承了基类ModuleBase,这个基类中定义了main()函数。

class MulticopterAttitudeControl : 	
			public ModuleBase<MulticopterAttitudeControl>, 
			public ModuleParams,
			public px4::WorkItem
	{---};

紧接着我们跳到基类ModuleBase的main()函数实现部分,我们重点来看if (strcmp(argv[1], “start”) == 0)这部分,如果strcmp(argv[1], “start”) == 0,则说明传入的命令为start,执行start_command_base(argc - 1, argv + 1)函数,传入的命令数量减一,传入的命令指针加一。

static int main(int argc, char *argv[])
	{
		if (argc <= 1 ||
		    strcmp(argv[1], "-h")    == 0 ||
		    strcmp(argv[1], "help")  == 0 ||
		    strcmp(argv[1], "info")  == 0 ||//这5种可能都说明在寻求帮助,那就打印帮助信息
		    strcmp(argv[1], "usage") == 0) {
			return T::print_usage();
		}
		if (strcmp(argv[1], "start") == 0) {
			// Pass the 'start' argument too, because later on px4_getopt() will ignore the first argument.
			return start_command_base(argc - 1, argv + 1);
		}
		if (strcmp(argv[1], "status") == 0) {
			return status_command();
		}
		if (strcmp(argv[1], "stop") == 0) {
			return stop_command();
		}
		lock_module(); // Lock here, as the method could access _object.
		int ret = T::custom_command(argc - 1, argv + 1);
		unlock_module();
		return ret;
	}

如果我们是第一次执行start命令,在下面的start_command_base()函数中,我们调用T::task_spawn(argc, argv)函数,其中的T是参数,此时T代表的是MulticopterAttitudeControl,即调用MulticopterAttitudeControl::task_spawn(argc, argv)。

static int start_command_base(int argc, char *argv[])
{
	int ret = 0;
	lock_module();
	if (is_running()) {
		ret = -1;
		PX4_ERR("Task already running");
	} else {
		ret = T::task_spawn(argc, argv);//系统第一次启动这个进程
		if (ret < 0) {
			PX4_ERR("Task start failed (%i)", ret);
		}
	}
	unlock_module();
	return ret;
}

在如下的task_spawn()函数中,我们的主要做三件事,一个是实例化一个类的对象,二是将这个模块给这对象初始化。要注意的是,实例化类的对象用了new关键字,说明是在堆区创建的实例,instance是类的指针,如果在堆区成功创建了MulticopterAttitudeControl类,则将类的地址储存在指针变量instance中,要明白,所谓的栈,堆只是人为划分并定义的一段内存而已,他们在物理层其实是一样的,比如在芯片中,栈、堆都只是ram中的某一个片段而已,在电脑硬件系统中,栈、堆都也只是内存条中的某一个片段而已,实际上内存条就是ram,我们常说的显卡中的显存也是ram。我们之所以将内存分区,是为了高效管理使用,实际的分区操作过程是操作系统完成的。

int MulticopterAttitudeControl::task_spawn(int argc, char *argv[])
{
	bool vtol = false;
	if (argc > 1) {
		if (strcmp(argv[1], "vtol") == 0) {
			vtol = true;
		}
	}
	MulticopterAttitudeControl *instance = new MulticopterAttitudeControl(vtol);
	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;
}
  • 4
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值