Skip to content

Commit

Permalink
Merge branch 'ros2-devel' into jazzy
Browse files Browse the repository at this point in the history
  • Loading branch information
David Conner committed Sep 27, 2024
2 parents e642815 + 92abd9c commit d7ab05f
Show file tree
Hide file tree
Showing 87 changed files with 2,120 additions and 689 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/flexbe_ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ jobs:
matrix:
ros: [jazzy]
include:
# - os: ubuntu-24.04
# ros: rolling
# python: python3
# ci_branch: ros2-devel
- os: ubuntu-24.04
ros: jazzy
python: python3
Expand Down
68 changes: 49 additions & 19 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
FlexBE is a high-level behavior engine coordinating the capabilities of a robot in order to solve complex tasks.
Behaviors are modeled as hierarchical state machines (HFSM) where states correspond to active actions
and transitions describe the reaction to outcomes.
Main advantage over similar approaches is the good operator integration and an
intuitive user interface.

The main advantage of FlexBE over similar approaches is the good operator integration and an intuitive user interface.
Besides executing behaviors in full autonomy, the operator can restrict execution of certain transitions or trigger them manually.
Furthermore, FlexBE supports modifying the whole structure of a behavior during its execution without restarting it.
The user interface features a runtime control interface as well as a graphical editor for state machines.
Expand All @@ -17,48 +17,78 @@ You may also want to check out the quick start tutorial demonstrations at [FlexB

Jazzy ![ROS Build Farm](https://build.ros2.org/job/Jdev__flexbe_behavior_engine__ubuntu_noble_amd64/badge/icon)

> Note: This version 4+ breaks compatibility with the FlexBE App. You must use the FlexBE WebUI [flexbe_webui](https://github.com/FlexBE/flexbe_webui.git) now.

## Installation

For released versions, FlexBE is available as ` apt install` package `ros-<DISTRO>-flexbe-*`
For released versions, FlexBE is available as `apt install` package `ros-<DISTRO>-flexbe-*`

To build from source, execute the following commands to install FlexBE for ROS 2 systems:

cd "ros2_ws"/src
git clone https://github.com/FlexBE/flexbe_behavior_engine.git
`cd "ros2_ws"/src`

`git clone https://github.com/FlexBE/flexbe_behavior_engine.git`

Next, navigate to the "ros2_ws" top-level directory and build FlexBE:

colcon build
`colcon build`

## Creating new FlexBE Behavior packages

To begin, create your own repository for behavior development in the `${WORKSPACE_ROOT}/src` folder:

`ros2 run flexbe_widget create_repo [your_project_name] <meta_package_name> <--non-interactive>`

This will clone a project template (requires internet access) that contains examples and proper package definitions,
and create the ROS 2 package structure and three subfolders.

Furthermore, create your own repository for behavior development (contains examples):
For example, running

ros2 run flexbe_widget create_repo [your_project_name]
`ros2 run flexbe_widget create_repo my_project my_flexbe_project`

This version of the flexbe_behavior_engine requires version 4.0+ of the FlexBE user interface.
from the `${WORKSPACE_ROOT}/src` folder will create:
- `${WORKSPACE_ROOT}/src/my_flexbe_project`
- `${WORKSPACE_ROOT}/src/my_flexbe_project/my_flexbe_project` - the ROS meta package
- `${WORKSPACE_ROOT}/src/my_flexbe_project/my_project_flexbe_behaviors`
- `${WORKSPACE_ROOT}/src/my_flexbe_project/my_project_flexbe_states`

It is recommended to install the FlexBE user interface by following one of these steps:
* https://github.com/FlexBE/flexbe_app.git - classic FlexBE App (iron or ros2-devel branches)
* https://github.com/FlexBE/flexbe_webui.git - new Python-based webserver version
These are intended to contain your custom FlexBE state implementations and HFSM-based behaviors.

This release of the FlexBE Behavior Engine requires version 4.1+ of the FlexBE UI.
This breaks compatibility with the older FlexBE App and now requires use of the FlexBE WebUI tool.

It is recommended to install the FlexBE WebUI user interface:

[FlexBE WebUI](https://github.com/FlexBE/flexbe_webui.git) - Python-based webserver version


## Usage

Use the following launch file for running the onboard engine:

ros2 launch flexbe_onboard behavior_onboard.launch.py
`ros2 launch flexbe_onboard behavior_onboard.launch.py`

Use the following launch file for running the operator control station (requires the FlexBE App or WebUI):

ros2 launch flexbe_webui flexbe_ocs.launch.py
`ros2 launch flexbe_webui flexbe_ocs.launch.py`

During testing is is recommended to start the base nodes and the UI client separately:

> Note: replace `flexbe_webui` with `flexbe_app` to run the "classic" UI (after `ros2 run flexbe_app nwjs_install`).
`ros2 launch flexbe_webui flexbe_ocs.launch.py headless:=True`

Use the following launch file to run both of the above, e.g., for testing on a single computer:
`ros2 run flexbe_webui webui_client`

ros2 launch flexbe_webui flexbe_full.launch.py
See the `flexbe_webui` README for more details.


Use the following launch file to run the entire FlexBE system, both onboard and OCS, e.g., for testing on a single computer:

`ros2 launch flexbe_webui flexbe_full.launch.py`

For running tests use:
`colcon test --ctest-args --packages-select <flexbe_package>`

`colcon test --ctest-args --packages-select <flexbe_package>`

## Next Steps

Expand Down Expand Up @@ -94,4 +124,4 @@ Let us know if you know a paper which should be added to the list.
## Maintainers

- Philipp Schillinger ([@pschillinger](https://github.com/pschillinger), [Contact](http://philserver.bplaced.net/fbe/contact.php))
- David Conner ([@dcconner](https://github.com/dcconner))
- David Conner ([@dcconner](https://github.com/dcconner)) [Contact](https://flexbe.readthedocs.io/en/latest/contactinfo.html)
12 changes: 11 additions & 1 deletion flexbe_behavior_engine/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,19 @@
Changelog for package flexbe_behavior_engine
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

3.0.6 (2024-08-05)
4.0.1 (2024-09-26)
------------------

4.0.0 (2024-08-24)
------------------
* Version 4.0.0 release using state_id for communication
* this breaks API with flexbe_app and requires version 4.1.0+ of the FlexBE WebUI API

3.0.7 (2024-08-24)
------------------

3.0.6 (2024-08-05)
------------------

3.0.5 (2024-07-02)
------------------
Expand Down
2 changes: 1 addition & 1 deletion flexbe_behavior_engine/package.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0"?>
<package format="2">
<name>flexbe_behavior_engine</name>
<version>3.0.6</version>
<version>4.0.1</version>
<description>
A meta-package to aggregate all the FlexBE packages
</description>
Expand Down
29 changes: 28 additions & 1 deletion flexbe_core/CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,33 @@
Changelog for package flexbe_core
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

4.0.1 (2024-09-26)
------------------
* codespell clean up
* exception inside concurrency will get re-thrown to preempt behavior
* report all states in deep_states including containers and finished states
* re-request outcome on sync request
* notify skipped for containers
* remove some stray spam;
* use jazzy test and increase some loop timings in tests due to intermittent test failure

4.0.0 (2024-08-24)
------------------
* Version 4.0.0 release using state_id for communication
* this breaks API with flexbe_app and requires version 4.1.0+ of the FlexBE WebUI API
* use state id consistently to avoid long path strings
* modify preempt and published outcome to improve sync
* add flexbe_outcome_listener node for simple monitoring

3.0.7 (2024-08-24)
------------------
* reduce default wait durations on proxy start ups; reduce start up spam
* clarify state map message
* allow controllable OSM and concurrency outputs; improve sync handling; unhandled state exception stops behavior
* modify clear action handling; retain action result status; reduce startup spam
* add initialize_flexbe_core for common initialization
* updates to ConcurrencyContainer and StateMachine to handle sync and forced outcomes

3.0.6 (2024-08-05)
------------------
* update cancel for action client
Expand Down Expand Up @@ -319,7 +346,7 @@ Changelog for package flexbe_core
* [flexbe_core] Added priority container
* [flexbe_core] Added some more documentation
* [flexbe_core] Fixed initialization of input userdata in inner statemachines
* [flexbe_core] Correctly preempt auxilliary control flows in concurrency container
* [flexbe_core] Correctly preempt auxiliary control flows in concurrency container
* [flexbe_core] Fixed a bug with concurrent execution:
State machines inside state machine inside concurrency containers still blocked during execution.
* [flexbe_core] Slightly reworked monitoring state
Expand Down
23 changes: 18 additions & 5 deletions flexbe_core/flexbe_core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,22 +43,34 @@
from .logger import Logger # noqa: F401
from .state_logger import StateLogger # noqa: F401

MIN_UI_VERSION = '4.0.0' # Minimum FlexBE App or UI version required to interact with this version of flexbe_core
MIN_UI_VERSION = '4.1.0' # Minimum FlexBE UI version required to interact with this version of flexbe_core

# pylint: disable=R0903


def set_node(node):
def initialize_flexbe_core(node):
"""Set node information and initialize classes."""
from .proxy import initialize_proxies # pylint: disable=C0415
from .core import RosState, RosStateMachine # pylint: disable=C0415
Logger.initialize(node)
Logger.localinfo('Initialize ROS enabled classes ...')
StateLogger.initialize_ros(node)
initialize_proxies(node)
RosState.initialize_ros(node)
RosStateMachine.initialize_ros(node)


def set_node(node):
"""Set node information and initialize classes."""
import warnings
warnings.warn(
'set_node function is deprecated and will be removed in a future version. Use initialize_flexbe_core(node) instead!',
DeprecationWarning,
stacklevel=2
)
initialize_flexbe_core(node)


class Autonomy:
"""Provides constants for the available required Autonomy Levels."""

Expand Down Expand Up @@ -93,14 +105,15 @@ class Autonomy:


__all__ = [
'Autonomy'
'Behavior',
'BehaviorLibrary',
'ConcurrencyContainer',
'EventState',
'Logger',
'OperatableStateMachine',
'PriorityContainer',
'Logger',
'StateLogger',
'set_node',
'Autonomy'
'initialize_flexbe_core',
'set_node', # To be deprecated in future release
]
35 changes: 23 additions & 12 deletions flexbe_core/flexbe_core/behavior.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@


"""This defines the superclass for all implemented behaviors."""
from flexbe_core.core import LockableStateMachine, OperatableStateMachine, PreemptableState
from flexbe_core.core import LockableStateMachine, OperatableStateMachine, PreemptableState, StateMap
from flexbe_core.logger import Logger

from flexbe_msgs.msg import BehaviorSync
Expand All @@ -44,14 +44,15 @@ def __init__(self):
self._state_machine = None
self.name = 'unnamed behavior'
self.beh_id = 0 # Behavior id checksum assigned by processing the file contents
self._state_map = None

self.contains = {}
self._behaviors = {}

self._autonomy_level = 3
self._debug = False

self.requested_state_path = None
self.requested_state_id = None

# Please implement this abstract method:
def create(self):
Expand Down Expand Up @@ -178,15 +179,25 @@ def set_parameter(self, name, value):

def confirm(self):
"""Confirm that this behavior is ready for execution."""
LockableStateMachine.path_for_switch = self.requested_state_path

self._state_machine.confirm(self.name, self.beh_id)

# def define_structure(self):
# """
# Calculate all state ids and prepare the ContainerStructure message
# """
# self._state_machine.define_structure()
self._state_map = StateMap()
self._state_machine.confirm(self.name, self.beh_id, self._state_map)
LockableStateMachine.path_for_switch = None
if self.requested_state_id is not None:
requested_state = self._state_map[self.requested_state_id]
LockableStateMachine.path_for_switch = requested_state.path

@property
def state_map_items(self):
"""Return two lists of keys and values from state map."""
if self._state_machine is not None:
return list(zip(*self._state_map.items))
return [], []

def get_state_by_id(self, st_id):
"""Return state reference from state map by id."""
if self._state_map is not None:
return self._state_map.get(st_id)
return None

def execute(self):
"""
Expand Down Expand Up @@ -225,7 +236,7 @@ def prepare_for_switch(self, state):
sm.replace_userdata(state_container.userdata)
state_container = state_container._parent
states[1].replace_state(state) # add to new state machine
self.requested_state_path = state.path # set start after switch
self.requested_state_id = state.state_id # set start after switch

def get_current_states(self):
"""Get all currently active (sub-)states."""
Expand Down
6 changes: 3 additions & 3 deletions flexbe_core/flexbe_core/behavior_library.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ def get_behavior(self, be_key):
try:
return self._behavior_lib[be_key]
except KeyError:
Logger.logwarn(f"Did not find ID '{be_key}' in libary, updating...")
Logger.logwarn(f"Did not find ID '{be_key}' in library, updating...")
self.parse_packages()
return self._behavior_lib.get(be_key, None)

Expand Down Expand Up @@ -166,12 +166,12 @@ def __find_behavior():
try:
return __find_behavior()
except StopIteration:
Logger.logwarn("Did not find behavior '%s' in current libary, updating..." % be_name)
Logger.logwarn("Did not find behavior '%s' in current library, updating..." % be_name)
self.parse_packages()
try:
return __find_behavior()
except StopIteration:
Logger.logerr("Still cannot find behavior '%s' in libary after update, giving up!" % be_name)
Logger.logerr("Still cannot find behavior '%s' in library after update, giving up!" % be_name)
return None, None

def count_behaviors(self):
Expand Down
32 changes: 20 additions & 12 deletions flexbe_core/flexbe_core/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@

from .concurrency_container import ConcurrencyContainer # noqa: F401
from .event_state import EventState # noqa: F401
from .exceptions import StateError # noqa: F401
from .exceptions import StateMachineError # noqa: F401
from .exceptions import UserDataError # noqa: F401
from .lockable_state import LockableState # noqa: F401
from .lockable_state_machine import LockableStateMachine # noqa: F401
from .manually_transitionable_state import ManuallyTransitionableState # noqa: F401
Expand All @@ -44,23 +47,28 @@
from .state import State # noqa: F401
from .state_machine import StateMachine # noqa: F401
from .state_map import StateMap # noqa: F401
from .topics import Topics
from .user_data import UserData # noqa: F401

__all__ = [
'PreemptableStateMachine',
'OperatableStateMachine',
'LockableStateMachine',
'RosStateMachine',
'StateMachine',
'ConcurrencyContainer',
'PriorityContainer',
'State',
'RosState',
'ManuallyTransitionableState',
'EventState',
'LockableState',
'PreemptableState',
'LockableStateMachine',
'ManuallyTransitionableState',
'OperatableState',
'EventState',
'OperatableStateMachine',
'PreemptableState',
'PreemptableStateMachine',
'PriorityContainer',
'RosState',
'RosStateMachine',
'State',
'StateError',
'StateMachine',
'StateMachineError',
'StateMap',
'UserData'
'Topics',
'UserData',
'UserDataError'
]
Loading

0 comments on commit d7ab05f

Please sign in to comment.