mainwindow.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426
  1. #include "mainwindow.h"
  2. #include "ui_mainwindow.h"
  3. #include <ostream>
  4. #include <strstream>
  5. MainWindow::MainWindow(QWidget *parent) :
  6. QMainWindow(parent),
  7. ui(new Ui::MainWindow)
  8. {
  9. ui->setupUi(this);
  10. //创建参数组合框
  11. CreateView();
  12. m_nP= 0;
  13. //启动定时器
  14. connect(&mTimer,SIGNAL(timeout()),this,SLOT(onTimer()));
  15. //启动mndtthread线程
  16. mndtthread.start();
  17. //设置窗口标题
  18. setWindowTitle("ADC NDT Mapping ------ Lidar Localization");
  19. }
  20. MainWindow::~MainWindow()
  21. {
  22. mndtthread.requestInterruption();
  23. while(!mndtthread.isFinished())
  24. {
  25. }
  26. delete ui;
  27. }
  28. void MainWindow::on_pushButton_Load_clicked()
  29. {
  30. //获取文件路径
  31. QString str = QFileDialog::getOpenFileName(this,tr("Open file"),"",tr("Record File(*.ivd)"));
  32. if(str.isEmpty())return;
  33. // ui->pushButton_Start->setEnabled(false);
  34. mbReplay = false;
  35. mMutex.lock();
  36. if(mFile.isOpen())mFile.close();
  37. mFile.setFileName(str);
  38. //以只读打开文件
  39. if(mFile.open(QFile::ReadOnly))
  40. {
  41. //设置当前文件打开状态
  42. mbOpen = true;
  43. //文件大小
  44. mnFileSize = mFile.size();
  45. //读取到文件的位置
  46. mnPos = 0;
  47. }
  48. // if(mbOpen)
  49. // {
  50. // ui->pushButton_Start->setEnabled(true);
  51. // }
  52. // else
  53. // {
  54. // ui->pushButton_Start->setEnabled(false);
  55. // }
  56. mMutex.unlock();
  57. //更新地图参数
  58. UpdateMapParam();
  59. //启动定时器
  60. mTimer.start(10);
  61. }
  62. //定时器执行程序
  63. void MainWindow::onTimer()
  64. {
  65. int nP;
  66. std::string str;
  67. //获取状态信息,获取全局变量g_np和gstr
  68. GetState(nP,str);
  69. //每执行一次point_ndtmapping操作,全局变量g_np会增加1,如果np有变化则更新文本框内的数据
  70. if(nP != m_nP)
  71. {
  72. ui->plainTextEdit->setPlainText(str.c_str());
  73. }
  74. //记录执行了多少次
  75. m_nP = nP;
  76. if(mndtthread.AbleNext())//如果可执行下一次
  77. {
  78. int nReadSize = 0;
  79. int nDataSize;
  80. char * strData;
  81. char * strName;
  82. // 读取记录
  83. bool bx = ReadARecord(nReadSize,&strName,&nDataSize,&strData);
  84. //循环读取数据,直到读取到"lidar_pc"
  85. while((bx == true)&&(strcmp(strName,"lidar_pc") != 0))
  86. {
  87. delete strData;
  88. delete strName;
  89. // 读取一条记录并将读取的结果赋值给变量:strName,nDataSize,strData
  90. bx = ReadARecord(nReadSize,&strName,&nDataSize,&strData);
  91. }
  92. //更新进度条
  93. ui->horizontalSlider->setValue(mFile.pos()*100/mnFileSize);
  94. // 文件读取完毕,进度条设为100,停止计时器
  95. if(bx == false)
  96. {
  97. ui->horizontalSlider->setValue(100);
  98. mTimer.stop();
  99. }
  100. else//读取到lidar数据
  101. {
  102. qDebug("find a lidar_pc");
  103. //预处理数据
  104. procapcd(strData,nDataSize);
  105. delete strData;
  106. delete strName;
  107. }
  108. }
  109. }
  110. //获取rh时间
  111. inline QDateTime MainWindow::GetDateTimeFromRH(iv::RecordHead rh)
  112. {
  113. QDateTime dt;
  114. QDate datex;
  115. QTime timex;
  116. datex.setDate(rh.mYear,rh.mMon,rh.mDay);
  117. timex.setHMS(rh.mHour,rh.mMin,rh.mSec,rh.mMSec);
  118. dt.setDate(datex);
  119. dt.setTime(timex);
  120. return dt;
  121. }
  122. //处理数据
  123. void MainWindow::procapcd(char *strdata, int nSize)
  124. {
  125. if(nSize <=16)return;
  126. //头文件大小
  127. unsigned int * pHeadSize = (unsigned int *)strdata;
  128. if(*pHeadSize > nSize)
  129. {
  130. // std::cout<<"ListenPointCloud data is small headsize ="<<*pHeadSize<<" data size is"<<nSize<<std::endl;
  131. }
  132. //构建点云对象
  133. pcl::PointCloud<pcl::PointXYZI>::Ptr point_cloud(
  134. new pcl::PointCloud<pcl::PointXYZI>());
  135. // pcl::PointCloud<pcl::PointXYZ>::Ptr point_cloud(
  136. // new pcl::PointCloud<pcl::PointXYZ>());
  137. // 获取名字
  138. int nNameSize;
  139. nNameSize = *pHeadSize - 4-4-8;
  140. char * strName = new char[nNameSize+1];strName[nNameSize] = 0;
  141. memcpy(strName,(char *)((char *)strdata +4),nNameSize);
  142. point_cloud->header.frame_id = strName;
  143. // 序列号
  144. memcpy(&point_cloud->header.seq,(char *)strdata+4+nNameSize,4);
  145. // 时间戳
  146. memcpy(&point_cloud->header.stamp,(char *)strdata+4+nNameSize+4,8);
  147. // 点数量
  148. int nPCount = (nSize - *pHeadSize)/sizeof(pcl::PointXYZI);
  149. int i;
  150. // 把点的数据赋值给点云对象中的变量
  151. pcl::PointXYZI * p;
  152. p = (pcl::PointXYZI *)((char *)strdata + *pHeadSize);
  153. for(i=0;i<nPCount;i++)
  154. {
  155. pcl::PointXYZI xp;
  156. xp.x = p->y;
  157. xp.y = p->x * (-1.0);
  158. xp.z = p->z;
  159. xp.intensity = p->intensity;
  160. point_cloud->push_back(xp);
  161. p++;
  162. }
  163. // 把点云数据传给处理点云数据的线程对象
  164. mndtthread.procapcd(point_cloud);
  165. }
  166. inline bool MainWindow::ReadARecord(int & nRecSize,char ** pstrName, int * pnDataSize, char ** pstrData)
  167. {
  168. char strmark[10];
  169. //消息总大小、消息头大小、消息名字大小、消息数据大小
  170. int nTotalSize,nHeadSize,nNameSize,nDataSize;
  171. int nRead = mFile.read(strmark,1);
  172. if(nRead == 0)return false;
  173. //获取消息总大小、消息头大小、消息名字大小、消息数据大小
  174. nRead = mFile.read((char *)&nTotalSize,sizeof(int));
  175. if(nRead < sizeof(int))return false;
  176. nRead = mFile.read((char *)&nHeadSize,sizeof(int));
  177. if(nRead < sizeof(int))return false;
  178. nRead = mFile.read((char *)&nNameSize,sizeof(int));
  179. if(nRead<sizeof(int))return false;
  180. nRead = mFile.read((char *)&nDataSize,sizeof(int));
  181. if(nRead<sizeof(int))return false;
  182. //校验数据关系
  183. if(nTotalSize !=(nHeadSize + nNameSize + nDataSize + 4*sizeof(int) ))
  184. {
  185. return false;
  186. }
  187. iv::RecordHead rh;
  188. char * strName = new char[1000];
  189. char * strData = new char[nDataSize];
  190. //获取时间
  191. nRead = mFile.read((char *)&rh,sizeof(iv::RecordHead));
  192. if(nRead < sizeof(iv::RecordHead))
  193. {
  194. delete strData;
  195. delete strName;
  196. return false;
  197. }
  198. mdtcurpos = GetDateTimeFromRH(rh);
  199. //获取名字
  200. nRead = mFile.read(strName,nNameSize);
  201. if(nRead < nNameSize)
  202. {
  203. delete strData;
  204. delete strName;
  205. return false;
  206. }
  207. // 使字符数组变为字符串
  208. strName[nNameSize] = 0;
  209. // qDebug(strName);
  210. // qDebug("file pos is %d ms is %d",mFile.pos(),rh.mMSec);
  211. //获取雷达数据
  212. nRead = mFile.read(strData,nDataSize);
  213. if(nRead < nDataSize)
  214. {
  215. delete strData;
  216. delete strName;
  217. return false;
  218. }
  219. //Share Data
  220. //指针赋值
  221. *pnDataSize = nDataSize;
  222. *pstrName = strName;
  223. *pstrData = strData;
  224. // delete strData;
  225. nRecSize = nTotalSize + 1;
  226. return true;
  227. }
  228. //点击save按钮
  229. void MainWindow::on_pushButton_Save_clicked()
  230. {
  231. // 获取存储的路径
  232. QString str = QFileDialog::getSaveFileName(this,tr("Open file"),"",tr("PCD File(*.pcd)"));
  233. if(str.isEmpty())return;
  234. if(!str.contains(".pcd"))str = str + ".pcd";
  235. //点云过滤网格尺寸
  236. double filter_res = mpLE_FilterResolution->text().toDouble();
  237. //存储地图
  238. savemap(str.toLatin1().data(),filter_res);
  239. }
  240. //创建左侧标题为"Param"的组合框
  241. void MainWindow::CreateView()
  242. {
  243. // QDesktopWidget* desktopWidget = QApplication::desktop();
  244. // QRect screenRect = desktopWidget->screenGeometry();
  245. // g_nActScreenW = screenRect.width();
  246. // g_nActScreenH = screenRect.height();
  247. // qDebug("width = %d, height = %d",g_nActScreenW,g_nActScreenH);
  248. QGroupBox * gp1 = new QGroupBox(ui->centralWidget);
  249. gp1->setTitle(QStringLiteral("Param"));
  250. gp1->setGeometry(QRect(10,60,350,400));
  251. QGridLayout * gll1 = new QGridLayout(ui->centralWidget);
  252. gp1->setLayout(gll1);
  253. CreateParamView(gll1);
  254. }
  255. //创建组合框内的Label和LineEdit,并设置初始化值
  256. void MainWindow::CreateParamView(QGridLayout *gl)
  257. {
  258. gl->setSpacing(10);
  259. int i = 0;
  260. QLabel * pl = new QLabel(this);
  261. pl->setText("Resolution");
  262. pl->setFixedWidth(200);
  263. QLineEdit * ple = new QLineEdit(this);
  264. ple->setFixedWidth(100);
  265. ple->setText("1");
  266. gl->addWidget(pl,i,0);
  267. gl->addWidget(ple,i,1);
  268. i++;
  269. mpLE_Resolution = ple;
  270. pl = new QLabel(this);
  271. pl->setText("Step Size");
  272. pl->setFixedWidth(200);
  273. ple = new QLineEdit(this);
  274. ple->setFixedWidth(100);
  275. ple->setText("0.1");
  276. gl->addWidget(pl,i,0);
  277. gl->addWidget(ple,i,1);
  278. i++;
  279. mpLE_StepSize = ple;
  280. pl = new QLabel(this);
  281. pl->setText("Transformation Epsilon");
  282. pl->setFixedWidth(200);
  283. ple = new QLineEdit(this);
  284. ple->setFixedWidth(100);
  285. ple->setText("0.01");
  286. gl->addWidget(pl,i,0);
  287. gl->addWidget(ple,i,1);
  288. i++;
  289. mpLE_TransFormationEpsilon = ple;
  290. pl = new QLabel(this);
  291. pl->setText("Maximum Iterations");
  292. pl->setFixedWidth(200);
  293. ple = new QLineEdit(this);
  294. ple->setFixedWidth(100);
  295. ple->setText("30");
  296. gl->addWidget(pl,i,0);
  297. gl->addWidget(ple,i,1);
  298. i++;
  299. mpLE_MaximumIterations = ple;
  300. pl = new QLabel(this);
  301. pl->setText("Leaf Size");
  302. pl->setFixedWidth(200);
  303. ple = new QLineEdit(this);
  304. ple->setFixedWidth(100);
  305. ple->setText("2");
  306. gl->addWidget(pl,i,0);
  307. gl->addWidget(ple,i,1);
  308. i++;
  309. mpLE_LeafSize = ple;
  310. pl = new QLabel(this);
  311. pl->setText("Minimum Scan Range");
  312. pl->setFixedWidth(200);
  313. ple = new QLineEdit(this);
  314. ple->setFixedWidth(100);
  315. ple->setText("5");
  316. gl->addWidget(pl,i,0);
  317. gl->addWidget(ple,i,1);
  318. i++;
  319. mpLE_MinimunScanRange = ple;
  320. pl = new QLabel(this);
  321. pl->setText("Maximum Scan Range");
  322. pl->setFixedWidth(200);
  323. ple = new QLineEdit(this);
  324. ple->setFixedWidth(100);
  325. ple->setText("200");
  326. gl->addWidget(pl,i,0);
  327. gl->addWidget(ple,i,1);
  328. i++;
  329. mpLE_MaximumScanRange = ple;
  330. pl = new QLabel(this);
  331. pl->setText("Minimum Add Scan Shift");
  332. pl->setFixedWidth(200);
  333. ple = new QLineEdit(this);
  334. ple->setFixedWidth(100);
  335. ple->setText("1");
  336. gl->addWidget(pl,i,0);
  337. gl->addWidget(ple,i,1);
  338. i++;
  339. mpLE_MinimumAddScanShfit = ple;
  340. pl = new QLabel(this);
  341. pl->setText("Mode");
  342. pl->setFixedWidth(200);
  343. QComboBox * pcb = new QComboBox(this);
  344. pcb->addItem("CPU");
  345. pcb->addItem("GPU");
  346. pcb->setFixedWidth(100);
  347. gl->addWidget(pl,i,0);
  348. gl->addWidget(pcb,i,1);
  349. i++;
  350. mpCB_Mode = pcb;
  351. pl = new QLabel(this);
  352. pl->setText("Filter Resolution");
  353. pl->setFixedWidth(200);
  354. ple = new QLineEdit(this);
  355. ple->setFixedWidth(100);
  356. ple->setText("0.2");
  357. gl->addWidget(pl,i,0);
  358. gl->addWidget(ple,i,1);
  359. i++;
  360. mpLE_FilterResolution = ple;
  361. QSpacerItem * xpsi2 = new QSpacerItem(200,1000,QSizePolicy::Maximum);
  362. gl->addItem(xpsi2,i,0);
  363. }
  364. void MainWindow::UpdateMapParam()
  365. {
  366. double resolution,stepsize,epsilon,maxiter,leafsize,minscan,maxscan,minscanshift;
  367. bool bUseGPU = false;
  368. resolution = mpLE_Resolution->text().toDouble();
  369. stepsize = mpLE_StepSize->text().toDouble();
  370. epsilon = mpLE_TransFormationEpsilon->text().toDouble();
  371. maxiter = mpLE_MaximumIterations->text().toDouble();
  372. leafsize = mpLE_LeafSize->text().toDouble();
  373. minscan = mpLE_MinimunScanRange->text().toDouble();
  374. maxscan = mpLE_MaximumScanRange->text().toDouble();
  375. minscanshift = mpLE_MinimumAddScanShfit->text().toDouble();
  376. SetParam(resolution,stepsize,epsilon,maxiter,leafsize,minscan,maxscan,minscanshift,bUseGPU);
  377. }