ros / xacro

Xacro is an XML macro language. With xacro, you can construct shorter and more readable XML files by using macros that expand to larger XML expressions.

Home Page:http://www.ros.org/wiki/xacro

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.

Could you please have a look at #271 and verify that this solves your issue?
I'm not sure we should target this for Melodic at all. This requires many, potentially breaking changes.
#272 provides a solution for Noetic.

I can still test #271 if you would like, I don't have a noetic install to test #272 but I can still give it a look over.

#271 doesn't work. You should go for #272. This latter works for both, Melodic and Noetic.

@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.