-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprint.html
760 lines (704 loc) · 57.4 KB
/
print.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
<!DOCTYPE HTML>
<html lang="zh" class="sidebar-visible no-js light">
<head>
<!-- Book generated using mdBook -->
<meta charset="UTF-8">
<title>上应大机协之书</title>
<meta name="robots" content="noindex" />
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="favicon.svg">
<link rel="shortcut icon" href="favicon.png">
<link rel="stylesheet" href="css/variables.css">
<link rel="stylesheet" href="css/general.css">
<link rel="stylesheet" href="css/chrome.css">
<link rel="stylesheet" href="css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="highlight.css">
<link rel="stylesheet" href="tomorrow-night.css">
<link rel="stylesheet" href="ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('mdbook-theme');
var sidebar = localStorage.getItem('mdbook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('mdbook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('mdbook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('mdbook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('mdbook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter"><li class="chapter-item expanded "><a href="关于本书/index.html"><strong aria-hidden="true">1.</strong> 关于本书</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="关于本书/参与贡献.html"><strong aria-hidden="true">1.1.</strong> 参与贡献</a></li></ol></li><li class="chapter-item expanded "><a href="开发须知/index.html"><strong aria-hidden="true">2.</strong> 开发须知</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="开发须知/运行环境.html"><strong aria-hidden="true">2.1.</strong> 运行环境</a></li><li class="chapter-item expanded "><a href="开发须知/开发工具.html"><strong aria-hidden="true">2.2.</strong> 开发工具</a></li><li class="chapter-item expanded "><a href="开发须知/学习资源.html"><strong aria-hidden="true">2.3.</strong> 学习资源</a></li><li class="chapter-item expanded "><a href="开发须知/其他经验.html"><strong aria-hidden="true">2.4.</strong> 其他经验</a></li></ol></li><li class="chapter-item expanded "><div><strong aria-hidden="true">3.</strong> 环境搭建</div></li><li><ol class="section"><li class="chapter-item expanded "><a href="环境部署/Ubuntu 20.04的安装与配置.html"><strong aria-hidden="true">3.1.</strong> Ubuntu20.04的安装与配置</a></li><li class="chapter-item expanded "><a href="环境部署/ROS noetic 的安装.html"><strong aria-hidden="true">3.2.</strong> ROS-noetic的安装</a></li><li class="chapter-item expanded "><a href="环境部署/ROS 开发环境的搭建.html"><strong aria-hidden="true">3.3.</strong> ROS开发环境的搭建</a></li><li class="chapter-item expanded "><a href="环境部署/启动激光雷达节点.html"><strong aria-hidden="true">3.4.</strong> 启动激光雷达节点</a></li><li class="chapter-item expanded "><a href="环境部署/启动机器人硬件.html"><strong aria-hidden="true">3.5.</strong> 启动机器人硬件</a></li><li class="chapter-item expanded "><a href="环境部署/启动机器人常用工具.html"><strong aria-hidden="true">3.6.</strong> 启动机器人常用工具</a></li><li class="chapter-item expanded "><a href="环境部署/启动机器人仿真环境.html"><strong aria-hidden="true">3.7.</strong> 启动机器人仿真环境</a></li></ol></li><li class="chapter-item expanded "><a href="硬件层/index.html"><strong aria-hidden="true">4.</strong> 硬件层</a></li><li><ol class="section"><li class="chapter-item expanded "><a href="硬件层/硬件驱动协议.html"><strong aria-hidden="true">4.1.</strong> ROS层硬件驱动协议</a></li><li class="chapter-item expanded "><div><strong aria-hidden="true">4.2.</strong> 上下位机通信协议</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">4.3.</strong> 下位机代码详解</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">4.4.</strong> IMU封装</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">4.5.</strong> 机器人底盘</div></li><li><ol class="section"><li class="chapter-item expanded "><div><strong aria-hidden="true">4.5.1.</strong> 底盘运动学讲解</div></li><li class="chapter-item expanded "><a href="硬件层/机器人底盘/底盘封装.html"><strong aria-hidden="true">4.5.2.</strong> 底盘封装</a></li></ol></li><li class="chapter-item expanded "><div><strong aria-hidden="true">4.6.</strong> 里程计封装</div></li></ol></li><li class="chapter-item expanded "><div><strong aria-hidden="true">5.</strong> 机器人导航</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">6.</strong> 计算机视觉</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">7.</strong> 机器人语音</div></li><li><ol class="section"><li class="chapter-item expanded "><div><strong aria-hidden="true">7.1.</strong> Respeaker方案</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">7.2.</strong> Android手机方案</div></li></ol></li><li class="chapter-item expanded "><div><strong aria-hidden="true">8.</strong> 机器人仿真</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">9.</strong> 机械臂</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">10.</strong> 篮球机器人</div></li><li><ol class="section"><li class="chapter-item expanded "><div><strong aria-hidden="true">10.1.</strong> 电磁炮</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">10.2.</strong> 起落架</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">10.3.</strong> 运动</div></li><li><ol class="section"><li class="chapter-item expanded "><div><strong aria-hidden="true">10.3.1.</strong> 定位</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">10.3.2.</strong> 地图</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">10.3.3.</strong> 导航</div></li></ol></li></ol></li><li class="chapter-item expanded "><div><strong aria-hidden="true">11.</strong> 常用工具</div></li><li><ol class="section"><li class="chapter-item expanded "><div><strong aria-hidden="true">11.1.</strong> 移动端控制网关</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">11.2.</strong> 位姿调试服务器</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">11.3.</strong> Qt小工具</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">11.4.</strong> 机器人键盘遥控</div></li><li class="chapter-item expanded "><div><strong aria-hidden="true">11.5.</strong> 机器人轮速转发调试器</div></li></ol></li></ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="rust">Rust</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
<button id="search-toggle" class="icon-button" type="button" title="Search. (Shortkey: s)" aria-label="Toggle Searchbar" aria-expanded="false" aria-keyshortcuts="S" aria-controls="searchbar">
<i class="fa fa-search"></i>
</button>
</div>
<h1 class="menu-title">上应大机协之书</h1>
<div class="right-buttons">
<a href="print.html" title="Print this book" aria-label="Print this book">
<i id="print-button" class="fa fa-print"></i>
</a>
</div>
</div>
<div id="search-wrapper" class="hidden">
<form id="searchbar-outer" class="searchbar-outer">
<input type="search" id="searchbar" name="searchbar" placeholder="Search this book ..." aria-controls="searchresults-outer" aria-describedby="searchresults-header">
</form>
<div id="searchresults-outer" class="searchresults-outer hidden">
<div id="searchresults-header" class="searchresults-header"></div>
<ul id="searchresults">
</ul>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<main>
<h2 id="编写本书的原因"><a class="header" href="#编写本书的原因">编写本书的原因</a></h2>
<p> 本书整理总结了2020年底到2021年底关于上海应用技术大学机器人爱好者协会的所有机器人技术成果,考虑后续的传承,故编写本书。希望后人的经验与成果也记录在本书中。本书将能够永远地保持更新下去,使传承不断,社团发展能够越来越好。</p>
<div style="break-before: page; page-break-before: always;"></div><h3 id="rust"><a class="header" href="#rust">Rust</a></h3>
<p> 由于本书基于由Rust编写的mdbook静态页面生成框架生成而成,故需要安装Rust编译环境。</p>
<p>https://rustup.rs/</p>
<h3 id="mdbook"><a class="header" href="#mdbook">mdbook</a></h3>
<p> mdbook的安装教程</p>
<p><a href="https://rust-lang.github.io/mdBook/guide/installation.html">Installation - mdBook Documentation</a></p>
<h3 id="git工具"><a class="header" href="#git工具">Git工具</a></h3>
<p> 直接<code>sudo apt install git</code></p>
<h3 id="marktext"><a class="header" href="#marktext">Marktext</a></h3>
<p> 所见即所得的markdown文档编辑器,以前推荐Typora,后来Typora收费了,推荐大家使用开源的markdown编辑器</p>
<h3 id="vscode"><a class="header" href="#vscode">VSCode</a></h3>
<p> 虽然为本书贡献基本不需要写代码,但是通过vscode管理mdbook的配置文件,作为可视化的git工具还是很好用的。</p>
<div style="break-before: page; page-break-before: always;"></div><p>这里总结了一系列开发须知与经验</p>
<div style="break-before: page; page-break-before: always;"></div><h2 id="运行环境"><a class="header" href="#运行环境">运行环境</a></h2>
<p>操作系统: Ubuntu20.04</p>
<p>ROS版本: 使用与 Ubuntu 20.04 配套的 ROS 的 Noetic 版本。</p>
<p> ROS Noetic与之前的版本最大的一个不同就是其Python环境的变更,在ROS melodic,kinetic 及更早的版本,使用的是 Python2.7 的运行环境,而 Noetic 原生完美支持 Python3.8 的运行环境,给我们的机器人开发带来了非常先进的 Python 开发体验。而 C++ 层面的变更到不大,基本可以兼容以前的代码。</p>
<blockquote>
<p>考古: 曾经19年之前,本社团机器人运行环境为更古老的 Ubuntu14.04 下的 ROS Indigo,远古代码的备份已存放至github。<a href="https://github.com/SIT-Robot/achieved2019">https://github.com/SIT-Robot/achieved2019</a>。后来,本人使用melodic环境重写了机器人的ros代码,经过数次迭代更新,最终迁移到最新的noetic环境,代码即如今现有的代码。</p>
</blockquote>
<div style="break-before: page; page-break-before: always;"></div><h3 id="开发工具"><a class="header" href="#开发工具">开发工具</a></h3>
<h4 id="vscode-1"><a class="header" href="#vscode-1">VSCode</a></h4>
<p> 推荐开发工具<strong>VSCode</strong>,安装ROS插件后即可愉快地开发。插件市场搜索相应插件,还可补全launch,urdf,xacro等ros下基于xml的描述配置的语言。可以直接支持打开整个工作空间,也可以只打开单个功能包,智能补全的配置大多装完插件后就自动完成了。</p>
<h4 id="clion"><a class="header" href="#clion">CLion</a></h4>
<p> CLion在开发真正的C++项目时是一个很好的选择,其智能补全与各种工程化的工具都相当好用,但是对ros而言,经常需要在多个功能包下跳转,以及需要同时编写C++和Python代码。 故推荐还是对纯C++功能包使用CLion,对混合语言功能包或多个功能包需要来回跳转编写及联合调试时使用vscode。</p>
<h4 id="qt"><a class="header" href="#qt">Qt</a></h4>
<p> Qt是一套能够编写GUI程序的框架,如果需要机器人的操作体验更好,可借助Qt实现一套图形界面的机器人控制台。我们经常使用一些rqt开头的ros工具命令,这些工具基本都是通过Qt编写的,包括Rviz及其插件也是需要通过Qt编写,有能力的同学可以编写rviz插件就可以定制出一个方便好用的图形化的机器人控制台界面。Qt底层虽然是C++编写,但其上层可不限定语言,如Python中你可以通过PyQt5编写图形程序。本人由于时间原因,未大量实现机器人的Qt图形程序,基本都是通过终端命令调用。</p>
<div style="break-before: page; page-break-before: always;"></div><h2 id="学习资源推荐"><a class="header" href="#学习资源推荐">学习资源推荐</a></h2>
<h3 id="文章资料"><a class="header" href="#文章资料">文章资料</a></h3>
<p><strong><a href="http://www.autolabor.com.cn/book/ROSTutorials/">【奥特学园--赵虚左】《ROS理论与实践》零基础教程</a></strong></p>
<p> 这篇文档与下面的奥特学院的ROS机器人入门教程是配套的,文档很详细,图也非常多,相当适合入门,其中也包含了实体机器人的部分。</p>
<p><strong>【古月居】《ROS 机器人开发实践》</strong></p>
<p>这是一个实体书籍,大家可以去学校图书馆免费借阅到。当初2020年11月的比赛全靠下面的ROS入门21讲+啃这本书完成的。书中使用的是Ubuntu20.04 ROS kinetic版本,目前已知的是其中的语音识别部分,smach状态机无法在 noetic 中使用,因为两者都需要依赖Python2.7的代码和库。</p>
<p><strong><a href="https://www.bilibili.com/read/cv12059277">【古月居】ROS入门21讲 视频补充资料</a></strong></p>
<h3 id="视频学习"><a class="header" href="#视频学习">视频学习</a></h3>
<p><strong><a href="https://www.bilibili.com/video/BV1Ci4y1L7ZZ">【奥特学园--赵虚左】ROS机器人入门课程《ROS理论与实践》零基础教程(ROS基础与仿真环境下的导航实现)</a></strong></p>
<p> 这个视频是本人在2021年初发现的关于ROS的视频学习资料,可以说是相当完美的学习资源。总共361集,可以说是相当详细的一部视频教程了。这个教程只要你肯花时间慢慢去学,一定能够学会ROS机器人开发入门。</p>
<p><strong><a href="https://www.bilibili.com/video/BV1Ub4y1a7PH">【奥特学园--赵虚左】《ROS理论与实践》第8、9章--ROS机器人操作系统(实体机器人的软硬件开发与导航实现)</a></strong></p>
<p> 这个视频是针对上一个361集视频资源的补充,原视频教程只包含了ROS的理论部分和仿真环境下的实践部分。本视频共91集,包含了上一个视频残缺的实体机器人的开发。其中涵盖了Arduino单片机开发,PID控制理论与实践,电机控制,串口协议开发,ROS实体机器人导航等知识点。</p>
<p><strong><a href="https://www.bilibili.com/video/BV1zt411G7Vn">【古月居】ROS入门21讲</a></strong></p>
<p> 这个视频是本人2020年底第一次学习机器人时看的第一个入门视频,当时在国内ROS的资料很少,尤其是视频教程。这个教程适合快速入门,快速了解上手机器人开发,但是讲的不够深入,不够细节,也不太适合零基础的小白。</p>
<div style="break-before: page; page-break-before: always;"></div><h2 id="经验之谈"><a class="header" href="#经验之谈">经验之谈</a></h2>
<h3 id="调试"><a class="header" href="#调试">调试</a></h3>
<p> ROS的 C++ 功能包本质就是一个 cmake 工程,可以直接通过 CLion/VSCode 这样的支持 cmake 工程的 ide 打开,这在调试 c++ 功能包时是及其有用的。</p>
<p> ROS的 Python 功能包与一般的 Python 项目无异,可以直接通过 Pycharm/VSCode 打开,不过如果你电脑上安装有 Anaconda 一类的Python环境,一定要注意切换使用 System Python 即可索引到相关依赖,开启智能补全。</p>
<p> 当然 Anaconda 这样的工具也是很有用的,但是不能直接在 conda 的虚拟环境中使用 ros 的功能包,需要单独配置。</p>
<h3 id="其他"><a class="header" href="#其他">其他</a></h3>
<p> 尽量熟悉 Git工具的使用,能够记录你代码的变动,也可以方便地多人协同,更能使我们的代码能够保留传承下去。</p>
<p> 善于利用 Github 上一些诸如 Github Action(CI工具) 这样提高效率的工具。</p>
<h3 id="推荐小工具"><a class="header" href="#推荐小工具">推荐小工具</a></h3>
<p>这里推荐一些其他提高开发效率的工具</p>
<ul>
<li>fish</li>
<li>zsh</li>
<li>...未完待续</li>
</ul>
<div style="break-before: page; page-break-before: always;"></div><h1 id="虚拟机安装"><a class="header" href="#虚拟机安装">虚拟机安装</a></h1>
<p>如果你仍在学习过程中,建议使用虚拟机的方式安装,虚拟机方式的安装与实体机安装大同小异
建议参考如下文章进行安装
http://www.autolabor.com.cn/book/ROSTutorials/chapter1/12-roskai-fa-gong-ju-an-zhuang.html</p>
<h1 id="实体机安装"><a class="header" href="#实体机安装">实体机安装</a></h1>
<p>一个真正的机器人运行时需要在实体机安装。
可以参考如下文字
https://blog.csdn.net/m0_60190682/article/details/118723468
也可以使用搜索引擎搜索"u盘安装 ubuntu20.04"</p>
<h1 id="安装建议"><a class="header" href="#安装建议">安装建议</a></h1>
<p>安装界面大概如下图所示,</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-03-23-50-image.png" alt="" /></p>
<ol>
<li>
<p>建议安装之前先断网,否则安装过程可能会自动更新,而未换源之前更新将直接连接国外服务器,会导致安装进度巨慢无比。建议断网安装结束后,进系统后手动换源后手动更新。</p>
</li>
<li>
<p>建议安装使用英文界面,不过Linux下中文不会像Windows那样轻易出现乱码情况(统一UTF-8编码),但是在纯终端界面下将会出现中文方块的情况。</p>
</li>
</ol>
<h1 id="虚拟机增强工具"><a class="header" href="#虚拟机增强工具">虚拟机增强工具</a></h1>
<blockquote>
<p>PS: 该内容仅虚拟机安装的用户需要关注。</p>
</blockquote>
<p>当我们安装完虚拟机后,通过安装虚拟机增强工具可以使得虚拟机与物理机进行方便地交互。</p>
<p>如果我们使用的是VMware虚拟机,那么我们可进行如下操作,</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-03-37-06-image.png" alt="" /></p>
<p>然后我们发现出现了一个光盘设备,在此处打开终端</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-03-38-23-image.png" alt="" /></p>
<p><a href="https://docs.vmware.com/cn/VMware-Workstation-Pro/16.0/com.vmware.ws.using.doc/GUID-08BB9465-D40A-4E16-9E15-8C016CC8166F.html">在 Linux 虚拟机中手动安装 VMware Tools</a></p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-03-46-22-image.png" alt="" /></p>
<p>当提示上述信息时,增强工具便安装成功,然后可以输入<code>reboot</code>命令重启电脑。</p>
<p>重启之后你会发现虚拟机的分辨率将会随着虚拟机窗口而进行缩放,剪切板也可相互共享,大大提高的虚拟机的便捷性。</p>
<h1 id="系统更新"><a class="header" href="#系统更新">系统更新</a></h1>
<p>断网安装完系统之后,就可以联网了。</p>
<blockquote>
<p>由于现在Ubuntu 22.04已发布,可能会弹窗提示升级Ubuntu 22.04,请不要升级,因为后面我们需要安装的ROS1 的noetic发行版是需要绑定Ubuntu 20.04的发行版的。</p>
</blockquote>
<p>需要先更换国内源,可以参考以下清华源或科大源的文档。</p>
<p><a href="https://mirrors.tuna.tsinghua.edu.cn/help/ubuntu/">ubuntu | 镜像站使用帮助 | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror</a></p>
<p><a href="https://mirrors.ustc.edu.cn/help/ubuntu.html">Ubuntu 源使用帮助 — USTC Mirror Help 文档</a></p>
<p>更换国内源后便可通过以下命令更新apt源</p>
<pre><code class="language-shell">sudo apt update
</code></pre>
<p>再运行以下命令执行系统软件包更新</p>
<pre><code class="language-shell">sudo apt upgrade -y
</code></pre>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-03-55-00-image.png" alt="" /></p>
<p>更新完毕</p>
<h1 id="中文输入法"><a class="header" href="#中文输入法">中文输入法</a></h1>
<p>中文输入法很有用,不管是写代码注释还是上网搜索均需要使用到中午输入。</p>
<p>如果你安装的是中文ubuntu,则已经会自带一个中文输入法;如果你安装的是英文ubuntu,则不会自带中文输入法。</p>
<p>不过,系统自带的中文输入法个人感觉较为难用。在此推荐安装使用搜狗输入法。</p>
<p><a href="https://shurufa.sogou.com/linux">搜狗输入法linux-首页</a></p>
<p>官网已有详细的安装说明,再次不展开赘述。(需要严格执行官方帮助中的每一条命令,如果输入法还是无法正常使用,请再次重复执行)</p>
<p>将搜狗输入法加入输入法列表中。</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-04-05-49-image.png" alt="" /></p>
<p>此时已经能够输入中文了</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/Ubuntu%2020.04%E7%9A%84%E5%AE%89%E8%A3%85%E4%B8%8E%E9%85%8D%E7%BD%AE/2022-09-18-04-14-18-image.png" alt="" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="参考文章"><a class="header" href="#参考文章">参考文章</a></h1>
<p>ROS的安装参考如下文章,</p>
<p>ROS官方wiki</p>
<p><a href="http://wiki.ros.org/noetic/Installation/Ubuntu">noetic/Installation/Ubuntu - ROS Wiki</a></p>
<p>奥特学园</p>
<p><a href="http://www.autolabor.com.cn/book/ROSTutorials/chapter1/12-roskai-fa-gong-ju-an-zhuang/124-an-zhuang-ros.html">1.2.4 安装 ROS · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程</a></p>
<h1 id="ros安装"><a class="header" href="#ros安装">ROS安装</a></h1>
<p>配置完ROS源之后,使用</p>
<pre><code class="language-shell">sudo apt install ros-noetic-desktop-full
</code></pre>
<p>即可开始漫长的安装过程。</p>
<blockquote>
<p>PS: Linux 绝大多数命令行输入都可以按键盘上的Tab键来自动补全,擅于使用补全有利于提高工作效率。</p>
</blockquote>
<p>如下图将开始漫长的ROS安装过程(此时你可以把电脑放一边去吃个饭什么的),</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20noetic%20%E7%9A%84%E5%AE%89%E8%A3%85/2022-09-18-04-22-17-image.png" alt="" /></p>
<p>下图便是下载完毕开始安装的步骤</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20noetic%20%E7%9A%84%E5%AE%89%E8%A3%85/2022-09-18-12-31-50-image.png" alt="" /></p>
<h1 id="ros配置"><a class="header" href="#ros配置">ROS配置</a></h1>
<p>最终ROS将会被安装到/opt/ros/noetic目录下,此时还无法运行ros相关命令,我们可以在ros安装目录下发现setup.bash文件,该文件为ros环境的初始化文件。</p>
<p>使用命令</p>
<pre><code class="language-shell">source /opt/ros/noetic/setup.bash
</code></pre>
<p>即可完成当前终端下的ros环境变量的配置。</p>
<p>此时运行<code>roscore</code>便可以启动ros master节点</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20noetic%20%E7%9A%84%E5%AE%89%E8%A3%85/2022-09-18-12-47-11-image.png" alt="" /></p>
<p>为了方便使用不用每次启动终端都需要source,可将环境变量配置到.bashrc文件中</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20noetic%20%E7%9A%84%E5%AE%89%E8%A3%85/2022-09-18-12-49-31-image.png" alt="" /></p>
<h1 id="ros测试"><a class="header" href="#ros测试">ROS测试</a></h1>
<p>开三个终端,每个终端分别运行如下命令</p>
<p><code>roscore</code></p>
<p><code>rosrun turtlesim turtlesim_node</code></p>
<p><code>rosrun turtlesim turtle_teleop_key</code></p>
<p>即可在第三个终端窗口下通过方向键操作第二个终端打开的小海龟窗口中的海龟了。</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20noetic%20%E7%9A%84%E5%AE%89%E8%A3%85/2022-09-18-12-54-16-image.png" alt="" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="参考文献"><a class="header" href="#参考文献">参考文献</a></h1>
<p><a href="http://www.autolabor.com.cn/book/ROSTutorials/chapter1/14-ros-ji-cheng-kai-fa-huan-jing-da-jian.html">1.4 ROS集成开发环境搭建 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程</a></p>
<p>根据文章中的指示去安装Terminator与VSCode</p>
<h1 id="vscode插件安装"><a class="header" href="#vscode插件安装">VSCode插件安装</a></h1>
<p>直接在插件市场搜索ros,安装排名第一的插件即可</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E7%9A%84%E6%90%AD%E5%BB%BA/2022-09-18-13-01-52-image.png" alt="" /></p>
<p>此时可以看到安装完ROS插件后已经会自动帮我们安装C/C++和Python相关的插件。</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/ROS%20%E5%BC%80%E5%8F%91%E7%8E%AF%E5%A2%83%E7%9A%84%E6%90%AD%E5%BB%BA/2022-09-18-13-03-30-image.png" alt="" /></p>
<div style="break-before: page; page-break-before: always;"></div><p>服务机器人上的激光雷达的ROS驱动程序可直接通过apt进行安装。</p>
<pre><code class="language-bash">sudo apt install ros-noetic-urg-node
</code></pre>
<p>然后使用命令</p>
<pre><code class="language-bash">rosrun urg_node urg_node
</code></pre>
<p>便可以启动激光雷达节点</p>
<p>通过<code>rostopic list</code>即可查看所有的话题列表中包含了激光雷达节点发布的话题/scan了</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E8%8A%82%E7%82%B9/2022-09-18-13-13-51-image.png" alt="" /></p>
<p>使用<code>rostopic echo /scan</code>即可查看/scan话题下发布的数据流。</p>
<p>也可在rviz的可视化工具中,添加LaserScan可视化组件</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E8%8A%82%E7%82%B9/2022-09-18-13-16-07-image.png" alt="" /></p>
<p>设置该可视化组件绑定的话题为/scan,然后便可在右侧三维空间中显示当前的激光雷达点云信息。(可能还需要设置全局坐标系为激光雷达的坐标系,默认为地图坐标系,但是地图此时还未加载)<img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%BF%80%E5%85%89%E9%9B%B7%E8%BE%BE%E8%8A%82%E7%82%B9/2022-09-18-13-17-35-image.png" alt="" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="ros工作目录"><a class="header" href="#ros工作目录">ROS工作目录</a></h1>
<p>如果还没有创建自己的ROS工作目录,请先创建一个自己的ROS工作目录。</p>
<p>请先完成如下章节实验</p>
<p><a href="http://www.autolabor.com.cn/book/ROSTutorials/chapter1/13-rosji-cheng-kai-fa-huan-jing-da-jian.html">1.3 ROS快速体验 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程</a></p>
<h1 id="下载代码"><a class="header" href="#下载代码">下载代码</a></h1>
<p>进入工作目录的src目录下,</p>
<p>从github上clone仓库(这一步之前请先安装git, <code>sudo apt install git</code>)</p>
<pre><code class="language-shell">git clone https://github.com/SIT-Robot/sit-robot-hardware.git
</code></pre>
<p>注意从github上clone代码可能需要配置代理服务器。</p>
<p>如果虚拟机中,已安装clash环境,则可直接使用以下命令配置git代理</p>
<pre><code class="language-bash">git config --global http.proxy http://127.0.0.1:7890
git config --global https.proxy http://127.0.0.1:7890
</code></pre>
<p>然后代码便下载成功</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A1%AC%E4%BB%B6/2022-09-18-13-38-17-image.png" alt="" /></p>
<p>然后返回catkin_ws即可运行<code>catkin_make</code>编译硬件层代码。</p>
<p>如果我们没有安装ros的串口包,可能会报错如下</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A1%AC%E4%BB%B6/2022-09-18-13-39-13-image.png" alt="" /></p>
<p>此时只需运行<code>sudo apt install ros-noetic-serial</code>即可完成ros串口驱动包的安装。</p>
<p>再次执行编译,即可完成硬件层代码的编译</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A1%AC%E4%BB%B6/2022-09-18-13-41-07-image.png" alt="" /></p>
<p>此时连接下位机串口,运行命令</p>
<p><code>rosrun sit_protocol protocol_forwarder_node</code>即可运行上下位机之间通信的节点。</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A1%AC%E4%BB%B6/2022-09-18-13-42-03-image.png" alt="" /></p>
<p>通过ls命令可以查看机器人硬件层的功能包如下,</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E7%A1%AC%E4%BB%B6/2022-09-18-13-43-27-image.png" alt="" /></p>
<p>其中,</p>
<ol>
<li>
<p><code>sit_protocol</code>便为上下位机通信包,主要负责数据包解析,发送,crc校验等工作</p>
</li>
<li>
<p><code>sit_protocol_msgs</code>为上下位机通信的消息文件,主要提供给其他硬件节点用于收发消息</p>
</li>
<li>
<p><code>sit_chassis</code>为底盘运动节点,高层模块可向该节点发送vx,vy方向的线速度与vw方向的角速度,该节点用于将速度按照具体的机器人物理结构分解为各个轮子的角速度并转换为相应的控制指令发送至<code>sit_protocol</code>节点,<code>sit_protocol</code>节点再进一步通过串口消息发送到下位机。同时,上位机还可发送实际轮速信息的询问消息,下位机将需要反馈实时的轮速。</p>
</li>
<li>
<p><code>sit_chassis_imu</code>为底盘imu节点,用于接收imu角度消息,其不断向<code>sit_protocol</code>节点发送询问imu的消息,<code>sit_protocol</code>节点也在不断反馈imu消息给<code>sit_chassis_imu</code>,并由<code>sit_chassis_imu</code>对外广播imu消息。</p>
</li>
<li>
<p><code>sit_odom</code>为里程计节点,其接受<code>sit_chassis</code>反馈回的实时速度信息与</p>
</li>
<li>
<p><code>sit_chassis_imu</code>反馈回的角度信息,通过积分后得到里程计信息。</p>
</li>
</ol>
<div style="break-before: page; page-break-before: always;"></div><h1 id="下载代码-1"><a class="header" href="#下载代码-1">下载代码</a></h1>
<pre><code class="language-shell">git clone https://github.com/SIT-Robot/sit-robot-tools.git
</code></pre>
<h1 id="编译代码"><a class="header" href="#编译代码">编译代码</a></h1>
<p><code>catkin_make</code></p>
<h1 id="启动机器人键盘控制器"><a class="header" href="#启动机器人键盘控制器">启动机器人键盘控制器</a></h1>
<p>运行命令</p>
<pre><code class="language-bash">rosrun sit_teleop teleop.py
</code></pre>
<p>即可启动控制器如下,</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E5%B8%B8%E7%94%A8%E5%B7%A5%E5%85%B7/2022-09-18-13-58-58-image.png" alt="" /></p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="建议"><a class="header" href="#建议">建议</a></h1>
<p>还是建议在完成了下面文章和视频的学习之后再进行本章的学习,如果能完整的学习完该视频与文档,那么本篇文章可能很快就能完成甚至发现文章中的疏漏。</p>
<p><a href="http://www.autolabor.com.cn/book/ROSTutorials/di-7-zhang-ji-qi-ren-dao-822a28-fang-771f29.html">第 7 章 机器人导航(仿真) · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程</a></p>
<p>还有配套视频</p>
<p>https://www.bilibili.com/video/BV1Ci4y1L7ZZ</p>
<p>P229-P328章节</p>
<p>本人当时学习完这些章节且搭建出自己的机器人仅需一天时间即可完成</p>
<h1 id="克隆代码"><a class="header" href="#克隆代码">克隆代码</a></h1>
<pre><code class="language-shell">git clone https://github.com/SIT-Robot/sit-service-robot.git
git clone https://github.com/SIT-Robot/sit-basketball-robot.git
</code></pre>
<h1 id="编译代码-1"><a class="header" href="#编译代码-1">编译代码</a></h1>
<pre><code class="language-shell">catkin_make
</code></pre>
<p>有可能报错如下,</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-10-19-41-image.png" alt="" /></p>
<pre><code class="language-shell">sudo apt install ros-noetic-navigation
sudo apt install ros-noetic-gmapping
</code></pre>
<h1 id="启动环境"><a class="header" href="#启动环境">启动环境</a></h1>
<p>此时启动机器人仿真环境</p>
<p>可能报错如下,我们需要安装urdf的python插件</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-10-30-53-image.png" alt="" /></p>
<pre><code class="language-shell">sudo apt install ros-noetic-urdfdom-py
</code></pre>
<p>再次启动仍可能报错如下,我们需要安装realsense2_description包</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-10-45-24-image.png" alt="" /></p>
<pre><code class="language-shell">sudo apt install ros-noetic-realsense2-description
</code></pre>
<p>此时已经成功启动机器人仿真环境,但是可能效果如下,显示异常</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-10-47-37-image.png" alt="" /></p>
<p>使用<code>roslaunch sit_service_description service_robot_viz.launch</code>打开rviz查看</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-10-55-48-image.png" alt="" /></p>
<p>发现似乎是tf全部失效。</p>
<p>根据以下文章,查看tf树</p>
<p><a href="http://www.autolabor.com.cn/book/ROSTutorials/di-5-zhang-ji-qi-ren-dao-hang/51-tfzuo-biao-bian-huan/515-zuo-biao-xi-guan-xi-cha-kan.html">5.1.5 坐标系关系查看 · Autolabor-ROS机器人入门课程《ROS理论与实践》零基础教程</a></p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-10-56-29-image.png" alt="" /></p>
<p>发现目前仅存在上述tf变换。</p>
<p>重开几次,有一定几率建立完整tf</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-11-08-37-image.png" alt="" /></p>
<p>此时继续启动service_robot_viz.launch,可发现机器人已经成功加载,并且显示出模型,雷达线等。</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-11-11-10-image.png" alt="" /></p>
<p>如果电脑性能较好,还可尝试订阅深度相机发布的点云消息,</p>
<p><img src="%E7%8E%AF%E5%A2%83%E9%83%A8%E7%BD%B2/%E5%90%AF%E5%8A%A8%E6%9C%BA%E5%99%A8%E4%BA%BA%E4%BB%BF%E7%9C%9F%E7%8E%AF%E5%A2%83/2022-09-19-11-14-03-image.png" alt="" /></p>
<h1 id="启动键盘控制器"><a class="header" href="#启动键盘控制器">启动键盘控制器</a></h1>
<p>启动键盘控制器</p>
<p><code>rosrun sit_teleop teleop.py</code></p>
<p>即可使用键盘控制rviz中的机器人了。</p>
<blockquote>
<p>PS: Gazebo中的场景贴图还是无法正常加载,我也不清楚为何,或许是虚拟机的问题。但是rviz中已经实现了机器人的可视化,并显示周围的环境感知。</p>
</blockquote>
<h1 id="slam建图"><a class="header" href="#slam建图">SLAM建图</a></h1>
<p><code>roslaunch sit_nav gmapping_slam.launch</code> 即可启动slam建图,使用键盘控制机器人运动,即可逐步建立环境地图。</p>
<div style="break-before: page; page-break-before: always;"></div><p>上海应用技术大学机器人爱好者协会机器人基本硬件层代码详解</p>
<div style="break-before: page; page-break-before: always;"></div><h1 id="代码仓库"><a class="header" href="#代码仓库">代码仓库</a></h1>
<p><img src="%E7%A1%AC%E4%BB%B6%E5%B1%82/%E7%A1%AC%E4%BB%B6%E9%A9%B1%E5%8A%A8%E5%8D%8F%E8%AE%AE/2022-03-19-14-46-24-image.png" alt="" /></p>
<p>https://github.com/SIT-Robot/sit-robot-hardware</p>
<h1 id="概要"><a class="header" href="#概要">概要</a></h1>
<p>我们在通过ros控制实体机器人时,免不了要跟真实的硬件打交道,这里的代码存放了与下位机通信的协议,对下位机的imu封装,对下位机底盘的运动学封装,对下位机里程计的封装。</p>
<p>这些功能包的依赖关系如下,</p>
<pre><code class="language-mermaid">graph TD;
A[sit_protocol_msgs]
B[sit_protocol]
C[sit_chassis]
D[sit_chassis_imu]
E[sit_odom]
A-->B
B-->C
B-->D
C-->E
D-->E
</code></pre>
<h2 id="sit_protocol_msgs"><a class="header" href="#sit_protocol_msgs">sit_protocol_msgs</a></h2>
<p>该功能包为一切与硬件通信的协议消息基石</p>
<p>规定机器人下位机与上位机之间任何消息传递均以数据帧为单位,对于任何ros层封装的硬件驱动,必须遵循此协议消息包进行封装。</p>
<h3 id="消息定义"><a class="header" href="#消息定义">消息定义</a></h3>
<h4 id="cmddataframemsg"><a class="header" href="#cmddataframemsg">CmdDataFrame.msg</a></h4>
<p>该消息规定了一帧消息协议</p>
<pre><code class="language-bash"># 机器人的串口数据帧
# 地址域 8位的单字节地址(禁止是0号地址)
uint8 address
# 命令域 8位的单字节指令
uint8 cmd
# 数据域 可变长的字节数组
uint8[] data
</code></pre>
<p>每个设备自身都有对应的一个8位的地址,存于address字段。</p>
<p>如果一个address确定,那么目标通讯设备将确定。</p>
<p>下位机设备收到消息后,读取8位的cmd字段确定需要执行什么操作,通过解析data数组中的内容,执行相应的操作。</p>
<h3 id="服务定义"><a class="header" href="#服务定义">服务定义</a></h3>
<h4 id="requestdataframesrv"><a class="header" href="#requestdataframesrv">RequestDataFrame.srv</a></h4>
<pre><code class="language-bash"># 发送请求数据帧
sit_protocol_msgs/CmdDataFrame request
# 等待响应的数据帧指令值
uint8 waitCmd
# 超时时间(单位ms) 默认值100ms
uint16 timeout = 100
---
# 接收响应数据帧
sit_protocol_msgs/CmdDataFrame response
</code></pre>
<p>上位机与下位机的通讯为同步的请求响应模型,上位机发送一个request数据帧,下位机收到后必须返回一个response数据帧,其中waitCmd为上位机期望的response中的cmd字段,若上位机在timeout时间内未收到response字段或response中的cmd与waitCmd不匹配,则视为请求超时,本次请求执行失败。</p>
<h2 id="sit_protocol"><a class="header" href="#sit_protocol">sit_protocol</a></h2>
<p>本功能包为与硬件通信的网关,所有的CmdDataFrame数据帧均传递到本功能包中</p>
<h3 id="代码"><a class="header" href="#代码">代码</a></h3>
<h4 id="cmddataframe结构体"><a class="header" href="#cmddataframe结构体">CmdDataFrame结构体</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_protocol/include/sit_protocol/CmdDataFrame.h">include/sit_protocol/CmdDataFrame.h</a></p>
<p>该头文件定义了与ros解耦的数据帧定义</p>
<p>其成员函数generateBytes实现了该帧数据帧消息的二进制序列化操作,主要添加包头包尾,添加地址,命令,数据长度,数据域,校验和等字节信息。</p>
<p>toByteString,toString这俩函数主要是调试时输出数据帧信息的调试专用函数。</p>
<p>这里节选generateBytes函数实现,可以看出其实现还是比较简单的</p>
<pre><code class="language-cpp"> std::vector<uint8_t> generateBytes(){
std::vector<uint8_t> bytes;
bytes.push_back(0x55);
bytes.push_back(0xAA);
bytes.push_back(address);
bytes.push_back(cmd);
bytes.push_back(data.size());
for(uint8_t i : data){
bytes.push_back(i);
}
// uint8_t sum = std::accumulate(bytes.begin()+2,bytes.end(),0);
uint8_t sum = crc8(bytes.begin()+2,bytes.end());
bytes.push_back(sum);
bytes.push_back(0xBB);
bytes.push_back(0xCC);
return bytes;
}
</code></pre>
<h4 id="dataframeparser类"><a class="header" href="#dataframeparser类">DataFrameParser类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_protocol/include/sit_protocol/DataFrameParser.h">include/sit_protocol/DataFrameParser.h</a></p>
<p>该头文件定义了数据帧解析类,同样与ros解耦</p>
<p>可以想象该类为一台机器,向其中扔一个个字节,当能够组合出一组合法的二进制串为DataFrame时,你便可通过popFrame拿到其加工好的DataFrame</p>
<p>该类的职责便是反序列化出一个个DataFrame对象,它有两个public的成员函数。</p>
<ul>
<li>
<p>pushByte(uint8_t byte)</p>
<ul>
<li>放入一个字节</li>
</ul>
</li>
<li>
<p>pushBytes(uint8_t *byte, int len)</p>
<ul>
<li>放入一堆字节</li>
</ul>
</li>
<li>
<p>CmdDataFrame popFrame()</p>
<ul>
<li>取出一个数据帧</li>
</ul>
</li>
<li>
<p>bool empty()</p>
<ul>
<li>是否为空,如果不为空,则代表可以popFrame取出一个数据帧</li>
</ul>
</li>
</ul>
<h4 id="serialcommunicator类"><a class="header" href="#serialcommunicator类">SerialCommunicator类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_protocol/include/sit_protocol/SerialCommunicator.h">include/sit_protocol/SerialCommunicator.h</a></p>
<p>该文件实现了基于串口面向字节流数据传输协议的通讯工具,其基于DataFrameParser类实现了在不可靠的串口通信下提供了基于帧数据传输,带有了错误校验的相对可靠的数据传输服务。</p>
<p>该类的构造函数需要传入一个Serial对象(本类依赖了serial串口通信库),然后其便提供了异步通信的如下函数</p>
<ul>
<li>
<p>void sendFrame(CmdDataFrame& frame)</p>
<ul>
<li>发送一个数据帧</li>
</ul>
</li>
<li>
<p>bool receivable()</p>
<ul>
<li>是否存在可接收的数据帧</li>
</ul>
</li>
<li>
<p>CmdDataFrame receive()</p>
<ul>
<li>接收一帧数据</li>
</ul>
</li>
</ul>
<p>还提供了更方便的同步通信函数</p>
<ul>
<li>
<p>bool requestFrame(CmdDataFrame req_frame, CmdDataFrame& resp_frame, uint16_t timeout = 40)</p>
<ul>
<li>
<p>该函数需传入请求数据帧信息,用于响应的接收数据帧(其需要接收数据,故使用引用传递),最大超时时间,同步请求必须设置超时时间,否则程序通信失败时本函数将卡死</p>
</li>
<li>
<p>该函数返回值表示是否接收到响应帧信息,只有接收到响应,本次请求才视为成功请求。</p>
</li>
</ul>
</li>
</ul>
<h4 id="protocolnode类"><a class="header" href="#protocolnode类">ProtocolNode类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_protocol/include/sit_protocol/ProtocolNode.h">include/sit_protocol/ProtocolNode.h</a></p>
<p>该类将SerialCommunicator类中的同步通信函数通过ros的服务通信机制封装了一层。</p>
<p>本类需要传入一个device_pool,这是一个map,其中key为uint8_t的整数,代表了设备地址,所有ros服务接收到的消息均通过其request数据帧中的地址查询device_pool分发到不同的设备。</p>
<h4 id="utilsh"><a class="header" href="#utilsh">utils.h</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_protocol/include/sit_protocol/utils.h">include/sit_protocol/utils.h</a></p>
<p>该头文件定义了一些常用工具,如crc8校验</p>
<h4 id="入口文件"><a class="header" href="#入口文件">入口文件</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_protocol/src/sit_protocol_serial.cpp">sit_protocol/src/sit_protocol_serial.cpp</a>
最后,该文件为主入口文件,main函数便定义在此,它完成了根据特定协议进行下位机自动发现,串口初始化,启动ProtocolNode类等操作。</p>
<div style="break-before: page; page-break-before: always;"></div><h4 id="achassis接口"><a class="header" href="#achassis接口">AChassis接口</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/include/sit_chassis/AChassis.h">sit_chassis/include/sit_chassis/AChassis.h</a></p>
<p>该文件定义了二维平面机器人的抽象接口,该接口存在两个待实现的纯虚函数。</p>
<pre><code class="language-cpp"> /**
* @brief 对底盘设置一个期望速度
*
* @param vx x轴方向的期望速度
* @param vy y轴方向上的期望速度
* @param vw 环绕z轴方向的转速
*/
virtual void setSpeed(double vx,double vy,double vw) = 0;
/**
* @brief 获取底盘当前时刻的速度
*
* @param vx x轴方向的实际速度
* @param vy y轴方向上的实际速度
* @param vw 环绕z轴方向的转速
*/
virtual void getSpeed(double& vx,double& vy,double& vw) = 0;
</code></pre>
<h4 id="athreechassis抽象类"><a class="header" href="#athreechassis抽象类">AThreeChassis抽象类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/include/sit_chassis/AThreeChassis.h">sit_chassis/include/sit_chassis/AThreeChassis.h</a></p>
<p>该类定义了一个抽象的三轮全向底盘的运动学实现的抽象类,它提供了两个纯虚函数,</p>
<pre><code class="language-cpp"> /**
* @brief 设置车轮的期望线速度,具体通过怎样的方式下发速度指令,继续由子类实现,
* 车轮线速度单位为 m/s
*
* @param v1 1号车轮的线速度
* @param v2 2号车轮的线速度
* @param v3 3号车轮的线速度
*/
virtual void setWheelSpeed(double v1, double v2, double v3) = 0;
/**
* @brief 获取当前时刻车轮速度
*
* @param v1 1号车轮的线速度
* @param v2 2号车轮的线速度
* @param v3 3号车轮的线速度
*/
virtual void getWheelSpeed(double& v1,double& v2,double& v3) = 0;
</code></pre>
<p>在本类中,我们假设调用这些纯虚函数即可实现设置轮速与获取轮速。</p>
<p>根据运动学公式,即可实现如下底盘的速度获取与设置的成员函数。</p>
<pre><code class="language-cpp"> void setSpeed(double vx, double vy, double vw) override
{
const double M_PI_6 = M_PI / 6;
//ROS_INFO("Speed:[%f, %f, %f]", vx, vy, vw);
//需要将速度进行分解到三个轮子上
double vb = -vy + vw * L;
double vl = -vx * cos(M_PI_6) + vy * sin(M_PI_6) + vw * L;
double vr = vx * cos(M_PI_6) + vy * sin(M_PI_6) + vw * L;
//设置轮速
setWheelSpeed(vb, vr, vl);
}
void getSpeed(double& vx,double& vy,double& vw) override
{
//需要获取三个轮子的轮速,合成出轮子速度
//获取三个轮子速度
double v1,v2,v3;
getWheelSpeed(v1,v2,v3);
//速度合成
vx = (v2 - v3) * (sqrt(3) / 3);
vy = (-2 * v1+ v2+ v3) / 3;
vw = (v1 + v2 + v3) / (3 * L);
}
</code></pre>
<h4 id="threechassis实现类"><a class="header" href="#threechassis实现类">ThreeChassis实现类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/include/sit_chassis/ThreeChassis.h">sit_chassis/include/sit_chassis/ThreeChassis.h</a></p>
<p>该类通过sit_protocol功能包实现向下位机获取与设置原始轮速,本类继续通过引入比例系数K,结合原始轮速实现了AThreeChassis抽象类中的设置与获取轮速的纯虚函数。</p>
<h4 id="chassisnode类"><a class="header" href="#chassisnode类">ChassisNode类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/include/sit_chassis/ChassisNode.h">sit_chassis/include/sit_chassis/ChassisNode.h</a></p>
<p>该类实现了AChassis接口与ros的发布订阅机制的结合,前面之所以划分出较为复杂的抽象层次结构,最精彩的便是在本类中体现,观察本类发现,其并不依赖于任何具体实现类,而仅依赖了AChassis接口。</p>
<p>熟悉设计模式的同学可以看出,这里实现了依赖倒置原则。它的好处就是,借助c++的动态多态性,我们可以实现更多的运动模型底盘实现类,其均可作为AChassis传入本类的构造函数,从而将底盘接入整个ros生态,这大大提高了软件的可复用性,降低了耦合度。</p>
<h4 id="主入口类"><a class="header" href="#主入口类">主入口类</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/src/three_chassis_node.cpp">sit_chassis/src/three_chassis_node.cpp</a></p>
<p>该类为主入口类,其实现较为简单,代码如下,</p>
<pre><code class="language-cpp">#include <ros/ros.h>
#include <sit_chassis/ThreeChassis.h>
#include <sit_chassis/ChassisNode.h>
int main(int argc, char **argv)
{
setlocale(LC_ALL, "");
ros::init(argc, argv, "three_chassis"); //初始化三轮底盘节点
ros::NodeHandle nh("~");
ThreeChassis chassis(nh);
ChassisNode cn(nh,&chassis);
for (ros::Rate rate(20); ros::ok(); rate.sleep())
{
cn.spinOnce();
ros::spinOnce();
}
return 0;
}
</code></pre>
<h4 id="launch文件"><a class="header" href="#launch文件">launch文件</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/launch/chassis.launch">sit_chassis/launch/chassis.launch</a></p>
<pre><code class="language-xml"><?xml version="1.0"?>
<launch>
<arg name="k" default="-4772.44"/>
<arg name="radius" default="0.1900"/>
<node pkg="sit_chassis" type="three_chassis_node" name="chassis_node" output="screen">
<param name="k" value="$(arg k)"/>
<param name="radius" value="$(arg radius)"/>
</node>
</launch>
</code></pre>
<p>该文件启动一个三轮底盘节点,需要传入两个标定系数k与底盘半径radius。</p>
<p>底盘半径radius一般为手动测量得出。</p>
<p>标定系数k可由脚本自动标定得出。</p>
<h4 id="script脚本"><a class="header" href="#script脚本">script脚本</a></h4>
<p><a href="https://github.com/SIT-Robot/sit-robot-hardware/blob/master/sit_chassis/scripts/calibrator.py">sit_chassis/scripts/calibrator.py</a></p>
<p>本脚本用于标定出底盘系数k。</p>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="elasticlunr.min.js" type="text/javascript" charset="utf-8"></script>
<script src="mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="searcher.js" type="text/javascript" charset="utf-8"></script>
<script src="clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="book.js" type="text/javascript" charset="utf-8"></script>
<!-- Custom JS scripts -->
<script type="text/javascript" src="mermaid.min.js"></script>
<script type="text/javascript" src="mermaid-init.js"></script>
<script type="text/javascript">
window.addEventListener('load', function() {
window.setTimeout(window.print, 100);
});
</script>
</body>
</html>