APM-3.5.2 UAVCAN筆記

20180402:
    UAVCAN使用的主要邏輯代碼,在AP_UAVCAN.cpp文件中,AP_UAVCAN類的任務是在硬件配置支持的情況下使用UAVCAN協議,進行數據的收發。UAVCAN協議的收發邏輯代碼太過於複雜,看了幾天仍然雲裏霧裏,所以我決定轉換思路,不再過深的去了解協議的收發邏輯代碼,轉而去了解需要經過哪些步驟,使用哪些UAVCAN協議提供的API,可以完成收發任務。
    接下來以GPS數據爲例,來梳理使用UAVCAN協議完成數據收發的過程:
    飛控要通過UAVCAN使用GPS信息,需要添加使用UAVCAN協議中GPS數據的類,APM中此類在AP_GPS_UAVCAN.cpp和AP_GPS_UAVCAN.h中。AP_UAVCAN類讀到UAVCAN協議的GPS信息後,存儲在_gps_node_state[AP_UAVCAN_MAX_GPS_NODES]結構體數組中,通過update_gps_state函數,將GPS信息傳遞給AP_GPS_UAVCAN類。
    AP_UAVCAN構造函數:
    _gps_nodes[AP_UAVCAN_MAX_GPS_NODES]:存放着發送GPS信息的節點(下文簡稱爲GPS信息源)ID
    _gps_node_taken[AP_UAVCAN_MAX_GPS_NODES]
    _gps_listener_to_node[AP_UAVCAN_MAX_LISTENERS]
    _gps_listeners[AP_UAVCAN_MAX_LISTENERS]
    注:宏定義見附錄。

AP_UAVCAN::AP_UAVCAN() :
    _node_allocator(
        UAVCAN_NODE_POOL_SIZE, UAVCAN_NODE_POOL_SIZE)
{
    AP_Param::setup_object_defaults(this, var_info);


    for (uint8_t i = 0; i < UAVCAN_RCO_NUMBER; i++) {
        _rco_conf[i].active = false;
    }


    for (uint8_t i = 0; i < AP_UAVCAN_MAX_GPS_NODES; i++) {
        _gps_nodes[i] = UINT8_MAX;
        _gps_node_taken[i] = 0;
    }


    for (uint8_t i = 0; i < AP_UAVCAN_MAX_BARO_NODES; i++) {
        _baro_nodes[i] = UINT8_MAX;
        _baro_node_taken[i] = 0;
    }


    for (uint8_t i = 0; i < AP_UAVCAN_MAX_MAG_NODES; i++) {
        _mag_nodes[i] = UINT8_MAX;
        _mag_node_taken[i] = 0;
    }


    for (uint8_t i = 0; i < AP_UAVCAN_MAX_LISTENERS; i++) {
        _gps_listener_to_node[i] = UINT8_MAX;
        _gps_listeners[i] = nullptr;


        _baro_listener_to_node[i] = UINT8_MAX;
        _baro_listeners[i] = nullptr;


        _mag_listener_to_node[i] = UINT8_MAX;
        _mag_listeners[i] = nullptr;
    }


    _rc_out_sem = hal.util->new_semaphore();


    debug_uavcan(2, "AP_UAVCAN constructed\n\r");
}

    這些變量在構造函數中賦值爲空或空閒,_gps_nodes[]在AP_UAVCAN.cpp的gnss_fix_cb函數中被調用的find_gps_node函數賦值。

AP_GPS::GPS_State *AP_UAVCAN::find_gps_node(uint8_t node)
{
    // Check if such node is already defined
    for (uint8_t i = 0; i < AP_UAVCAN_MAX_GPS_NODES; i++) {
        if (_gps_nodes[i] == node) {
            return &_gps_node_state[i];
        }
    }


    // If not - try to find free space for it
    for (uint8_t i = 0; i < AP_UAVCAN_MAX_GPS_NODES; i++) {
        if (_gps_nodes[i] == UINT8_MAX) {
            _gps_nodes[i] = node;
            return &_gps_node_state[i];
        }
    }


    // If no space is left - return nullptr
    return nullptr;
}

    find_gps_node函數完成兩個功能,一、如果_gps_node[]中有存放GPS信息源的節點ID,則返回,與節點ID對應的_gps_node_state[]的指針。二、如果_gps_node中並沒有存放GPS信息源的節點ID,則遍歷_gps_node[]中處於空閒的成員,將GPS信息源的節點ID賦值給找到的第一個空閒的_gps_node[]。並返回與之對應的_gps_node_state[]指針。_gps_node[]與_gps_node_state[]是一一對應的。但_gps_node[]存放着哪個GPS信息源是不固定的,是程序運行時確定的,相應的_gps_node_state[]存放這那個GPS信息源的GPS數據也是不固定的,是程序運行時確定的。


    _gps_node_taken[]、_gps_listener_to_node[]、_gps_listeners[]這些變量在AP_GPS.cpp的detect_instance函數中被調用的AP_UAVCAN中的函數賦有含義的值。

#if HAL_WITH_UAVCAN
    // user has to explicitly set the UAVCAN type, do not use AUTO
    case GPS_TYPE_UAVCAN:
        dstate->auto_detected_baud = false; // specified, not detected
        if (AP_BoardConfig_CAN::get_can_num_ifaces() >= 1) {
            for (uint8_t i = 0; i < MAX_NUMBER_OF_CAN_DRIVERS; i++) {
                if (hal.can_mgr[i] != nullptr) {
                    AP_UAVCAN *uavcan = hal.can_mgr[i]->get_UAVCAN();


                    if (uavcan != nullptr) {
                        uint8_t gps_node = uavcan->find_gps_without_listener();


                        if (gps_node != UINT8_MAX) {
                            new_gps = new AP_GPS_UAVCAN(*this, state[instance], nullptr);
                            ((AP_GPS_UAVCAN*) new_gps)->set_uavcan_manager(i);
                            if (uavcan->register_gps_listener_to_node(new_gps, gps_node)) {
                                if (AP_BoardConfig_CAN::get_can_debug() >= 2) {
                                    printf("AP_GPS_UAVCAN registered\n\r");
                                }
                                goto found_gps;
                            } else {
                                delete new_gps;
                            }
                        }
                    }
                }
            }
        }
        return;
#endif

 


    




附錄


#define AP_UAVCAN_MAX_GPS_NODES 4
#define AP_UAVCAN_MAX_LISTENERS 4
AP_BoardConfig_CAN::get_can_num_ifaces(),返回啓用的CAN接口總數。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章