Xacro insert_block parameter

I was hoping to use the insert_block xacro capability to insert blocks as arguments to macros. However, I can't figure out how to send blocks as parameters to xacros and there's not much documentation or examples that I can find. Here's a simple example:

<xacro:macro name="blockInserterMacro" params="*block_to_insert">
<xacro:insert_block name="block_to_insert"/>
</xacro:macro>

<xacro:macro name="mycallerMacro" params="x y">
<xacro:macro name="insertedBlockGenerator">
<xacro:someOtherMacroA x="${x}"> <xacro:someOtherMacroB y="${y}>
</xacro:macro>

<xacro:blockInserterMacro block_to_insert="insertedBlockGenerator"/>
</xacro:macro>

<xacro:myCallerMacro x="5" y="3"/>


I have one xacro, blockInserterMacro, that is supposed to insert whatever the contents of the bock_to_insert parameter are inside the <link> it creates. This xacro is used by another xacro, myCallerMacro, which first defines an inner macro that is supposed to generate the block to be inserted based on given parameters x and y using other macros defined elsewhere, and then passes the generated block as the block_to_insert parameter to blockInserterMacro. Finally, myCallerMacro is called with specific values for the x and y parameters.

Why would I want to do this? Basically I want to have a macro that generates a special kind of component with associated link and joint, but the physics blocks of the link (such as inertia and collision geometry) should be customizable. That way I can easily generate this component with different physics blocks.

Please let me know if there's a better way to do this.

System: Ubuntu 18.04 64-bit ROS Melodic

edit retag close merge delete

Sort by » oldest newest most voted

Hi @Dan_RR.

First of all, to do what you want there is no need to have multiple macros since you can have params and containers (blocks) in the same macro; the key is how you declare what is a param and what is a block to insert. Take a look at the following example:

Imagine I have your blockInserterMacro to accept a container, so instead of having it like *block_to_insert it will be something like:

<xacro:macro name="blockInserterMacro" params="**block_to_insert">
<xacro:insert_block name="block_to_insert"/>
</xacro:macro>


Please note de double *. From this you can have also parameters together with the block like params="x y **block_to_insert" but to follow your set up you will need something like:

<xacro:macro name="mycallerMacro" params="x y">
<xacro:macro name="insertedBlockGenerator">
<xacro:someOtherMacroA x="${x}"> <xacro:someOtherMacroB y="${y}>
</xacro:macro>

<xacro:blockInserterMacro>
<block_to_insert>
<block_param_1>...</block_param_1>
<block_param_2>...</block_param_2>
...
</block_to_insert>
</xacro:blockInserterMacro>
</xacro:macro>

<xacro:myCallerMacro x="5" y="3"/>


But remember this is practically the same as having only one macro for that block inclusion:

<xacro:macro name="mycallerMacro" params="x y **block_to_insert">
<xacro:macro name="insertedBlockGenerator">
<xacro:someOtherMacroA x="${x}"> <xacro:someOtherMacroB y="${y}>
</xacro:macro>

<xacro:insert_block name="block_to_insert"/>
</xacro:macro>

<xacro:myCallerMacro x="5" y="3">
<block_to_insert>
<block_param_1>...</block_param_1>
<block_param_2>...</block_param_2>
...
</block_to_insert>
<xacro:myCallerMacro/>


Hopw that helps you in with the problem.

Regards.

more

I see. I think first, I didn't understand that block arguments aren't really sent to to macros as parameters, like x and y, because I didn't realize that xacro calls don't have to be self-closing tags. The block are encapsulated between opening and closing tags like <xacro:mymacro x="5"> <your blocks="" to="" insert="" here=""> </xecro:mymacro> Second, I didn't understand that you can wrap multiple blocks in some arbitrary tag to make them a single block, as with your <block_to_insert>. I think, together, those two realizations solve my problem.

I am still confused what the difference is between single * and double ** before the block parameter name. Single * seems to work even if there are other normal parameters to the macro.

I am also still confused if if it's possible to have default blocks, especially to insert nothing if no block ...(more)

( 2020-08-02 00:49:52 -0500 )edit

@Dan_RR, the main difference between * and ** is that when you use * you are inserting a tag, E.g.: <origin xyz="0 0 0" rpy="0 0 0" /> --> <xacro:insert_block name="origin" /> while when you use ** what you are doing is inserting a group of tags not only one. The name does not need to be the same as the tag, only is important that the name is the same as the param name specified in the macro params. Imagine it as having a group of params in which you have integers (x and y) and pointers or vectors (param and *param), a function can have those parameters together and they are differentiated by their name and memory location.

On the other hand you cannot specified with block parameters default values, but you can specify an empty block in which nothing is declare. Like <block_to_insert/>.

( 2020-08-02 06:34:14 -0500 )edit