Macros inside macros are not private once ran
Doomerdinger opened this issue · comments
Melodic v1.13.9
example.xacro
<?xml version="1.0" ?>
<robot name="example" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="testMacro" params="">
<xacro:macro name="testInnerMacro" params="">
</xacro:macro>
</xacro:macro>
<xacro:testMacro/>
<xacro:testInnerMacro/>
</robot>
The above xacro file will succeed when it should not. The testInnerMacro
should not be available outside of the testMacro
. The documentation states that "Properties and macros defined within a macro are local to this macro, i.e. not visible outside."
example2.xacro
<?xml version="1.0" ?>
<robot name="example" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="testMacro" params="">
<xacro:property name="foo" value="bar"/>
</xacro:macro>
<xacro:testMacro/>
<link name="${foo}"/>
</robot>
The above file fails as I would expect, because foo
should not be accessible outside of testMacro
That's a use case, we didn't yet consider. I agree with you, that the current behaviour doesn't comply to the doc. However, changing the behaviour might break existing code. Do you face problems due to the described behaviour?
As you probably noticed yourself, the inner macro becomes visible only after evaluating the outer one:
<?xml version="1.0" ?>
<robot name="example" xmlns:xacro="http://www.ros.org/wiki/xacro">
<xacro:macro name="testMacro" params="">
<xacro:macro name="testInnerMacro" params="">
</xacro:macro>
</xacro:macro>
<xacro:testInnerMacro/> <!-- fails, because testInnerMacro is not (yet) visible -->
<xacro:testMacro/>
</robot>
I do face problems, they are easily solved by renaming macros to be unique but I fear people who are less knowledgeable about the system will not name macros with such uniqueness and may run into issues that may not be clear to them.
One place I run into this issue in my system is I loop over arrays from a configuration file and do something with them, often times creating other parts of the system by calling xacros. I do this loop structure in several places, and originally called the macro loop_lt
(loop while less than). All of the loops have the same flow so it makes sense to name them that (they are all loops that iterate while less than some value), but different bodies and arguments. Since some of these loops call other macro files that also call the loop, then the parent loop will try to call the child loop and things break.
For an example of my loop:
<xacro:macro name="loop_lt" params="current:=0
max:=^
foo:=whatever"
>
<xacro:if value="${max > current}">
<do_things>This may call another macro which has its own loop_lt defined</do_things>
<xacro:loop_lt current="${current+1}"/>
</xacro:if>
</xacro:macro>
Example use case: I would call the above macro to iterate over all items in a yaml array, each of which is the configuration for some sub-piece of the system, so the loop would call another macro creating that piece.
@Doomerdinger, did you had a chance to reviewed/test #272?
I have not, the last few weeks have been quite hectic. I'll get around to testing it here soon.
The changed is #272 appear to fix the issues I was seeing. I was only able to test in melodic.