日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

项目实训 - 智能车系统 - 第七周记录

發布時間:2023/12/20 windows 70 豆豆
生活随笔 收集整理的這篇文章主要介紹了 项目实训 - 智能车系统 - 第七周记录 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

項目實訓 - 智能車系統 - 第七周記錄

日期:4.04 – 4.10

項目進度

本周工作進展:

  • 更換了底層的通信框架(shm)
  • 熟悉速騰雷達驅動,以及ros相關驅動,為二次開發驅動做準備

1、更換底層通信框架

上周解決的utility讀寫問題,本周運行之后又出現了之前的錯誤:進程在初始化后會隨機崩潰掉,然后重啟,有時候會穩定,有時候會移植崩潰。

暫時查不出原因來,于是回到程序本身,在多線程std::thread、mmap的通信框架里找問題。

然后讓師兄看了一下代碼,師兄發現了代碼的一個大問題。

我們本來用的mmap框架搭建通信機制。

經過師兄的調撥,認識到mmap作為通信框架會出現問題(雖然暫時沒有遇到)

先簡單梳理一下mmap的工作機制

  • 首先,將文件從原本的存儲介質中映射到內存的一塊區域
  • 對于文件的讀取可以直接從內存中進行讀取,所以mmap的通常用途是用于加快文件讀取速率
  • 但是多個文件映射同一個文件時,并不像之前我們認為的那樣映射到同一塊內存區域中,而是各自有各自的內存映射區域。至于為什么每個進程返回的共享內存首地址是同一個值,是因為返回的是虛擬地址,一個相同的虛擬地址可以對應不同的物理地址,當不同的進程通過虛擬地址進行寫入時,表面上是對同一個地址進行寫入,實際上內核會找到對應的物理地址進行寫入
  • 而且,寫入不會直接寫入到內存中,而是會首先寫入到緩存中,然后經由緩存寫入到磁盤,同時內存的相應位置設置為臟頁,其他文件讀取時,會從磁盤中將更新的頁換入到內存中進行讀取。
  • 這就造成了使用mmap進行內存共享時,讀寫時不同步的,時間差取決于系統的負載情況,所以有可能遷移到實際情況中后,效果會明顯變差,這取決于底層存儲介質的讀寫速度。

總結一下:mmap機制,共享通過內存–緩存–硬盤–內存–進程

于是我們考慮換掉mmap,使用shm重寫一下接口(至于為什么不用socket通信,我只能說那樣要改的太多了,只能說開始取巧偷懶了,現在就要填坑了)。

方便的是,由于我們的讀寫更新速度比較快,所以使用死循環的方式應該會優于使用信號量的方式,所以我們只需要在最底層的通信接口內部,用shm替代mmap

以下是新的通信框架

/*** @brief used to define share memory* @param fd:共享內存區域ID* @param point:共享內存區域首地址* */ struct MemoryDefinition {int fd;void* point; };key_t get_id(const string fileName) {key_t ret = 0;for(int i = 0; i < fileName.size(); i++){ret += fileName[i];}//cout<<fileName<<' '<<ret<<endl;return ret + 1000000; }/*** @brief Create a shm object* * @param shm_key 共享內存鍵值* @param shm_num 共享內存字節長度* @param shm_flag 權限 (默認權限為讀寫權限)* @return void* */ MemoryDefinition* createShareMemory(const string shm_key, size_t shm_num)//, int shm_flag = 1) {MemoryDefinition* shm_point = new MemoryDefinition();;int shm_flag = IPC_CREAT | 0666;int fd = shmget(get_id(shm_key), shm_num, shm_flag);void* point;if(fd != -1) {//point = shmat(fd, 0, 0);if((int*)point != (int*)-1) {//初始化memset(point, 0, shm_num);shm_point->fd = fd;shm_point->point = point;return shm_point;} else {perror("get shareMemory error");}} else {perror("get shareMemory error");}return shm_point; }/*** @brief 連接共享內存* * @param shm_key 共享內存鍵值* @param shm_num 共享內存字節長度* @param shm_flag 權限 (默認權限為讀寫權限)* @return void* */ MemoryDefinition* connectShareMemory(const string shm_key, size_t shm_num)//, int shm_flag = 1) {MemoryDefinition* shm_point = new MemoryDefinition();int shm_flag = IPC_CREAT | 0666;int fd = shmget(get_id(shm_key), shm_num, shm_flag);void* point;if(fd != -1) {//point = shmat(fd, 0, 0);if((int*)point != (int*)-1) {shm_point->fd = fd;shm_point->point = point;cout<<shm_key<<' '<<fd<<' '<<point<<endl;return shm_point;} else {perror("get shareMemory error");}} else {perror("get shareMemory error");}return shm_point; }void unMap(const MemoryDefinition* definition) {shmdt(definition->point);}#endif

修改后項目能夠正常進行

預想的超過共享內存上限值的問題沒有發生(查查多少MB)

而且改成shm后,今天最開始要解決的進程崩潰問題好了。說明不是讀取文件流的問題,是mmap本身的問題

2、速騰雷達驅動 – 文檔閱讀

最開始,我的計劃是針對雷達的通信方式,直接從0開始寫一個驅動程序。于是開始閱讀速騰雷達的官方文檔。

網址: https://www.robosense.cn/resources-27

下面是一些記錄:

UDP通信協議

數據包存在于MSOP包中

發送間隔1.33ms

單回波和雙回波

https://www.zhihu.com/question/473355887/answer/2011499085

  • 激光發射后 隨著距離的增大,會出現散射的現象;當激光到達透明物體或者物體邊緣時,會有部分散射的激光繼續前進

  • 雙回波會收集兩次回波,但是可能會造成數據的重復收集

  • 只反射了一次回波。但是接收器仍然將其識別為兩次回波。

數據包格式分析

幀頭 42byte

1 - 8byte:用于包頭檢測

  • 序列:0x55,0xAA,0x05,0x0A,0x5A,0xA5,0x50,0xA0

21 - 30byte:存儲時間戳



31byte:表示激光雷達的型號

數據段

數據塊區間是 MSOP 包中傳感器的測量值部分,共 1200byte。它由 12 個 data block 組成,每個 block 長度為 100byte,代表一組完整的測距數據。Data block 中 100byte 的空間包括:2byte 的標志位,使用 0xffee 表示;2byte 的 Azimuth,表示水平旋轉角度信息,每個角度信息對應著 32 個的 channel data,包含 2 組完整的 16 通道信息。

3、rslidar 驅動 二次開發 準備

看了半天,發現從頭寫不太現實,于是還是去網上看一下ros環境下的使用流程。

整理出一些有用的文章:

ROS功能包在線把速騰聚創點云格式轉為velodyne點云格式 https://blog.csdn.net/weixin_53073284/article/details/123344981

libpcap詳解 https://blog.csdn.net/superbfly/article/details/51199161 (數據包捕獲函數庫,是Unix/Linux平臺下的網絡數據包捕獲函數庫。它是一個獨立于系統的用戶層包捕獲的API接口,為底層網絡監測提供了一個可移植的框架。)

https://github.com/RoboSense-LiDAR/rslidar_sdk Rlidar_SDK是運行在Ubuntu操作系統上的激光雷達驅動軟件開發工具包,它包含了激光雷達驅動核、ROS支持、ROS 2支持和Protobuf-UDP通信功能。對于希望通過ROS或ROS 2獲得點云的用戶,可以直接使用此軟件開發工具包。對于那些想要做高級開發或將激光雷達驅動器集成到他們自己的項目中的人,請參考激光雷達驅動器核心rs_Driver。

https://blog.csdn.net/weixin_53073284/article/details/123344981 ROS功能包在線把速騰聚創點云格式轉為velodyne點云格式

https://blog.csdn.net/weixin_53073284/article/details/122680587 速騰rs16激光雷達安裝驅動使用方法

所以如果在ros的環境下 大致流程是

  • 安裝速騰雷達的驅動
  • 二次開發一下?(可能是點云格式的一些問題)
  • (如果直接需要速騰格式的)直接發布就行了
  • (如果需要velodyne格式的)經過rs_to_velodyne進行轉換(流程就是訂閱上面發布的話題,轉換成對應格式繼續發布)
  • 訂閱話題(后面要注意一下,是否需要將坐標系繼續轉換 (取決于算法的實現 需要再看))

所以我現在的流程

  • 安裝速騰雷達的驅動(不使用里面的ros的相關功能)
  • 二次開發(根據ros的實現,轉換為我們自定義的點云格式)
  • 根據rs_to_velodyne的實現,繼續轉換點云格式
  • 自定義發布

所以現在不需要我從頭開始寫UDP編程了,接著速騰雷達的驅動進行二次開發

  • 安裝驅動

看到了一個同學的博客

https://blog.csdn.net/weixin_53073284/article/details/122680587

現根據他的博客,安裝了一個驅動,這個驅動應該是專門為ros設計的

git clone https://github.com/BluewhaleRobot/ros_rslidar_robosense.git

這個在我編譯的時候出了點小問題

  • 一直提示我一個頭文件下的類沒有定義
  • 經過查找是鏈接的時候出的問題

解決:

  • 先找到pcl庫的路徑
    • 小技巧:在編譯的時候打印依賴的庫的信息
    • 找到了對應的文件
    • 然后發現缺失的那個頭文件 不在打印的信息里面
    • 所以在鏈接的地方添加這個路徑即可
#add_dependencies(talker ${${PROJECT_NAME}_EXPORTED_TARGETS}) target_link_libraries(range_node range_conversion${catkin_LIBRARIES}/usr/lib/x86_64-linux-gnu/libpcl_visualization.so )#message(STATUS "?????????????????????????????????????????????????????????????????? ${catkin_LIBRARIES}")

核心驅動包 :

兩個主要的節點

  • rslidar_driver
  • rslidar_pointcloud

針對代碼的具體分析體現在代碼中,不在博客中記錄了。

這里只記錄一下一些概念和主要流程:

msgs格式

rslidarScan.msg

# LIDAR scan packets.Header header # standard ROS message header rslidarPacket[] packets # vector of raw packets

rslidarPacket.msg

# Raw LIDAR packet.time stamp # packet timestamp uint8[1248] data # packet contents

1248字節是一個UDP協議包的有效荷載字長

Scan則是一個packet的數組,保存一組packet

基于發布的話題

msop_output_ = node.advertise<rslidar_msgs::rslidarScan>("rslidar_packets", 10);

可以認為,訂閱了該話題的節點 是用于處理數據的

關于水平轉角的一個信息

  • 差值
RS-LiDAR-16 每隔一組 16 線激光測距才輸出一次水平旋轉角度信息,因此在單回 波模式下,對于沒有輸出水平旋轉角度信息的那組 16 線激光測距需要通過插值來獲得。 有很多種方式可以插值,下面的方法是最簡單和直接的一種。 對于一個 Packet 中的數據,Block 1 和 Block 2 的第一個數據采集的時間間隔是 ~100us,可以認為在這個期間雷達是勻速旋轉的。因此可以計算第 N+1 組 16 線激光測 距的第一個數據的水平角度是第 N 組 16 線激光測距的第一個數據的水平角度和第 N+2 組 16 線激光測距的第一個數據的水平角度的均值

rawdata.h

最上面定義了一些靜態的雷達相關參數(暫時沒看)

struct raw_block
// block typedef struct raw_block //一個block 2byte 的標志位,使用 0xffee 表示;2byte 的 Azimuth,表示水平旋轉角度信息,每 個角度信息對應著 32 個的 channel data,包含 2 組完整的 16 通道信息。 {uint16_t header; ///< UPPER_BANK or LOWER_BANKuint8_t rotation_1; uint8_t rotation_2; /// combine rotation1 and rotation2 together to get 0-35999, divide by 100 to get degreesuint8_t data[BLOCK_DATA_SIZE]; // 96 32 * 2(一個block出去標志位和水平轉角信息的數據大小) } raw_block_t;
struct raw_packet

整個數據包

  • revolution和status參數還沒搞懂是干嘛的

loadConfigFile函數

從配置文件中加載參數

  • 原本的項目中沒有對應的配置文件
  • 我從其他包中找到了對應的參數
  • 但是可能還要根據雷達具體的參數來判斷(比如角度等等)

在項目接受的點云數據中:基本上每幀的width都是 16000左右

與樓下這個數字基本上接近

  • 代表的是有多少個點
    • 16:16線
    • 24:一個包掃描了24次(對應于不同的水平角度)
    • 84:進行了84次掃描
    • /2不知道為啥

unpack函數

從第43byte開始解析(前42byte是head部分)

然后逐個block解析(12個)

更新溫度信息(不重要)

計算水平偏角

  • 配合深度信息計算xyz

  • 一組通道中的每個通道的水平偏角,按照源代碼的計算方式來看,是不同的

  • int azi1, azi2; // 插值計算一個block中的后半段的角度azi1 = 256 * raw->blocks[block + 1].rotation_1 + raw->blocks[block + 1].rotation_2;azi2 = 256 * raw->blocks[block].rotation_1 + raw->blocks[block].rotation_2;azimuth_diff = (float)((36000 + azi1 - azi2) % 36000);for (int firing = 0, k = 0; firing < RS16_FIRINGS_PER_BLOCK; firing++) // 2{for (int dsr = 0; dsr < RS16_SCANS_PER_FIRING; dsr++, k += RAW_SCAN_SIZE) // 16 3{//計算出每個通道的水平偏角azimuth_corrected_f = azimuth + (azimuth_diff * ((dsr * RS16_DSR_TOFFSET) + (firing * RS16_FIRING_TOFFSET)) /RS16_BLOCK_TDURATION); ////取整azimuth_corrected = ((int)round(azimuth_corrected_f)) % 36000; // convert to integral value...
  • 計算方法:

    • azimuth_diff代表的是第i個block的第一個通道的偏角 與 第i+1個block的第一個通道的偏角的差值(最后一個block用的與前一個block的差值)
    • 后面計算每個通道的水平偏角
      • RS16_DSR_TOFFSET 代表每個通道掃描的時間間隔
      • RS16_FIRING_TOFFSET 代表第一個組16通道掃描的時間
      • RS16_BLOCK_TDURATION 代表一組block掃描的時間(RS16_FIRING_TOFFSET 的二倍)
      • 通過上面的公式計算出每個通道的水平偏角

然后直接將intensity信息賦值

注:

這里發布的點云信息不具備ring信息和stamp信息

  • 這里結合rs_to_velodyne的代碼
  • time可以直接用ros的時間戳
    • 如果不行的,手動賦值
    • 通過起始的ros時間戳+差值的方式(均勻
    • 看了lio的項目,雀氏是需要每個點的時間戳的
    • 雀氏可以手動賦值
    • 先看一下原始代碼吧
  • ring直接賦值通道數就可以了應該(而且應用的時候貌似也不需要ring?)

認為:

  • rs雷達的time格式是時間點
  • velodyne雷達的time格式是該點的時間戳 與 這一組點云的開始點的時間戳的 差值

而項目里實際需要的就是時間戳

  • 在項目中應該有轉換成實際時間戳的操作

優化方向

  • 接收的點云數據 加上角度信息

  • rslidar_node.cpp中啟動該節點,首先初始化一個rslidar_driver::rslidarDriver類

    • 構造函數中,從配置文件中讀取一系列參數,并且初始化話題的發布(msop和difop,我們需要的是msop)
      • 發布的話題的消息類型是:rslidar_msgs::rslidarScan,在后面解釋
    • 并且初始化socket通信,在input.cc中,通過socket網絡編程與雷達建立起通信連接。
  • 節點后面while循環執行樓上類的poll函數,該函數用于輪詢雷達設備

    • 初始化rslidarPacket,讀取npackets次數據包(84),通過input中的getpacket函數
  • rslidar_pointcloud中的節點訂閱rslidar_driver發布的話題

  • 將原始數據解析成點云數據

  • 發布

4、rs_to_velodyne

還需要注意的是,大多數slam項目所適配的點云格式都是velodyne雷達(一個國外的牌子),而我們項目所使用的是國內的速騰雷達,產生的點云格式與velodyne有些許差別,需要轉換。github上找到了相關程序,不過是針對ros的,需要改動。

https://github.com/HViktorTsoi/rs_to_velodyne

大體思路就是:

  • 訂閱發布的rslidar點云話題
  • 轉換
  • 發布velodyne格式點云話題

梳理完成,可以開始進行驅動的編寫了

技術難點

rdlidar雷達驅動

socket通信

bug記錄

沒啥大bug

其他

總結

以上是生活随笔為你收集整理的项目实训 - 智能车系统 - 第七周记录的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 免费av一级片 | 亚洲国产精品综合 | 亚洲视频网站在线观看 | 成人亚洲在线 | 中文字幕在线播放第一页 | 欧美精品v| 日本裸体网站 | 亚洲一区二区综合 | 韩产日产国产欧产 | 国产美女菊爆在线播放APP | 成人免费av网站 | 亚洲小说区图片区 | 黄色网免费观看 | 国产一级爱 | 国产啪视频 | 久久久国产精品一区 | 免费国产在线观看 | 久久久久久久 | 日韩成人精品一区二区三区 | 午夜视频在线免费 | 亚洲一区二区三区在线看 | 日韩中文网 | 中文在线www| 一区二区日韩欧美 | 老妇裸体性猛交视频 | 经典毛片| 成人av免费观看 | 一本大道久久a久久综合婷婷 | 91重口味 | 中文字幕一区二区人妻视频 | 青娱乐国产视频 | 久久精品免费网站 | 久久亚洲电影 | 亚洲在线视频播放 | 大学生一级片 | 日本不卡三区 | 久久yy | jlzzjlzz亚洲日本少妇 | 国产精品无码电影 | 自拍视频一区二区 | 日日爱99 | 手机av在线看 | 毛片一级在线观看 | 亚洲精品少妇久久久久久 | 亚洲精品字幕在线观看 | 香蕉视频在线观看黄 | 影音先锋中文字幕资源 | www日本视频 | 91国偷自产一区二区三区女王 | 内射合集对白在线 | 天天在线免费视频 | 欧美性大战久久久久久久 | 免费视频一二三区 | 色婷婷av在线 | 天天干夜操 | av爱爱| 免费不卡毛片 | 日韩精品播放 | 99riav国产| 天堂在线国产 | 中文字幕视频 | 亚洲欧美另类国产 | jizz成熟丰满老女人 | 国产日韩欧美视频在线观看 | www色网站 | 久久亚洲AV无码专区成人国产 | 男人的天堂久久久 | 国产二区精品视频 | 国内自拍99 | 日韩精品一区在线播放 | 国产福利一区二区视频 | 色999日韩 | 国产中文字幕三区 | 黄色网址中文字幕 | 涩涩视频免费观看 | 一级特黄特色的免费大片视频 | 五月婷婷天 | 国产高清视频在线播放 | 一道本在线观看视频 | 久久久久香蕉视频 | 亚洲香蕉一区 | 老湿机69福利区午夜x片 | 国产精品91视频 | av电影免费在线播放 | 亚洲一区二区电影 | 一区视频在线免费观看 | www成人在线观看 | 色图av | 久久久久久久一区 | 日本女人毛茸茸 | 无码人妻久久一区二区三区蜜桃 | 538精品一线 | 深夜成人福利视频 | 欧美三级小视频 | 香蕉视频国产在线观看 | 一级影片在线观看 | 岛国av免费在线 | 97超碰国产精品无码蜜芽 | 色综合社区 |