Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

xacro:loop macro #291

Draft
wants to merge 3 commits into
base: noetic-devel
Choose a base branch
from
Draft

xacro:loop macro #291

wants to merge 3 commits into from

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