APM和PX4之间的联系
位置:X:\ardupilot\libraries\AP_HAL_PX4\HAL_PX4_Class.cpp
const AP_HAL::HAL& AP_HAL::get_HAL() {
static const HAL_PX4 hal_px4;
return hal_px4;
}
下面是进程启动时,运行的代码:
void HAL_PX4::run(int argc, char * const argv[], Callbacks* callbacks) const
{
int i;
const char *deviceA = UARTA_DEFAULT_DEVICE;
const char *deviceC = UARTC_DEFAULT_DEVICE;
const char *deviceD = UARTD_DEFAULT_DEVICE;
const char *deviceE = UARTE_DEFAULT_DEVICE;
const char *deviceF = UARTF_DEFAULT_DEVICE;
if (argc < 1) {
printf("%s: missing command (try '%s start')",
SKETCHNAME, SKETCHNAME);
usage();
exit(1);
}
assert(callbacks);
g_callbacks = callbacks;//传入参数
for (i=0; i i + 1) {
deviceA = strdup(argv[i+1]);
} else {
printf("missing parameter to -d DEVICE\n");
usage();
exit(1);
}
}
if (strcmp(argv[i], "-d2") == 0) {
// set uartC terminal device
if (argc > i + 1) {
deviceC = strdup(argv[i+1]);
} else {
printf("missing parameter to -d2 DEVICE\n");
usage();
exit(1);
}
}
if (strcmp(argv[i], "-d3") == 0) {
// set uartD terminal device
if (argc > i + 1) {
deviceD = strdup(argv[i+1]);
} else {
printf("missing parameter to -d3 DEVICE\n");
usage();
exit(1);
}
}
if (strcmp(argv[i], "-d4") == 0) {
// set uartE 2nd GPS device
if (argc > i + 1) {
deviceE = strdup(argv[i+1]);
} else {
printf("missing parameter to -d4 DEVICE\n");
usage();
exit(1);
}
}
if (strcmp(argv[i], "-d5") == 0) {
// set uartF
if (argc > i + 1) {
deviceF = strdup(argv[i+1]);
} else {
printf("missing parameter to -d5 DEVICE\n");
usage();
exit(1);
}
}
}
usage();
exit(1);
}
在NUTTX系统启动之后,通过脚本传递相关参数,并创建任务。下面是启动方法:
static void usage(void)
{
printf("Usage: %s [options] {start,stop,status}\n", SKETCHNAME);
printf("Options:\n");
printf("\t-d DEVICE set terminal device (default %s)\n", UARTA_DEFAULT_DEVICE);
printf("\t-d2 DEVICE set second terminal device (default %s)\n", UARTC_DEFAULT_DEVICE);
printf("\t-d3 DEVICE set 3rd terminal device (default %s)\n", UARTD_DEFAULT_DEVICE);
printf("\t-d4 DEVICE set 2nd GPS device (default %s)\n", UARTE_DEFAULT_DEVICE);
printf("\t-d5 DEVICE set uartF (default %s)\n", UARTF_DEFAULT_DEVICE);
printf("\n");
}
HAL_PX4::run创建任务“main_loop ”,这里面调用的APM中的"set"和"loop"
static int main_loop(int argc, char **argv)
{
hal.uartA->begin(115200);
hal.uartB->begin(38400);
hal.uartC->begin(57600);
hal.uartD->begin(57600);
hal.uartE->begin(57600);
hal.scheduler->init();
// init the I2C wrapper class
PX4_I2C::init_lock();
/*
run setup() at low priority to ensure CLI doesn't hang the
system, and to allow initial sensor read loops to run
*/
hal_px4_set_priority(APM_STARTUP_PRIORITY);//58
schedulerInstance.hal_initialized();
g_callbacks->setup();//调用APM的ArduCopter.cpp的setup
hal.scheduler->system_initialized();
perf_counter_t perf_loop = perf_alloc(PC_ELAPSED, "APM_loop");//measure the time elapsed performing an event(测量执行一个事件的时间)
perf_counter_t perf_overrun = perf_alloc(PC_COUNT, "APM_overrun");//count the number of times an event occurs(计算事件发生的次数)
struct hrt_call loop_overtime_call;
thread_running = true;//线程正式开始运行
/*
switch to high priority for main loop
*/
hal_px4_set_priority(APM_MAIN_PRIORITY);
while (!_px4_thread_should_exit) {
perf_begin(perf_loop);
/*
this ensures a tight loop waiting on a lower priority driver
will eventually give up some time for the driver to run. It
will only ever be called if a loop() call runs for more than
0.1 second
*/
hrt_call_after(&loop_overtime_call, 100000, (hrt_callout)loop_overtime, nullptr);
g_callbacks->loop();//调用APM的ArduCopter.cpp的loop
if (px4_ran_overtime) {
/*
we ran over 1s in loop(), and our priority was lowered
to let a driver run. Set it back to high priority now.
*/
hal_px4_set_priority(APM_MAIN_PRIORITY);//180
perf_count(perf_overrun);//count the number of times an event occurs(计算事件发生的次数)
px4_ran_overtime = false;//设置为false,恢复高优先级
}
perf_end(perf_loop);
/*
give up 250 microseconds of time, to ensure drivers get a
chance to run. This relies on the accurate semaphore wait
using hrt in semaphore.cpp
*/
hal.scheduler->delay_microseconds(250);//250us
}
thread_running = false;//线程结束
return 0;
}
上面的代码调用了下面的函数,该程序将主程序的优先级设置低,让APM中的其他任务运行。
注意:这里的主程序的优先级会被周期性的修改。
/*
this is called when loop() takes more than 1 second to run. If that
happens then something is blocking for a long time in the main
sketch - probably waiting on a low priority driver. Set the priority
of the APM task low to let the driver run.
*/
static void loop_overtime(void *)
{
hal_px4_set_priority(APM_OVERTIME_PRIORITY);//10
px4_ran_overtime = true;//设置为true,设置为低优先级
}
APM的代码
位置:X:\ardupilot\ArduCopter\ArduCopter.cpp,该文件的最后一行为
AP_HAL_MAIN_CALLBACKS(&copter);
该行只是一个简单的宏定义
位置:X:\ardupilot\libraries\AP_HAL\AP_HAL_Main.h
#pragma once
#include "HAL.h"
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4 || CONFIG_HAL_BOARD == HAL_BOARD_VRBRAIN
#define AP_MAIN __EXPORT ArduPilot_main
#endif
#ifndef AP_MAIN
#define AP_MAIN main
#endif
#define AP_HAL_MAIN() \
AP_HAL::HAL::FunCallbacks callbacks(setup, loop); \
extern "C" { \
int AP_MAIN(int argc, char* const argv[]); \
int AP_MAIN(int argc, char* const argv[]) { \
hal.run(argc, argv, &callbacks); \
return 0; \
} \
}
#define AP_HAL_MAIN_CALLBACKS(CALLBACKS) extern "C" { \
int AP_MAIN(int argc, char* const argv[]); \
int AP_MAIN(int argc, char* const argv[]) { \
hal.run(argc, argv, CALLBACKS); \
return 0; \
} \
}
我的个人理解是将代码以C的方式编译,并直接调用"hal.run(argc, argv, CALLBACKS)"
对象"hal"和传参"CALLBACKS",都在下面这个文件中
位置: X:\ardupilot\ArduCopter\Copter.cpp
#include "Copter.h"
#define FORCE_VERSION_H_INCLUDE
#include "version.h"
#undef FORCE_VERSION_H_INCLUDE
const AP_HAL::HAL& hal = AP_HAL::get_HAL();
/*
constructor for main Copter class
*/
Copter::Copter(void)
: DataFlash(fwver.fw_string, g.log_bitmask),
flight_modes(&g.flight_mode1),
control_mode(STABILIZE),
scaleLongDown(1),
simple_cos_yaw(1.0f),
simple_sin_yaw(0.0f),
super_simple_last_bearing(0),
super_simple_cos_yaw(1.0),
super_simple_sin_yaw(0.0f),
initial_armed_bearing(0),
climb_rate(0),
target_rangefinder_alt(0.0f),
baro_alt(0),
baro_climbrate(0.0f),
land_accel_ef_filter(LAND_DETECTOR_ACCEL_LPF_CUTOFF),
rc_throttle_control_in_filter(1.0f),
auto_yaw_mode(AUTO_YAW_LOOK_AT_NEXT_WP),
yaw_look_at_WP_bearing(0.0f),
yaw_look_at_heading(0),
yaw_look_at_heading_slew(0),
yaw_look_ahead_bearing(0.0f),
inertial_nav(ahrs),
pmTest1(0),
fast_loopTimer(0),
mainLoop_count(0),
auto_trim_counter(0),
in_mavlink_delay(false),
param_loader(var_info),
flightmode(&mode_stabilize)
{
memset(¤t_loc, 0, sizeof(current_loc));
// init sensor error logging flags
sensor_health.baro = true;
sensor_health.compass = true;
}
Copter copter;
这个文件中的"AP_HAL::get_HAL()",在HAL_PX4_Class.cpp文件的最下面有定义。
其中用到的类HAL_PX4,定义在下面的文件中。这个类中刚好有且只有一个"run"方法。
位置:X:\ardupilot\libraries\AP_HAL_PX4\HAL_PX4_Class.h
#pragma once
#include
#if CONFIG_HAL_BOARD == HAL_BOARD_PX4
#include "AP_HAL_PX4.h"
#include "AP_HAL_PX4_Namespace.h"
#include
#include
class HAL_PX4 : public AP_HAL::HAL {
public:
HAL_PX4();
void run(int argc, char* const argv[], Callbacks* callbacks) const override;
};
void hal_px4_set_priority(uint8_t priority);
#endif // CONFIG_HAL_BOARD == HAL_BOARD_PX4
文件中的AP_HAL::HAL,在下面的位置定义
位置:X:\ardupilot\libraries\AP_HAL\HAL.h
#pragma once
class AP_Param;
#include "AP_HAL_Namespace.h"
#include "AnalogIn.h"
#include "GPIO.h"
#include "RCInput.h"
#include "RCOutput.h"
#include "SPIDevice.h"
#include "Storage.h"
#include "UARTDriver.h"
#include "system.h"
#include "OpticalFlow.h"
#if HAL_WITH_UAVCAN
#include "CAN.h"
#endif
#if defined(HAL_NEEDS_PARAM_HELPER)
#include
class AP_Param_Helper;
#endif
class AP_HAL::HAL {
public:
HAL(AP_HAL::UARTDriver* _uartA, // console
AP_HAL::UARTDriver* _uartB, // 1st GPS
AP_HAL::UARTDriver* _uartC, // telem1
AP_HAL::UARTDriver* _uartD, // telem2
AP_HAL::UARTDriver* _uartE, // 2nd GPS
AP_HAL::UARTDriver* _uartF, // extra1
AP_HAL::I2CDeviceManager* _i2c_mgr,
AP_HAL::SPIDeviceManager* _spi,
AP_HAL::AnalogIn* _analogin,
AP_HAL::Storage* _storage,
AP_HAL::UARTDriver* _console,
AP_HAL::GPIO* _gpio,
AP_HAL::RCInput* _rcin,
AP_HAL::RCOutput* _rcout,
AP_HAL::Scheduler* _scheduler,
AP_HAL::Util* _util,
AP_HAL::OpticalFlow *_opticalflow,
#if HAL_WITH_UAVCAN
AP_HAL::CANManager* _can_mgr[MAX_NUMBER_OF_CAN_DRIVERS])
#else
AP_HAL::CANManager** _can_mgr)
#endif
:
uartA(_uartA),
uartB(_uartB),
uartC(_uartC),
uartD(_uartD),
uartE(_uartE),
uartF(_uartF),
i2c_mgr(_i2c_mgr),
spi(_spi),
analogin(_analogin),
storage(_storage),
console(_console),
gpio(_gpio),
rcin(_rcin),
rcout(_rcout),
scheduler(_scheduler),
util(_util),
opticalflow(_opticalflow)
{
#if HAL_WITH_UAVCAN
if (_can_mgr == nullptr) {
for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++)
can_mgr[i] = nullptr;
} else {
for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++)
can_mgr[i] = _can_mgr[i];
}
#endif
AP_HAL::init();
}
struct Callbacks {
/* 纯虚函数,该类也就是一个抽象类,不能用来实例化对象的,只能用来作基类*/
virtual void setup() = 0;
virtual void loop() = 0;
};
struct FunCallbacks : public Callbacks {
FunCallbacks(void (*setup_fun)(void), void (*loop_fun)(void));
void setup() override { _setup(); }
void loop() override { _loop(); }
private:
void (*_setup)(void);
void (*_loop)(void);
};
virtual void run(int argc, char * const argv[], Callbacks* callbacks) const = 0;
AP_HAL::UARTDriver* uartA;
AP_HAL::UARTDriver* uartB;
AP_HAL::UARTDriver* uartC;
AP_HAL::UARTDriver* uartD;
AP_HAL::UARTDriver* uartE;
AP_HAL::UARTDriver* uartF;
AP_HAL::I2CDeviceManager* i2c_mgr;
AP_HAL::SPIDeviceManager* spi;
AP_HAL::AnalogIn* analogin;
AP_HAL::Storage* storage;
AP_HAL::UARTDriver* console;
AP_HAL::GPIO* gpio;
AP_HAL::RCInput* rcin;
AP_HAL::RCOutput* rcout;//输出到电机的
AP_HAL::Scheduler* scheduler;
AP_HAL::Util *util;
AP_HAL::OpticalFlow *opticalflow;
#if HAL_WITH_UAVCAN
AP_HAL::CANManager* can_mgr[MAX_NUMBER_OF_CAN_DRIVERS];
#else
AP_HAL::CANManager** can_mgr;
#endif
};
文件中的AP_HAL是一个命名空间
位置:X:\ardupilot\libraries\AP_HAL\AP_HAL_Namespace.h
#pragma once
#include "string.h"
#include "utility/functor.h"
namespace AP_HAL {
/* Toplevel pure virtual class Hal.*/
class HAL;
/* Toplevel class names for drivers: */
class UARTDriver;
class I2CDevice;
class I2CDeviceManager;
class Device;
class SPIDevice;
class SPIDeviceDriver;
class SPIDeviceManager;
class AnalogSource;
class AnalogIn;
class Storage;
class DigitalSource;
class GPIO;
class RCInput;
class RCOutput;
class Scheduler;
class Semaphore;
class OpticalFlow;
class CANManager;
class CAN;
class Util;
/* Utility Classes */
class Print;
class Stream;
class BetterStream;
/* Typdefs for function pointers (Procedure, Member Procedure)
For member functions we use the FastDelegate delegates class
which allows us to encapculate a member function as a type
*/
typedef void(*Proc)(void);
FUNCTOR_TYPEDEF(MemberProc, void);
/**
* Global names for all of the existing SPI devices on all platforms.
*/
enum SPIDeviceType {
// Devices using AP_HAL::SPIDevice abstraction
SPIDevice_Type = -1,
};
// Must be implemented by the concrete HALs.
const HAL& get_HAL();
}
无论如何,请相信自己
请继续期待。。。。。