Skip to content

Conversation

@rhaschke
Copy link
Contributor

@rhaschke rhaschke commented Oct 4, 2021

As pointed out by @captain-yoshi in #280 (comment) xacro can be used to realize loops:

<robot name="loop" xmlns:xacro="http://www.ros.org/wiki/xacro">
	<xacro:macro name="loop" params="items:=^">
		<xacro:if value="${items}">
			<!-- pop first item from list -->
			<xacro:property name="item" value="${items.pop(0)}"/>

			<item>${item}</item>

			<!-- recursively call myself -->
			<xacro:loop/>
		</xacro:if>
	</xacro:macro>
	<xacro:loop items="${[1,2,3,4,5]}"/>
</robot>

However, it would be even nicer if we could define a generic loop macro like this:

<xacro:macro name="loop" params="items **body:=^">
	<xacro:if value="${items}">
		<!-- pop first item from list -->
		<xacro:property name="item" value="${items[0]}"/>
		<xacro:insert_block name="body" />
		<!-- recursively call myself -->
		<xacro:loop items="${items[1:]}"/>
	</xacro:if>
</xacro:macro>

and then just call it with an arbitrary body:

<xacro:loop items="${python.range(5)}">
	<body>
		<item>${item}</item>
	</body>
</xacro:loop>

The attached commits are two (failed) attempts to achieve this. The culprit is the recursive handling of nested macros, which seems to be required to due lazy evaluation of the first generation of xacro.

Fails, because we cannot re-pass the body block into next loop iterations.
Error: Not enough blocks
This allows recursive calls with identical block args, i.e. loop works.
However, I had to drop early evaluation of body (which is conceptually wrong, I believe).

This breaks test_pr2 and test_should_replace_before_macroexpand!
This is required for using properties within the block that are only
defined in the header of the calling macro (before calling insert_block).

However, the old code (e.g. test_should_replace_before_macroexpand) now fails
with `maximum recursion depth exceeded while calling a Python object` due to infinite recursion.
@Doomerdinger
Copy link
Contributor

Doomerdinger commented Jun 9, 2022

This is interesting, would be a great feature! Many of the issues I've posted to this repo (back to Jan or Feb 2021) were all relating back to some unusual ways I was using xacro, the main one of which was using it to perform looping operations - particularly over arbitrarily sized lists in yaml configurations.

I think in at least one of them I mentioned the desire for this, but I lack the python expertise/familiarity with this repo (and time, mainly time) to try it myself. I ended up doing some other terribleness for speedups (parallelized runs of multiple xacro calls which I stitch together at the end).

If I ever have the time I'll try to look into it more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants