<<測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式>> 開發(fā)實(shí)例三 rs_driver

1 簡(jiǎn)介

rs_driver是RoboSense雷達(dá)的基本驅(qū)動(dòng)时甚。

這次的工作是對(duì)rs_driver v1.3.2的重構(gòu)寥袭,重構(gòu)后的代碼是v1.5.7锨能。

2 做了哪些變更?

2.1 從大類中拆分出小類

classes_from_decoder.png
  • 從Decoder中分拆出一系列小類离熏。這些類方便作單元測(cè)試佳谦。
  • Decoder計(jì)算三角函數(shù)值時(shí),使用查表方式滋戳,以便減少計(jì)算量钻蔑。Trigon類包裝了這部分邏輯。
  • 對(duì)于機(jī)械式式雷達(dá)奸鸯,Decoder計(jì)算每個(gè)通道的時(shí)間和角度時(shí)咪笑,需要先計(jì)算MSOP Packet中每個(gè)Block的時(shí)間偏移和角度偏移。BlockDiff定義了這個(gè)接口府喳,SingleReturnBlockDiff蒲肋、DualReturnBlockDiff分別實(shí)現(xiàn)了單回波模式蘑拯、雙回波模式下的時(shí)間角度偏移的計(jì)算方式钝满。
  • Decoder需要將連續(xù)的MSOP包中的點(diǎn)分幀。SplitStrategy定義了這個(gè)接口申窘,SplitStrategyByAngle和SplitStrategyByNum分別實(shí)現(xiàn)了兩種分幀模式弯蚜,也就是機(jī)械式雷達(dá)按角度分幀和按照MSOP包數(shù)量分幀。SplitStrategySeq則實(shí)現(xiàn)了MEMS雷達(dá)按MSOP包序列號(hào)分幀剃法。
  • 對(duì)于機(jī)械式雷達(dá)碎捺,Decoder需要加載和保存垂直角和水平角標(biāo)定數(shù)據(jù)。ChanAngles類包裝了這部分邏輯。
  • 對(duì)于機(jī)械式雷達(dá)收厨,AzmuthSection對(duì)點(diǎn)的角度作校驗(yàn)晋柱。DistanceSection分別對(duì)點(diǎn)的距離作校驗(yàn)。雖然這兩部分邏輯比較簡(jiǎn)單诵叁,但把它們獨(dú)立出來雁竞,也會(huì)讓Decoder更容易理解。

2.2 將一個(gè)大類拆分成一組基類+派生類

classes_input.png
  • Input類是一個(gè)龐大的類拧额,解析PCAP文件的邏輯與從Socket接收的邏輯混在一起碑诉。將它拆分成一個(gè)基類+派生類的組合,是合適的侥锦。
  • 新的Input類定義數(shù)據(jù)源的接口进栽。InputSock類實(shí)現(xiàn)從Socket接收的邏輯,InputPcap實(shí)現(xiàn)從PCAP解析的邏輯恭垦,新增的InputRaw從用戶調(diào)用得到數(shù)據(jù)并解析快毛。
  • InputFactory用于創(chuàng)建Input類的實(shí)例。

2.3 改變庫的接口設(shè)計(jì) - 有沒有更平滑的實(shí)現(xiàn)方式番挺?

packet_replay.png
  • 原來MSOP/DIFOP Packet的錄制與回放的設(shè)計(jì)祸泪,回放有單獨(dú)的函數(shù)接口和實(shí)現(xiàn)。實(shí)際上這個(gè)實(shí)現(xiàn)與Socket和PCAP數(shù)據(jù)源的后端處理是一樣的建芙,所以把它當(dāng)做一個(gè)新的數(shù)據(jù)源InputRaw没隘,也是順理成章的。

2.4 將代碼轉(zhuǎn)移到更合適的位置上

decoder_get_const_param.png
  • 機(jī)械式雷達(dá)有很多公共的邏輯禁荸,如從DIFOP包解析參數(shù)右蒲,分幀策略等,所以從Decoder創(chuàng)建一個(gè)公共的派生類DecoderMech赶熟。
  • 計(jì)算每個(gè)通道的時(shí)間和角度偏移所依賴的發(fā)射時(shí)序瑰妄,是特定于雷達(dá)的,將這個(gè)計(jì)算放到單獨(dú)的函數(shù)getConstParam()中映砖。
  • 同樣地间坐,判斷當(dāng)前回波模式的代碼,也放到單獨(dú)的函數(shù)getEchoMode()中邑退。

2.5 讓類之間的依賴關(guān)系變得更簡(jiǎn)單

decoder_get_timestamp.png
  • 原來的設(shè)計(jì)竹宋,使用了函數(shù)指針等比較復(fù)雜的方式,來確定"使用雷達(dá)時(shí)間還是主機(jī)時(shí)間作為點(diǎn)云的時(shí)間"地技。這其實(shí)搞得有點(diǎn)復(fù)雜了蜈七,改成簡(jiǎn)單的if/else邏輯,還更容易理解莫矗。

2.6 考慮限制條件飒硅,去掉不必要的考慮砂缩,簡(jiǎn)化代碼

inline void InputSock::recvPacket()
{
 ...
 std::shared_ptr<Buffer> pkt = cb_get_(MAX_PKT_LEN);
 ssize_t ret = recvfrom(fds_[0], pkt->buf(), pkt->bufSize(), 0, NULL, NULL);
 ...
}

  • 以太網(wǎng)包的長(zhǎng)度是有限制的,為它分配1400個(gè)字節(jié)三娩,還是1500個(gè)字節(jié)庵芭,其實(shí)對(duì)內(nèi)存占用的影響并不大,不值得為了長(zhǎng)度保存一個(gè)變量并把它計(jì)算得精確雀监。就用一個(gè)夠用的估計(jì)值15xx就好喳挑,可以讓代碼簡(jiǎn)單很多。

2.7 刪除不需要的功能 - 有更簡(jiǎn)單的替代方法嗎滔悉?

template <typename T_Point>
inline void LidarDriverImpl<T_Point>::initPointCloudTransFunc()
{
  if (driver_param_.saved_by_rows)
  {
    point_cloud_transform_func_ = [](const typename PointCloudMsg<T_Point>::PointCloudPtr input_ptr,
                                     const size_t& height) -> typename PointCloudMsg<T_Point>::PointCloudPtr
    {
      typename PointCloudMsg<T_Point>::PointCloudPtr row_major_ptr =
          std::make_shared<typename PointCloudMsg<T_Point>::PointCloud>();
      row_major_ptr->resize(input_ptr->size());
      size_t width = input_ptr->size() / height;
      for (int i = 0; i < static_cast<int>(height); i++)
      {
        for (int j = 0; j < static_cast<int>(width); j++)
        {
          row_major_ptr->at(i * width + j) = input_ptr->at(j * height + i);
        }
      }
      return row_major_ptr;
    };
  }
}
  • 點(diǎn)云中的點(diǎn)伊诵,默認(rèn)是按照掃描順序保存的,也就是按列保存回官。其實(shí)按行保存的目的曹宴,無非是按行訪問。由于列的點(diǎn)數(shù)是一定的歉提,所以按列保存的點(diǎn)云笛坦,按行訪問也是方便的,跳過列的點(diǎn)數(shù)訪問就可以了苔巨。
  • 按行保存的實(shí)現(xiàn)版扩,實(shí)際上將點(diǎn)云復(fù)制了一遍,這個(gè)對(duì)CPU占用影響較大侄泽,是客戶不希望的礁芦。所以不如干脆去除這個(gè)特性。

3 重構(gòu)的設(shè)計(jì)原則

  • 費(fèi)腦子的計(jì)算工作悼尾,讓單元測(cè)試幫忙做
  • 不在同一維度的邏輯柿扣,切分成不同小塊
  • 去除代碼的壞氣味(比如不好理解的邏輯),讓它有層次闺魏、有條理未状。
  • 讓生活輕松一點(diǎn),再輕松一點(diǎn)析桥。

相關(guān)鏈接

測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 為什么使用測(cè)試驅(qū)動(dòng)開發(fā)
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 從入門到精通
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - C++書籍及網(wǎng)站
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 適應(yīng)并改進(jìn)軟件設(shè)計(jì)過程
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 讓“理想結(jié)構(gòu)”與“快速變更”并行
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 提速 — 在紙上做細(xì)節(jié)設(shè)計(jì)
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 開發(fā)實(shí)例一 DVR-POS庫
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 開發(fā)實(shí)例二 JSON過濾庫
測(cè)試驅(qū)動(dòng)開發(fā)與設(shè)計(jì)模式 - 開發(fā)實(shí)例三 DVR-POS庫

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末司草,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子泡仗,更是在濱河造成了極大的恐慌埋虹,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,858評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件沮焕,死亡現(xiàn)場(chǎng)離奇詭異吨岭,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)峦树,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,372評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門辣辫,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人魁巩,你說我怎么就攤上這事急灭。” “怎么了谷遂?”我有些...
    開封第一講書人閱讀 165,282評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵葬馋,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我肾扰,道長(zhǎng)畴嘶,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,842評(píng)論 1 295
  • 正文 為了忘掉前任集晚,我火速辦了婚禮窗悯,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘偷拔。我一直安慰自己蒋院,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,857評(píng)論 6 392
  • 文/花漫 我一把揭開白布莲绰。 她就那樣靜靜地躺著欺旧,像睡著了一般。 火紅的嫁衣襯著肌膚如雪蛤签。 梳的紋絲不亂的頭發(fā)上辞友,一...
    開封第一講書人閱讀 51,679評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音震肮,去河邊找鬼踏枣。 笑死,一個(gè)胖子當(dāng)著我的面吹牛钙蒙,可吹牛的內(nèi)容都是我干的茵瀑。 我是一名探鬼主播,決...
    沈念sama閱讀 40,406評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼躬厌,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼马昨!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起扛施,我...
    開封第一講書人閱讀 39,311評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤鸿捧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后疙渣,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體匙奴,經(jīng)...
    沈念sama閱讀 45,767評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,945評(píng)論 3 336
  • 正文 我和宋清朗相戀三年妄荔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泼菌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片谍肤。...
    茶點(diǎn)故事閱讀 40,090評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哗伯,靈堂內(nèi)的尸體忽然破棺而出荒揣,到底是詐尸還是另有隱情,我是刑警寧澤焊刹,帶...
    沈念sama閱讀 35,785評(píng)論 5 346
  • 正文 年R本政府宣布系任,位于F島的核電站,受9級(jí)特大地震影響虐块,放射性物質(zhì)發(fā)生泄漏俩滥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,420評(píng)論 3 331
  • 文/蒙蒙 一贺奠、第九天 我趴在偏房一處隱蔽的房頂上張望霜旧。 院中可真熱鬧,春花似錦敞嗡、人聲如沸颁糟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,988評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽棱貌。三九已至,卻和暖如春箕肃,著一層夾襖步出監(jiān)牢的瞬間婚脱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,101評(píng)論 1 271
  • 我被黑心中介騙來泰國(guó)打工勺像, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留障贸,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,298評(píng)論 3 372
  • 正文 我出身青樓吟宦,卻偏偏與公主長(zhǎng)得像篮洁,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子殃姓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,033評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容