• PX4模块设计之二十八:RCInput模块


    1. RCInput模块简介

    RC遥控支持如下协议:

    1. PPM
    2. SBUS
    3. DSM
    4. SUMD
    5. ST24
    6. CRSF
    7. GHST
    ### Description
    This module does the RC input parsing and auto-selecting the method. Supported methods are:
    - PPM
    - SBUS
    - DSM
    - SUMD
    - ST24
    - TBS Crossfire (CRSF)
    
    rc_input  [arguments...]
     Commands:
       start       
         [-d ] /dev/ttyS3 "RC device"
    
       bind          Send a DSM bind command (module must be running)
    
       stop
    
       status        print status info
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    注:print_usage函数是具体对应实现。

    class RCInput : public ModuleBase, public ModuleParams, public px4::ScheduledWorkItem
    
    • 1

    注:RCInput模块采用了ModuleBaseWorkQueue设计。

    2. 模块入口函数

    2.1 主入口rc_input_main

    同样继承了ModuleBase,由ModuleBase的main来完成模块入口。

    rc_input_main
     └──> return RCInput::main(argc, argv)
    
    • 1
    • 2

    2.2 自定义子命令custom_command

    除start/stop/status命令,自定义命令支持bind,主要用于接收机与发射机的绑定。

    RCInput::custom_command
     ├──> 
     │   ├──> uORB::Publication vehicle_command_pub{ORB_ID(vehicle_command)}
     │   ├──> vehicle_command_s vcmd{}
     │   ├──> vcmd.command = vehicle_command_s::VEHICLE_CMD_START_RX_PAIR
     │   ├──> vcmd.timestamp = hrt_absolute_time()
     │   ├──> vehicle_command_pub.publish(vcmd)
     │   └──> return 0
     ├──> 
     │   ├──> int ret = RCInput::task_spawn(argc, argv)
     │   └──> 
     │       └──> return ret
     └──> return print_usage("unknown command")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    2.3 模块状态print_status【重载】

    这里重载了ModuleBase的print_status方法,将RCInput相关的状态信息进行输出。

    RCInput::print_status
     ├──> PX4_INFO("Max update rate: %u Hz", 1000000 / _current_update_interval)
     ├──> <_device[0] != '\0'>
     │   ├──> PX4_INFO("UART device: %s", _device)
     │   └──> PX4_INFO("UART RX bytes: %"  PRIu32, _bytes_rx)
     ├──> PX4_INFO("RC state: %s: %s", _rc_scan_locked ? "found" : "searching for signal", RC_SCAN_STRING[_rc_scan_state])
     ├──> <_rc_scan_locked>
     │   ├──> 
     │   │   └──> PX4_INFO("CRSF Telemetry: %s", _crsf_telemetry ? "yes" : "no")
     │   ├──> 
     │   │   └──> PX4_INFO("GHST Telemetry: %s", _ghst_telemetry ? "yes" : "no")
     │   ├──> 
     │   │   └──> PX4_INFO("SBUS frame drops: %u", sbus_dropped_frames())
     │   └──> 
     │       └──> [No Prints]
     ├──> <_analog_rc_rssi_stable>
     │   └──> PX4_INFO("vrssi: %dmV", (int)(_analog_rc_rssi_volt * 1000.0f))
     ├──> perf_print_counter(_cycle_perf)
     ├──> perf_print_counter(_publish_interval_perf)
     ├──> 
     │   └──> print_message(ORB_ID(input_rc), _rc_in)
     └──> return 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    3. RCInput模块重要函数

    3.1 task_spawn

    RCInput::task_spawn
     ├──> [解析RC通信设备,默认:RC_SERIAL_PORT] // KakuteF7 --> "/dev/ttyS4"
     ├──> 
     │   └──> return PX4_ERROR // device error
     ├──> RCInput *instance = new RCInput(device_name)
     ├──> 
     │   ├──> PX4_ERR("alloc failed")
     │   └──> return PX4_ERROR
     ├──> _object.store(instance)
     ├──> _task_id = task_id_is_work_queue
     ├──> instance->ScheduleOnInterval(_current_update_interval)  //250Hz
     └──> return PX4_OK
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    3.2 instantiate

    注:鉴于该模块不采用任务(线程),所以ModuleBase::run_trampoline无需执行,所以可以不实现。

    3.3 init

    注:鉴于涉及底层实现,从模块业务角度不再展开,后续有时间我们在深入讨论。

    3.4 Run

    RCInput::Run
     ├──> [优雅退出处理]
     ├──> [RC设备通信初始化]
     ├──> <_parameter_update_sub.updated()>
     │   ├──> parameter_update_s param_update;
     │   ├──> _parameter_update_sub.copy(¶m_update);
     │   └──> updateParams();
     ├──> <_vehicle_status_sub.updated()><_vehicle_status_sub.copy(&vehicle_status)>
     │   └──> _armed = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED)
     ├──> <_vehicle_cmd_sub.update(&vcmd)>
     │   ├──> uint8_t cmd_ret = vehicle_command_s::VEHICLE_CMD_RESULT_UNSUPPORTED
     │   ├──> 
     │   │   └──> [DSM bind RxTx]
     │   ├──> vehicle_command_ack_s command_ack{};
     │   ├──> command_ack.command = vcmd.command;
     │   ├──> command_ack.result = cmd_ret;
     │   ├──> command_ack.target_system = vcmd.source_system;
     │   ├──> command_ack.target_component = vcmd.source_component;
     │   ├──> command_ack.timestamp = hrt_absolute_time();
     │   ├──> uORB::Publication vehicle_command_ack_pub{ORB_ID(vehicle_command_ack)};
     │   └──> vehicle_command_ack_pub.publish(command_ack);
     ├──> 
     │   └──> [ADC RSSI 信号强度及状态更新]
     ├──> [500ms进行RC协议扫描,支持SBUS/DSM/ST24/SUMD/PPM/CRSF/GHST]
     ├──> [发布ORB_ID(input_rc)消息]
     └──> [超过3秒成功锁定协议,设置RC_INPUT_PROTO]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    4. 总结

    后续针对RC通信方面可以继续深入单总线串行口底层实现以及各协议格式的深入研究,入口如下:

    1. PPM解析函数 --> hrt_ppm_decode
    2. SBUS解析函数 --> sbus_parse
    3. DSM解析函数 --> dsm_parse
    4. SUMD解析函数 --> sumd_decode
    5. ST24解析函数 --> st24_decode
    6. CRSF解析函数 --> crsf_parse
    7. GHST解析函数 --> ghst_parse
    8. 单总线串口底层初始化 --> RCInput::init

    注:关于RC控制的检测/判断/决策等相关逻辑,请参阅PX4模块设计之二十九:RCUpdate模块

    5. 参考资料

    【1】PX4开源软件框架简明简介
    【2】PX4模块设计之十一:Built-In框架
    【3】PX4模块设计之十二:High Resolution Timer设计
    【4】PX4模块设计之十三:WorkQueue设计
    【5】PX4模块设计之十七:ModuleBase模块
    【6】PX4 modules_main
    【7】RC Protocols Explained: SBUS, CRSF, PWM, FPort and More

  • 相关阅读:
    【双指针】Leetcode 11. 盛最多水的容器
    Java 成员内部类
    JUC下的常用类
    mapreduce的流程
    C++Builder6.0 启动参数设置,不打开默认工程,不显示启动画面
    三维模型3DTILE格式轻量化压缩主要技术方法浅析
    UVa658 It’s not a Bug, it’s a Feature!(Dijkstra)
    python-Template字符串模板的使用
    Chrome浏览器调试页面详解 | 青训营笔记
    初识C语言—常见关键字
  • 原文地址:https://blog.csdn.net/lida2003/article/details/126647143