-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathprototypes.tex
361 lines (312 loc) · 17.8 KB
/
prototypes.tex
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
\chapter{Prototypes}\label{chap:prototypes}
The RoFI project as defined in the previous chapter is broad and, therefore,
implementing all of the proposed solutions in the full depth is far beyond the
reach of the thesis. Therefore, we focused on three of the most important
aspects of the RoFI project. We want to show that:
\begin{itemize}
\item the docking mechanism can be built and that it features claimed
properties,
\item integration of TCP/IP communication in the system using a custom
hardware layer is possible, and
\item the universal module can be built.
\end{itemize}
All the source codes and CAD models of results presented here are available at
\url{https://github.com/paradise-fi/RoFi}.
\section{Docking Mechanism}
To test the properties of the docking mechanism proposed in section
\ref{sec:dock}, we successfully built several copies of the mechanism and tested
its properties.
The docks can be easily printed on a commonly available 3D printer. In our
setting, the dock was printed on Prusa i3 MK3 using the PLA filament and
standard settings with a layer height of 0.15~mm. We prepared the model for
printing by splitting some complex components into several bodies, which were
printed separately, and after the print they were glued together using
cyanoacrylate glue. As our experiences show, such procedure yields better and
faster results as our model does not need any support material, which needs to
been manually removed. Removing the support material is time-consuming and in
our observation, gluing components together is much faster. Also, surfaces
relying on a support material always yield much worse surface finish than
surfaces with no supports. This is crucial for our model, as a poor quality of
the surface finish on the helix slot negatively affects the dock.
Overall, to build a single dock following material is needed: eight meters of a
filament, four M2$\times$6~mm screws with a countersunk head, two 2$\times$16~mm
steel pins, four 2$\times$10~mm, four 2$\times$8~mm stell pins and a motor.
A single dock takes about 4 hours to print and with a little bit of practice, it
can be assembled in 30 minutes. Due to tweaks in the design, there is
practically no manual deburring necessary, which is usually required with 3D
printed parts.
We tried to evaluate the features of the dock. However, please note that the
results we present are not as thorough as they potentially could be as we do not
feature the equipment and skills to evaluate the mechanical properties of the
docks properly.
\begin{figure}[!t]
\centering
\includegraphics[width=\textwidth]{figures/dock_test_setup.jpg}
\caption{The test setup. A stand was mounted on the docks to easily position
them and a printed grid was used to create various setups.}
\label{fig:dock_test_setup}
\end{figure}
\begin{figure}[!t]
\centering
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/docks_aligned.jpg}
\caption{Perfect alignment}
\label{fig:dock_test_aligned}
\end{subfigure}
~
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/docks_distance.jpg}
\caption{Distance misalignment}
\label{fig:dock_test_distance}
\end{subfigure}
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/docks_shift.jpg}
\caption{Parallel misalignment}
\label{fig:dock_test_parallel}
\end{subfigure}
~
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/docks_rot.jpg}
\caption{Rotational misalignment}
\label{fig:dock_test_rot}
\end{subfigure}
\caption{Types of alignment.}
\label{fig:dock_diplacement}
\end{figure}
To properly evaluate the docks, we 3D printed a stand on which a single dock was
mounted. The docks we used for testing were manually controlled. A photo of our
setup can be found in figure \ref{fig:dock_test_setup}. This setup was used for
testing of connection repeatability and load capacity.
\subsection{Connection repeatability}
Two docking mechanisms were brought together in various arrangements and a
series of 10 connects was performed. The docks were placed on a grid to arrange
them in the initial position with one dock being strongly fixed in its position,
the other one being able to move.
First, we performed an analysis of perfectly aligned docks (see figure
\ref{fig:dock_test_aligned}). The connection was established in all 10 cases for
both, simultaneous and sequential docking procedure.
Second, we varied the docking distance (see figure
\ref{fig:dock_test_distance}). By decreasing the docking distance by 6~mm, the
docks were able to push themselves apart and connect properly in all 10 cases.
When the docks were brought together by more than 6~mm, we observed that the
docks are not able to connect simultaneously -- their hooks collide and they do
not align properly. However, when the connection was performed sequentially, the
docks connected reliably even when they were touching as the rotated hooks no
longer collide. Then we increased the distance compared to the aligned position.
By increasing the distance by 2~mm, docks were able to connect in 9 out of 10
cases. When we increased the distance by 4~mm docks were able to connect in 5
cases. For displacement larger than 5~mm the docs were not able to connect.
Third, we varied the parallel alignment (see figure
\ref{fig:dock_test_parallel}). By misaligning the docks by 2~mm we got 9
successful connections. By increasing the misalignment to 4~mm the docks
connected in 6 cases, for the 6~mm it was only 3 cases. We did not observe any
difference between simultaneous and sequential attempts.
Last, we varied the rotation of the docks (see figure \ref{fig:dock_test_rot}).
We performed an only rotation in a horizontal plane as the docs are symmetric
and therefore, they should perform the same for other orientations. By rotating
the docks less than $5^\circ$ the docks connected in all 10 cases. When we
increased the rotation to $10^\circ$, we got 7 successful connections for
sequential connection and 5 for the simultaneous connection. For displacement of
$15^\circ$ we got only 1 connection of 10 tries for the sequential connection
and no success for the simultaneous procedure.
When the connection was not successful it was mainly due to the hooks colliding
into each other. The collision usually caused a motor stall, which can be easily
detected by increasing current flow into the motor. This fact could be used by
the robots to detect such collision, and the robots could retry the connection.
\subsection{Load capacity}
\begin{figure}[t!]
\centering
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/dock_tang_load.jpg}
\caption{Normal stress}
\label{fig:dock_test_tang}
\end{subfigure}
~
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/dock_norm_load.jpg}
\caption{Shear stress}
\label{fig:dock_test_norm}
\end{subfigure}
\caption{Testing the load capacity of the docks. The load was attached to
the green carabiner.}
\label{fig:dock_test_load}
\end{figure}
We tested the load capacity in two different setups -- in a normal and a
shear direction (see figure \ref{fig:dock_test_load}) -- by attaching weights
to a carabiner hooked to one of the connected docks. The mating dock was fixed
to a support.
In the shear direction, we were able to repeatably attach a weight of 4.5~kg
until the docks disconnected. The disconnection left no harm on the docks. We
assume the plastic hooks bent under the load as the plastic is quite flexible,
the skirts got loose and therefore, the docks slipped from the connection.
\begin{figure}[t!]
\centering
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/dock_damage_1.jpg}
\caption{Dock hooks}
\end{subfigure}
~
\begin{subfigure}[b]{0.45\textwidth}
\includegraphics[width=\textwidth]{figures/dock_damage_2.jpg}
\caption{Broken pieces of the hook}
\end{subfigure}
\caption{Damage caused by load testing on the docks. The broken hooks are
highlighted using red circles. In the second figure, it can be seen that the
hooks broke exactly between the 3D printed layers.}
\label{fig:dock_damage}
\end{figure}
In the normal direction, we were able to attach a weight of 8~kg until the
malfunction of the connection happened. In this case, the connection mechanism
was damaged -- two hooks on one dock and one hook on the other dock broke. For a
photo of the damage see figure \ref{fig:dock_damage}. The pieces were broken
between two layers of the 3D printed component. The form of the damage leads us
to a suggestion for future experiments -- printing the hooks such that the
layers of the 3D print are oriented differently.
\section{Inter-module Communication}
We proposed in section \ref{sec:communication} that the modules in a RoFI system
should communicate using TCP/IP networking as it allows to easily adapt
existing algorithms and technical solutions. The proposed solution implements a
custom layer two of the standard ISO/OSI model.
To show the feasibility of the proposed solution, we have implemented a simple
prototype. The prototype does not provide any mechanical hardware, it consists
only of several interconnected development modules with microcontrollers. We
implemented a firmware for the ATMega328p microcontroller providing the dock
protocol (section \ref{sec:dock_interface}) and a corresponding part of the RoFI
driver for the ESP32 microcontroller -- a dock driver, an address mapping
protocol and an interface for the lwIP TCP/IP stack. Both implementations can be
found in the project repository.
The ATMega328p was chosen due to the availability of cheap development modules
in the form Arduino Nano and low-effort development. This decision allowed us to
quickly get a working prototype, however, at the cost of not providing a
solution with high performance as we reached memory and computational limits of
the microcontroller. The limitations come in form of limited SPI clock speed
(100~kHz) and a smaller maximal blob size (128 bytes). We consider the
implementation of the firmware straightforward and not worth further
description.
On the contrary, the implementation of the RoFI driver for ESP32 we provide is
intended for future use. The driver is written in C++14. It is structured in two
classes: \texttt{Dock} (a direct interface for a single dock) and \texttt{Roif}
(a network interface built on top docks).
\texttt{Dock} automatically handles communication with the docks, i.e., hides
all details of the communication (e.g., interrupt handling) and provides a
simple interface: a user can supply a binary blob (in form of the \texttt{pbuf}
structure from lwIP) or be notified about an incoming blob via a callback. The
interface for changing or querying a dock state (retracting or expanding of the
dock, querying the state of the power lines, etc.) is implemented in a similar
fashion. Our implementation prevents congestion of the shared SPI bus by
limiting the number of pending queries per dock and therefore, allowing for a
fair usage of the bus.
The challenge of the implementation was mapping SPI transaction to the interface
provided by the ESP32 development framework (ESP-IDF). ESP-IDF provides a way to
queue asynchronous SPI transactions with distinct read and write phases
including a delay between the phases. However, it does not support transactions
with a variable length, which are required by our protocol. The transactions have
to be implemented using several SPI transactions offered by ESP-IDF. The naive
implementation is not possible as transactions from multiple docks could
interleave and therefore, yield incorrect results. There are two possible
approaches to tackle this problem: we can either queue transactions in advance
and modify them on the fly, or we can use a separate FreeRTOS task executing
blocking SPI transactions. Our implementation uses the second solution as our
analysis of the ESP-IDF source code shows that changing already queued
transactions is not safe and also, the first solution requires non-trivial
locking. The second solution also produces easier to follow code with no
explicit locking as all the locking is handled by FreeRTOS.
\texttt{Roif} (\emph{Ro}Fi network \emph{i}ter\emph{f}ace) provides a glue
between docks and lwIP. It handles the registration of a new network interface
and all the required callbacks as we mentioned in section \ref{sec:networking}.
It also features an implementation of the address mapping protocol to determine
which dock should be used for outgoing communication.
As a by-product of the RoFI driver implementation, we implemented a set of C++
wrappers for the FreeRTOS API. Unlike the already existing C++ wrappers we are
aware of, we do not simply rename functions and group them in classes like these
wrappers. Our wrappers respect C++ idioms and also provide proper C++ copy and
move semantics (i.e., our wrappers support all types, not only primitively
copyable types). Such wrapper allows the user to write easier to understand and
less error-prone code. At the time of writing this thesis, the FreeRTOS wrapper
have not been separated into a~stand-alone project yet.
\begin{figure}[!t]
\centering
\includegraphics[width=\textwidth]{figures/communication_setup.pdf}
\caption{The setup for our inter-module communication prototype. Physical
realization is shown in figure \ref{fig:comm_setup_p}.}
\label{fig:comm_setup}
\end{figure}
\begin{figure}[!t]
\centering
\includegraphics[width=\textwidth]{figures/com_setup.jpg}
\caption{Physical realization of the setup shown in figure \ref{fig:comm_setup}.}
\label{fig:comm_setup_p}
\end{figure}
We tested our implementation in a simple setup shown in figure
\ref{fig:comm_setup}. We used three ESP32-DevkitCs simulating module controllers
and four Arduino Nanos simulating the docks. We wired them as shown in the
figure \ref{fig:comm_setup_p}. Then, we were able to successfully establish
both, TCP and UDP, connections. The codes for establishing the connections are
simple examples inspired by official demo codes. There are no modifications
specific for our setup made to the code. The example codes can be found in the
project repository.
Replication of our results should be fairly simple as we ship all the code as
PlatformIO\footnote{\url{https://platformio.org/}} projects, therefore no
complicated toolchain setup is necessary; and also, the hardware we use is
commonly available. However, during testing of our firmware, we encountered a
bug in lwIP implementation preventing a TCP connection from being opened. The
bug has been already fixed in the lwIP upstream repository, however, at the time
of writing this thesis, the lwIP library shipped with ESP-IDF was not updated.
Therefore, to successfully run the TCP example, a manual update of the library
is necessary.
\section{Universal Module}
So far, we have built several prototypes of the universal module; some of the
key iterations are shown in figure \ref{fig:um_evolution}. There were several
challenges during the design of the module; first, the module should be as rigid
as possible to be able to support large structures of RoFI systems (this is
challenging mainly due to the presence of the $\gamma$-axis), second, the
internal arrangement of components has to be compact to fit in the 10cm cube
grid and third, the module should be strong enough to lift at least two other
robots.
\begin{figure}[!t]
\centering
\includegraphics[width=\textwidth]{figures/um_evolution.jpg}
\caption{Evolution of the universal module. The first paper prototype
(left), the first 3D printed version (middle), and the current state
(right).}
\label{fig:um_evolution}
\end{figure}
The last prototype (figure \ref{fig:um_photos}) fulfills our goals -- it
features a rigid construction and we were able to fit sufficiently strong
servomotors (Heculex DRS-0101) inside the body while still leaving a reasonable
amount of space for the control electronics and an accumulator. The electronics
and an accumulator are supposed to fit in the central part of the robot; some
small components can be also placed in the cavity below and above motors for
$\alpha$- and $\beta$-axes.
\begin{figure}[!t]
\centering
\begin{subfigure}[b]{\textwidth}
\includegraphics[width=\textwidth]{figures/um_persp.jpg}
\caption{Perspective view}
\end{subfigure}
\begin{subfigure}[b]{\textwidth}
\includegraphics[width=\textwidth]{figures/um_side.jpg}
\caption{Side view}
\end{subfigure}
\begin{subfigure}[b]{\textwidth}
\includegraphics[width=\textwidth]{figures/um_top.jpg}
\caption{Top view}
\end{subfigure}
\caption{Photos of the universal module.}
\label{fig:um_photos}
\end{figure}
The prototype was 3D printed using the same settings as the docking mechanism.
The CAD models are available in the project repository. To produce all
components for a single module, 65 meters of a filament are needed with the
print time of 20 hours (excluding the docks). The additional components needed
for assembling the robots are: 3 motors DRS-0101, 1 ball bearing
$25\times32\times4$~mm, 4 ball bearings $15\times20\times4$~mm, 4
M$2\times18$~mm screws with a countersunk head, 18 M$2\times12$~mm screws with
countersunk head, 42 M$2\times6$~mm screws with a countersunk head and
4~M$2\times12$~mm screws with a regular head. Assembling the modules takes about
1 to 2 hours of work, most of the time takes to manually tap the threads.
We designed the components not to only be easily 3D printable but also to be
reasonably manufacturable by other techniques -- specifically milling (the body)
or sheet metal bending (the shoes). Such techniques could not only produce
stronger components from stronger materials but also, speed up the
manufacturing process.