diff --git a/README.rst b/README.rst index e76a8c2..33e8f5f 100644 --- a/README.rst +++ b/README.rst @@ -7,7 +7,7 @@ Zephyr Behaviour Tree ##################### -This repository is the Zephyr Behavior Tree module. +This repository is the Zephyr Behaviour Tree module. Preparation *********** @@ -86,18 +86,20 @@ Make sure that all requirements are meet: Examples ******** +* The `Tutorial`_ guide you step by step on ZephyrBT (comming soon). + * The `Minimal`_ is an example how to use the ZephyrBT without any IDE. + * The `Dynamic`_ uses their own thread and generate data and stubs from `Groot2`_ IDE. -* The ``Tutorial`` guide you step by step on ZephyrBT (comming soon). + +.. _Tutorial: + samples/subsys/zephyrbt/tutorial/README.rst .. _Minimal: - https://github.com/OSSystems/ZephyrBT/blob/master/samples/subsys/zephyrbt/minimal/README.rst + samples/subsys/zephyrbt/minimal/README.rst .. _Dynamic: - https://github.com/OSSystems/ZephyrBT/blob/master/samples/subsys/zephyrbt/dynamic/README.rst - -.. _Tutorial: - https://github.com/OSSystems/ZephyrBT/blob/master/samples/subsys/zephyrbt/tutorial/README.rst + samples/subsys/zephyrbt/dynamic/README.rst .. _Groot2: https://www.behaviortree.dev/groot/ @@ -105,8 +107,8 @@ Examples Tests ***** -To execute the tests just run twister pointing the TESTSUITE_ROOT to your $HOME/zephyrbt -folder. +To execute the tests just run twister pointing the TESTSUITE_ROOT to your +$HOME/zephyrbt folder. .. code-block:: console diff --git a/include/zephyr/zephyrbt/zephyrbt.h b/include/zephyr/zephyrbt/zephyrbt.h index bd1b71c..a5e6b93 100644 --- a/include/zephyr/zephyrbt/zephyrbt.h +++ b/include/zephyr/zephyrbt/zephyrbt.h @@ -2,7 +2,7 @@ * Copyright (c) 2024 O.S. Systems Software LTDA. * Copyright (c) 2024 Freedom Veiculos Eletricos * - * SPDX-License-Identifier: UNLICENSED + * SPDX-License-Identifier: Apache-2.0 */ #ifndef ZEPHYR_INCLUDE_ZEPHYRBT_ZEPHYRBT_H_ diff --git a/samples/subsys/zephyrbt/tutorial/CMakeLists.txt b/samples/subsys/zephyrbt/tutorial/CMakeLists.txt new file mode 100644 index 0000000..2757898 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/CMakeLists.txt @@ -0,0 +1,26 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +include(${ZEPHYR_ZEPHYRBT_MODULE_DIR}/cmake/zephyrbt-from-behaviourtreecpp-xml.cmake) + +project(zephyrbt_tutorial) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_sources(app PRIVATE + src/main.c +) + +zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 +) diff --git a/samples/subsys/zephyrbt/tutorial/README.rst b/samples/subsys/zephyrbt/tutorial/README.rst new file mode 100644 index 0000000..c407fe5 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/README.rst @@ -0,0 +1,63 @@ +.. Copyright (c) 2024 O.S. Systems Software LTDA. +.. Copyright (c) 2024 Freedom Veiculos Eletricos +.. SPDX-License-Identifier: Apache-2.0 +.. _zephyrbt_tutorial: + +Zephyr Behaviour Tree - Tutorial +################################ + +Overview +******** + +The Let's Drink tutorial was implemented to promote the ZephyrBT at +first Zephyr Zurich meetup on 21 Nov 2024. The application is simpler +and the documentation was written to guide in the basics of Behaviour +Tree using the Groot2 IDE and demonstrate the flexibility of the +technology. + +.. image:: lessons/img/Zephyr-meetup-general-Zurich-Switzerland-November-21-2024.webp + :scale: 50 % + :alt: Zephyr meetup Zurich Switzerland November 21-2024 + +Pre-requirements +================ + +Make sure you executed the steps from `zephyrbt git hub page`_. + +.. _zephyrbt git hub page: + https://github.com/OSSystems/ZephyrBT + +Building and Running +==================== + +This application can be built and executed on ``native_posix_64`` as follows: + +.. code-block:: console + + west build -p -b native_posix_64 samples/subsys/zephyrbt/tutorial -t run + +Check the application running on the console. + +Lessons +******* + +* `lesson 1 - Implement the First Action`_ +* `lesson 2 - The Action initialization function`_ +* `lesson 3 - Share data between nodes`_ +* `lesson 4 - The Behaviour Tree user data holder`_ +* `lesson 5 - Using ZBUS`_ + +.. _lesson 1 - Implement the First Action: + lessons/lesson-1/lesson-1.rst + +.. _lesson 2 - The Action initialization function: + lessons/lesson-2/lesson-2.rst + +.. _lesson 3 - Share data between nodes: + lessons/lesson-3/lesson-3.rst + +.. _lesson 4 - The Behaviour Tree user data holder: + lessons/lesson-4/lesson-4.rst + +.. _lesson 5 - Using ZBUS: + lessons/lesson-5/lesson-5.rst diff --git a/samples/subsys/zephyrbt/tutorial/lessons/img/Zephyr-meetup-general-Zurich-Switzerland-November-21-2024.webp b/samples/subsys/zephyrbt/tutorial/lessons/img/Zephyr-meetup-general-Zurich-Switzerland-November-21-2024.webp new file mode 100644 index 0000000..2609a75 Binary files /dev/null and b/samples/subsys/zephyrbt/tutorial/lessons/img/Zephyr-meetup-general-Zurich-Switzerland-November-21-2024.webp differ diff --git a/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-1.png b/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-1.png new file mode 100644 index 0000000..1c3b015 Binary files /dev/null and b/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-1.png differ diff --git a/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-3.png b/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-3.png new file mode 100644 index 0000000..ada8bbb Binary files /dev/null and b/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-3.png differ diff --git a/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-4.png b/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-4.png new file mode 100644 index 0000000..4d9f38c Binary files /dev/null and b/samples/subsys/zephyrbt/tutorial/lessons/img/bt-lesson-4.png differ diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/lesson-1.rst b/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/lesson-1.rst new file mode 100644 index 0000000..a57a009 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/lesson-1.rst @@ -0,0 +1,71 @@ +.. Copyright (c) 2024 O.S. Systems Software LTDA. +.. Copyright (c) 2024 Freedom Veiculos Eletricos +.. SPDX-License-Identifier: Apache-2.0 +.. _zephyrbt_tutorial_lesson_1: + +Zephyr Behaviour Tree - Tutorial - Lesson 1 +########################################### + +Implement the First Action +************************** + +The first example how to implement the Grab Beer Action. The change is add a +counter to make the action fail after some iterations. This simpler example can +be easier translated to check some hardware condition like ADC's, actuators etc. + +.. image:: ../img/bt-lesson-1.png + :scale: 50 % + :alt: Initial Behaviour Tree + +1- Add a new file at /src/grab_beer.c + +2- Add the following content + +.. code-block:: c + + #include + #include + #include + + #include + LOG_MODULE_REGISTER(grab_beer, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + + enum zephyrbt_child_status + zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + static int count = 0; + + ++count; + + LOG_DBG("\nGrab Beer try: %d\n", count); + + if (count < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + +3- Update the CMakeLists.c + +.. code-block:: cmake + + target_sources(app PRIVATE + src/main.c + src/grab_beer.c + ) + +4- Run the program again + +.. code-block:: console + + $> west build - run + +5- Compare the execution + +At this time the initial output will be the same but after 3 iterations the +system will grab the water as a fallback action. + +You can explore more ideas and try to implement other actions to play with the +application. diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/resources/CMakeLists.txt b/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/resources/CMakeLists.txt new file mode 100644 index 0000000..906e570 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/resources/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +include(${ZEPHYR_ZEPHYRBT_MODULE_DIR}/cmake/zephyrbt-from-behaviourtreecpp-xml.cmake) + +project(zephyrbt_tutorial) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_sources(app PRIVATE + src/main.c + src/grab_beer.c +) + +zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 +) diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/resources/src/grab_beer.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/resources/src/grab_beer.c new file mode 100644 index 0000000..3835a08 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-1/resources/src/grab_beer.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(grab_beer, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +enum zephyrbt_child_status +zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + static int count = 0; + + ++count; + + LOG_DBG("\nGrab Beer try: %d\n", count); + + if (count < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/lesson-2.rst b/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/lesson-2.rst new file mode 100644 index 0000000..3a66d7e --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/lesson-2.rst @@ -0,0 +1,141 @@ +.. Copyright (c) 2024 O.S. Systems Software LTDA. +.. Copyright (c) 2024 Freedom Veiculos Eletricos +.. SPDX-License-Identifier: Apache-2.0 +.. _zephyrbt_tutorial_lesson_1: + +Zephyr Behaviour Tree - Tutorial - Lesson 2 +########################################### + +The Action initialization function +********************************** + +In this example the counter will be moved to the Node Context. The Node Context +is a special place that can be used to store user data. The data is stored by +Node Instance. This means that if an Action is used multiple times in the tree, +each individual node will have their own context. In this case, it is the user +that defines how this will be implemented. + +1- Override the zephyrbt_action_grab_beer_init function on the grab_beer.c +file. The _init signature is executed only once when the ZephyrBT +thread is started. The goal of this function is to provide a way to initialize +the Action node. + +.. code-block:: c + + struct zephyrbt_action_grab_beer_context { + int counter; + }; + + enum zephyrbt_child_status + zephyrbt_action_grab_beer_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + LOG_DBG("zephyrbt_action_grab_beer_init stub function"); + + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + + grab_beeer_ctx = k_malloc(sizeof(struct zephyrbt_action_grab_beer_context)); + self->ctx = grab_beeer_ctx; + + if (grab_beeer_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(grab_beeer_ctx, 0, sizeof(struct zephyrbt_action_grab_beer_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + +At this stage it is possible to understand that there are multiple contexts. +Each node can have their own and there is a centralized tree context. The tree +context will be explored later. + +2- Update the zephyrbt_action_grab_beer action + +.. code-block:: c + + enum zephyrbt_child_status + zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + grab_beeer_ctx = (struct zephyrbt_action_grab_beer_context *)self->ctx; + + ++grab_beeer_ctx->counter; + + LOG_DBG("\nGrab Beer try: %d\n", grab_beeer_ctx->counter); + + if (grab_beeer_ctx->counter < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + +3- Try again with a Action Context + +At this moment you have created an Action node that can be used multiple times +in your Behaviour Tree. In the first example the shared counter would be used by +all the instances. In the ZephyrBT each tree uses their own thread. Since the +Behaviour Tree execution is well defined there is no issues about shared +resources. It is not recommended that user create their own thread inside a +node. There are other ways to communicate between process and this topic will be +explored in future examples. + +4- Try to change the tree and add another Grab Beer node. + +It could be interesting to explorer using Zephyr Logs. Remember that the +behaviour of the action is the same, unless some random() actions take place. + +5- Explore the initialization on other nodes + +You can now explore more initialization functions on other nodes and expand to +your own super let's drink app. One idea is to use GPIOs and LEDs to have more +feedback. The easy way to start is to look on the code generated to grab the +functions signature and the enumeration. All the generated files are save by the +generation script on the place you define. + +The ``zephyrbt_define_from_behaviourtreecpp_xml`` cmake function have the +following parameters: + +.. code-block:: cmake + + target # The current target used to add the generated files + input_file # The behaviour tree input file + output_inc # Output directory of the generated header + output_src # Output directory of the generated sources + stack_size # The amount of RAM used to run the BT + thread_prio # The Thread Priority + +This function define that the groot2 xml file format will be used as behaviour +tree input. Then the ``output_inc`` and ``output_src`` places are used to save +the generated files. In this tutorial we used the cmake default ``binary`` +folder. + +.. code-block:: cmake + + zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 + ) + +Each behaviour tree like ``.xml`` will generate an include file named +``.h`` and two source files ``_data.xml`` and +``_stub.xml``. This information is create for any user defined node. + +The include files will contain all the functions signatures and the enumeration +related to some node. The enumeration is create based on the ports that user +define. + +The data file contain three definitions: + + * The ``zephyrbt_node`` vector structure with the behaviour tree + * The ``zephyrbt_blackboard_item`` vector structure with the blackboard + * And define the behaviour tree thread. + +The stub file define all the skeletons to allow the program compile. This allows +the developer define their actions and at same time run the program. diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/resources/CMakeLists.txt b/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/resources/CMakeLists.txt new file mode 100644 index 0000000..906e570 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/resources/CMakeLists.txt @@ -0,0 +1,27 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +include(${ZEPHYR_ZEPHYRBT_MODULE_DIR}/cmake/zephyrbt-from-behaviourtreecpp-xml.cmake) + +project(zephyrbt_tutorial) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_sources(app PRIVATE + src/main.c + src/grab_beer.c +) + +zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 +) diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/resources/src/grab_beer.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/resources/src/grab_beer.c new file mode 100644 index 0000000..795cde4 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-2/resources/src/grab_beer.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(grab_beer, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +struct zephyrbt_action_grab_beer_context { + int counter; +}; + +enum zephyrbt_child_status +zephyrbt_action_grab_beer_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + LOG_DBG("zephyrbt_action_grab_beer_init stub function"); + + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + + grab_beeer_ctx = k_malloc(sizeof(struct zephyrbt_action_grab_beer_context)); + self->ctx = grab_beeer_ctx; + + if (grab_beeer_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(grab_beeer_ctx, 0, sizeof(struct zephyrbt_action_grab_beer_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + grab_beeer_ctx = (struct zephyrbt_action_grab_beer_context *)self->ctx; + + ++grab_beeer_ctx->counter; + + LOG_DBG("\nGrab Beer try: %d\n", grab_beeer_ctx->counter); + + if (grab_beeer_ctx->counter < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/lesson-3.rst b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/lesson-3.rst new file mode 100644 index 0000000..8d30c82 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/lesson-3.rst @@ -0,0 +1,149 @@ +.. Copyright (c) 2024 O.S. Systems Software LTDA. +.. Copyright (c) 2024 Freedom Veiculos Eletricos +.. SPDX-License-Identifier: Apache-2.0 +.. _zephyrbt_tutorial_lesson_1: + +Zephyr Behaviour Tree - Tutorial - Lesson 3 +########################################### + +Share data between nodes +************************ + +At moment it is possible to create very interresting behaviours. However, you may +already be missing a way to communicate and exchange information between the +nodes. + +1- Change tutorial model. Add the ``fridge_door_is_open`` port. + +.. image:: ../img/bt-lesson-3.png + :scale: 50 % + :alt: Add Action Port + +In the open/close actions add a port named ``fridge_door_is_open``. Keep open +action as output and close action as input. In the value field add +``{fridge_door_is_open}``. + +The port create an entry point that can be used as storage area or can access an +external entry point. The internal are is defined per node instance when the +value is empty or have some default C initialization value. It can be an +integer, a string a enumeration constant etc. It is important that the compiler +can find and process the default value to avoid compiler errors. The shared +entry point is defined by using the syntax ``{`` place name ``}``. The shared +place is thread safe since only one node each time can access the node. + +2- Now it is necessary to create ``fridge.c`` file inside src folder. Remember +to add on CMakeLists.txt. Inside this file you can add the following code for +the Open and Close actions. + +.. code-block:: c + + #include + #include + #include + + #include + LOG_MODULE_REGISTER(fridge, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + + #include "tutorial.h" + + struct zephyrbt_action_fridge_context { + struct zephyrbt_blackboard_item *is_open; + }; + + enum zephyrbt_child_status + zephyrbt_action_open_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_OPEN_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + enum zephyrbt_child_status + zephyrbt_action_close_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_CLOSE_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + enum zephyrbt_child_status + zephyrbt_action_open(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) true) { + LOG_DBG("Fridge is already open, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Open the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) true; + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + enum zephyrbt_child_status + zephyrbt_action_close(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) false) { + LOG_DBG("Fridge is already closed, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Close the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) false; + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + +This unit shares the same context struct and the action nodes will share some +data. If you run the program now you will see messages that nodes are +Open/Closing the Fridge. diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/CMakeLists.txt b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/CMakeLists.txt new file mode 100644 index 0000000..3c9aea6 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/CMakeLists.txt @@ -0,0 +1,28 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +include(${ZEPHYR_ZEPHYRBT_MODULE_DIR}/cmake/zephyrbt-from-behaviourtreecpp-xml.cmake) + +project(zephyrbt_tutorial) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_sources(app PRIVATE + src/main.c + src/fridge.c + src/grab_beer.c +) + +zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 +) diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/models/tutorial.btproj b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/models/tutorial.btproj new file mode 100644 index 0000000..83b32cd --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/models/tutorial.btproj @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/models/tutorial.xml b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/models/tutorial.xml new file mode 100644 index 0000000..e59e0f9 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/models/tutorial.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/src/fridge.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/src/fridge.c new file mode 100644 index 0000000..df8cba9 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/src/fridge.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(fridge, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +#include "tutorial.h" + +struct zephyrbt_action_fridge_context { + struct zephyrbt_blackboard_item *is_open; +}; + +enum zephyrbt_child_status +zephyrbt_action_open_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_OPEN_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_close_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_CLOSE_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_open(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) true) { + LOG_DBG("Fridge is already open, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Open the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) true; + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_close(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) false) { + LOG_DBG("Fridge is already closed, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Close the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) false; + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/src/grab_beer.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/src/grab_beer.c new file mode 100644 index 0000000..795cde4 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-3/resources/src/grab_beer.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(grab_beer, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +struct zephyrbt_action_grab_beer_context { + int counter; +}; + +enum zephyrbt_child_status +zephyrbt_action_grab_beer_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + LOG_DBG("zephyrbt_action_grab_beer_init stub function"); + + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + + grab_beeer_ctx = k_malloc(sizeof(struct zephyrbt_action_grab_beer_context)); + self->ctx = grab_beeer_ctx; + + if (grab_beeer_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(grab_beeer_ctx, 0, sizeof(struct zephyrbt_action_grab_beer_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + grab_beeer_ctx = (struct zephyrbt_action_grab_beer_context *)self->ctx; + + ++grab_beeer_ctx->counter; + + LOG_DBG("\nGrab Beer try: %d\n", grab_beeer_ctx->counter); + + if (grab_beeer_ctx->counter < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/lesson-4.rst b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/lesson-4.rst new file mode 100644 index 0000000..53a3e66 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/lesson-4.rst @@ -0,0 +1,59 @@ +.. Copyright (c) 2024 O.S. Systems Software LTDA. +.. Copyright (c) 2024 Freedom Veiculos Eletricos +.. SPDX-License-Identifier: Apache-2.0 +.. _zephyrbt_tutorial_lesson_1: + +Zephyr Behaviour Tree - Tutorial - Lesson 4 +########################################### + +The Behaviour Tree user data holder +********************************** + +1- The Behaviour Tree user data holder can be used as a global context for the +whole tree. It can be direct injected when developer wants fine grained control +over the thread or it can be easily managed as the first node init function. +This means that when developer uses code generation it is possible yet to know +and inject this information at code generation phase. After this, any other node +that require access to user global context can do it. + +.. image:: ../img/bt-lesson-4.png + :scale: 50 % + :alt: Init User Context + +.. code-block:: c + + enum zephyrbt_child_status + zephyrbt_action__init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) + { + struct *data; + + data = k_malloc(sizeof(struct )); + ctx->user_data = data; + + if (data == NULL) { + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(data, 0, sizeof(struct )); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + +The global context can be very important to allow one behaviour tree talk with +external components. This components can be other behaviour tree, communication +channels or even thread. In the case of threads the developer should take care +of all shared objects once the premise of the synchronous flow does not exist +anymore. + +The developer should pay attention about how much time an action can take to +execute. In this case, a state could be introduced to handle this situations +with the use of ZEPHYRBT_CHILD_RUNNING_STATUS. This means that a node can block +forever if measures to avoid that are not taken. + +2- The magical ``zephyrbt_user.h`` file. + +When the developer define a file denominated ``zephyrbt_user.h`` it will be +automatically added into ``.h`` header file. This is necessary to allow +user defined types be used on the Groot2 IDE, for instance. The example add this +file to define the ``tutorial_context`` structure. diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/CMakeLists.txt b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/CMakeLists.txt new file mode 100644 index 0000000..ff6a52e --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +include(${ZEPHYR_ZEPHYRBT_MODULE_DIR}/cmake/zephyrbt-from-behaviourtreecpp-xml.cmake) + +project(zephyrbt_tutorial) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_sources(app PRIVATE + src/main.c + src/fridge.c + src/global_ctx.c + src/grab_beer.c +) + +zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 +) diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/include/zephyrbt_user.h b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/include/zephyrbt_user.h new file mode 100644 index 0000000..35308c5 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/include/zephyrbt_user.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYRBT_USER_H +#define ZEPHYRBT_USER_H + +struct tutorial_context { + uint8_t my_global_var; +}; + +#endif /* ZEPHYRBT_USER_H */ diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/models/tutorial.btproj b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/models/tutorial.btproj new file mode 100644 index 0000000..f1ee154 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/models/tutorial.btproj @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/models/tutorial.xml b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/models/tutorial.xml new file mode 100644 index 0000000..d58fa7b --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/models/tutorial.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/fridge.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/fridge.c new file mode 100644 index 0000000..df8cba9 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/fridge.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(fridge, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +#include "tutorial.h" + +struct zephyrbt_action_fridge_context { + struct zephyrbt_blackboard_item *is_open; +}; + +enum zephyrbt_child_status +zephyrbt_action_open_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_OPEN_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_close_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_CLOSE_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_open(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) true) { + LOG_DBG("Fridge is already open, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Open the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) true; + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_close(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) false) { + LOG_DBG("Fridge is already closed, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Close the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) false; + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/global_ctx.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/global_ctx.c new file mode 100644 index 0000000..65bb76b --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/global_ctx.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(global_ctx, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +#include "tutorial.h" + +enum zephyrbt_child_status +zephyrbt_action_init_tree_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct tutorial_context *global_ctx; + + global_ctx = k_malloc(sizeof(struct tutorial_context)); + self->ctx = global_ctx; + + if (global_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(global_ctx, 0, sizeof(struct tutorial_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/grab_beer.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/grab_beer.c new file mode 100644 index 0000000..795cde4 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-4/resources/src/grab_beer.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(grab_beer, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +struct zephyrbt_action_grab_beer_context { + int counter; +}; + +enum zephyrbt_child_status +zephyrbt_action_grab_beer_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + LOG_DBG("zephyrbt_action_grab_beer_init stub function"); + + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + + grab_beeer_ctx = k_malloc(sizeof(struct zephyrbt_action_grab_beer_context)); + self->ctx = grab_beeer_ctx; + + if (grab_beeer_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(grab_beeer_ctx, 0, sizeof(struct zephyrbt_action_grab_beer_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + grab_beeer_ctx = (struct zephyrbt_action_grab_beer_context *)self->ctx; + + ++grab_beeer_ctx->counter; + + LOG_DBG("\nGrab Beer try: %d\n", grab_beeer_ctx->counter); + + if (grab_beeer_ctx->counter < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/lesson-5.rst b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/lesson-5.rst new file mode 100644 index 0000000..130a5a6 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/lesson-5.rst @@ -0,0 +1,56 @@ +.. Copyright (c) 2024 O.S. Systems Software LTDA. +.. Copyright (c) 2024 Freedom Veiculos Eletricos +.. SPDX-License-Identifier: Apache-2.0 +.. _zephyrbt_tutorial_lesson_1: + +Zephyr Behaviour Tree - Tutorial - Lesson 5 +########################################### + +Using ZBUS +********** + +1 - In this instruction will be necessary to use some board. The content was +developed using the ST Nucleo F767-ZI. + +In this case, to build you need to change your command to: + +.. code-block:: console + + west build -p -b nucleo_f767zi samples/subsys/zephyrbt/tutorial + +.. code-block:: console + + west flash [-r openocd] + +2- This example consist in turn a led On/Off depending on the fridge door state. +To copy the files, navigate to ``samples/subsys/zephyrbt/tutorial`` folder and +execute the following command. + +.. code-block:: console + + cp -r lessons/lesson-5/resources/* . + +In the boards folder a new configuration was created to enable PWM leds. In the +``zbus_peripherals.h`` file it is defined the structs to handle the peripherals +states. In this case, the ``ZBUS_PERIPHERAL_WRITE`` abstracts the peripherals +and update the state in case of changes. The ``zbus_peripherals.c`` is given to +fullfil the purpose of the sample. It defines a channel and the peripherals +thread. With those files it is possible to update the fridge.c file. + +.. code-block:: c + + /* Add the new two include files */ + #include + #include "zbus_peripherals.h" + + /* Declare the channel to allow send data */ + ZBUS_CHAN_DECLARE(peripherals_channel); + + /* Use the channel */ + ZBUS_PERIPHERAL_WRITE(.led_green.state = LEDS_STATES_ON); + + /* Multiple peripherals can be updated at same time */ + ZBUS_PERIPHERAL_WRITE( + .led_green.state = LEDS_STATES_ON, + .led_red.state = LEDS_STATES_OFF + ); diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/CMakeLists.txt b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/CMakeLists.txt new file mode 100644 index 0000000..af8edc9 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/CMakeLists.txt @@ -0,0 +1,30 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +cmake_minimum_required(VERSION 3.20.0) + +find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) +include(${ZEPHYR_ZEPHYRBT_MODULE_DIR}/cmake/zephyrbt-from-behaviourtreecpp-xml.cmake) + +project(zephyrbt_tutorial) + +zephyr_include_directories( + ${CMAKE_CURRENT_SOURCE_DIR}/include +) + +target_sources(app PRIVATE + src/main.c + src/fridge.c + src/global_ctx.c + src/grab_beer.c + src/zbus_peripherals.c +) + +zephyrbt_define_from_behaviourtreecpp_xml(app + models/tutorial.xml + ${CMAKE_BINARY_DIR}/include + ${CMAKE_BINARY_DIR}/src + 1024 + 0 +) diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/boards/nucleo_f767zi.overlay b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/boards/nucleo_f767zi.overlay new file mode 100644 index 0000000..a864e9c --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/boards/nucleo_f767zi.overlay @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * SPDX-License-Identifier: Apache-2.0 + */ + +/ { + /delete-node/ aliases; + /delete-node/ leds; + + pwmleds: pwmleds { + compatible = "pwm-leds"; + led_green: led_green { + pwms = <&pwm3 3 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + led_red: led_red { + pwms = <&pwm4 2 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + led_power: led_power { + pwms = <&pwm12 1 PWM_MSEC(20) PWM_POLARITY_NORMAL>; + }; + }; +}; + +&timers3 { + st,prescaler = <10000>; + status = "okay"; + + pwm3: pwm { + status = "okay"; + pinctrl-0 = <&tim3_ch3_pb0>; + pinctrl-names = "default"; + }; +}; + +&timers4 { + st,prescaler = <10000>; + status = "okay"; + + pwm4: pwm { + status = "okay"; + pinctrl-0 = <&tim4_ch2_pb7>; + pinctrl-names = "default"; + }; +}; + +&timers12 { + st,prescaler = <10000>; + status = "okay"; + + pwm12: pwm { + status = "okay"; + pinctrl-0 = <&tim12_ch1_pb14>; + pinctrl-names = "default"; + }; +}; diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/include/zbus_peripherals.h b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/include/zbus_peripherals.h new file mode 100644 index 0000000..654d0a5 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/include/zbus_peripherals.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZBUS_PERIPHERALS_H +#define ZBUS_PERIPHERALS_H + +enum led_state { + LEDS_STATES_OFF = 1, + LEDS_STATES_ON, + LEDS_STATES_PWM, +} __attribute__((__packed__)); + +struct pwm_led_state { + enum led_state state; + uint32_t high_period; + uint32_t low_period; +} __attribute__((__packed__)); + +struct tutorial_peripherals { + struct pwm_led_state led_green; + struct pwm_led_state led_red; +}; + +#define ZBUS_PERIPHERAL_WRITE(...) \ + zbus_chan_pub(&peripherals_channel, ((struct tutorial_peripherals[]){{__VA_ARGS__}}), \ + K_NO_WAIT) + +#endif diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/include/zephyrbt_user.h b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/include/zephyrbt_user.h new file mode 100644 index 0000000..35308c5 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/include/zephyrbt_user.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef ZEPHYRBT_USER_H +#define ZEPHYRBT_USER_H + +struct tutorial_context { + uint8_t my_global_var; +}; + +#endif /* ZEPHYRBT_USER_H */ diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/models/tutorial.btproj b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/models/tutorial.btproj new file mode 100644 index 0000000..f1ee154 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/models/tutorial.btproj @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/models/tutorial.xml b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/models/tutorial.xml new file mode 100644 index 0000000..d58fa7b --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/models/tutorial.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/prj.conf b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/prj.conf new file mode 100644 index 0000000..74b575e --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/prj.conf @@ -0,0 +1,24 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y + +CONFIG_ZEPHYR_BEHAVIOUR_TREE=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_DYNAMIC=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_NODE_INFO=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_NODE_INIT=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_NODE_CONTEXT=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL_DBG=y + +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_POOL_SIZE=10 +CONFIG_THREAD_STACK_INFO=y + +CONFIG_KERNEL_MEM_POOL=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 + +CONFIG_ZBUS=y +CONFIG_PWM=y +CONFIG_LED=y diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/fridge.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/fridge.c new file mode 100644 index 0000000..cb3e4c1 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/fridge.c @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include + +#include +LOG_MODULE_REGISTER(fridge, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +ZBUS_CHAN_DECLARE(peripherals_channel); + +#include "tutorial.h" +#include "zbus_peripherals.h" + +struct zephyrbt_action_fridge_context { + struct zephyrbt_blackboard_item *is_open; +}; + +enum zephyrbt_child_status +zephyrbt_action_open_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_OPEN_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_close_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + + fridge_ctx = k_malloc(sizeof(struct zephyrbt_action_fridge_context)); + self->ctx = fridge_ctx; + + if (fridge_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(fridge_ctx, 0, sizeof(struct zephyrbt_action_fridge_context)); + + fridge_ctx->is_open = + zephyrbt_search_blackboard(ctx, self->index, + ZEPHYRBT_CLOSE_ATTRIBUTE_FRIDGE_DOOR_IS_OPEN); + + if (fridge_ctx->is_open == NULL) { + LOG_ERR("Not possible to get fridge 'is_open' slot"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_open(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) true) { + LOG_DBG("Fridge is already open, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Open the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) true; + ZBUS_PERIPHERAL_WRITE(.led_green.state = LEDS_STATES_ON); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_close(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_fridge_context *fridge_ctx; + fridge_ctx = (struct zephyrbt_action_fridge_context *)self->ctx; + + if (fridge_ctx->is_open->item == (zephyrbt_node_context_t) false) { + LOG_DBG("Fridge is already closed, let's skip..."); + return ZEPHYRBT_CHILD_SKIP_STATUS; + } + + LOG_DBG("Close the fridge door"); + + fridge_ctx->is_open->item = (zephyrbt_node_context_t) false; + ZBUS_PERIPHERAL_WRITE(.led_green.state = LEDS_STATES_OFF); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/global_ctx.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/global_ctx.c new file mode 100644 index 0000000..65bb76b --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/global_ctx.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(global_ctx, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +#include "tutorial.h" + +enum zephyrbt_child_status +zephyrbt_action_init_tree_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct tutorial_context *global_ctx; + + global_ctx = k_malloc(sizeof(struct tutorial_context)); + self->ctx = global_ctx; + + if (global_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(global_ctx, 0, sizeof(struct tutorial_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/grab_beer.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/grab_beer.c new file mode 100644 index 0000000..89bdd23 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/grab_beer.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(grab_beer, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +struct zephyrbt_action_grab_beer_context { + int counter; +}; + +enum zephyrbt_child_status +zephyrbt_action_grab_beer_init(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + LOG_DBG("zephyrbt_action_grab_beer_init stub function"); + + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + + grab_beeer_ctx = k_malloc(sizeof(struct zephyrbt_action_grab_beer_context)); + self->ctx = grab_beeer_ctx; + + if (grab_beeer_ctx == NULL) { + LOG_ERR("Context can not be allocate. Need more memory!!"); + return ZEPHYRBT_CHILD_FAILURE_STATUS; + } + + memset(grab_beeer_ctx, 0, sizeof(struct zephyrbt_action_grab_beer_context)); + + return ZEPHYRBT_CHILD_SUCCESS_STATUS; +} + +enum zephyrbt_child_status +zephyrbt_action_grab_beer(struct zephyrbt_context *ctx, + struct zephyrbt_node *self) +{ + struct zephyrbt_action_grab_beer_context *grab_beeer_ctx; + grab_beeer_ctx = (struct zephyrbt_action_grab_beer_context *)self->ctx; + + ++grab_beeer_ctx->counter; + + LOG_DBG("\nGrab Beer try: %d\n", grab_beeer_ctx->counter); + k_msleep(1000); + + if (grab_beeer_ctx->counter < 3) { + return ZEPHYRBT_CHILD_SUCCESS_STATUS; + } + + return ZEPHYRBT_CHILD_FAILURE_STATUS; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/main.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/main.c new file mode 100644 index 0000000..ac3d951 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/main.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +int main(void) +{ + return 0; +} diff --git a/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/zbus_peripherals.c b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/zbus_peripherals.c new file mode 100644 index 0000000..dda083d --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/lessons/lesson-5/resources/src/zbus_peripherals.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include + +#include +LOG_MODULE_REGISTER(peripherals, CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL); + +#include "zbus_peripherals.h" + +ZBUS_CHAN_DEFINE(peripherals_channel, struct tutorial_peripherals, NULL, NULL, + ZBUS_OBSERVERS(peripherals_thread_subscriber), ZBUS_MSG_INIT(0)); +ZBUS_SUBSCRIBER_DEFINE(peripherals_thread_subscriber, 4); + +static const char *peripherals_leds_state[] = { + "Undefined", + "off", + "on", + "blink", +}; + +static int _set_led(struct pwm_led_state *current_state, struct pwm_led_state *new_state, + uint32_t index, const char *name) +{ + static const struct device *const dev = DEVICE_DT_GET(DT_NODELABEL(pwmleds)); + int ret = 0; + + if (memcmp(current_state, new_state, sizeof(struct pwm_led_state)) == 0) { + return ret; + } + + LOG_INF("set %s %s", name, peripherals_leds_state[new_state->state]); + + switch (new_state->state) { + case LEDS_STATES_OFF: + ret = led_off(dev, index); + break; + case LEDS_STATES_ON: + ret = led_on(dev, index); + break; + case LEDS_STATES_PWM: + ret = led_blink(dev, index, new_state->high_period, new_state->low_period); + break; + } + + if (ret) { + LOG_ERR("fail to set %s %s", name, + peripherals_leds_state[new_state->state]); + return ret; + } + + memcpy(current_state, new_state, sizeof(struct pwm_led_state)); + + return ret; +} + +#define set_led(new_state, dt_name) \ + static struct pwm_led_state current_##dt_name; \ + static const uint32_t index_##dt_name = DT_NODE_CHILD_IDX(DT_NODELABEL(dt_name)); \ + _set_led(¤t_##dt_name, new_state, index_##dt_name, STRINGIFY(dt_name)) + +static void peripherals_thread(void) +{ + const struct zbus_channel *channel; + struct tutorial_peripherals peripherals; + + LOG_DBG("peripherals_thread"); + + while (!zbus_sub_wait(&peripherals_thread_subscriber, &channel, K_FOREVER)) { + zbus_chan_read(&peripherals_channel, &peripherals, K_FOREVER); + + if (peripherals.led_green.state) { + set_led(&peripherals.led_green, led_green); + } + if (peripherals.led_red.state) { + set_led(&peripherals.led_red, led_red); + } + } +} + +K_THREAD_DEFINE(peripherals_thread_id, 2048, peripherals_thread, NULL, NULL, NULL, + (CONFIG_MAIN_THREAD_PRIORITY + 4), 0, 0); diff --git a/samples/subsys/zephyrbt/tutorial/models/tutorial.btproj b/samples/subsys/zephyrbt/tutorial/models/tutorial.btproj new file mode 100644 index 0000000..f525b0b --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/models/tutorial.btproj @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/models/tutorial.xml b/samples/subsys/zephyrbt/tutorial/models/tutorial.xml new file mode 100644 index 0000000..4c7c596 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/models/tutorial.xml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/samples/subsys/zephyrbt/tutorial/prj.conf b/samples/subsys/zephyrbt/tutorial/prj.conf new file mode 100644 index 0000000..2b2aa38 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/prj.conf @@ -0,0 +1,20 @@ +# Copyright (c) 2024 O.S. Systems Software LTDA. +# Copyright (c) 2024 Freedom Veiculos Eletricos +# SPDX-License-Identifier: Apache-2.0 + +CONFIG_LOG=y +CONFIG_LOG_MODE_MINIMAL=y + +CONFIG_ZEPHYR_BEHAVIOUR_TREE=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_DYNAMIC=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_NODE_INFO=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_NODE_INIT=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_NODE_CONTEXT=y +CONFIG_ZEPHYR_BEHAVIOUR_TREE_LOG_LEVEL_DBG=y + +CONFIG_DYNAMIC_THREAD=y +CONFIG_DYNAMIC_THREAD_POOL_SIZE=10 +CONFIG_THREAD_STACK_INFO=y + +CONFIG_KERNEL_MEM_POOL=y +CONFIG_HEAP_MEM_POOL_SIZE=8192 diff --git a/samples/subsys/zephyrbt/tutorial/src/main.c b/samples/subsys/zephyrbt/tutorial/src/main.c new file mode 100644 index 0000000..ac3d951 --- /dev/null +++ b/samples/subsys/zephyrbt/tutorial/src/main.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2024 O.S. Systems Software LTDA. + * Copyright (c) 2024 Freedom Veiculos Eletricos + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include + +int main(void) +{ + return 0; +} diff --git a/scripts/generate-zephyrbt-from-behaviourtreecpp-xml b/scripts/generate-zephyrbt-from-behaviourtreecpp-xml index 029eb79..6d6ea13 100755 --- a/scripts/generate-zephyrbt-from-behaviourtreecpp-xml +++ b/scripts/generate-zephyrbt-from-behaviourtreecpp-xml @@ -25,7 +25,7 @@ REPO_ROOT = Path(__file__).absolute().parents[1] HEADER = """/* * Autogenerated file * - * SPDX-License-Identifier: UNLICENSED + * SPDX-License-Identifier: Apache-2.0 */ """ diff --git a/subsys/zephyrbt/zephyrbt.c b/subsys/zephyrbt/zephyrbt.c index 1c7eb98..6e0c98a 100644 --- a/subsys/zephyrbt/zephyrbt.c +++ b/subsys/zephyrbt/zephyrbt.c @@ -92,12 +92,12 @@ void zephyrbt_thread_func(void *zephyrbt_ctx, void *, void *) { struct zephyrbt_context *ctx = (struct zephyrbt_context *)zephyrbt_ctx; if (ctx == NULL) { - LOG_ERR("The behavior tree context is invalid. Thread aborted!"); + LOG_ERR("The behaviour tree context is invalid. Thread aborted!"); return; } if (ctx->node == NULL) { - LOG_ERR("The behavior tree API is invalid. Thread aborted!"); + LOG_ERR("The behaviour tree API is invalid. Thread aborted!"); return; }