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:
-1selects the last element.-2selects 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
RUNNINGwhile iterating. - It returns
FAILUREas soon as the child fails. - It returns
SUCCESSafter 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
RUNNINGwhile checking elements. - It returns
SUCCESSas soon as the child succeeds, or when the vector is empty. - It returns
FAILUREafter 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
AddToVector, AddPoseStampedToVector, and AddPointCloudToVector are deprecated and will be removed in a future release. Use PushBackVector instead.
- The
AddToVectorObjective appends throughGetSizeOfVectorandInsertInVector. AddPoseStampedToVectorappends ageometry_msgs::msg::PoseStampedto a typed pose vector.AddPointCloudToVectorappends asensor_msgs::msg::PointCloud2to 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 PathObjective. - 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.
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.