Skip to main content
Version: 10

Manipulate Vectors in Behavior Trees

This how-to guide explains how to create, modify, and iterate over vectors (dynamic arrays) in MoveIt Pro Behavior Trees. For port details, see the API reference.

Overview​

The general-purpose vector Behaviors operate on std::vector<BT::Any>. A vector may contain values of any supported blackboard type, but Behaviors that add or replace an element require it to match the type of the existing elements. MoveIt Pro also provides specialized Behaviors for some typed vectors.

Most modifying Behaviors have separate input and output vector ports. To update one blackboard entry in place, connect both ports to the same entry, for example input_vector="{poses}" output_vector="{poses}".

Create and Reset a Vector​

CreateVector Objective​

Use the CreateVector Objective to create an empty general-purpose vector on the blackboard. It wraps ResetVector and is the recommended high-level starting point when composing an Objective.

ResetVector​

Use ResetVector to directly create or clear a general-purpose vector. ResetPoseStampedVector provides the corresponding operation for a typed vector of geometry_msgs::msg::PoseStamped messages.

Inspect a Vector​

GetSizeOfVector​

Use GetSizeOfVector to write the number of elements in a vector to its vector_size output port.

GetElementOfVector​

Use GetElementOfVector to copy the element at index to its element output port. It supports negative indexing:

  • -1 selects the last element.
  • -2 selects the second-to-last element.
  • Other negative values continue backward from the end.

The Behavior returns FAILURE when the index is out of bounds or a required input is missing.

Modify a Vector​

PushBackVector​

Use PushBackVector to append an element. Connect the existing vector to input_vector and the resulting vector to output_vector.

If the input vector is empty, the first element establishes its element type. Otherwise, the new element must match the type of the existing elements.

InsertInVector​

Use InsertInVector to insert an element at index. Elements at and after that position shift toward the end. An index equal to the vector size appends the element.

Negative indexes count backward from the end. The inserted element must match the type of the existing elements unless the vector is empty.

ReplaceInVector​

Use ReplaceInVector to replace the element at index. Negative indexes count backward from the end, and the replacement must match the type of the existing elements.

RemoveFromVector​

Use RemoveFromVector to remove the element at index. Negative indexes count backward from the end. The default index is -1, which removes the last element.

ReverseVector​

Use ReverseVector to reverse a general-purpose vector into a new output vector. Use ReversePoseStampedVector for a typed vector of geometry_msgs::msg::PoseStamped messages.

Iterate Over a Vector​

ForEach​

ForEach is a decorator Behavior that ticks its child to completion for each element in vector_in. Before processing each element, it writes the current zero-based index and element (out) to the blackboard.

  • It returns RUNNING while iterating.
  • It returns FAILURE as soon as the child fails.
  • It returns SUCCESS after every element has succeeded or been skipped, including when the vector is empty.

ForEachUntilSuccess​

ForEachUntilSuccess is a decorator Behavior that tries elements until its child succeeds. It also exposes the current index and element (out).

  • It returns RUNNING while checking elements.
  • It returns SUCCESS as soon as the child succeeds, or when the vector is empty.
  • It returns FAILURE after every element has failed or been skipped.

Use it to search for an element that satisfies a condition or to try an operation against several candidates.

Deprecated Specialized Nodes​

Use PushBackVector for New Objectives

AddToVector, AddPoseStampedToVector, and AddPointCloudToVector are deprecated and will be removed in a future release. Use PushBackVector instead.

  • The AddToVector Objective appends through GetSizeOfVector and InsertInVector.
  • AddPoseStampedToVector appends a geometry_msgs::msg::PoseStamped to a typed pose vector.
  • AddPointCloudToVector appends a sensor_msgs::msg::PointCloud2 to a typed point-cloud vector and creates that vector when its bidirectional port is unset.

These nodes remain documented so existing Objectives can be understood and migrated, but they should not be used in new Objectives.

Practical Examples​

Vector and String Example​

The Vector and String Example Objective in the lab_sim robot configuration package demonstrates creating a vector, inserting, retrieving, replacing, and removing string messages, and checking the vector size.

Vector Subtrees Example​

The built-in Vector Subtrees Example Objective demonstrates how to:

  • Create a vector with CreateVector.
  • Append poses with PushBackVector.
  • Call the Find Nearest Pose In Path Objective.
  • Retrieve and validate the selected element.

Find Nearest Pose In Path​

The built-in Find Nearest Pose In Path Objective uses ForEach to find the pose with the lowest Euclidean distance to a search pose. It demonstrates how to expose each element and index while maintaining state across iterations.

Build a Semicolon-Separated String from User Input​

GetTextFromUser takes a vector of strings for prompts and default_values and returns one answer per prompt in text_output, also a vector of strings. In XML, a semicolon inside a vector port's literal value separates entries, so default_values="0.0;0.0;0.0" is three defaults, not one default holding a vector. Single quotes do not escape the separator. The Behavior fails if prompts and default_values have different lengths.

To collect a value with several components, such as a tool's center of gravity, ask one prompt per component, read each answer with GetElementOfVector, and join them in a Script. Run these Behaviors in a Sequence:

<Action ID="GetTextFromUser"
prompts="Tool CoG X (m);Tool CoG Y (m);Tool CoG Z (m)"
default_values="0.0;0.0;0.0"
text_output="{tool_cog_inputs}" />
<Action ID="GetElementOfVector" vector_in="{tool_cog_inputs}"
index="0" element="{tool_cog_x}" />
<Action ID="GetElementOfVector" vector_in="{tool_cog_inputs}"
index="1" element="{tool_cog_y}" />
<Action ID="GetElementOfVector" vector_in="{tool_cog_inputs}"
index="2" element="{tool_cog_z}" />
<Action ID="Script"
code="tool_cog_xyz := tool_cog_x .. ';' .. tool_cog_y .. ';' .. tool_cog_z" />

GetElementOfVector indexes from zero, so the first prompt is index 0. In the Script, .. concatenates strings and := creates the tool_cog_xyz blackboard entry. The semicolons survive here because code is a string port, not a vector port, so BehaviorTree.CPP's XML parser does not split it; ';' is a string literal in the Script language. Answers 0.1, -0.2, and 0.3 produce 0.1;-0.2;0.3.

A formatted string is not a validated numeric vector

tool_cog_xyz is a string, not a validated numeric vector. Connect it only to an input port that converts from a semicolon-separated string, and validate the values before using them for motion.

Error Handling​

Vector manipulation Behaviors return FAILURE when applicable for conditions such as:

  • An index is out of bounds.
  • An inserted or replacement element has an incompatible type.
  • An operation requires an element from an empty vector.
  • A required input port is missing.