WEBVTT

00:00.000 --> 00:16.000
All right, so let's say you switch to retinab and now you need to implement your behavior

00:16.000 --> 00:17.000
please.

00:17.000 --> 00:20.000
Probably below is going to present an option for that.

00:20.000 --> 00:21.000
Thank you very much.

00:21.000 --> 00:23.000
All right, yeah.

00:23.000 --> 00:25.000
Thank you for this nice transition.

00:25.000 --> 00:26.000
So I'm Robin.

00:26.000 --> 00:28.000
I'm from the Technical University in Downset.

00:29.000 --> 00:31.000
And I work mostly with aerial robotics.

00:31.000 --> 00:37.000
And for a few years ago, I started working with my master thesis,

00:37.000 --> 00:42.000
and I tried to develop an automated mission management tool

00:42.000 --> 00:44.000
for using it with PX4.

00:44.000 --> 00:47.000
And I tried to use behavior trees for this,

00:47.000 --> 00:49.000
and this is how this project is developed,

00:49.000 --> 00:52.000
because there was no real integration with Rust

00:52.000 --> 00:57.000
through that that allowed me to use it in PX4 as I wanted.

00:57.000 --> 01:02.000
So yeah, I don't have the time to explain to you

01:02.000 --> 01:07.000
what behavior trees are, but I was just giving you a small introduction.

01:07.000 --> 01:10.000
So why do we need something like behavior trees,

01:10.000 --> 01:11.000
or state machines?

01:11.000 --> 01:16.000
It basically gives us the possibility for intelligent robotics

01:16.000 --> 01:20.000
to implement decision-making logic and reactive mechanisms.

01:20.000 --> 01:23.000
And usually behavior trees, they promise,

01:23.000 --> 01:28.000
composability, modularity, and this reactivity that I spoke of.

01:28.000 --> 01:32.000
And it doesn't let us drown in this spaghetti logic

01:32.000 --> 01:35.000
that state machines usually do,

01:35.000 --> 01:39.000
because in state machines each state has a transition

01:39.000 --> 01:43.000
to another and the more states, the more suggestions you have.

01:43.000 --> 01:48.000
So this can get very complicated once your project scales.

01:48.000 --> 01:55.000
So I looked into the ecosystem, and I found that there's lots of frameworks

01:55.000 --> 01:58.000
or lots of implementations of behavior trees,

01:58.000 --> 02:02.000
and also some integrations into Rust.

02:02.000 --> 02:07.000
And I found that the Python integrations are usually a bit more usable

02:07.000 --> 02:10.000
than the C++ ones.

02:10.000 --> 02:16.000
But I wanted to have the deterministic timing of C++

02:16.000 --> 02:20.000
and also the robustness in resource-constrained environments

02:20.000 --> 02:22.000
since I was working with drones.

02:22.000 --> 02:26.000
And this could become an issue when the future.

02:26.000 --> 02:29.000
So I decided to do this in C++,

02:29.000 --> 02:31.000
and there obviously there was behavior TCPP,

02:31.000 --> 02:34.000
and the video by now you should be very flattered

02:34.000 --> 02:40.000
since it's another default call at dev talk that mentions your work.

02:40.000 --> 02:45.000
And I tried to find different ways of integrating that into Rust

02:45.000 --> 02:48.000
and have two, for example, or behavior tree Rust.

02:48.000 --> 02:56.000
Since in my opinion, it wasn't quite fitting my needs to set us

02:56.000 --> 02:58.000
by me, basically.

02:58.000 --> 03:01.000
So I set basically three design goals.

03:01.000 --> 03:06.000
I wanted to develop a domain-agnostic development framework

03:06.000 --> 03:11.000
for behavior trees that allows us to do behavior-based control

03:11.000 --> 03:14.000
and automated planning, without depending on

03:14.000 --> 03:17.000
what we have to or something like this, for example.

03:17.000 --> 03:20.000
I also wanted to reduce the configuration overhead,

03:20.000 --> 03:23.000
that usually comes with C++ projects,

03:23.000 --> 03:26.000
and to lower the barrier to entry.

03:26.000 --> 03:29.000
And also I wanted to focus really on modularity and reusability

03:29.000 --> 03:33.000
since I wanted to be a generalized framework.

03:33.000 --> 03:36.000
Okay, so with this motivation out of the way,

03:36.000 --> 03:39.000
how does it work now in detail?

03:39.000 --> 03:43.000
So behavior trees would usually use in a robotics

03:43.000 --> 03:47.000
architecture like this, where you have your user domain with your notes,

03:47.000 --> 03:49.000
or I call it skills here.

03:49.000 --> 03:52.000
For example, this could be the easy-nav framework,

03:52.000 --> 03:56.000
and then you would have the behavior trees for orchestrating your skills,

03:56.000 --> 04:00.000
your functions of your robots,

04:00.000 --> 04:04.000
and behavior trees therefore represent policies or plans,

04:04.000 --> 04:08.000
and they use functions of the robot through clients

04:08.000 --> 04:11.000
or decolon notes with behavior trees.

04:13.000 --> 04:16.000
So I think for getting more into detail,

04:16.000 --> 04:18.000
we need like a little examples.

04:18.000 --> 04:21.000
So I created a little robot simulation

04:21.000 --> 04:24.000
that we're going to follow along here.

04:24.000 --> 04:28.000
We're going to use for explaining the behavior tree framework,

04:28.000 --> 04:31.000
and this robot exposes two interfaces.

04:31.000 --> 04:35.000
So one sensory interface for reading the position of the hand,

04:35.000 --> 04:41.000
the current position, and a actuator basically.

04:41.000 --> 04:44.000
So we can send velocity commands to the hand,

04:44.000 --> 04:47.000
so it moves to the left or to the right.

04:47.000 --> 04:51.000
And for creating a wave behavior now,

04:51.000 --> 04:54.000
what we do is to create the behavior,

04:54.000 --> 04:58.000
or the build request for the executor for the behavior.

04:58.000 --> 05:02.000
And for behavior tree CPP, it looks something like this,

05:02.000 --> 05:05.000
so we have an XML schema,

05:05.000 --> 05:09.000
and on the right, you see the visual representation of it.

05:09.000 --> 05:12.000
And the behavior in this case, it's pretty simple.

05:12.000 --> 05:15.000
We want to move to an end position for doing the wave,

05:15.000 --> 05:17.000
and maybe repeat it for once or twice,

05:17.000 --> 05:20.000
and then we want to move back to the center.

05:20.000 --> 05:23.000
So this is the first example I'm going to show you,

05:23.000 --> 05:26.000
and I'm going to show you how to implement it with RAPMS.

05:26.000 --> 05:28.000
So first of all, we need notes.

05:28.000 --> 05:30.000
Since all of the behavior trees,

05:30.000 --> 05:33.000
they are implemented or they use these notes

05:33.000 --> 05:36.000
that call the robot skills,

05:37.000 --> 05:40.000
and there's potentially lots of them.

05:40.000 --> 05:42.000
So we need a way to organize them.

05:42.000 --> 05:45.000
So we have a node manifest in RAPMS.

05:45.000 --> 05:48.000
It's basically just YAML configurations,

05:48.000 --> 05:51.000
where you specify a plugin,

05:51.000 --> 05:53.000
and then some other configurations.

05:53.000 --> 05:56.000
And for example, for this behavior,

05:56.000 --> 05:57.000
we have four notes.

05:57.000 --> 05:59.000
So we have move for the site,

05:59.000 --> 06:03.000
stop movement, and hand reach end position, and hand is centered.

06:03.000 --> 06:07.000
And you might have noticed that we reused

06:07.000 --> 06:10.000
this existing implementation of a velocity publisher,

06:10.000 --> 06:12.000
in this case,

06:12.000 --> 06:15.000
but by just configuring different ports,

06:15.000 --> 06:18.000
different default values for the velocity port,

06:18.000 --> 06:20.000
we give it a different semantic meaning.

06:20.000 --> 06:22.000
So we have two distinct notes,

06:22.000 --> 06:25.000
but we're reusing the C++ implementation,

06:25.000 --> 06:28.000
which allows us to really write as little code

06:28.000 --> 06:31.000
as we really need to write,

06:31.000 --> 06:33.000
and not just change a little thing,

06:33.000 --> 06:38.000
and we just have the same code and repeat ourselves.

06:38.000 --> 06:44.000
And this is also the case for the position interface.

06:44.000 --> 06:47.000
So with these notes,

06:47.000 --> 06:51.000
we need to go into our C-Mac list of our package,

06:51.000 --> 06:53.000
and it's a C++ project.

06:53.000 --> 06:57.000
We configure a C++ project with C-Mac,

06:58.000 --> 07:01.000
and it looks something like this with this framework.

07:01.000 --> 07:05.000
So first of all, we need to register our plugins,

07:05.000 --> 07:07.000
in a C-Mac all like that.

07:07.000 --> 07:10.000
Now, remember, we have two plugins,

07:10.000 --> 07:12.000
and in the second code block,

07:12.000 --> 07:14.000
you see that we link these plugins

07:14.000 --> 07:17.000
with the node manifests that I've showed you before.

07:17.000 --> 07:20.000
So this is where we do the mapping between

07:20.000 --> 07:22.000
the registration names of the notes,

07:22.000 --> 07:25.000
and the implementation that we want to use

07:26.000 --> 07:28.000
when we're calling these notes.

07:28.000 --> 07:31.000
So in this integration into C-Mac,

07:31.000 --> 07:33.000
we get some benefits out of it.

07:33.000 --> 07:34.000
So first of all,

07:34.000 --> 07:37.000
we register our configurations,

07:37.000 --> 07:38.000
workspace-wise,

07:38.000 --> 07:40.000
so we can reuse it in the future

07:40.000 --> 07:42.000
in our distributed workspaces,

07:42.000 --> 07:45.000
and we can do some compile-time validation checks

07:45.000 --> 07:48.000
that helps avoiding runtime errors

07:48.000 --> 07:50.000
that are usually harder to debug.

07:50.000 --> 07:54.000
And also it allows us to generate code automatically,

07:54.000 --> 07:58.000
for example the XML file for the node models

07:58.000 --> 08:02.000
that you usually use with visual editors,

08:02.000 --> 08:03.000
like Brut,

08:03.000 --> 08:06.000
and also in this very specific to our APMS,

08:06.000 --> 08:08.000
we generate a C++ header

08:08.000 --> 08:12.000
that we use with our together with our builder API.

08:12.000 --> 08:15.000
And I'm going to show you what exactly this is

08:15.000 --> 08:18.000
in the coming slides.

08:18.000 --> 08:20.000
So now we have the node manifest,

08:20.000 --> 08:21.000
we have the builder requests,

08:21.000 --> 08:25.000
so we're basically able to deploy the behavior

08:25.000 --> 08:27.000
by now.

08:27.000 --> 08:32.000
And for this we call another macro in the configuration file,

08:32.000 --> 08:35.000
where we just specify our build request,

08:35.000 --> 08:37.000
that is basically an XML file,

08:37.000 --> 08:39.000
and we give it an alias,

08:39.000 --> 08:42.000
and also we link to this behavior,

08:42.000 --> 08:44.000
or to this definition of the behavior,

08:44.000 --> 08:46.000
we link a specific node manifest,

08:46.000 --> 08:50.000
and we can do this both for doing the waving to the left,

08:50.000 --> 08:52.000
and the waving to the right.

08:52.000 --> 08:55.000
And don't need to redefine our behavior or something like this.

08:55.000 --> 08:57.000
We just switch out the nodes,

08:57.000 --> 08:59.000
and then we have a different behavior.

08:59.000 --> 09:03.000
So this is what's denoted by this side variable here.

09:03.000 --> 09:08.000
So we would do this called twice for once left and once right.

09:08.000 --> 09:12.000
And then also we basically with this configuration,

09:12.000 --> 09:15.000
we're able to just run this behavior

09:15.000 --> 09:18.000
with our unified CLI tool for running behaviors,

09:18.000 --> 09:21.000
and then we define the identity of the behavior we want to run,

09:21.000 --> 09:24.000
and we might also just define some blackboard values

09:24.000 --> 09:27.000
to give some variables to the behavior.

09:27.000 --> 09:29.000
And then it looks something like this.

09:29.000 --> 09:30.000
So we call this this command here,

09:30.000 --> 09:32.000
and the hand moves to the left,

09:32.000 --> 09:33.000
repeats its twice,

09:33.000 --> 09:36.000
and the same thing happens for doing it on the left.

09:36.000 --> 09:38.000
And then it looks something like this.

09:38.000 --> 09:42.000
So we call this this command here,

09:42.000 --> 09:44.000
and the hand moves to the left,

09:44.000 --> 09:46.000
repeats its twice,

09:46.000 --> 09:49.000
and the same thing happens for doing it to the right,

09:49.000 --> 09:54.000
and we just need to change a little namespace here.

09:54.000 --> 09:57.000
And we have two different, two very distinct behaviors,

09:57.000 --> 09:59.000
but using minimal code,

09:59.000 --> 10:01.000
minimal configuration,

10:01.000 --> 10:04.000
and minimal XML definition.

10:04.000 --> 10:09.000
Because we maximize the reusability through this framework.

10:09.000 --> 10:14.000
Okay, so by now I've shown you how you work with this framework,

10:14.000 --> 10:17.000
using the existing practices that you know,

10:17.000 --> 10:20.000
when you've tried behavior to CPP.

10:20.000 --> 10:23.000
But let me tell you, there's more to this framework

10:23.000 --> 10:25.000
than just to plain behavior trees.

10:25.000 --> 10:30.000
So it's just defining the behavior tree as an XML file.

10:30.000 --> 10:36.000
There's also the possibility to customize your behavior generation pipeline.

10:36.000 --> 10:41.000
And this basically needs us to understand what a behavior is.

10:41.000 --> 10:47.000
So in our IPMS, we're defining a behavior as a collection of components.

10:47.000 --> 10:51.000
So first of all, the most important component probably is a build request.

10:51.000 --> 10:54.000
So this is the XML definition I've showed you before.

10:54.000 --> 10:56.000
And then we have a build handler,

10:56.000 --> 11:01.000
and this is a very innovative approach, I'd say.

11:01.000 --> 11:08.000
So we are just going to find this component as the algorithm that is responsible for creating

11:08.000 --> 11:13.000
the run out of the executable behavior tree out of the build request.

11:13.000 --> 11:16.000
And this can be anything like depending on your use case,

11:16.000 --> 11:18.000
you just write your plugin,

11:18.000 --> 11:20.000
define a format for your build requests,

11:20.000 --> 11:26.000
and you create a behavior tree that fits your needs.

11:26.000 --> 11:30.000
So the idea of the build handler is interesting,

11:30.000 --> 11:32.000
so but why do we need it?

11:32.000 --> 11:37.000
Let's say we want to move the hand now twice to the left, twice to the right,

11:37.000 --> 11:38.000
and then once left, once right.

11:38.000 --> 11:42.000
So very specific behavior that we couldn't do with our current definition,

11:42.000 --> 11:45.000
because we would only wave left or right.

11:45.000 --> 11:50.000
And now you might say, obviously we can just rewrite our behavior,

11:50.000 --> 11:52.000
we could just quickly sketch a new behavior,

11:52.000 --> 11:54.000
it is not a big thing,

11:54.000 --> 11:56.000
but that's not really the cool thing to do.

11:56.000 --> 12:02.000
We want to automate this because potentially we want to kind of also integrate

12:03.000 --> 12:07.000
some variables for this build mechanism,

12:07.000 --> 12:11.000
and this doesn't solve probably potentially very beneficial

12:11.000 --> 12:16.000
if we automate this because of the future,

12:16.000 --> 12:19.000
because of scalability basically.

12:19.000 --> 12:21.000
And for this behavior now,

12:21.000 --> 12:27.000
I want to show you how to solve this by creating a new build handler.

12:27.000 --> 12:30.000
So we create also a new build request

12:30.000 --> 12:35.000
that specifies only the very interesting parts of the request.

12:35.000 --> 12:38.000
So only if you want to move left or right and when.

12:38.000 --> 12:42.000
So this is basically a sequence of characters with L&Rs.

12:42.000 --> 12:45.000
And this is what for what build build handler,

12:45.000 --> 12:49.000
and this is what build handler like this could look like.

12:49.000 --> 12:53.000
And you see here we just import or create a new behavior tree

12:53.000 --> 12:57.000
from our existing behaviors that we have in our workspace already.

12:58.000 --> 13:03.000
So in this case we import the behavior tree for moving to the end position,

13:03.000 --> 13:06.000
and we do this for both moving to the left and to the right,

13:06.000 --> 13:09.000
and then rename it, we rename it,

13:09.000 --> 13:13.000
and this is all happening through the tree build API.

13:13.000 --> 13:16.000
And in the second code blog we parse the build request

13:16.000 --> 13:18.000
that we give the build handler,

13:18.000 --> 13:21.000
and it generates the behavior tree,

13:21.000 --> 13:23.000
the corresponding behavior tree,

13:23.000 --> 13:27.000
automatically by just executing this for loop,

13:27.000 --> 13:32.000
and then inserting the subtries in the sequence

13:32.000 --> 13:35.000
where we're supposed to be.

13:35.000 --> 13:40.000
And then we're returning this tree and it can be executed by the executor.

13:40.000 --> 13:42.000
So this is the implementation,

13:42.000 --> 13:46.000
obviously we need to register this again with the configuration in CMake.

13:46.000 --> 13:49.000
So we call another macro just to register the build handler,

13:49.000 --> 13:53.000
so this is its name, and then we call the macro for registering a behavior.

13:53.000 --> 13:57.000
And now you might have noticed this says register behavior,

13:57.000 --> 13:59.000
the previous one said register trees.

13:59.000 --> 14:03.000
So this is a bit more of an abstract definition now,

14:03.000 --> 14:05.000
because it's not only a tree,

14:05.000 --> 14:07.000
it's a whole new definition of a behavior.

14:07.000 --> 14:11.000
Since we have a different format for the build request,

14:11.000 --> 14:15.000
and we want to handle this build request with a specific algorithm.

14:15.000 --> 14:17.000
So this is what we specify here.

14:17.000 --> 14:21.000
I'm just going to statically register the behavior definition here,

14:21.000 --> 14:25.000
the request, and link it with this builder.

14:25.000 --> 14:29.000
So the executor knows during runtime how to interpret this message.

14:29.000 --> 14:34.000
So we can run this behavior with the same CLI tool as I've shown you before.

14:34.000 --> 14:36.000
And this is what it looks like.

14:36.000 --> 14:40.000
You know, see there's lots of behaviors already in the workspace,

14:40.000 --> 14:43.000
also a custom one, and this one we're going to execute now.

14:43.000 --> 14:49.000
So it sends the builder request and the hand moves left, left, right, right, left, right.

14:49.000 --> 14:53.000
And you could also do this just dynamically.

14:53.000 --> 14:59.000
You could just load the build handler and send an arbitrary builder request

14:59.000 --> 15:01.000
that just respects the format.

15:01.000 --> 15:05.000
You have to find with this build handler and change the behavior

15:05.000 --> 15:11.000
that's been generated during runtime as you like in your application.

15:12.000 --> 15:14.000
And now you also have like this, this,

15:14.000 --> 15:19.000
the engine of reactivity that people usually want with behavior trees,

15:19.000 --> 15:25.000
because you could not only just hard code the reactivity in the behavior,

15:25.000 --> 15:31.000
but you can also just make the behavior generation reactive by itself.

15:31.000 --> 15:37.000
So the executor is basically, this is all unified within one executor note

15:37.000 --> 15:42.000
in this framework that just awaits these,

15:42.000 --> 15:46.000
well, these definitions, the components of the behavior definition.

15:46.000 --> 15:50.000
So they request handler and then entry point in the node manifest,

15:50.000 --> 15:56.000
optionally, and also is compliant with the rawst to action interface.

15:56.000 --> 16:01.000
And this is basically happening just like with standard rawst,

16:01.000 --> 16:06.000
there's only one command that you have to like run and this is like a standalone executable

16:06.000 --> 16:08.000
that doesn't require an F2.

16:08.000 --> 16:11.000
So is the main diagnostic solution,

16:11.000 --> 16:18.000
and yeah, you can start creating your own behavior definitions for use cases.

16:18.000 --> 16:22.000
Okay, so I'm coming to the answer of my talk now.

16:22.000 --> 16:27.000
I've officially also released this project with the rawst index.

16:27.000 --> 16:34.000
It's up for you to install it with as any other project that you install

16:34.000 --> 16:37.000
individually, and I encourage you to give it a try,

16:37.000 --> 16:40.000
and streamline your rawst to project.

16:40.000 --> 16:43.000
And also there's something interesting coming up.

16:43.000 --> 16:48.000
I'm actually working together with a group of students in my university, computer science students,

16:48.000 --> 16:53.000
and we're trying to create like a behavior management tool that is web-based.

16:53.000 --> 16:58.000
So we have all our behaviors that we've registered in our workspace,

16:58.000 --> 17:03.000
at hand, at a visualization in the browser,

17:03.000 --> 17:06.000
and we can run it as we like.

17:06.000 --> 17:11.000
So we have basically a remote mission manager always in the browser.

17:11.000 --> 17:15.000
If we want to manage our mission with behavior trees.

17:15.000 --> 17:20.000
Okay, thank you very much for this for your attention.

17:20.000 --> 17:24.000
And all the material or the code is on GitHub.

17:24.000 --> 17:28.000
Also there's extensive user guides for this project.

17:28.000 --> 17:31.000
And I found that the AI generated docs are actually also very helpful,

17:31.000 --> 17:34.000
especially if you pipe them into some LLMs.

17:34.000 --> 17:36.000
It's very interesting what's possible.

17:36.000 --> 17:38.000
Okay, thank you very much.

17:38.000 --> 17:51.000
I have plenty of time for questions, anybody?

17:51.000 --> 17:53.000
No, nobody.

17:53.000 --> 17:54.000
Anything online?

17:54.000 --> 17:55.000
No?

17:55.000 --> 17:59.000
Oh, there's one.

17:59.000 --> 18:01.000
Yeah, thanks for the presentation.

18:01.000 --> 18:05.000
So you mentioned that this is kind of integrated with the NAFER framework.

18:05.000 --> 18:06.000
No, it is not.

18:06.000 --> 18:07.000
It's not.

18:07.000 --> 18:08.000
It's not.

18:08.000 --> 18:10.000
But it's the main agnostic.

18:10.000 --> 18:16.000
Okay, I was wondering if it's also possible to use this for like the movement framework.

18:16.000 --> 18:22.000
Yeah, so well, I mean, the problem is that with NAF2,

18:22.000 --> 18:25.000
the implement of their own behavior executor.

18:25.000 --> 18:33.000
And it is not compatible with the way that like this executor works with the customization options

18:34.000 --> 18:39.000
and the modularity because it instantiates the behavior trees in a different way.

18:39.000 --> 18:48.000
So the problem here is that you cannot really reuse existing notes for your other projects.

18:48.000 --> 18:56.000
You should kind of, you must like create a custom bridge for these functionalities.

18:56.000 --> 18:58.000
Yeah.

18:59.000 --> 19:00.000
Anybody else?

19:00.000 --> 19:02.000
We have plenty of time.

19:11.000 --> 19:16.000
So your command line says that it's doing a build.

19:16.000 --> 19:19.000
So at run time you're doing code compilation.

19:19.000 --> 19:22.000
That's that right.

19:22.000 --> 19:27.000
Yeah, well, at run time we're doing the redundant code compilation.

19:27.000 --> 19:28.000
At run time.

19:28.000 --> 19:30.000
To what exactly are you referring?

19:30.000 --> 19:31.000
I might ask.

19:31.000 --> 19:36.000
So if you're building a custom behavior, you've got your custom behavior builder.

19:36.000 --> 19:37.000
Yeah.

19:37.000 --> 19:40.000
Are you, is that just running at run time?

19:40.000 --> 19:41.000
It's already compiled.

19:41.000 --> 19:43.000
Well, it's a plugin.

19:43.000 --> 19:48.000
It's a plugin that is loaded dynamically to the executor.

19:48.000 --> 19:53.000
So this code is loaded once you request to behavior to be started.

19:54.000 --> 19:57.000
And then the request for the behavior.

19:57.000 --> 20:03.000
So the definition of it, as it's a string, is given to this, to this algorithm.

20:03.000 --> 20:10.000
And then the algorithm generates the behavior that we can return to the executor and the executor executed.

20:10.000 --> 20:11.000
Got it.

20:11.000 --> 20:12.000
Thank you.

20:12.000 --> 20:15.000
So there's no compilation, but there's generation of the tree.

20:15.000 --> 20:16.000
I don't know.

20:16.000 --> 20:18.000
Maybe this was kind of misleading.

20:18.000 --> 20:19.000
No, no.

20:19.000 --> 20:20.000
I think I just misunderstood.

20:20.000 --> 20:22.000
I'd add a quick check as well.

20:22.000 --> 20:28.000
I think the answer is yes, but I wanted to check, which is, can you call the custom builders from other nodes?

20:28.000 --> 20:30.000
Yes.

20:30.000 --> 20:35.000
So you know, it's complying with the rust to action interface.

20:35.000 --> 20:39.000
And you see there's a field saying build handler.

20:39.000 --> 20:48.000
So if I understand the question correctly, you can just specify this build handler by your different way, by your other node.

20:48.000 --> 20:52.000
And give it to the executor and the executor loads it dynamically, as you'd like.

20:52.000 --> 20:53.000
Yeah.

20:53.000 --> 20:54.000
Thank you.

20:58.000 --> 21:02.000
All right, so if we have no more question, we do have.

21:02.000 --> 21:03.000
Okay.

21:03.000 --> 21:05.000
Thank you for the talk.

21:05.000 --> 21:09.000
I have a question regarding the durability.

21:09.000 --> 21:17.000
If we use a custom node, and we messed up the build of the node,

21:17.000 --> 21:21.000
how do we find what is the problem?

21:21.000 --> 21:27.000
Can we see the generated XML or a way to deliver it?

21:27.000 --> 21:28.000
Okay.

21:28.000 --> 21:29.000
Well, yeah.

21:29.000 --> 21:37.000
So I mean, if there's a problem with your implementation and it throws like a runtime error, and this is,

21:37.000 --> 21:44.000
I mean, obviously you have the source code in your project, but the model of it is generated.

21:44.000 --> 21:55.000
And you can see the XML representation of the model, but I'm not really sure if I understand the question correctly,

21:55.000 --> 22:01.000
because if it's a runtime error, then you have to debug it on your own, obviously.

22:01.000 --> 22:10.000
I cannot help you with this, but if you don't know how the node is actually expecting inputs or something,

22:10.000 --> 22:13.000
then there's a compatibility issue.

22:13.000 --> 22:16.000
This is what these node models are for.

22:16.000 --> 22:28.000
So they tell the behavior tree what inputs it allows, which arguments, and it's doing this building.

22:28.000 --> 22:32.000
It's also checking for compatibility issues.

22:32.000 --> 22:40.000
When you like insert nodes here in this builder API, it validates that it's compatible with one another.

22:40.000 --> 22:44.000
And it's the right plugin, which is loaded.

22:44.000 --> 22:50.000
So you don't have to do all this linking and this configuration management by your own.

22:50.000 --> 22:55.000
All right.

22:55.000 --> 22:59.000
Let's have a little bit longer break with about eight minutes until the next stop.

22:59.000 --> 23:09.000
Thank you so much.

