【移植Ardupilot的日志记录方法到linux上】

说明

采用二进制文件记录,可在mission planer查看

  1. 支持所有数据类型记录
  2. 精巧移植方便
  3. 可直接在地面站绘制曲线查看
  4. 可导出生成mat文件在matlab上分析
    提供的日志目标结构
    在这里插入图片描述

日志结构组成

  1. 日志头
  2. 日志消息类型
  3. 消息长度
  4. 日志消息名称
  5. 数据类型标识
  6. 数据标签
  7. 数据单位
  8. 数据格式
    数据结构体定义:
// 用于定义日志记录格式的结构
struct LogStructure {
    uint8_t msg_type;
    uint8_t msg_len;
    const char *name;
    const char *format;
    const char *labels;
    const char *units;
    const char *multipliers;
};

日志写入操作

预定义日志项

该日志项为预先设定好,使用时无需在进行日志名称定义。
预先设置的日志项如下:

// 日志头声明处理
const struct LogStructure log_structure[] = {

  { LOG_FORMAT_MSG, sizeof(log_Format), \
      "FMT", "BBnNZ",      "Type,Length,Name,Format,Columns", "-b---", "-----" },
  { LOG_FORMAT_UNITS_MSG, sizeof(log_Format_Units), \
      "FMTU", "QBNN",      "TimeUS,FmtType,UnitIds,MultIds","s---", "F---" },
  {
    LOG_TEST_MSG, sizeof(struct log_TEST),
    "TEST", "QH",         "TimeUS,value","S-","F-"
  },
  { LOG_MESSAGE_MSG, sizeof(log_Message), \
    "MSG",  "QZ",     "TimeUS,Message", "s-", "F-"}, 
};

其中,LOG_FORMAT_MSG与LOG_FORMAT_UNITS_MSG是必须的,这个是地面站能够正常解析日志的关键,其他为用户自定义。
预先设置的日志写入函数:

// 预先定义类型的日志记录测试函数实体
void Write_Test(uint64_t time_us, uint16_t value)
{
  struct log_TEST pkt = {
    LOG_PACKET_HEADER_INIT(LOG_TEST_MSG),
    .time_us = time_us,
    .value   = value,
  };
  WriteBlock(&pkt, sizeof(pkt));
}

uint64_t micros64()
{
    uint64_t sys_time;
    //在此处赋值系统时间戳
    //sys_time = ;
    return sys_time;
}
// 在日志中写入文本消息的函数实体
bool Write_Message(const char *message)
{
    struct log_Message pkt{
        LOG_PACKET_HEADER_INIT(LOG_MESSAGE_MSG),
        time_us : micros64(),
        msg  : {}
    };
    strncpy(pkt.msg, message, sizeof(pkt.msg));
    return WriteBlock(&pkt, sizeof(pkt));
}

运行时添加日志项的方法

很多时候想临时添加一组日志来对某些状态进行记录分析,直接进行日志结构体构造会省很多事,所以专门提供了一个进行此操作的接口。

/* Write support */
void Write_Log(const char *name, const char *labels, const char *units, const char *mults, const char *fmt, ...)
{
    va_list arg_list;

    va_start(arg_list, fmt);
    WriteV(name, labels, units, mults, fmt, arg_list);
    va_end(arg_list);
}

单例测试

主函数代码:
主要实现了日志初始化,对预先设定的日志项进行一百次的写入,之后对文本消息进行写入操作。

int main()
{
    //初始化日志
    Log_Init();

    //循环写入100次各项日志
    for(uint16_t i=0; i<100; i++){
        Write_Test(i,i);                //预先写好的日志实体测试
        Write_Log("WTS","T1,T2,T3",     //运行时添加的任意日志
            "s--","F--","HHH",
            i,i,i);

        Write_Log_test();               //写入不同数据类型的数据
    }

    //以下为消息日志记录,每次写入的字符串不能大于64字节
    Write_Message("This logging method is applicable to Linux systems");
    Write_Message("In the case of MCU system with SD card,");
    Write_Message("it is also necessary to adjust the write function");
    Write_Message("Take a closer look at the WriteBlock function");
    
    return 0;
}

编译方法

  1. 进入logts目标,创建build文件夹
mkdir build
  1. 进入build目录
cd build
  1. 运行cmake
cmake ..
  1. 编译源码
make

在这里插入图片描述
运行demo

./log

可看到在build目录下生成了log1.bin文件,该文件即为我们需要的日志文件,此时可使用地面站打开次文件查看相关内容
在这里插入图片描述

查看数据

  1. 查看常规数据
    打开mission planner地面站,选择回顾日志,打开log1.bin,选择对应的日志项勾选对应的标签即可查看数据。
    在这里插入图片描述
  2. 查看文本消息日志
    勾选Data Table,再对消息进行滤波,选择MSG日志项。
    在这里插入图片描述
    在这里插入图片描述
    文件日志也可以在该界面上右键导出csv文件。
  3. 导出成matlab文件可使用地面站的创建matlab文件 功能

其他

  1. 将本例程放入到实际系统去时还需要考虑每次开始记录时按照递进的方式对文件名曾1,否则会直接在文件尾继续写入新数据。
  2. 若在MCU上使用,则需要另外封装读写函数,主要是WriteBlock函数

资料下载链接:
https://download.csdn.net/download/qq_39016531/87720027

<think>嗯,用户想了解如何将APM的AP_Scheduler迁移到其他环境或系统。我需要先理解AP_Scheduler是什么,它属于哪个项目,有什么依赖。APM指的是ArduPilot Mega,一个开源自动驾驶系统,AP_Scheduler是其任务调度器,负责管理各个任务的执行频率和顺序。 首先,迁移需要考虑目标环境的硬件和操作系统是否支持。AP_Scheduler可能在特定硬件架构或实时操作系统上运行,比如Linux或ChibiOS。需要检查目标系统的兼容性,比如处理器架构、时钟源、中断处理等。 然后,代码依赖的部分需要处理。AP_Scheduler可能依赖其他APM模块,比如AP_HAL(硬件抽象层)、定时器模块等。移植时需要确保这些依赖库在目标环境中可用,或者进行相应的适配。比如,如果目标系统使用不同的硬件抽象层,可能需要修改HAL接口的实现。 接下来,任务调度逻辑和配置参数可能需要调整。不同的系统资源(如内存、处理能力)会影响调度器的配置,比如任务堆栈大小、优先级设置。还要验证定时器中断和任务切换机制是否在目标环境中正常工作,确保调度精度。 编译工具链也是一个关键点。原有的编译环境可能基于特定的交叉编译器或构建系统,迁移到新环境可能需要调整Makefile或构建脚本,确保所有依赖项正确链接,并且没有平台相关的编译选项问题。 测试阶段需要逐步验证,从基础功能开始,比如调度器初始化、单个任务运行,再逐步增加任务负载,检查系统稳定性和实时性是否符合预期。同时,利用日志和调试工具排查问题,比如任务死锁或优先级反转。 另外,用户提供的引用内容似乎和问题关联不大,但需要注意是否有权限控制或初始化相关的配置,比如引用[1]提到的GID映射,可能在系统权限设置中有影响;引用[2]的ACL权限控制可能涉及任务调度的安全机制;引用[3]的架构分离提示可能需要考虑前后台系统的交互。不过这些引用可能更多是示例,需要具体看AP_Scheduler的文档是否有相关部分。 最后,生成相关问题时,要考虑用户可能遇到的后续疑问,比如依赖处理、硬件适配、调试方法等,确保覆盖迁移过程中的常见挑战。</think>### APM AP_Scheduler 迁移指南 AP_Scheduler是ArduPilot飞行控制框架中的任务调度模块,负责周期任务的时序管理[^1]。其迁移需要以下关键步骤: #### 一、环境适配 1. **硬件抽象层(HAL)适配** - 需实现目标平台的`AP_HAL`接口,包括定时器、中断控制器等硬件驱动 - 示例时钟源适配: ```cpp // 目标系统定时器实现示例 class LinuxTimer : public AP_HAL::Timer { uint64_t micros() override { return system_clock_now() * 1000; // 转换为微秒 } }; ``` 2. **依赖组件移植** - 必须同步迁移依赖模块:`AP_Param`(参数系统)、`AP_Math`(数学库)等 - 验证内存映射一致性,特别是`AP_Param`的EEPROM模拟实现 #### 二、调度配置调整 $$ 任务周期公式:T_{n} = \frac{1}{f_{max}} \times 2^{n-1} $$ 其中$f_{max}$为基准频率,$n$为任务优先级等级 需根据目标处理器性能调整: - 修改`AP_Scheduler.cpp`中的`_loop_rate_hz`基准频率 - 调整`scheduler_tasks[]`数组中的任务时间预算(单位微秒) #### 三、编译系统改造 1. 创建新平台的`wscript`构建配置文件 2. 示例编译配置片段: ```python variant_env = Environment( CCFLAGS = '-mcpu=cortex-a53 -O2', LIBPATH = ['/custom_hal/lib'] ) variant_env.Program(target='ap_scheduler', source=['main.cpp']) ``` #### 四、验证测试 1. 使用逻辑分析仪验证任务时序 2. 压力测试建议参数: ```markdown | 任务数 | CPU负载阈值 | 抖动容限 | |--------|-------------|----------| | ≤8 | 70% | ±50μs | | 9-15 | 85% | ±100μs | ``` #### 五、已知兼容问题 - STM32H7系列需关闭ICache避免时序抖动[^2] - Linux系统需要配置`CONFIG_PREEMPT_RT`实时补丁 ```mermaid graph TD A[原系统] -->|导出配置| B(参数迁移) B --> C{硬件差异分析} C -->|相同架构| D[直接移植] C -->|不同架构| E[重写HAL层] E --> F[性能调优] D --> F F --> G[回归测试] ```
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值