[Music]
welcome back
our next speaker will be brett downing
he'll be speaking on the topic of g
streamer and ros roz a tale of two
messaging frameworks
brett is a hardware hacker whose passion
for robotics dragged him into software
development
there before we're going to see either
software or robotics
brett will allow time for questions at
the end so please enter any on the tab
in venulis
take it away brett
okay
um
so i've
been hacking on a software project to
essentially bridge
g streamer and rolls
um
pipelines are really cool if you were at
my last talk i discussed a bit about how
pipelines can help you
build reliable software that can be
extended maintained all the good stuff
especially as it applies to
advanced robotics meeting hardware
but pipelines as a general approach to
software make a lot of sense in a lot of
applications
you can
use them for large software projects and
then all of the components all of the
functionality becomes quite small quite
maintainable
you can write new applications using
proven utilities and you can teach old
applications new tricks by creating new
plugins for them
pipeline elements practically operate in
isolation elements pass messages between
each other but they aren't really aware
of each other beyond that
when you build applications with a
pipeline architecture the components can
become very simple and can become very
reliable
if an element does more than one thing
it usually just gets broken to more
elements
elements tend to inherit a lot of code
from some base package that often
includes the inspection tooling and the
build system not everyone likes that but
it certainly helps maintainers
a pipeline diagram is
easy to read and understand
especially understand what the pipeline
as a whole is trying to do
inspection tools that work on the single
pipeline element for the base element
work on all elements
the elements themselves share a lot of
code conventions making them easier to
read easier to share
easier to resurrect
gstreamer is a pipeline framework
designed for broadcast media it has very
strict timing and every media converter
you could think of
gstreamer's timing is so strict that
it's been picked up for gravity wave
gravity wave observatories
if you want to build new multimedia
applications and you want all of the
codecs and drivers
and a proven pipeline architecture use
geostreamer
gstream has so many drivers for cameras
that it's starting to show up as a core
dependency for self-driving cars
ros on the other hand is a pipeline
framework built for robots it shows up
in consumer robotics vacuum cleaners
it moves stuff around warehouses and it
forms the core of a lot of driver assist
technologies certainly in research
um
between the two
they have basically the same topology um
so there's a bit of
a jargon that they use different names
for um i will be using the terms pretty
much interchangeably and hoping that i'm
clear
uh
ask questions if it's not clear i'm open
to heckling
so
roz started round about 2007 with
the aim to end a decades-long academic
abandonware cycle
every new student would throw out most
of the work of the predecessor and spend
all of their time fiddling with power
systems and simple mechanics
roz was developed to encourage
roboticists to think
uh to think about their robots as
modular constructions to break them down
into a few fairly consistent interfaces
under a shared build tool
researchers competing on a mapping or
grasping problem could at least share
the code that makes the robot drive
around
roz doesn't trust the coding practices
of novice roboticists so every node is a
wholly separate program
this prevents a lot of conflicts and
side effects
ros nodes inherit a lot of functionality
from ros so they almost always build
using the default build system and the
default dependency manager
gstreamer was built to make it easy to
build capable and extensible multimedia
multimedia systems
gstreamer wanted to aggregate new and
unheard of
multimedia processing techniques under
one stable and versatile framework that
could be easily included into other
applications
gstreamer provides mesh messaging
framework and handles the scheduling
problems associated with complex
concurrent media streams gstreamer aims
for everything to be easily included
into even simple programs so it keeps
all of its computing the pipeline
elements under one process id making it
one program
gstreamer elements need to inherit a lot
of code from gstreamer so almost all
elements are built using the default
build system
fundamentally robot perception
and robot response data most of the
things that go through a robotics
pipeline
is the same kind of information as a
streaming multimedia platform
g streamer and roz chose the same
topology as an answer to basically the
same technical problem
and then for very good reasons
implemented that topology with nearly
opposite design decisions
gstreamer is
difficult to use for distributed
computing problems because it does not
provide network transports sensibly
passing that responsibility onto its
elements and there's so many of those
ros 2 is so flexible about message
passing
as a as a framework
that you almost never need to care which
computer your node is sitting on
ros 2 gains flexibility at the cost of
efficiency so while it can do image
processing the overheads associated mean
you don't want to use it for all of your
streaming media
rolls 2
mitigates most of those overheads that
were found in ros 1 but it still can't
beat the strict tempo rendering that
g-stream offers
there's a couple of robot ros packages
that use g-stream internally
if you build robots that see you're
probably going to look for at least one
camera driver the chances are if you
can't find a linux driver you'll find
driver in g-streamer
gs cam sticks a g streamer pipeline in a
ros node and whatever comes out of the
pipeline is put into an image message
and then transported on the ros message
bus
if you build a robot that can hear or
make noise raws is certainly not the
best framework for capturing or
processing real-time audio
audio common uses g-streamer to handle
raw audio
raw and then uses roles to move
compressed payloads between machines
i was disappointed to discover that it
discards all of the metadata and then
supports exactly one mp3 bit rate
transporting only binary payloads
but this was a very early package um
early 2010s i think
that was only really intended for
telepresence to
one machine
ros one without the package called
plug-in lib moved everything over a
socket
through a through a buffer through the
kernel
and not very efficiently at that so
copying raw images took forever
the compression options were limited and
i never did work out how to tune them
plug-in lib was the first ros package to
break the one node one process rules and
allow messages to be passed between
nodes by pointer
without copying or serializing data
nodes under plug-in lib share a couple
of threads in a single process just like
elements in a gstreamer pipeline
ros 2 expanded plugin lib to cover all
of the nodes making it easy to stuff all
of your nodes into a single process not
just the ones that inherited plug-in lib
plug-in lib is still around it just has
different use cases now
the defining features of ros 2 over ros
1 was pluggable transport systems
one such transport option allows
disparate processors on the same host to
allocate messages
to allocate message memory inside a
daemon
and then pass the message by pointer to
downstream elements and more than one of
them
so you get zero copy messaging from one
node to all downstream elements
there's a theme here ros one's messaging
efficiency was painful for more than a
decade rost2
fixed it in every way anyone could think
of
most of the time if you want to do some
image processing
you collect the image
from somewhere
turn it into an opencv matrix and then
do your preliminary white balance and
contrast adjustments in the privacy of
your process before implementing your
algorithm on that data
opencv is great but does a node a ros
node need that additional complexity
should a roboticist implement color
adjustments in every algorithm they
write
would other nodes benefit from the same
preliminary number crunching
in ros one that was very easy to answer
transporting images was so nightmarishly
expensive that you couldn't afford the
cpu time involved to share anything but
the final result it was cheaper to just
reprocess data
in ros2 it might be fine but then you're
just burning developer time replicating
a bunch of g-stream elements
so the images on screen now are the the
nodes and elements on screen now are
practically equivalent in every way
you could literally substitute them
so
if you want to use g streamer's ability
to efficiently manipulate video streams
and audio streams and multimedia in a
robotics perception pipeline
why not just bridge them
so i ended up putting a ros node inside
a g streamer element
for
g streaming this is kind of
run-of-the-mill it's just yet another
network transport for roz developers
though
this was a saw point that desperately
needed some systematic action
and
i mean i knew it would get used but this
is the first time i've had an open
source project gain traction
by putting whole g streamer pipelines
inside a rolls node you could launch
whole perception chains from a single
bring up command in ros
i'll demonstrate some of that later
as every good software project begins i
started by underestimating the problem
roz and gstreamer are both pipelines but
they're about as different as they can
be while still being pipelines
ros 2 relaxed the definition of a node a
little more than ros1 so a node is
really just anything that can announce
that it's a ros node
g stream elements on the other hand
can't exist in isolation so the only
practical way of bridging the two was
for a g streamer element to announce
that it's a ros node
robotics tends to have
many low bandwidth streams and a very
relaxed view on time
reactions should be as soon as possible
but a robust control system can deal
with modest latency in a bit of timing
jitter
if your video stutters though
you get mad
and
on the other hand a seven second delay
on live broadcast media is traditional
uh special relativity says that a time
without a place is meaningless
in gstream other play in gstreamer the
place is one hardware device typically a
sound card and all of the clocks and
timing is propagated from there
gstreamer provides powerful
synchronization algorithms to make sure
audio from say your bluetooth headset
matches video on maybe your second
monitor they're not sharing clocks but
they're in sync
ros timestamps on the other hand always
come with a frame id so for multiple
robots with multiple clocks you can use
the frame id to talk about which robot
you derived the clock from for a time
measurement
roz can't guess how your dozen clocks
are going to drift or interact
and it can't guess how you're going to
prioritize your time sources so it
doesn't
i'm reasonably certain these two stances
on the nature of time can't be
reconciled within either g stream or
raws but there's a couple of tools that
we can use to you know make it a bit
easier to manage
when you set up a
piece of a pipeline for broadcast media
you really don't want to start it all at
once
and you certainly don't want to touch it
until you're done
if part of the stream fails
you usually want the stream to just
all drop dead so that you can switch to
an alternate stream
when you set up a robot
the control pipelines you use to walk to
the kitchen might not be the same as the
control pipelines you use to open the
fridge
if part of the software dies on a robot
you want to turn on the remote control
and have the robot discover the remote
control
so that you can drive it back to the lab
instead of having to go and get the
forklift
gstreamer keeps metadata with the
pipeline and it has a complicated format
negotiation step that goes upstream and
downstream and puts together the most
efficient pipeline to do a given
a given streaming task very well
ros
packs complete metadata with each image
which gives it a bit more overhead but
it means that node developers don't need
to remember complicated things like
video formats
they can just process each image like it
was new by promoting stateless software
design you make it very easy for novice
developers to write testable code
this also means that you can play back a
bag full of archive perception data into
a new control system
and the new control system will behave
like it was on the actual robot this is
great if you've just plowed 100 acres of
farmland but you hit a rock along the
way and tripped up the old controller
you want to see if the new controller is
tripped up by the same thing
you can just snip it
the the problem part of the
the perception data feed it into the new
control system
and see how it behaves there's no
setup thing at the beginning that you
have to go and collect you can just
start anywhere
this difference though means that if a
ros node is a source of data for a g
stream of a pipeline the pipeline can't
start its negotiation phase until the
first ros message arrives
so
i plugged two pipelines together
and i didn't realize how
uh how much was hanging on this how much
software needed this
i've never felt like i was thrown
further into the deep end
i had a lot of people doing very strange
things with
perception data
robotics
i started getting issues showing up on
an issue tracker
i started having bugs and bug reports
some of them would you know
were the same bug over and over so
i had to set up regression tests and and
build tests uh ros is a
ros has two stable editions at any given
time both are supported by one api but
there's a rolling addition ahead of time
so you can kind of
hitch your build tools to the rolling
the rolling release and then get sort of
advanced notice for when an api changes
on you
licensing clarity
i had a company show up asking for
a bit more clarity on the license i was
offering it under
they wanted to use it for
as far as i can tell
using robot perception data on safe
uh air transport
uh drone traffic control that sort of
thing
um
autonomous robots and certainly
self-driving cars is not a thing um
no one currently has a fully autonomous
anything
but semi-autonomous certainly so driver
operate driver interaction operator
interaction during a semi-autonomous
procedure
everyone wants that and gstream is a
great tool to put together a
means of moving perception data from one
machine to another
really really efficiently
uh
had people doing strange things with
cameras underwater
they wanted to do stereo imaging but
their
their pressure envelope meant that they
couldn't
actually connect the two cameras as a
stereo rig they had to treat them as
independent cameras and then stitch them
after which included things like time
stitching
and of course when you make something
that feels like infrastructure
in something that sort of
bridges two worlds of self-driving cars
and machine learning all these memes of
course it's going to become homework at
some point
feature creep was
a thing
fortunately people in the roz community
seem to have
very realistic expectations and
understanding of how much work something
takes so
i had some discussions with people about
the weirdest camera formats i've ever
heard of
now i kind of started building this
because i wanted robots to interact with
people
like a webrtc
thing i actually wanted to use webrtc
uh because i've got a lot of friends who
do their work in workshop environments
and they move around their workshop
environment you can't just tie them to a
chair and have a chat with them you need
to follow them around
this was especially for
um immunocompromised friends in
their workshop where they got to play
with their tools but if you wanted to
hang out at their workshop you had to do
it without
bringing yourself there
um
turns out people don't like fiddling
with audio and ros
not sure why
uh gstreamer developers can treat this
plug-in this collection of elements like
any other network transport
these elements aren't started by roz
they're actually started by a pipeline
so
i had to wrap
i'd wrap the
i'll get to it
jstreamer has rigorous definitions for
binary encodings of images and audio
which is a very good thing because the
the endianness of an audio stream almost
never matches the endingness of the
system that it's carried by
there's a lot of legacy code
roz uses opencv for most of its image
processing and opencv can deal with
almost any
binary packaging that gstreamer can
throw at it likewise g streaming can
describe and handle any encoding that
roz can describe
i didn't have to touch transcoding at
all in the end the images image formats
that there was a one-to-one
correspondence with at least one format
on both sides
so the images the the the element and
the node they just
pass on a block of data without touching
it
roz
a ros image topic can
carry any kind of image but it's up to
the node to read the message metadata
when the image actually arrives
jstreamer configures all of its elements
ahead of time and that needs to know the
image format and dimensions of the image
before going from pause to playback so
i had to add a tool to
add a
parameter so you can pass the ros node a
format string to hand to g streamer so
that g streamer can go straight from
pause to playback it's a hack and i want
to talk to a g streamer dev about
renegotiating
uh
the pipeline format during runtime
so if you know how to do that let me
know
uh if you leave the format string empty
the ros source will
block the pipeline from going to
playback until the first message arrives
gstreamer's sense of time is
very strict very well defined it's
really good
uh genestreamer times timestamps
buffers through its messaging framework
as
nanoseconds since playback start
roz treats time as a relative thing and
then frowns on the use of datums
so the bridge nodes sample the various
clocks at startup and then apply offsets
so the times represent something
sensible in both pipelines
i ended up wrapping the gstreamer launch
syntax with a python node that is a ros
node
ros node implemented in python
a little like gscam does
but the pipeline string can be passed in
from configuration
in ros so that you can package
uh
essentially a version controlled ros
package that says
this robot needs these packages and
needs to start these nodes with this
configuration all as one version
controllable configuration file a
configuration package
now i wanted to use
i wanted to use the raspberry pi camera
over the internet
so both ros and gstreamer allow
parameters or properties the same thing
to be altered on the fly allowing you to
tune things as you go
robots often
often end up on the end of a very long
internet connection a very long unstable
one
and the easiest way of limiting
bandwidth is to reduce the bit rate on
the camera
so
the easiest way of tuning the camera
bitrate on the raspberry pi the h264
compression in its gpu
a bit of background the pi cam
attaches to the pi in a low level
interface
that data goes straight to the gpu where
it does hardware h.264 compression
and then passes that onto the cpu
through a bit of a memory bottleneck
which then can be picked up by
applications such as the pycam software
which has been wrapped by a gstreamer
node and is available in the public
archives
so if you want to
adjust
the bitrate of the h.264 encoding you
need to change the g stream of property
now that isolation property of
of pipeline frameworks
means that the pi cam is not guaranteed
to exist in any given pipeline so if i
wanted to capture
the h.264 bit rate
and expose it to ros i needed to capture
all of the properties of
all of the elements in every pipeline
and expose them to roz the bit rate had
to be captured by a general solution
uh
demo time
so behind me
last session i had a robert claw
and i didn't point out in that session
the second camera was this robot here
uh
so on the screen now is the
all of the nodes that are currently
running on that robot
so
i can go ahead and
launch
from a package
some node with some configuration
and that goes and loads up a gstreamer
pipeline it goes and loads up a joystick
driver
which
then show up
and stitch together a pipeline using ros
the joystick
and
the the teleoperation tools are exactly
the same
as i used to drive the claw but this
time it's targeting a wheeled robot
the mixer node
handles the the vector from the joystick
and then passes that on to
[Music]
the actual
the motor system
at the same time i've got the gstreamer
pipeline
which has a bunch of properties which
can't be mapped
ignoring gst objects
ignoring
structures that whatever
so these are these are jstream of
properties that are exposed by elements
that can't be mapped in a type safe
manner to a ros property
it's picked up a joystick
and it started
the udp stream
which gives me access to
the image topic
sorry
access to the gstreamer
compressed video feed
as
a ros
uh image message
so this here is a video
in ros as a ros
as ros
message and then if i turn the motors on
uh not that
so
this one is just
a raspberry pi
pi camera
a
servo
server control breakout a couple of
batteries couple of motor controllers
and that's it the the whole thing can be
put together for
only 50 bucks
i'm gonna put that down uh
those ones um
those ones debuted at
those robots are actually the same as
the
the one that i'm about to drive
uh
these robots are again a pi zero
with pi cam
with motor controllers
and that little mount there is for
adjusting pole these debuted at
the canberra python user group and we
had a great time
jousting with them in the park
there's two of them
and they are just identical they're
exactly the same as the little robot
it's just they're using skateboard
wheels and larger batteries
so if there's any questions i'm happy to
take them now
that's kind of all the
demo that i needed to get through
but i have a bunch of other stuff that i
can show while i'm answering questions
um particularly
i want to show the
so by using
raws by using a pipeline framework
i can using
pipeline introspection tools to just
discover everything
on the network
so here's a list of
all the nodes on my
local network so the raspberry pi and
the laptop stuff is all discovered
automatically i don't have to worry
about where my nodes sit
um
the other one is
i can use g streamer inspection tools
if i tell it where i've built the
gstreamer plugin
i can inspect any of the
elements that i've put together
and gstreamer just provides
automatic documentation features this is
amazing for
uh
software
conservancy
um
especially when you've got academics
going through and
um
you know
building building up robots where
it's their first time touching
electronics touching hardware touching
software the ability for people to
just write some code and have it
automatically get documented and then
you know read their own docs
to figure out what's what might be wrong
what might be misconfigured this is
extremely valuable to novice developers
ros gst bridge is the plugin name
it's just a shared object
the image sync is what i'm inspecting
now
uh all of this
is inherited from
the jstreamer framework
and then right down at the bottom i have
just what's novel about
using raws
in jstreamer
so i ended up having to write
not an enormous amount of code
in order to make something that was
really quite capable
uh
the other one is because i've loaded
ros nodes into gstreamer elements i can
put together
you know additional snippets of pipeline
using just
gstreamer launch
so
something that's really common in
robotics is you have high quality
cameras
in a high quality lab
on a high quality network
and
your robot never encounters mud until
it's too late
so something you often want to do is
either like do a bit of pre-processing
or
damage
your video feed before passing it on to
the control system
so if i run that
and pray to the demo gods
then i should have
some amount of debris
on my camera feed
that's provided by gstreamer
so then on the node graph
i've got all the joystick stuff
joystick stuff all the way to motor
control
i've got the
the ros node that is inside the
gstreamer pipeline
producing an image message
hands it on to another ros node inside
another g-stream pipeline
which does pre-processing
that comes out here
which then gets picked up by
the
iqt gui
interface um now i said i covered
uh source and sync for
images audio and text
this install setup dot bash is a raw's
invocation to set up some environment
variables
uh
it is a little bit tedious and there are
some people who have put together
some extremely compelling bash aliases
um
so this
so here i'm using g streamer launch
syntax to
invoke
ros nodes
uh
ros image source
puts it in some namespace
uh i've got some
rostopic
and then i give the node some name
the video convert is
because i'm not taking chances of the
live demo
rolls text source
to put a text overlay over the top
so that one
might show up
i've got high dead sinks on because
there's a lot of
background clutter
now all of those nodes again show up
their topics when i ask for them there's
text overlay
let's minimize that
so image
processed image text this is the same
image on a different ros topic
and then i can publish to it
text overlay it's a strongly typed
message
where am i
that's a
using the bash escaping rules
and i've got text overlay on a video
i've pulled
what i've done i've taken
a ros command line tool
to produce
messages onto what was that
if i keep that going
it'll show up in rqt
so i've got the command line client
submitting messages text messages to a
text overlay topic which gets picked up
by a ros node inside a gstream or
pipeline
which gets composited
onto
wow that's unhappy
composited into my video feed and then
emitted onto
another ros topic
again this is kind of unremarkable for
jstreamer
but
this kind of flexibility
with this many image manipulation tools
is just something that rolls hasn't had
yet
and i've had a hell of a time
a wonderful time
talking to community members about
you know
what they're trying to achieve with
this bridge package what they're trying
to achieve with
ross perception data
um
and then
not just you know what community members
are trying to do with perception data
but uh
you know what they think about
uh my code what they think about uh
testing practices
like having an open source project just
take off on you when you're not quite
ready for it
is
as an experience but the ros community
have been really quite
gracious about it
and of course when you do that much
compositing you get a whole lot of
latency and you can't control the robot
hello
hi brett i just came in to help you with
the questions
great thank you we have a couple of
questions appeared
first of all uh which approach do you
prefer uh bridge the two different
framework uh ros and g
streamer or to provide a distributed
framework that transparently subsumes
ros and g streamer
i don't think you can can subsume both
ros and g streamer
um
both g streamer and raz are moving
targets roz certainly is a bit
less api stable than g streamer
um
the
the api and api the binary interface
stability in raws is something they're
emphasizing within a release
uh api compatibility should be
maintained between two releases
but there's not really
much benefit
in
trying to subsume
two enormous squiggly frameworks
uh you would end up creating a whole
pile of conventions that a lot of people
just don't agree with because
the conventions of roles are so
dissimilar from the convention of g
streamer
so
what i've ended up doing is
essentially merging the two
on both sides
so gstreamer has a launch syntax
which you just saw
you can launch a bunch of stuff on the
command line you can describe your
pipeline
as
a bunch of stuff separated by
exclamation marks so by putting
pipelines in configuration strings in
rows you can start g streamer pipelines
in ros nodes
likewise by placing ros nodes inside g
streamer elements you can start ros
pipelines in gstreamer
so i don't think that the two
should be subsumed by another framework
because they they can work so nicely
together
okay
the next question is is there a way i
can play with this stuff without having
all the physical equipment
absolutely
so there's simulation tools
um
so in my last talk uh i believe it was
recorded and released um
the claw behind me i have a full
i described it in ros sorry i described
the claw in openscad
printed it exported kinematics
descriptions from openscad into
rvs into some kinematics tools on the
command line and then ran a simulation
of the claw responding to joystick input
as though it was a real thing and in
that talk i had the physical model
um
the physical model
uh
doing exactly the same motions as the
simulated model at the same time so
you don't need
any real hardware at all
uh just a laptop running
usually just ubuntu linux
um
and then there's gazebo uh ignition
robotics has the gazebo
simulation environment which gives you
physics and then you can add plugins
the the gazebo simulation environment
has plug-ins which support g-streamer
pipelines so you can actually
i haven't played with that yet i'm
looking forward to that
so you can put a camera into your
simulation environment and then attach
it to a robot
and then have your control system just
everything is in simulation
great
so
what would you like to do now would you
like to continue the demo would you like
to finish or there are no more questions
currently
cool um
so there's the github to the
um
to the bridge that i've been building
the other thing i wanted to
maybe look into
maybe talk about was the
the launch syntax
with robots you usually have hardware
that moves a little bit slower than
software so you need to version control
like people like to have
robots
their software and their
control systems version controlled
alongside
um
alongside hardware it revisions
uh
so in this case i have
uh
launch descriptions um
this is the launch the ros launch syntax
in python it is just a python program
it's a little bit verbose and there's
actually some motion to
putting something together that's a
little
nicer
but you can see in this one
on the robot at least i've got
this is the motor driver node
and then i've got the pipeline
with the same package i've got the mixer
which handles joystick input
and then
uh handling the the hardware device to
synthesize the server commands
um
on the robot i load the raspberry pi
camera
oh yeah that was the other one uh
bitrate is
a jstreamer property so
where's the parameter table
the bitrate is a gstreamer property
which means that i can
let's
do this
so on the robot i've got the raspberry
cam udp
node this thing handles
the
raspberry pi camera source
the h.264
parsing and payloading
and these are all the properties for all
of those elements
which means
if i can find the bit rate
so this this node is running on my
laptop the raspberry pi camera is
attached to physical hardware
on the
robot i should be able to
if i select the node
camera node
a bit rate
i've lost it again
and i get that
it'll interrogate the robot and using
the ros pub sub um
metaphors on its bus it'll come out with
some integer value
now
the same parameter
i should be able to set
with a number
that is lower
and then on the device
it starts to reduce the quality of the
feed if i can drag that down
really low
you can see it gets real grainy very
quickly
i think i can drag that a little lower
until it's
you know scarcely visible so
this was actually inspired by
a
hackaday author that developed solarboy
which was a
cross-country
uh rover which was on the internet uh
this property mapping was intended as
an option for him to
uh
manage his bandwidth more sort of
automatically on the device
okay bret we just have a last question i
think before we wrap up
what runtime are you using on the esp32
oh
that was also my previous talk that was
the whole talk um the runtime on the
esp32 is called micro gross
and then it announces itself on
the the local network as a whole rolls
node uh
really cool very recent uh really
excited about that one go take a look at
the previous talk
excellent thank you
well thank you for the wonderful talk
and
that's it for now we have a 10 minute
break before the next session
great thank you thank you brett