說到機(jī)器人自主定位導(dǎo)航解決方案及技術(shù),大家腦海里肯定會(huì)浮現(xiàn)“定位”、“建圖”、“避障”、“路徑規(guī)劃”等字眼。
在思嵐提供的自主定位導(dǎo)航解決方案中,主要是通過雷達(dá)和里程計(jì)的數(shù)據(jù)來進(jìn)行定位。雖然激光雷達(dá)在一定范圍之內(nèi)會(huì)糾正里程計(jì)的誤差,但在某些特殊環(huán)境下(如雷達(dá)掃描的有效點(diǎn)較少時(shí)),里程計(jì)的準(zhǔn)備度還是會(huì)影響定位的效果。
因此,對于需要自主定位導(dǎo)航的服務(wù)機(jī)器人而言,電機(jī)里程計(jì)的精準(zhǔn)度,往往是決定整個(gè)機(jī)器人定位精度的關(guān)鍵因素之一。
SDP Mini 里程計(jì)
里程計(jì)類型的選擇:
常用的機(jī)器人底盤電機(jī)編碼器按實(shí)現(xiàn)原理來分類,包括光電編碼器及霍爾編碼器;按照其編碼方式分類,主要包括增量型和絕對型。對于基于slamware的機(jī)器人底盤來說,里程計(jì)的分辨率需要在1mm以下,且總誤差最多不能超過5%,如果超過此數(shù)值,機(jī)器人將無法正常實(shí)現(xiàn)定位導(dǎo)航的功能。因此,無論選擇哪種編碼器,必須要達(dá)到其精度的要求??梢詤⒖家韵屡袛喙剑?/p>
(2π/每轉(zhuǎn)編碼器脈沖數(shù))×輪子半徑≤0.001米
注:輪子半徑單位為米
系統(tǒng)電機(jī)應(yīng)答流程:
(以兩輪差動(dòng)電機(jī)為例)
SLAMWARE Core 每間隔delta時(shí)間,會(huì)向底盤發(fā)送左右輪的速度,向前為正,向后為負(fù),即SET_BASE_MOTOR(0x40)。底盤會(huì)回復(fù)此時(shí)的左右輪里程計(jì)的累計(jì)值,即GET_BASE_MOTOR_DATA(0x31)。
請注意,無論輪子向前運(yùn)動(dòng)或向后運(yùn)動(dòng),里程計(jì)的度數(shù)均遞增,因?yàn)镾LAMWARE Core在下發(fā)速度時(shí),已經(jīng)區(qū)分了向前還是向后。
SLAMWARE Core發(fā)送SET_BASE_MOTOR的請求報(bào)文為, 速度的單位為mm/s:
里程計(jì)代碼示例詳見:
SET_BASE_MOTOR
typedefstruct_base_set_motor_request
{
_s32 motor_speed_mm[4];
} __attribute__((packed)) base_set_motor_request_t;
對應(yīng)下面的代碼:
SET_BASE_MOTOR
caseSLAMWARECORECB_CMD_SET_BASE_MOTOR:
{
base_set_motor_request_t *ans_pkt = (base_set_motor_request_t *) request->payload;
if(!bumpermonitor_filter_motorcmd(ans_pkt->motor_speed_mm[0], ans_pkt->motor_speed_mm[1])) {
set_walkingmotor_speed(ans_pkt->motor_speed_mm[0], ans_pkt->motor_speed_mm[1]);
}
net_send_ans(channel, NULL, 0);
}
break;
底盤會(huì)通過響應(yīng)GET_BASE_MOTOR_DATA, 將左右輪的累計(jì)里程發(fā)給SLAMWARE Core,響應(yīng)報(bào)文為,距離單位為mm:
GET_BASE_MOTOR_DATA
typedefstruct_base_motor_status_response
{
_s32 motor_cumulate_dist_mm_q16[4];
} __attribute__((packed)) base_motor_status_response_t;
對應(yīng)的代碼:
GET_BASE_MOTOR_DATA
caseSLAMWARECORECB_CMD_GET_BASE_MOTOR_DATA:
{
base_motor_status_response_t ans_pkt;
memset(&ans_pkt, 0, sizeof(ans_pkt));
ans_pkt.motor_cumulate_dist_mm_q16[0] = (_s32) (cumulate_walkingmotor_ldist_mm());
ans_pkt.motor_cumulate_dist_mm_q16[1] = (_s32) (cumulate_walkingmotor_rdist_mm());
net_send_ans(channel, &ans_pkt, sizeof(base_motor_status_response_t));
}
break;
里程計(jì)部分代碼示例:
每米編碼器脈沖數(shù)ODOMETER_EST_PULSE_PER_METER,需要根據(jù)每轉(zhuǎn)編碼器脈沖數(shù)以及輪子的直徑來確定,公式如下:
每米編碼器脈沖數(shù)=每轉(zhuǎn)編碼器脈沖數(shù)/(π×輪子直徑)
注:輪子直徑單位為米
Odometry
//每米編碼器脈沖數(shù)
#define ODOMETER_EST_PULSE_PER_METER 6390UL
//行走電機(jī)速度控制頻率:60hz
#define CONF_MOTOR_HEARTBEAT_FREQ 60
#define CONF_MOTOR_HEARTBEAT_DURATION (1000/(CONF_MOTOR_HEARTBEAT_FREQ))
/*
* 刷新行走電機(jī)的里程數(shù)據(jù)函數(shù)
*/
staticvoid_refresh_walkingmotor_odometer(_u32 durationMs)
{
_u32 irqSave = enter_critical_section(); //臨界資源保護(hù)
for(size_tcnt = 0; cnt < WALKINGMOTOR_CNT; ++cnt) {
_lastEncoderTicksDelta[cnt] = _encoderTicksDelta[cnt]; //獲得delta時(shí)間內(nèi)編碼器的脈沖數(shù)
_motorAccumulatedTicks[cnt] += _encoderTicksDelta[cnt]; //獲得累計(jì)編碼器的脈沖數(shù)
_encoderTicksDelta[cnt] = 0;
}
leave_critical_section(irqSave);
if(durationMs == 0) //防止除零
durationMs = 1;
for(size_tcnt = 0; cnt < WALKINGMOTOR_CNT; ++cnt) { //根據(jù)delta的編碼器數(shù)據(jù)計(jì)算這段時(shí)間內(nèi)速度,即當(dāng)前速度
_lastOdometerSpeedAbs[cnt] = (float) _lastEncoderTicksDelta[cnt] * (1000.0 / ODOMETER_EST_PULSE_PER_METER) * 1000.0 / durationMs;
}
}
/*
* 計(jì)算左行走電機(jī)累計(jì)里程函數(shù)
* 單位:mm
*/
_u32 cumulate_walkingmotor_ldist_mm(void)
{
return(_motorAccumulatedTicks[WALKINGMOTOR_LEFT_ID] * 1000) / ODOMETER_EST_PULSE_PER_METER;
}
/*
* 計(jì)算右行走電機(jī)累計(jì)里程函數(shù)
* 單位:mm
*/
_u32 cumulate_walkingmotor_rdist_mm(void)
{
return(_motorAccumulatedTicks[WALKINGMOTOR_RIGHT_ID] * 1000) / ODOMETER_EST_PULSE_PER_METER;
}
那么,對于里程計(jì)而言,我們該如何判斷其定位數(shù)據(jù)是否準(zhǔn)確呢?下面,就要借助可擴(kuò)展的機(jī)器人管理與開發(fā)應(yīng)用軟件:Robo Studio
首先,先將準(zhǔn)備工作做好:
在調(diào)試之前,請找到一處合適測試的區(qū)域,該區(qū)域需有清晰的邊界,比如,矩形的空房間。安裝好Robo Studio,并連接上機(jī)器人(如SDP Mini)。Robo Studio下載鏈接及在線文檔可至思嵐官網(wǎng)下載安裝。
利用Robo Studio調(diào)試?yán)锍逃?jì)準(zhǔn)確度測試方法:
1.將機(jī)器人控制到離一面直墻若干米的位置,面朝直墻,如下圖所示。
2.將之前建好的地圖清除掉,點(diǎn)擊清空地圖,此時(shí),機(jī)器人當(dāng)前的區(qū)域會(huì)重建。當(dāng)前區(qū)域重建好之后,可以點(diǎn)擊暫停建圖,停止地圖更新。最后,可以將暫停定位開啟,開啟后,將關(guān)閉激光定位,僅用里程計(jì)的數(shù)據(jù)來定位。
3.控制機(jī)器人向前朝墻運(yùn)動(dòng),觀察激光點(diǎn)是否和墻重合,如果和墻重合,證明里程計(jì)較為準(zhǔn)確;
如果激光點(diǎn)超出墻,證明底盤上報(bào)的里程計(jì)數(shù)據(jù)要大于實(shí)際運(yùn)動(dòng)的距離,里程計(jì)偏大。
如果激光點(diǎn)在墻之內(nèi),證明底盤上報(bào)的里程計(jì)數(shù)據(jù)要小于實(shí)際運(yùn)動(dòng)的距離,里程計(jì)偏小。
如果激光點(diǎn)和墻重合,可以繼續(xù)控制機(jī)器人倒退,左右轉(zhuǎn)動(dòng),看看激光點(diǎn)是否和周圍環(huán)境匹配;
關(guān)鍵字:激光雷达,SLAM