質問編集履歴

4

解決したので、経緯を追記

2020/02/28 06:25

投稿

yoddy
yoddy

スコア10

test CHANGED
File without changes
test CHANGED
@@ -315,3 +315,231 @@
315
315
  - 無視するheader部分の行数が間違っていたので、`ignore_line > 9` を、` ignore_line > 8` に変更
316
316
 
317
317
  - `line = f.readline()` を削除
318
+
319
+
320
+
321
+ ### 修正:解決編(2020/2/28 14:55)
322
+
323
+ yuki23様のご指摘にあった、**出力されている角度が360を超えている問題**を解決すべく、元々のC++のソースと、自身が改変したC++を見比べ、可能な限り元の状態を維持しつつ、必要なデータを加えていくように修正を行いました。
324
+
325
+ その結果、360度以上のデータが出力されることはなくなりました。
326
+
327
+ そのままの形では、依然θと距離しか出力されてませんので、上述の修正後ソースをさらに修正し、Ⅹ座標とY座標に変換したところ、以下のように、部屋の形がきちんと描画されました。
328
+
329
+ ![点群データ](71d3adec7886822f2bcc9bf131d80e4c.jpeg)
330
+
331
+
332
+
333
+ 元のソース、修正しておかしくなっていたソース、最終的に正常に動いたソースは以下の通りです。
334
+
335
+
336
+
337
+ [オリジナルC++ソース(抜粋)]
338
+
339
+ ```C++
340
+
341
+ while (1) {
342
+
343
+ rplidar_response_measurement_node_hq_t nodes[8192];
344
+
345
+ size_t count = _countof(nodes);
346
+
347
+
348
+
349
+ op_result = drv->grabScanDataHq(nodes, count);
350
+
351
+ if (IS_OK(op_result)) {
352
+
353
+ drv->ascendScanData(nodes, count);
354
+
355
+ for (int pos = 0; pos < (int)count ; ++pos) {
356
+
357
+ printf("%s theta: %03.2f Dist: %08.2f Q: %d \n",
358
+
359
+ (nodes[pos].flag & RPLIDAR_RESP_MEASUREMENT_SYNCBIT) ?"S ":" ",
360
+
361
+ (nodes[pos].angle_z_q14 * 90.f / (1 << 14)),
362
+
363
+ nodes[pos].dist_mm_q2/4.0f,
364
+
365
+ nodes[pos].quality);
366
+
367
+ }
368
+
369
+ }
370
+
371
+
372
+
373
+ if (ctrl_c_pressed){
374
+
375
+ break;
376
+
377
+ }
378
+
379
+ }
380
+
381
+
382
+
383
+ ```
384
+
385
+
386
+
387
+ [修正失敗版C++ソース(抜粋)]
388
+
389
+ ```C++
390
+
391
+ while (1) {
392
+
393
+ rplidar_response_measurement_node_t nodes[8192];
394
+
395
+ size_t count = _countof(nodes);
396
+
397
+
398
+
399
+ op_result = drv->grabScanData(nodes, count);
400
+
401
+
402
+
403
+ if (IS_OK(op_result)) {
404
+
405
+ drv->ascendScanData(nodes, count);
406
+
407
+ for (int pos = 0; pos < (int)count ; ++pos) {
408
+
409
+ clock_gettime(CLOCK_REALTIME, &ts);
410
+
411
+ std::strftime(buf, sizeof buf, "%F %T", std::localtime(&ts.tv_sec));
412
+
413
+
414
+
415
+ millisec = ts.tv_nsec / 100000000;
416
+
417
+ theta = (nodes[pos].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f;
418
+
419
+ dist = nodes[pos].distance_q2/4.0f;
420
+
421
+
422
+
423
+ outfile << buf
424
+
425
+ << ":"
426
+
427
+ << millisec
428
+
429
+ << ","
430
+
431
+ << std::to_string(theta)
432
+
433
+ << ","
434
+
435
+ << std::to_string(dist)
436
+
437
+ << "\n";
438
+
439
+
440
+
441
+ printf("%s.%ld,%03.2f,%08.2f\n",
442
+
443
+ buf,
444
+
445
+ millisec,
446
+
447
+ (nodes[pos].angle_q6_checkbit >> RPLIDAR_RESP_MEASUREMENT_ANGLE_SHIFT)/64.0f,
448
+
449
+ nodes[pos].distance_q2/4.0f);
450
+
451
+ }
452
+
453
+ }
454
+
455
+
456
+
457
+ if (ctrl_c_pressed){
458
+
459
+ break;
460
+
461
+ }
462
+
463
+ }
464
+
465
+
466
+
467
+ ```
468
+
469
+ [最終版C++ソース(抜粋)]
470
+
471
+ ```C++
472
+
473
+ while (1) {
474
+
475
+ rplidar_response_measurement_node_hq_t nodes[8192];
476
+
477
+ size_t count = _countof(nodes);
478
+
479
+
480
+
481
+ op_result = drv->grabScanDataHq(nodes, count);
482
+
483
+ if (IS_OK(op_result)) {
484
+
485
+ drv->ascendScanData(nodes, count);
486
+
487
+ for (int pos = 0; pos < (int)count ; ++pos) {
488
+
489
+ clock_gettime(CLOCK_REALTIME, &ts);
490
+
491
+ std::strftime(buf, sizeof buf, "%F %T", std::localtime(&ts.tv_sec));
492
+
493
+ millisec = ts.tv_nsec / 100000000;
494
+
495
+ printf("%s.%ld,%03.2f,%08.2f\n",
496
+
497
+ buf,
498
+
499
+ millsec,
500
+
501
+ (nodes[pos].angle_z_q14 * 90.f / (1 << 14)),
502
+
503
+ nodes[pos].dist_mm_q2/4.0f);
504
+
505
+ }
506
+
507
+ }
508
+
509
+
510
+
511
+ if (ctrl_c_pressed){
512
+
513
+ break;
514
+
515
+ }
516
+
517
+ }
518
+
519
+
520
+
521
+ ```
522
+
523
+
524
+
525
+ whileブロックに入ってすぐの、` rplidar_response_measurement_node_hq_t nodes[8192]; `というところで、hqがついたりつかなかったりしていますが、
526
+
527
+ 修正失敗版を最初にmakeした時、「hqありは使えない、ないのを使え」みたいなエラーをはかれたため、修正し、その後発生するエラーに対応していったら、結果的に上述のようになった次第です。
528
+
529
+ 今回、改めてSDKを落とすと、バージョンが上がっており、それが原因か、単に以前が自分のミスだったのかは不明ですが、するっとmakeできてしまい、動くに至りました。
530
+
531
+ もっと細かく、何がどうしてエラーだったか、ご報告するのが本来の在り方だとは承知しておりますが、いかんせん、この問題とはこの1年、何度か中断しつつ付き合ってきたため、最初の頃の記憶があいまいで、説明のしようがありません。
532
+
533
+ ご理解、ご容赦の程よろしくお願いいたします。
534
+
535
+
536
+
537
+ ### 謝辞
538
+
539
+ 最後に、皆様のご助言のおかげで、無事にきれいな点群(と言っても16000点前後/秒程度ですが、これはLidarの限界です)の取得に成功しましたこと、心より感謝いたします。
540
+
541
+ ずっと一人で作業をしていたら、動いているからと、元のソースを見直すことを頑なに拒んでいたかもしれません。
542
+
543
+ こちらで、私などよりもはるかに知見のある皆様の意見に、素直に耳を傾けることができ、解決することができました。
544
+
545
+ 本当にありがとうございました。

3

ファイルアップロード完了とソース修正の通知を追加

2020/02/28 06:25

投稿

yoddy
yoddy

スコア10

test CHANGED
File without changes
test CHANGED
@@ -301,3 +301,17 @@
301
301
 
302
302
 
303
303
  ```
304
+
305
+
306
+
307
+ ### 修正と追加(2020/2/28 11:05)
308
+
309
+ Githubに[専用のリポジトリ](https://github.com/taobody/RPLidar_A3)を作って、Pythonのソースと部屋の中で取得した点群データをアップしました。
310
+
311
+ ソースも一部修正をしています。
312
+
313
+ 具体的には、if ブロック内の以下の点です。
314
+
315
+ - 無視するheader部分の行数が間違っていたので、`ignore_line > 9` を、` ignore_line > 8` に変更
316
+
317
+ - `line = f.readline()` を削除

2

掲載する修正後ソースが間違っていたのだ、訂正して再掲。

2020/02/28 02:20

投稿

yoddy
yoddy

スコア10

test CHANGED
File without changes
test CHANGED
@@ -221,3 +221,83 @@
221
221
  何をどう書いていいかもよくわからないまま、思いつくことを書いてまいりましたが、ほかに必要な情報がありましたら、ご指摘いただければ幸いです。
222
222
 
223
223
  よろしくお願いいたします。
224
+
225
+
226
+
227
+ ### 修正(2020/2/27 16:30)
228
+
229
+ 修正後のソースで、角度をラジアンに変換して、三角関数の引数のする箇所を間違っていました。
230
+
231
+ ただ、この点に関して、ラジアンに変換せずにthetaを直接使用するように改変したかといいうと、
232
+
233
+ 1. Lidarの仕様書に、thetaが角度として図示されており、
234
+
235
+ 1. 参考ソースで変換した際に点群が前述の画像の通り、歪んでいたため
236
+
237
+
238
+
239
+ です。
240
+
241
+ 最初に使用した修正後ソースは以下の通りです。
242
+
243
+
244
+
245
+ [修正後ソース]
246
+
247
+ ```Python
248
+
249
+ #!/usr/bin/python3
250
+
251
+
252
+
253
+ import math
254
+
255
+
256
+
257
+ file = "lidarlog2.txt" # Lidarログ出力ファイル
258
+
259
+
260
+
261
+ f = open(file, 'r')
262
+
263
+ line = f.readline()
264
+
265
+ ignore_line = 1
266
+
267
+
268
+
269
+ for line in f:
270
+
271
+ if ignore_line > 9: # headerを無視
272
+
273
+ line = line.strip().rstrip('\n')
274
+
275
+ line_data = line.split(",")
276
+
277
+ s = float(line_data[1])
278
+
279
+ c = float(line_data[2])
280
+
281
+ print(s)
282
+
283
+ r = s * math.pi /180
284
+
285
+ a = c * math.cos(r) # X座標
286
+
287
+ b = c * math.sin(r) # Y座標
288
+
289
+ print(line_data[0] + " " + str(a) + " " + str(b))
290
+
291
+ line = f.readline()
292
+
293
+ else:
294
+
295
+ ignore_line = ignore_line + 1
296
+
297
+
298
+
299
+ f.close()
300
+
301
+
302
+
303
+ ```

1

Slamtec社の社名を修正(Slamtech → Slamtec)

2020/02/27 07:41

投稿

yoddy
yoddy

スコア10

test CHANGED
File without changes
test CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  初めて質問させていただきます。
6
6
 
7
- 現在、Slamtech社のRPLidar A3(https://www.slamtec.com/en/Lidar/A3)を用いた、マッピングシステムを、RaspberryPi3 B+ にて作成しております。
7
+ 現在、Slamtec社のRPLidar A3(https://www.slamtec.com/en/Lidar/A3)を用いた、マッピングシステムを、RaspberryPi3 B+ にて作成しております。
8
8
 
9
9
  SDKが公開されているので、その中のultra_simpleというアプリケーションでテストを行い、C++には不慣れながらも、出力データに日付と時刻を付与するところまではできました。
10
10