@@ -21,26 +21,21 @@ InputPort<Position2D>("goal")
2121### 2. Generic/Weakly Typed Ports (AnyTypeAllowed)
2222
2323A port is ** generic** (not strongly typed) when:
24- - Declared without a type parameter: ` InputPort<>("my_port") `
25- - Declared with ` AnyTypeAllowed ` : ` InputPort<AnyTypeAllowed>("my_port") `
26- - Declared with ` BT::Any ` : ` InputPort<BT::Any>("my_port") `
24+ - Declared without a type parameter
25+ - Declared with ` AnyTypeAllowed `
26+ - Declared with ` BT::Any `
27+ - Declared with ` std::string ` (** OoutputPort** only)
2728
2829``` cpp
2930// All of these create generic ports:
3031InputPort<>(" value" ) // defaults to AnyTypeAllowed
3132InputPort<AnyTypeAllowed>(" value" ) // explicit AnyTypeAllowed
3233InputPort<BT::Any>(" value" ) // BT::Any type
34+ OoutputPort<std::string>(" value" ) // Can be connected to strong typed input
3335```
3436
3537The ` isStronglyTyped() ` method returns ` false ` for these ports:
3638
37- ``` cpp
38- // From basic_types.h
39- bool isStronglyTyped () const
40- {
41- return type_info_ != typeid(AnyTypeAllowed) && type_info_ != typeid(BT::Any);
42- }
43- ```
4439
4540## Port Connection Rules
4641
@@ -49,13 +44,9 @@ bool isStronglyTyped() const
4944Ports of the ** exact same type** can always be connected:
5045
5146``` cpp
52- // Node A
47+ // Connection allowed
5348OutputPort<int >(" value" ) // writes int
54-
55- // Node B
5649InputPort<int >(" value" ) // reads int
57-
58- // Connection: OK
5950```
6051
6152** Test reference:** ` gtest_port_type_rules.cpp ` - ` SameType_IntToInt ` , ` SameType_StringToString ` , ` SameType_CustomTypeToCustomType ` tests
@@ -65,13 +56,9 @@ InputPort<int>("value") // reads int
6556A ** generic port** (` AnyTypeAllowed ` or ` BT::Any ` ) can connect to any other port:
6657
6758``` cpp
68- // Node A with generic output
59+ // Connection: OK - generic port accepts any type
6960OutputPort<>(" output" ) // generic, can write anything
70-
71- // Node B with typed input
7261InputPort<int >(" input_int" ) // expects int
73-
74- // Connection: OK - generic port accepts any type
7562```
7663
7764** Test reference:** ` gtest_port_type_rules.cpp ` - ` GenericPort_AcceptsInt ` , ` GenericPort_AcceptsString ` , ` GenericOutput_ToTypedInput ` tests
@@ -80,24 +67,13 @@ InputPort<int>("input_int") // expects int
8067
8168When a blackboard entry is created as ` std::string ` , it can be connected to ports of ** any type** that has a ` convertFromString<T>() ` specialization. This is the "string as generic port" rule.
8269
83- ** Source:** ` xml_parsing.cpp `
84- ``` cpp
85- // special case related to convertFromString
86- bool const string_input = (prev_info->type () == typeid(std::string));
87-
88- if(port_type_mismatch && !string_input)
89- {
90- // Error thrown only if NOT a string input
91- throw RuntimeError("The creation of the tree failed...");
92- }
93- ```
70+ Note that this may cause a run-time error if the string is not convertible.
9471
9572** Example:**
9673``` xml
9774<Sequence >
9875 <!-- Creates blackboard entry "value" as string with value "42" -->
9976 <SetBlackboard value =" 42" output_key =" value" />
100-
10177 <!-- Reads "value" as int - OK because string can convert to int -->
10278 <NodeExpectingInt input =" {value}" />
10379</Sequence >
@@ -113,15 +89,6 @@ if(port_type_mismatch && !string_input)
11389
11490When using ` Blackboard::set<std::string>() ` , the entry is created with ` AnyTypeAllowed ` type, not ` std::string ` :
11591
116- ** Source:** ` blackboard.h `
117- ``` cpp
118- // if a new generic port is created with a string, it's type should be AnyTypeAllowed
119- if constexpr (std::is_same_v<std::string, T>)
120- {
121- entry = createEntryImpl(key, PortInfo(PortDirection::INOUT)); // AnyTypeAllowed
122- }
123- ```
124-
12592This allows subsequent writes of different types to the same entry.
12693
12794** Test reference:** ` gtest_port_type_rules.cpp ` - ` BlackboardSetString_CreatesGenericEntry ` , ` StringEntry_CanBecomeTyped ` tests
@@ -130,37 +97,15 @@ This allows subsequent writes of different types to the same entry.
13097
13198Once a blackboard entry receives a ** strongly typed** value, its type is locked:
13299
133- ** Source:** ` blackboard.h `
134- ``` cpp
135- // special case: entry exists but it is not strongly typed... yet
136- if (!entry.info.isStronglyTyped())
137- {
138- // Use the new type to create a strongly typed entry
139- entry.info = TypeInfo::Create<T >();
140- // ...
141- return;
142- }
143- ```
144-
145- After this, writing a different type will fail (with exceptions noted below).
100+ After this, writing a different type will fail (with exception).
146101
147102** Test reference:** ` gtest_port_type_rules.cpp ` - ` TypeLock_CannotChangeAfterTypedWrite ` , ` TypeLock_XMLTreeCreation_TypeMismatch ` , ` TypeLock_RuntimeTypeChange_Fails ` tests
148103
149104### Rule 6: BT::Any Bypasses Type Checking
150105
151- When a blackboard entry is ** created with type ` BT::Any ` ** , it can store different types over time. This requires the entry to be explicitly created as ` BT::Any ` type.
106+ When a blackboard entry is ** created with type ` BT::Any ` ** , it can store different types over time.
152107
153- ** Important:** Wrapping a value with ` BT::Any() ` does ** not** bypass type checking - the wrapper is unwrapped and the inner type is used:
154-
155- ``` cpp
156- // This creates an entry of type int, NOT BT::Any
157- bb->set ("key", BT::Any(42));
158-
159- // This will FAIL - entry is int, not BT::Any
160- bb->set("key", BT::Any("hello")); // throws LogicError
161- ```
162-
163- To actually allow different types, create the entry as `BT::Any`:
108+ This requires the entry to be explicitly created as ` BT::Any ` type.
164109
165110``` cpp
166111// Create entry explicitly as BT::Any type
@@ -282,56 +227,3 @@ The following names **cannot** be used for ports:
282227- Names starting with ` _ ` - Reserved for internal use
283228
284229** Test reference:** ` gtest_port_type_rules.cpp ` - ` ReservedPortName_ThrowsOnRegistration ` test
285-
286- ## Common Patterns
287-
288- ### Pattern 1: Type-Safe Port Chain
289- ``` xml
290- <Sequence >
291- <CalculateGoal goal =" {GoalPosition}" /> <!-- Output: Position2D -->
292- <PrintTarget target =" {GoalPosition}" /> <!-- Input: Position2D -->
293- </Sequence >
294- ```
295-
296- ### Pattern 2: String Literal to Typed Port
297- ``` xml
298- <Sequence >
299- <SetBlackboard value =" 1.5;2.5" output_key =" pos" />
300- <MoveToPosition target =" {pos}" /> <!-- Converts string to Position2D -->
301- </Sequence >
302- ```
303-
304- ### Pattern 3: Generic Intermediate Storage
305- ``` xml
306- <Sequence >
307- <TypedNode output_int =" {value}" /> <!-- Writes int to generic entry -->
308- <GenericNode input =" {value}" /> <!-- Generic port reads it -->
309- <AnotherTypedNode input_int =" {value}" /> <!-- Int port reads it -->
310- </Sequence >
311- ```
312-
313- ## Error Messages
314-
315- Common type-related errors:
316-
317- 1 . ** "The creation of the tree failed because the port [ X] was initially created with type [ A] and, later type [ B] was used somewhere else."**
318- - Cause: Two nodes use same blackboard key with incompatible types
319- - Solution: Ensure consistent types or use string/generic ports
320-
321- 2 . ** "Blackboard::set(X): once declared, the type of a port shall not change."**
322- - Cause: Runtime attempt to change entry type
323- - Solution: Use consistent types or BT::Any
324-
325- 3 . ** "The port with name X and value Y can not be converted to Z"**
326- - Cause: Literal value cannot be parsed to port type
327- - Solution: Fix value format or add ` convertFromString ` specialization
328-
329- ## References
330-
331- - Source: ` include/behaviortree_cpp/basic_types.h ` - Type system definitions
332- - Source: ` include/behaviortree_cpp/blackboard.h ` - Blackboard type checking
333- - Source: ` src/xml_parsing.cpp ` - Tree creation validation
334- - Tests: ` tests/gtest_port_type_rules.cpp ` - Comprehensive port type rule tests
335- - Tests: ` tests/gtest_ports.cpp ` - Port connection tests
336- - Tests: ` tests/gtest_blackboard.cpp ` - Blackboard tests
337- - Tutorial: ` examples/t03_generic_ports.cpp ` - Custom type example
0 commit comments