-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVirtualRobot.html
725 lines (677 loc) · 62.8 KB
/
VirtualRobot.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
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.17: http://docutils.sourceforge.net/" />
<title>VirtualRobot — iss22 1.0 documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
<script src="_static/jquery.js"></script>
<script src="_static/underscore.js"></script>
<script src="_static/doctools.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
<link rel="next" title="Using WEnv" href="UsingWEnv.html" />
<link rel="prev" title="RaspBasicCode" href="RaspBasicCode.html" />
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
<meta name="viewport" content="width=device-width, initial-scale=0.9, maximum-scale=0.9" />
</head><body>
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<section id="virtualrobot">
<h1>VirtualRobot<a class="headerlink" href="#virtualrobot" title="Permalink to this headline">¶</a></h1>
<p>Unibo ha sviluppato un ambiente virtuale (denominato <code class="docutils literal notranslate"><span class="pre">WEnv</span></code> ) che include un robot
che simula un <em>Differential Drive robot</em> (<strong>DDR</strong>) reale.</p>
<section id="differential-drive-robot">
<h2>Differential Drive robot<a class="headerlink" href="#differential-drive-robot" title="Permalink to this headline">¶</a></h2>
<p>Un <a class="reference external" href="https://www.youtube.com/watch?v=aE7RQNhwnPQ">DDR Robot</a> possiede due ruote motrici sullo stesso asse e una terza ruota condotta (non motrice).
La tecnica <em>differential drive</em> consiste nel far muovere le ruote motrici a velocità
indipendenti l’una dall’altra.</p>
<p>Nel seguito faremo riferimento a una forma semplificata di DDR in cui le possibìili mosse sono:</p>
<ul class="simple">
<li><p>muoversi avanti-indietro lungo una direzione costante</p></li>
<li><p>fermarsi</p></li>
<li><p>ruotare di 90° a destra o sinistra</p></li>
</ul>
<p>Queste mosse sono realizzate inviando opportuni comandi al robot (simulato o reale).</p>
<section id="robot-reali">
<h3>Robot reali<a class="headerlink" href="#robot-reali" title="Permalink to this headline">¶</a></h3>
<p>Per la costruzione di un DDR reale si veda <a class="reference external" href="./_static/devsDdr.html">devsDdr</a>.
Al momento useremo una versione simulata, che descriviamo nella sezione <a class="reference internal" href="#wenv"><span class="std std-ref">WEnv</span></a>.</p>
<p>Lo scopo non è certo quello di affrontare i problemi di progettazione tipici di un corso di robotica, ma quello di
introdurre casi di studio non banali per la costruzione di sistemi software distribuiti <strong>reattivi</strong>, <strong>proattivi</strong> e
<strong>situati</strong> in un ambiente che può essere fonte di <a class="reference internal" href="Eventi.html#eventi"><span class="std std-ref">Eventi</span></a>.</p>
</section>
</section>
<section id="wenv">
<h2>WEnv<a class="headerlink" href="#wenv" title="Permalink to this headline">¶</a></h2>
<p>L’ambiente virtuale WEnv è stato realizzato principalmente da <a class="reference external" href="https://github.com/PierfrancescoSoffritti/ConfigurableThreejsApp">Pierfrancesco Soffritti</a> utilizzando la
libreria JavaScript <a class="reference external" href="https://threejs.org/">three.js</a>. Il codice è disponibile nel progetto <code class="docutils literal notranslate"><span class="pre">it.unibo.virtualRobot2020</span></code>.</p>
<p>Per attivare WEnv:</p>
<ul class="simple">
<li><p>Installare <a class="reference external" href="https://nodejs.org/it/">Node.js</a></p></li>
<li><p>In <code class="docutils literal notranslate"><span class="pre">it.unibo.virtualRobot2020\node\WEnv\server</span></code>, eseguire <strong>npm install</strong></p></li>
<li><p>In <code class="docutils literal notranslate"><span class="pre">it.unibo.virtualRobot2020\node\WEnv\WebGLScene</span></code>, eseguire <strong>npm install</strong></p></li>
<li><p>In <code class="docutils literal notranslate"><span class="pre">it.unibo.virtualRobot2020\node\WEnv\server\src</span></code>, eseguire <strong>node WebpageServer.js</strong></p></li>
</ul>
<section id="usare-wenv">
<h3>Usare WEnv<a class="headerlink" href="#usare-wenv" title="Permalink to this headline">¶</a></h3>
<p>Aprendo un browser su <strong>localhost:8090</strong>, WEnv mostrerà una scena MASTER in cui sono abilitati i <strong>comandi da tastiera</strong>: <span class="blue">w,a,s,d,h</span>.</p>
<p>Se apriamo <em>‘Strumenti di sviluppo’</em> del browser, vedremo i messaggi inviati su <code class="docutils literal notranslate"><span class="pre">console.log</span></code> dal codice Javascript
(embedded nel file <code class="docutils literal notranslate"><span class="pre">IndexOk.html</span></code>) che gestisce la scena e i comandi da tastiera.</p>
<p>La figura che segue mostra:</p>
<ol class="arabic simple">
<li><p>Il comando di attivazione di <code class="docutils literal notranslate"><span class="pre">WebpageServer.js</span></code></p></li>
<li><p>Il browser con <code class="docutils literal notranslate"><span class="pre">console.log</span></code></p></li>
<li><p>La console di un programma applicativo.</p></li>
</ol>
<a class="reference internal image-reference" href="_images/vrExplain.PNG"><img alt="_images/vrExplain.PNG" class="align-center" src="_images/vrExplain.PNG" style="width: 100%;" /></a>
<p>WEnv si può attivare anche usando una immagine docker; si veda <a class="reference internal" href="#wenv-come-immagine-docker"><span class="std std-ref">WEnv come immagine docker</span></a>.</p>
</section>
<section id="scene-per-wenv">
<h3>Scene per WEnv<a class="headerlink" href="#scene-per-wenv" title="Permalink to this headline">¶</a></h3>
<p>La scena del WEnv è costruita da una descrizione che può essere facilmente definita da un progettista di applicazioni
modificando il file <code class="docutils literal notranslate"><span class="pre">sceneConfig.js</span></code>.</p>
<section id="sceneconfig-js">
<h4>sceneConfig.js<a class="headerlink" href="#sceneconfig-js" title="Permalink to this headline">¶</a></h4>
<p>Un esempio (relativo alla scena della figura precedente) può essere trovato in <code class="docutils literal notranslate"><span class="pre">sceneConfig.js</span></code>.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">const</span> <span class="n">config</span> <span class="o">=</span> <span class="p">{</span>
<span class="n">floor</span><span class="p">:</span> <span class="p">{</span>
<span class="n">size</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mi">31</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mi">24</span> <span class="p">}</span>
<span class="p">},</span>
<span class="n">player</span><span class="p">:</span> <span class="p">{</span>
<span class="n">position</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.10</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.16</span> <span class="p">},</span> <span class="o">//</span><span class="n">INIT</span>
<span class="o">//</span><span class="n">position</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.5</span> <span class="p">},</span> <span class="o">//</span><span class="n">CENTER</span>
<span class="o">//</span><span class="n">position</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.8</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.85</span> <span class="p">},</span> <span class="o">//</span><span class="n">END</span>
<span class="n">speed</span><span class="p">:</span> <span class="mf">0.2</span>
<span class="p">},</span>
<span class="n">sonars</span><span class="p">:</span> <span class="p">[</span>
<span class="p">],</span>
<span class="n">movingObstacles</span><span class="p">:</span> <span class="p">[</span>
<span class="p">],</span>
<span class="n">staticObstacles</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"plasticBox"</span><span class="p">,</span>
<span class="n">centerPosition</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.34</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.4</span><span class="p">},</span>
<span class="n">size</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.03</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.07</span><span class="p">}</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"wallUp"</span><span class="p">,</span>
<span class="n">centerPosition</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.44</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.97</span><span class="p">},</span>
<span class="n">size</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.88</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.01</span><span class="p">}</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"wallDown"</span><span class="p">,</span>
<span class="n">centerPosition</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.44</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.01</span><span class="p">},</span>
<span class="n">size</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.85</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.01</span><span class="p">}</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"wallLeft"</span><span class="p">,</span>
<span class="n">centerPosition</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.02</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.48</span><span class="p">},</span>
<span class="n">size</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.01</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.94</span><span class="p">}</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"wallRight"</span><span class="p">,</span>
<span class="n">centerPosition</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.98</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.5</span><span class="p">},</span>
<span class="n">size</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.01</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.99</span><span class="p">}</span>
<span class="p">}</span>
<span class="p">]</span>
<span class="p">}</span>
<span class="n">export</span> <span class="n">default</span> <span class="n">config</span><span class="p">;</span>
</pre></div>
</div>
<p>E’ possibile cambiare la scena in modo interattivo con la console che compare nella scena, per poi modificare manualmente il file
<code class="docutils literal notranslate"><span class="pre">sceneConfig.js</span></code> per conservare le modifiche.</p>
</section>
</section>
<section id="sensori-virtuali">
<h3>Sensori virtuali<a class="headerlink" href="#sensori-virtuali" title="Permalink to this headline">¶</a></h3>
<p>Il robot virtuale è dotato di due sensori di impatto, uno posto davanti e uno posto nella parte posteriore del robot.</p>
<p>E’ inoltre possibile introdurre ostacoli mobili e sonar virtuali che rilevano la posizione corrente del robot
(o di ostacoli mobili) nella scena.
Ad esempio:</p>
<table class="colwidths-given docutils align-default" style="width: 100%">
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><a class="reference internal image-reference" href="_images/wenvscenewithsonars.PNG"><img alt="_images/wenvscenewithsonars.PNG" class="align-center" src="_images/wenvscenewithsonars.PNG" style="width: 100%;" /></a>
<p>Si noti anche un esempio (commentato) di ostacolo mobile.</p>
</td>
<td><p>La scena alla sinistra si ottiene includendo in <a class="reference internal" href="#sceneconfig-js"><span class="std std-ref">sceneConfig.js</span></a> la seguente specifica:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">sonars</span><span class="p">:</span> <span class="p">[</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"sonar1"</span><span class="p">,</span>
<span class="n">position</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">0.40</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.04</span> <span class="p">},</span>
<span class="n">senseAxis</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="n">false</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">true</span> <span class="p">}</span>
<span class="p">},</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"sonar2"</span><span class="p">,</span>
<span class="n">position</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="mf">1.00</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="mf">0.95</span><span class="p">},</span>
<span class="n">senseAxis</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="n">true</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">false</span> <span class="p">}</span>
<span class="p">}</span>
<span class="p">],</span>
<span class="n">movingObstacles</span><span class="p">:</span> <span class="p">[</span>
<span class="o">/*</span>
<span class="p">{</span>
<span class="n">name</span><span class="p">:</span> <span class="s2">"movingobstacle"</span><span class="p">,</span>
<span class="n">position</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="o">.</span><span class="mi">64</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="o">.</span><span class="mi">42</span> <span class="p">},</span>
<span class="n">directionAxis</span><span class="p">:</span> <span class="p">{</span> <span class="n">x</span><span class="p">:</span> <span class="n">true</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">true</span> <span class="p">},</span>
<span class="n">speed</span><span class="p">:</span> <span class="mf">0.4</span><span class="p">,</span>
<span class="nb">range</span><span class="p">:</span> <span class="mi">8</span>
<span class="p">}</span><span class="o">*/</span>
<span class="p">],</span>
</pre></div>
</div>
</td>
</tr>
</tbody>
</table>
</section>
</section>
<section id="comandi-base-per-il-robot-in-cril">
<h2>Comandi-base per il robot in cril<a class="headerlink" href="#comandi-base-per-il-robot-in-cril" title="Permalink to this headline">¶</a></h2>
<p>Il linguaggio per esprimere comandi di movimento del robot virtuale
(detto <em>concrete-robot interaction language</em> o <span class="blue">cril</span> ) può essere
introdotto in modo analogo al <a class="reference internal" href="Enablers.html#linguaggio-base-di-comando"><span class="std std-ref">Linguaggio-base di comando</span></a> per i dispostivi del RadarSystem,
come campi di una stringa JSON della forma che segue:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="s2">"robotmove"</span><span class="p">:</span><span class="s2">"MOVE"</span><span class="p">,</span> <span class="s2">"time"</span><span class="p">:</span><span class="n">T</span><span class="p">}</span>
<span class="n">MOVE</span> <span class="p">:</span><span class="o">:=</span> <span class="s2">"turnLeft"</span> <span class="o">|</span> <span class="s2">"turnRight"</span> <span class="o">|</span>
<span class="s2">"moveForward"</span> <span class="o">|</span> <span class="s2">"moveBackward"</span> <span class="o">|</span> <span class="s2">"alarm"</span>
<span class="n">T</span> <span class="p">:</span><span class="o">:=</span> <span class="n">naturalNum</span>
</pre></div>
</div>
<p>Ad esempio, il comando</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">{"robotmove":"moveForward",</span> <span class="pre">"time":800}</span></code></p>
</div></blockquote>
<p>muove in avanti il robot per <code class="docutils literal notranslate"><span class="pre">800</span> <span class="pre">msec</span></code>. Il significato di <strong>“alarm”</strong> è di fermare il robot
(non è stato chiamato <code class="docutils literal notranslate"><span class="pre">halt</span></code> per motivi ‘storici’).</p>
<p>Stringhe-comando di questa forma possono essere inviate a WEnv in due modi diversi:</p>
<ul class="simple">
<li><p>come messaggi HTTP POST inviati sulla porta <strong>8090</strong></p></li>
<li><p>come messaggi inviati su un websocket alla porta <strong>8091</strong></p></li>
</ul>
<a class="reference internal image-reference" href="_images/logicInteraction.PNG"><img alt="_images/logicInteraction.PNG" class="align-center" src="_images/logicInteraction.PNG" style="width: 80%;" /></a>
<section id="interazioni-mediante-http">
<h3>Interazioni mediante HTTP<a class="headerlink" href="#interazioni-mediante-http" title="Permalink to this headline">¶</a></h3>
<p>L’invio di messaggi con HTTP implica una interazione logica di tipo request-response che blocca il
chiamante.</p>
<p>Dopo l’esecuzione del comando, WEnv invia al chiamante una <span class="blue">risposta</span>, espressa in JSON :</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="s2">"endmove"</span><span class="p">:</span><span class="s2">"RESULT"</span><span class="p">,</span> <span class="s2">"move"</span><span class="p">:</span><span class="n">MOVE</span><span class="p">}</span>
<span class="n">RESULT</span> <span class="p">:</span><span class="o">:=</span> <span class="n">true</span> <span class="o">|</span> <span class="n">false</span>
</pre></div>
</div>
<p>Il significato dei valori di <code class="docutils literal notranslate"><span class="pre">RESULT</span></code> è il seguente:</p>
<ul class="simple">
<li><p><strong>true</strong>: mossa completata con successo</p></li>
<li><p><strong>false</strong>: mossa fallita (il robot virtuale ha incontrato un ostacolo)</p></li>
</ul>
<p><span class="remark">Non è possibile interrompere l’esecuzione di una mossa attivata da un comando POST con un altro comando POST.</span></p>
<p>Tuttavia si può sempre interrompere una mossa in esecuzione inviando un <code class="docutils literal notranslate"><span class="pre">alarm</span></code> su WebSocket <code class="docutils literal notranslate"><span class="pre">8091</span></code>.</p>
</section>
<section id="interazioni-mediante-ws">
<h3>Interazioni mediante WS<a class="headerlink" href="#interazioni-mediante-ws" title="Permalink to this headline">¶</a></h3>
<p>L’invio di un comando di movimento al robot (mossa) mediante WebSocket <a class="reference external" href="https://www.npmjs.com/package/ws">ws</a> sulla porta <strong>8091</strong>
implica una forma di comunicazione <span class="blue">asincrona</span> (<em>fire-and-forget</em>).</p>
<p>Poichè l’invio asincrono di un comando non blocca il chiamante, un client può inviare un nuovo
comando prima che il precedente sia terminato. Per gestire situazioni di questo tipo, WEnv adotta la
regola che segue:</p>
<p><span class="remark">è possibile interrompere l’esecuzione di una mossa solo con il comando alarm.</span></p>
<section id="messaggi-di-stato">
<h4>Messaggi di stato<a class="headerlink" href="#messaggi-di-stato" title="Permalink to this headline">¶</a></h4>
<p>Un cliente connesso a WEnv mediante una connessione WS può ricevere informazioni
su variazioni dello stato del ‘mondo’ (che qui denominiamo <strong>messaggi di stato</strong>), quali:</p>
<ul class="simple">
<li><p>dati emessi dai sonar presenti nella scena, se rilevano il robot in movimento</p></li>
<li><p>dati emessi dai sensori di impatto posti davanti e dietro al robot, quando rilevano un ostacolo.</p></li>
</ul>
<p>Si noti che dati relativi a sonar presenti nella scena possono essere emessi indipendentemente dalla esecuzione
di mosse del robot, ad esempio in relazione alla rilevazione di ostacoli mobili.
Ad esempio:</p>
<blockquote>
<div><div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="s2">"sonarName"</span><span class="p">:</span> <span class="s2">"sonarName"</span><span class="p">,</span> <span class="s2">"distance"</span><span class="p">:</span> <span class="mi">1</span><span class="p">,</span> <span class="s2">"axis"</span><span class="p">:</span> <span class="s2">"x"</span> <span class="p">}</span>
</pre></div>
</div>
</div></blockquote>
<p>I <em>messaggi di stato</em> connessi alla esecuzione asincrona di un comando possono essere:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="p">{</span><span class="s2">"endmove"</span><span class="p">:</span><span class="s2">"RESULT"</span><span class="p">,</span> <span class="s2">"move"</span><span class="p">:</span><span class="n">MINFO</span> <span class="p">}</span>
<span class="n">RESULT</span> <span class="p">:</span><span class="o">:=</span> <span class="n">true</span> <span class="o">|</span> <span class="n">false</span>
<span class="n">MINFO</span> <span class="p">:</span><span class="o">:=</span> <span class="n">MOVEID</span> <span class="o">|</span> <span class="n">MOVEID_halted</span> <span class="o">|</span> <span class="n">MOVEID_notallowed</span>
<span class="n">MOVEID_</span> <span class="p">:</span><span class="o">:=</span> <span class="n">moveForward</span> <span class="o">|</span> <span class="n">moveBackward</span> <span class="o">|</span> <span class="n">turnLeft</span> <span class="o">|</span> <span class="n">turnRight</span>
</pre></div>
</div>
<p>Il significato dei valori di <code class="docutils literal notranslate"><span class="pre">MINFO</span></code> è il seguente:</p>
<ul class="simple">
<li><p><strong>MOVEID_halted</strong>: mossa <code class="docutils literal notranslate"><span class="pre">MOVEID</span></code> interrotta perchè il robot ha ricevuto un comando <code class="docutils literal notranslate"><span class="pre">alarm</span></code></p></li>
<li><p><strong>MOVEID_notallowed</strong>: mossa <code class="docutils literal notranslate"><span class="pre">MOVEID</span></code> rifiutata (non eseguita) in quanto la mossa relativa al comando precedente
non è ancora terminata.</p></li>
</ul>
<p>Se l’invio di un comando <code class="docutils literal notranslate"><span class="pre">moveForward</span></code> provoca il contatto con la parete ‘sud’ della stanza, il cliente riceve
l’inforazione <em>collision</em> invece di <em>endmove</em>.</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">{"collision":"moveForward","target":"wallDown"}</span></code></p>
</div></blockquote>
</section>
</section>
<section id="esempi-di-uso-naive-di-wenv">
<h3>Esempi di uso ‘naive’ di WEnv<a class="headerlink" href="#esempi-di-uso-naive-di-wenv" title="Permalink to this headline">¶</a></h3>
<p>Il progetto <code class="docutils literal notranslate"><span class="pre">unibo.wenvUsage22</span></code> include esempi di programma Java che eseguono mosse-base del robot mediante
comandi in <a class="reference internal" href="#comandi-base-per-il-robot-in-cril"><span class="std std-ref">cril</span></a> contenuti in richieste HTTP-POST alla porta <code class="docutils literal notranslate"><span class="pre">8090</span></code>
o messaggi inivati su WebSocket alla porta <code class="docutils literal notranslate"><span class="pre">8091</span></code>.</p>
<section id="clientnaiveusinghttp">
<h4>ClientNaiveUsingHttp<a class="headerlink" href="#clientnaiveusinghttp" title="Permalink to this headline">¶</a></h4>
<table class="colwidths-given docutils align-default" style="width: 100%">
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>ClientNaiveUsingHttp</strong>.java</p>
<p>Esegue mosse di base del robot inviando comandi scritti in <a class="reference internal" href="#comandi-base-per-il-robot-in-cril"><span class="std std-ref">cril</span></a></p>
</td>
<td><p><span class="blue">Key point</span>: Richiesta <span class="blue">sincrona</span>.</p>
<p>Richiede 1 thread.</p>
</td>
</tr>
</tbody>
</table>
<p>Osserviamo che:</p>
<ul class="simple">
<li><p>Il codice di comunicazione è scritto completamente dal progettista dell’applicazione.</p></li>
<li><p>Una mossa può terminare prima del tempo indicato nel comando, restituendo la risposta <code class="docutils literal notranslate"><span class="pre">{"endmove":</span></code> <strong>false</strong> <code class="docutils literal notranslate"><span class="pre">,</span> <span class="pre">"move":MINFO</span> <span class="pre">}</span></code>.</p></li>
<li><p>La gestione delle risposte JSON viene eseguita utilizzando la libreria <a class="reference external" href="https://www.baeldung.com/java-org-json">org.json</a>
(vedi anche <a class="reference external" href="https://www.baeldung.com/java-org-json">Introduzione a JSON-Java</a> ).</p></li>
</ul>
</section>
<section id="clientnaiveusingws">
<h4>ClientNaiveUsingWs<a class="headerlink" href="#clientnaiveusingws" title="Permalink to this headline">¶</a></h4>
<table class="colwidths-given docutils align-default" style="width: 100%">
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p><strong>ClientNaiveUsingWs</strong>.java</p>
<p>Esegue mosse di base del robot inviando comandi scritti in <a class="reference internal" href="#comandi-base-per-il-robot-in-cril"><span class="std std-ref">cril</span></a></p>
</td>
<td><p><span class="blue">Key point</span>: Richiesta <span class="blue">asincrona</span></p>
<p>Richiede 4 thread, a causa della libreria <code class="docutils literal notranslate"><span class="pre">javax.websocket</span></code>.</p>
</td>
</tr>
</tbody>
</table>
<p>Dal punto di vista ‘sistemistico’, osserviamo che:</p>
<ul>
<li><p>Il codice di comunicazione è scritto completamente dal progettista dell’applicazione, che utilizza
la libreria <code class="docutils literal notranslate"><span class="pre">javax.websocket</span></code> (vedi anche <a class="reference external" href="http://losviluppatore.it/i-websocket-comunicazione-asincrona-full-duplex-per-il-web/">I WebSocket Comunicazione Asincrona Full-Duplex Per Il Web</a> )</p></li>
<li><p>Gli eventi del ciclo di vita dell’endpoint WebSocket sono gestiti mediante <a class="reference internal" href="Annotazioni.html#annotazioni"><span class="std std-ref">Annotazioni</span></a>
secondo lo schema che segue:</p>
<div class="highlight-Java notranslate"><div class="highlight"><pre><span></span><span class="nd">@ClientEndpoint</span> <span class="c1">//La classe viene trattata come un client WebSocket</span>
<span class="n">implementa</span> <span class="n">IssWsSupport</span> <span class="n">di</span> <span class="n">classe</span> <span class="n">pubblicaIssOperations</span><span class="p">{</span>
<span class="p">...</span>
<span class="kd">public</span> <span class="nf">IssWsSupport</span><span class="p">(</span> <span class="n">String</span> <span class="n">url</span> <span class="p">){</span> <span class="p">...</span> <span class="p">}</span>
<span class="nd">@OnOpen</span> <span class="c1">//richiamato quando si avvia una nuova connessione WebSocket</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onOpen</span><span class="p">(</span><span class="n">Session</span> <span class="n">userSession</span><span class="p">){</span> <span class="p">...</span> <span class="p">}</span>
<span class="nd">@OnMessage</span> <span class="c1">//richiamato quando arriva un messaggio</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onMessage</span><span class="p">(</span><span class="n">String</span> <span class="n">message</span><span class="p">){</span> <span class="p">...</span> <span class="p">}</span>
<span class="nd">@OnError</span> <span class="c1">//richiamato quando si verifica un problema con la comunicazione</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">disconnesso</span> <span class="p">(</span><span class="n">sessione</span> <span class="n">di</span> <span class="n">sessione</span><span class="p">,</span> <span class="n">errore</span> <span class="n">lanciabile</span><span class="p">){...}</span>
<span class="nd">@Chiudi</span> <span class="c1">//chiamato alla chiusura della connessione WebSocket</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">onClose</span><span class="p">(</span><span class="n">Session</span> <span class="n">userSession</span><span class="p">,</span><span class="n">CloseReason</span> <span class="n">reason</span><span class="p">){...}</span>
<span class="p">}</span>
</pre></div>
</div>
</li>
</ul>
<p>Dal punto di vista ‘applicativo’, osserviamo che:</p>
<ul class="simple">
<li><p>Il chiamante esegue concettualmente una <em>fire-and-forget</em>.</p></li>
<li><p>Un eventuale messaggio di stato viene ‘iniettato’ nell’applicazione tramite una chiamata al metodo annotato
con <code class="docutils literal notranslate"><span class="pre">@OnMessage</span></code>.</p></li>
<li><p>E’ possibile <span class="blue">interrompere</span> la esecuzione di una mossa inviando il comando <strong>alarm</strong>.</p></li>
</ul>
</section>
</section>
</section>
<section id="naivegui">
<h2>NaiveGui<a class="headerlink" href="#naivegui" title="Permalink to this headline">¶</a></h2>
<p>Il progetto <code class="docutils literal notranslate"><span class="pre">unibo.wenvUsage22</span></code> include un file <code class="docutils literal notranslate"><span class="pre">resources/NaiveGui.html</span></code> che permette di interagire con WEnv
attraverso un browser.</p>
<p>Il programma presenta una interfaccia che permette a un utente di:</p>
<ul class="simple">
<li><p>inviare comandi (in <a class="reference internal" href="#comandi-base-per-il-robot-in-cril"><span class="std std-ref">cril</span></a>) al VirtualRobot attraverso un insieme di pulsanti</p></li>
<li><p>visualizzare nella DisplayArea le informazioni emesse da WEnv</p></li>
</ul>
<p>Ad esempio:</p>
<a class="reference internal image-reference" href="_images/NaiveGui.PNG"><img alt="_images/NaiveGui.PNG" class="align-center" src="_images/NaiveGui.PNG" style="width: 80%;" /></a>
<p>Il programma usa le WebSocket JavaScript per interagire con WEnv attraverso una connessione sulla porta <code class="docutils literal notranslate"><span class="pre">8091</span></code>.</p>
</section>
<section id="interaction2021-per-http-e-ws">
<h2>Interaction2021 per HTTP e WS<a class="headerlink" href="#interaction2021-per-http-e-ws" title="Permalink to this headline">¶</a></h2>
<p>Il progetto <code class="docutils literal notranslate"><span class="pre">unibo.actor22</span></code> introduce le implementazioni di <a class="reference internal" href="RadarSystemProdottiAnalisi.html#interaction2021"><span class="std std-ref">L’interfaccia Interaction2021</span></a> per HTTP (<code class="docutils literal notranslate"><span class="pre">HttpConnection</span></code>) e
per WebSocket (<a class="reference internal" href="#wsconnection"><span class="std std-ref">WsConnection</span></a>) estendendo l’insieme dei <a class="reference internal" href="RadarSystemAnalisi.html#tipi-di-protocollo"><span class="std std-ref">Tipi di protocollo</span></a> che possiamo usare per
realizzare la nostra <span class="blue">astrazione connessione</span>.</p>
<p>Ciò consente di riscrivere le applicazioni di esempio precedenti in modo più semplice e compatto.</p>
<section id="httpconnection">
<h3>HttpConnection<a class="headerlink" href="#httpconnection" title="Permalink to this headline">¶</a></h3>
<p>La implementazione di <a class="reference internal" href="RadarSystemProdottiAnalisi.html#interaction2021"><span class="std std-ref">L’interfaccia Interaction2021</span></a> per HTTP non pone particolari problemi: si tratta di utilizzare una libreria
che fornisce un HTTP-client. Noi abbiamo usato <a class="reference external" href="https://square.github.io/okhttp/">okhttp3</a>, adatta anche per Kotlin. La semplicità consiste nel fatto
che si tratta di realizzare schemi request-response sincroni.</p>
</section>
<section id="wsconnection">
<h3>WsConnection<a class="headerlink" href="#wsconnection" title="Permalink to this headline">¶</a></h3>
<p>La implementazione di <a class="reference internal" href="RadarSystemProdottiAnalisi.html#interaction2021"><span class="std std-ref">L’interfaccia Interaction2021</span></a> per WS (WebSocket) è ancora basata su <code class="docutils literal notranslate"><span class="pre">okhttp3</span></code> (si veda <a class="reference external" href="https://square.github.io/okhttp/4.x/okhttp/okhttp3/-web-socket/">okhttp3Ws</a>)
ma modifica la struttura del codice (ne abbiamo parlato in <a class="reference internal" href="#clientnaiveusingws"><span class="std std-ref">ClientNaiveUsingWs</span></a>)
in quanto le interazioni sono asincrone.</p>
<p>Su una WS-connection possono cioè giungere informazioni
che sono risposte a messaggi inviati in precedenza o anche di altro tipo (ad esempio dati di un sensore, allarmi, etc.).</p>
<p>Per meglio gestire queste informazioni in ingresso,
questo tipo di connessione è stato realizzato come un POJO <strong>osservabile</strong> (che implementa <a class="reference internal" href="SonarObservable.html#iobservable"><span class="std std-ref">IObservable</span></a>),
in modo da permettere al livello
applicativo di gestire i messaggi in arrivo da parte di ossservatori che implementano <a class="reference internal" href="SonarObservable.html#iobserver"><span class="std std-ref">IObserver</span></a>.</p>
<section id="wsconnsysobserver">
<h4>WsConnSysObserver<a class="headerlink" href="#wsconnsysobserver" title="Permalink to this headline">¶</a></h4>
<p>Viene fornito un osservatore ‘di sistema’ definito dalla classe <code class="docutils literal notranslate"><span class="pre">WsConnSysObserver</span></code>, il quale:</p>
<ul class="simple">
<li><p>riceve al momento della costruzione il nome di un attore (detto <strong>owner</strong>) che può assumere il valore <code class="docutils literal notranslate"><span class="pre">null</span></code></p></li>
<li><p>implementa <a class="reference internal" href="SonarObservable.html#iobserver"><span class="std std-ref">IObserver</span></a> e funziona come osservatore dei <a class="reference internal" href="#messaggi-di-stato"><span class="std std-ref">Messaggi di stato</span></a> ricevuti sulla WS</p></li>
<li><p>per ogni messaggio ricevuto (osservato) sulla WS, crea un messaggio <a class="reference internal" href="ContestiContenitori.html#iapplmessage"><span class="std std-ref">IApplMessage</span></a> che ha come
msgId il valore <code class="docutils literal notranslate"><span class="pre">"wsEvent"</span></code> e come payload il messaggio osservato. Questo messaggio è un <span class="blue">evento</span>
(si veda <a class="reference internal" href="Eventi.html#eventi"><span class="std std-ref">Eventi</span></a>) se <code class="docutils literal notranslate"><span class="pre">owner==</span> <span class="pre">null</span></code> oppure un <span class="blue">dispatch</span> (si veda <a class="reference internal" href="ContestiContenitori.html#struttura-dei-messaggi-applicativi"><span class="std std-ref">Struttura dei messaggi applicativi</span></a>)
con <strong>owner</strong> come destinatario, se <code class="docutils literal notranslate"><span class="pre">owner!=</span> <span class="pre">null</span></code>.</p></li>
</ul>
<p>In altre parole:</p>
<p><span class="remark">WsConnSysObserver trasforma informazioni in eventi o dispatch</span></p>
</section>
</section>
<section id="esempi-di-uso-di-httpconnection-e-wsconnection">
<h3>Esempi di uso di HttpConnection e WsConnection<a class="headerlink" href="#esempi-di-uso-di-httpconnection-e-wsconnection" title="Permalink to this headline">¶</a></h3>
<p>Il progetto <code class="docutils literal notranslate"><span class="pre">unibo.wenvUsage22</span></code> introduce esempi di uso di questi nuovi tipi di connessione per realizzare
interazioni con WEnv:</p>
<table class="colwidths-given docutils align-default" style="width: 100%">
<colgroup>
<col style="width: 25%" />
<col style="width: 75%" />
</colgroup>
<tbody>
<tr class="row-odd"><td><p>ClientUsingHttp.java</p></td>
<td><p>Esegue mosse di base del robot inviando comandi scritti in <a class="reference internal" href="#comandi-base-per-il-robot-in-cril"><span class="std std-ref">cril</span></a>
su una connessione <code class="docutils literal notranslate"><span class="pre">HttpConnection</span></code>.</p></td>
</tr>
<tr class="row-even"><td><p>ClientUsingWs</p></td>
<td><p>Esegue mosse di base del robot inviando comandi scritti in <a class="reference internal" href="#comandi-base-per-il-robot-in-cril"><span class="std std-ref">cril</span></a>
su una connessione <code class="docutils literal notranslate"><span class="pre">WsConnection</span></code>. Funge anche da observer dei <a class="reference internal" href="#messaggi-di-stato"><span class="std std-ref">Messaggi di stato</span></a>.</p></td>
</tr>
<tr class="row-odd"><td><p>ClientUsingWsHttp</p></td>
<td><p>Interagisce con WEnv utilizzando sia una connessione <code class="docutils literal notranslate"><span class="pre">HttpConnection</span></code> sia una connessione <code class="docutils literal notranslate"><span class="pre">WsConnection</span></code>,
permettendo di verificare come l’applicazione possa agire come observer della evoluzione dello stato del mondo
in seguito alla esecuzione di un comando HTTP-POST al VirtualRobot.</p></td>
</tr>
</tbody>
</table>
</section>
<section id="casi-di-interazione">
<h3>Casi di interazione<a class="headerlink" href="#casi-di-interazione" title="Permalink to this headline">¶</a></h3>
<p>Il <a class="reference external" href="https://unibo.cloud.panopto.eu/Panopto/Pages/Sessions/List.aspx#folderID=%227673bfec-c7b6-4a96-8ff8-aca7011ae972%22">videoWEnv</a> mostra un insieme di possibili interazioni:</p>
<ol class="arabic simple">
<li><p>Invio di comandi asincroni su WS mediante programma Java o mediante <a class="reference internal" href="#naivegui"><span class="std std-ref">NaiveGui</span></a>.</p></li>
<li><p>Invio di comandi sincroni su HTTP mediante programma Java o mediante <a class="reference internal" href="#naivegui"><span class="std std-ref">NaiveGui</span></a>.</p></li>
<li><p>Come nei due punti precedenti attivando uno o più osservatori su WS come programmi Java o come pagine Web</p></li>
</ol>
<p>Se invio un comando <code class="docutils literal notranslate"><span class="pre">moveForward</span></code> mediante HTTP-POST
e poi <code class="docutils literal notranslate"><span class="pre">halt</span></code> mediante <a class="reference internal" href="#naivegui"><span class="std std-ref">NaiveGui</span></a>: ricevo come risposta</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">{"endmove":false,"move":"interrupted"}</span></code></p>
</div></blockquote>
</section>
</section>
<section id="note-di-implementazione">
<h2>Note di implementazione<a class="headerlink" href="#note-di-implementazione" title="Permalink to this headline">¶</a></h2>
<p>L’implementazione di WEnv si basa su due componenti principali:</p>
<ul class="simple">
<li><p><strong>server</strong>: che definisce il programma <code class="docutils literal notranslate"><span class="pre">WebpageServer.js</span></code> scritto con il framework Node express</p></li>
<li><p><strong>WebGLScene</strong>: componente che gestisce la scena</p></li>
</ul>
<section id="architettura-di-wenv">
<h3>Architettura di WEnv<a class="headerlink" href="#architettura-di-wenv" title="Permalink to this headline">¶</a></h3>
<a class="reference internal image-reference" href="_images/WenvArch.PNG"><img alt="_images/WenvArch.PNG" class="align-center" src="_images/WenvArch.PNG" style="width: 100%;" /></a>
<p><code class="docutils literal notranslate"><span class="pre">WebpageServer.js</span></code> utilizza due diversi tipi di WebSocket:</p>
<ul>
<li><p>un socket (detto <strong>sceneSocket</strong>) basato sulla libreria <a class="reference external" href="https://socket.io/docs/v4/">socket.io</a> che viene utilizzato per gestire
l’interazione con <strong>WebGLScene</strong>.</p>
<p><span class="remark">socket.io non è un’implementazione WebSocket.</span></p>
<p>Sebbene <a class="reference external" href="https://socket.io/docs/v4/">socket.io</a> utilizzi effettivamente WebSocket come trasporto quando possibile,
aggiunge alcuni metadati a ciascun pacchetto: il tipo di pacchetto, lo spazio dei nomi
e l’ID di riconoscimento quando è necessario un riconoscimento del messaggio.
Ecco perché un client WebSocket non sarà in grado di connettersi correttamente a un server Socket.IO
e un client <a class="reference external" href="https://socket.io/docs/v4/">socket.io</a> non sarà in grado di connettersi a un server WebSocket.</p>
</li>
<li><p>il websocker <strong>8091</strong> basato sulla libreria <a class="reference external" href="https://www.npmjs.com/package/ws">ws</a> : questo socket viene utilizzato per gestire comandi
applicativi asincroni per muovere il robot inviati da client remoti e per inviare a client remoti
<a class="reference internal" href="#messaggi-di-stato"><span class="std std-ref">Messaggi di stato</span></a>.</p>
<p>WEnv utilizza la libreria Node <a class="reference external" href="https://github.com/einaros/ws">einaros</a> per accettare questi comendi.</p>
<p><span class="remark">Il modulo ws non funziona nel browser: bisogna utilizzare l’oggetto WebSocket nativo.</span></p>
</li>
</ul>
<p>Quando <code class="docutils literal notranslate"><span class="pre">WebvGLScene</span></code> rileva una collisione tra il robot virtuale e un ostacolo,
invoca l’utilità <code class="docutils literal notranslate"><span class="pre">eventBus.js</span></code> per ‘emettere un evento collisione’
oltre lo <strong>sceneSocket</strong>.</p>
<p>Questo evento è gestito da un apposito handler (vedi <code class="docutils literal notranslate"><span class="pre">sceneSocketInfoHandler</span></code> in <code class="docutils literal notranslate"><span class="pre">WebpageServer.js</span></code>),
che reindirizza le informazioni a tutti i client connessi sulla <code class="docutils literal notranslate"><span class="pre">8091</span></code>.</p>
</section>
<section id="wenv-come-immagine-docker">
<h3>WEnv come immagine docker<a class="headerlink" href="#wenv-come-immagine-docker" title="Permalink to this headline">¶</a></h3>
<p>WEnv viene anche distribuito come immagine Docker.</p>
<section id="dockerfile-e-creazione-dell-immagine">
<h4>Dockerfile e creazione dell’immagine<a class="headerlink" href="#dockerfile-e-creazione-dell-immagine" title="Permalink to this headline">¶</a></h4>
<p>Il file di nome <strong>Dockerfile</strong> nella directory <code class="docutils literal notranslate"><span class="pre">it.unibo.virtualRobot2020</span></code> contiene le istruzioni per creare una
immagine Docker (per una introduizione a Docker si veda <a class="reference external" href="./_static/IntroDocker22.html">Introduction to Docker and DockerCompose</a>).</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">node</span><span class="p">:</span><span class="mi">17</span><span class="o">-</span><span class="n">alpine</span>
<span class="n">RUN</span> <span class="n">mkdir</span> <span class="o">-</span><span class="n">p</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span>
<span class="n">EXPOSE</span> <span class="mi">8090</span>
<span class="n">EXPOSE</span> <span class="mi">8091</span>
<span class="n">COPY</span> <span class="o">./</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">server</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">server</span>
<span class="n">COPY</span> <span class="o">./</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">WebGLScene</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">WebGLScene</span>
<span class="c1">#set default dir so that next commands executes in it</span>
<span class="n">WORKDIR</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">WebGLScene</span>
<span class="n">RUN</span> <span class="n">npm</span> <span class="n">install</span>
<span class="n">WORKDIR</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">server</span>
<span class="n">RUN</span> <span class="n">npm</span> <span class="n">install</span>
<span class="n">WORKDIR</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">server</span><span class="o">/</span><span class="n">src</span>
<span class="n">CMD</span> <span class="p">[</span><span class="s2">"node"</span><span class="p">,</span> <span class="s2">"WebpageServer"</span><span class="p">]</span>
</pre></div>
</div>
<p>L’immagine Docker può essere creata sul proprio PC eseguendo il comando (nella directory che contiene il <em>Dockerfile</em>):</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">docker</span> <span class="pre">build</span> <span class="pre">-t</span> <span class="pre">virtualrobotdisi:4.0</span> <span class="pre">.</span></code> //Notare il .</p>
</div></blockquote>
</section>
<section id="esecuzione-della-immagine">
<h4>Esecuzione della immagine<a class="headerlink" href="#esecuzione-della-immagine" title="Permalink to this headline">¶</a></h4>
<p>L’immagine Docker di WEnv può essere attivata sul PC con il comando:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">docker</span> <span class="n">run</span> <span class="o">-</span><span class="n">ti</span> <span class="o">-</span><span class="n">p</span> <span class="mi">8090</span><span class="p">:</span><span class="mi">8090</span> <span class="o">-</span><span class="n">p</span> <span class="mi">8091</span><span class="p">:</span><span class="mi">8091</span> <span class="o">--</span><span class="n">rm</span> <span class="n">virtualrobotdisi</span><span class="p">:</span><span class="mf">4.0</span>
</pre></div>
</div>
<p>Il comando:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">docker</span> <span class="n">run</span> <span class="o">-</span><span class="n">ti</span> <span class="o">-</span><span class="n">p</span> <span class="mi">8090</span><span class="p">:</span><span class="mi">8090</span> <span class="o">-</span><span class="n">p</span> <span class="mi">8091</span><span class="p">:</span><span class="mi">8091</span>
<span class="o">--</span><span class="n">rm</span> <span class="n">virtualrobotdisi</span><span class="p">:</span><span class="mf">4.0</span> <span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">sh</span>
</pre></div>
</div>
<p>permette di ispezionare il contenuto della macchina virtuale e di attivare manualmente il sistema
(eseguendo <code class="docutils literal notranslate"><span class="pre">node</span> <span class="pre">WebpageServer.js</span></code>).</p>
</section>
<section id="modificare-la-scena-nella-immagine">
<h4>Modificare la scena nella immagine<a class="headerlink" href="#modificare-la-scena-nella-immagine" title="Permalink to this headline">¶</a></h4>
<p>Una volta attivata l’immagine docker, il comando</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">dockerps</span> <span class="pre">ps</span> <span class="pre">-a</span></code></p>
</div></blockquote>
<p>restituisce una tabella con 7 campi:</p>
<blockquote>
<div><p><code class="docutils literal notranslate"><span class="pre">CONTAINERID</span>   <span class="pre">IMAGE</span>     <span class="pre">COMMAND</span>   <span class="pre">CREATED</span>   <span class="pre">STATUS</span>    <span class="pre">PORTS</span>     <span class="pre">NAMES</span></code></p>
</div></blockquote>
<p>Per modificare il file che definisce la scena, si può copiare una nuova versione attraverso il comando <code class="docutils literal notranslate"><span class="pre">docker</span> <span class="pre">cp</span></code>
e rendere permanente la modifica salvando il container.</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="o">//</span><span class="n">change</span> <span class="n">the</span> <span class="n">scene</span>
<span class="n">docker</span> <span class="n">cp</span> <span class="n">sceneConfig</span><span class="o">.</span><span class="n">js</span>
<span class="n">CONTAINERID</span><span class="p">:</span><span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">node</span><span class="o">/</span><span class="n">WEnv</span><span class="o">/</span><span class="n">WebGLScene</span><span class="o">/</span><span class="n">sceneConfig</span><span class="o">.</span><span class="n">js</span>
<span class="o">//</span><span class="n">Save</span> <span class="n">the</span> <span class="n">cotainer</span>
<span class="n">docker</span> <span class="n">commit</span> <span class="n">CONTAINERID</span>
</pre></div>
</div>
</section>
<section id="esecuzione-con-docker-compose">
<h4>Esecuzione con docker-compose<a class="headerlink" href="#esecuzione-con-docker-compose" title="Permalink to this headline">¶</a></h4>
<p>L’immagine viene distribuita anche su <a class="reference external" href="https://hub.docker.com/">Docker Hub</a> in <code class="docutils literal notranslate"><span class="pre">docker.io/natbodocker/virtualrobotdisi:4.0</span></code>
come risulta nella spefifica del file <code class="docutils literal notranslate"><span class="pre">virtualRobotOnly4.0.yaml</span></code>:</p>
<section id="virtualrobotonly3-0-yaml">
<h5>virtualRobotOnly3.0.yaml<a class="headerlink" href="#virtualrobotonly3-0-yaml" title="Permalink to this headline">¶</a></h5>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">version</span><span class="p">:</span> <span class="s1">'3'</span>
<span class="n">services</span><span class="p">:</span>
<span class="n">wenv</span><span class="p">:</span>
<span class="n">image</span><span class="p">:</span> <span class="n">docker</span><span class="o">.</span><span class="n">io</span><span class="o">/</span><span class="n">natbodocker</span><span class="o">/</span><span class="n">virtualrobotdisi</span><span class="p">:</span><span class="mf">4.0</span>
<span class="n">ports</span><span class="p">:</span>
<span class="o">-</span> <span class="mi">8090</span><span class="p">:</span><span class="mi">8090</span>
<span class="o">-</span> <span class="mi">8091</span><span class="p">:</span><span class="mi">8091</span>
</pre></div>
</div>
<p>Il file <code class="docutils literal notranslate"><span class="pre">virtualRobotOnly3.0.yaml</span></code> permette l’attivazione di WEnv attraverso l’uso di docker-compose:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">docker</span><span class="o">-</span><span class="n">compose</span> <span class="o">-</span><span class="n">f</span> <span class="n">virtualRobotOnly4</span><span class="o">.</span><span class="mf">0.</span><span class="n">yaml</span> <span class="n">up</span> <span class="o">//</span><span class="n">per</span> <span class="n">attivare</span>
<span class="n">docker</span><span class="o">-</span><span class="n">compose</span> <span class="o">-</span><span class="n">f</span> <span class="n">virtualRobotOnly4</span><span class="o">.</span><span class="mf">0.</span><span class="n">yaml</span> <span class="n">down</span> <span class="o">//</span><span class="n">per</span> <span class="n">terminare</span>
</pre></div>
</div>
<p><span class="worktodo">WORKTODO: vacuumCleaner</span></p>
<ul class="simple">
<li><p>Muovere il VirtualRobot in modo da coprire tutta la superficie di una stanza vuota.</p></li>
</ul>
</section>
</section>
</section>
</section>
</section>
</div>
</div>
</div>
<div class="sphinxsidebar" role="navigation" aria-label="main navigation">
<div class="sphinxsidebarwrapper">
<p class="logo">
<a href="index.html">
<img class="logo" src="_static/logo-unibo.gif" alt="Logo"/>
<h1 class="logo logo-name">iss22</h1>
</a>
</p>
<h3>Navigation</h3>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="Introduzione.html">Introduzione</a></li>
<li class="toctree-l1"><a class="reference internal" href="CostruireSoftware.html">Costruire software</a></li>
<li class="toctree-l1"><a class="reference internal" href="WorkspaceSetup.html">WorkspaceSetup</a></li>
<li class="toctree-l1"><a class="reference internal" href="RadarSystem.html">RadarSystem</a></li>
<li class="toctree-l1"><a class="reference internal" href="RadarSystemAnalisi.html">Analisi del problema</a></li>
<li class="toctree-l1"><a class="reference internal" href="RadarSystemProdottiAnalisi.html">Prodotti della analisi</a></li>
<li class="toctree-l1"><a class="reference internal" href="RadarSystemProgetto.html">Progettazione e sviluppo</a></li>
<li class="toctree-l1"><a class="reference internal" href="RadarSystemSupporti.html">Supporti per comunicazioni</a></li>
<li class="toctree-l1"><a class="reference internal" href="Enablers.html">Abilitatori di comunicazione</a></li>
<li class="toctree-l1"><a class="reference internal" href="ContestiContenitori.html">Contesti-contenitori</a></li>
<li class="toctree-l1"><a class="reference internal" href="SonarObservable.html">Il SonarObservable</a></li>
<li class="toctree-l1"><a class="reference internal" href="Attori.html">Attori</a></li>
<li class="toctree-l1"><a class="reference internal" href="Eventi.html">Eventi</a></li>
<li class="toctree-l1"><a class="reference internal" href="Annotazioni.html">Annotazioni</a></li>
<li class="toctree-l1"><a class="reference internal" href="RaspberrySoftware.html">RaspberrySoftware</a></li>
<li class="toctree-l1"><a class="reference internal" href="RaspBasicCode.html">RaspBasicCode</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">VirtualRobot</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#differential-drive-robot">Differential Drive robot</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#robot-reali">Robot reali</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#wenv">WEnv</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#usare-wenv">Usare WEnv</a></li>
<li class="toctree-l3"><a class="reference internal" href="#scene-per-wenv">Scene per WEnv</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#sceneconfig-js">sceneConfig.js</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#sensori-virtuali">Sensori virtuali</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#comandi-base-per-il-robot-in-cril">Comandi-base per il robot in cril</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#interazioni-mediante-http">Interazioni mediante HTTP</a></li>
<li class="toctree-l3"><a class="reference internal" href="#interazioni-mediante-ws">Interazioni mediante WS</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#messaggi-di-stato">Messaggi di stato</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#esempi-di-uso-naive-di-wenv">Esempi di uso ‘naive’ di WEnv</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#clientnaiveusinghttp">ClientNaiveUsingHttp</a></li>
<li class="toctree-l4"><a class="reference internal" href="#clientnaiveusingws">ClientNaiveUsingWs</a></li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#naivegui">NaiveGui</a></li>
<li class="toctree-l2"><a class="reference internal" href="#interaction2021-per-http-e-ws">Interaction2021 per HTTP e WS</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#httpconnection">HttpConnection</a></li>
<li class="toctree-l3"><a class="reference internal" href="#wsconnection">WsConnection</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#wsconnsysobserver">WsConnSysObserver</a></li>
</ul>
</li>
<li class="toctree-l3"><a class="reference internal" href="#esempi-di-uso-di-httpconnection-e-wsconnection">Esempi di uso di HttpConnection e WsConnection</a></li>
<li class="toctree-l3"><a class="reference internal" href="#casi-di-interazione">Casi di interazione</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="#note-di-implementazione">Note di implementazione</a><ul>
<li class="toctree-l3"><a class="reference internal" href="#architettura-di-wenv">Architettura di WEnv</a></li>
<li class="toctree-l3"><a class="reference internal" href="#wenv-come-immagine-docker">WEnv come immagine docker</a><ul>
<li class="toctree-l4"><a class="reference internal" href="#dockerfile-e-creazione-dell-immagine">Dockerfile e creazione dell’immagine</a></li>
<li class="toctree-l4"><a class="reference internal" href="#esecuzione-della-immagine">Esecuzione della immagine</a></li>
<li class="toctree-l4"><a class="reference internal" href="#modificare-la-scena-nella-immagine">Modificare la scena nella immagine</a></li>
<li class="toctree-l4"><a class="reference internal" href="#esecuzione-con-docker-compose">Esecuzione con docker-compose</a><ul>
<li class="toctree-l5"><a class="reference internal" href="#virtualrobotonly3-0-yaml">virtualRobotOnly3.0.yaml</a></li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="UsingWEnv.html">Using WEnv</a></li>
<li class="toctree-l1"><a class="reference internal" href="Actors22.html">Actors22</a></li>
<li class="toctree-l1"><a class="reference internal" href="RobotCleaner.html">RobotCleaner</a></li>
</ul>
<div class="relations">
<h3>Related Topics</h3>
<ul>
<li><a href="index.html">Documentation overview</a><ul>
<li>Previous: <a href="RaspBasicCode.html" title="previous chapter">RaspBasicCode</a></li>
<li>Next: <a href="UsingWEnv.html" title="next chapter">Using WEnv</a></li>
</ul></li>
</ul>
</div>
<div id="searchbox" style="display: none" role="search">
<h3 id="searchlabel">Quick search</h3>
<div class="searchformwrapper">
<form class="search" action="search.html" method="get">
<input type="text" name="q" aria-labelledby="searchlabel" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false"/>
<input type="submit" value="Go" />
</form>
</div>
</div>
<script>$('#searchbox').show(0);</script>
</div>
</div>
<div class="clearer"></div>
</div>
<div class="footer">
©2021, Antonio Natali.
|
Powered by <a href="http://sphinx-doc.org/">Sphinx 4.4.0</a>
& <a href="https://github.com/bitprophet/alabaster">Alabaster 0.7.12</a>
|
<a href="_sources/VirtualRobot.rst.txt"
rel="nofollow">Page source</a>
</div>
</body>
</html>