gkjohnson / xacro-parser

Utility for parsing and converting ROS Xacro files in Javascript.
MIT License
24 stars 10 forks source link

Error importing XacroLoader in my typescript project #77

Closed joaopfg closed 2 years ago

joaopfg commented 2 years ago

Hello,

When trying to import { XacroLoader } from 'xacro-parser'; in my typescript project I'm getting the error:

Error: node_modules/xacro-parser/src/XacroParser.d.ts:3:75 - error TS7006: Parameter 'command' implicitly has an 'any' type.

3     rospackCommands?: { [key: string]: (...args:string[]) => string } | ((command, ...args: string[]) => string);

My typescript compiler options are:

"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"sourceMap": true,
"declaration": false,
"downlevelIteration": true,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "es2017",
"module": "es2020",
"lib": [
      "es2018",
      "dom"
]
gkjohnson commented 2 years ago

Thanks! Looks like I hadn't set up typescript linting on this project. Would you like to make a PR that adds typescript file validation to catch these kinds of errors and fix the above issue?

You can see the typescript command included in the lint script here in the three-mesh-bvh package. And here's the tsconfig file used in that project which can be reused here.

joaopfg commented 2 years ago

Hello, @gkjohnson , I will try it today

joaopfg commented 2 years ago

@gkjohnson I put thetsconfig.json inside the xacro-parser package and updated the lint script. It works for simple .xacro in my typescript project (I created a pull request). However, it doesn't work if the .xacro calls rospack commands. For example, the following .xacro.

<?xml version="1.0"?>
<!-- Revolute-Revolute Manipulator -->
<robot name="rrbot" xmlns:xacro="http://www.ros.org/wiki/xacro">

  <!-- Constants for robot dimensions -->
   <xacro:property name="width" value="0.1" />   <!-- Beams are square in length and width -->
  <xacro:property name="height1" value="2" />   <!-- Link 1 -->
  <xacro:property name="height2" value="1" />   <!-- Link 2 -->
  <xacro:property name="height3" value="1" />   <!-- Link 3 -->
  <xacro:property name="axle_offset" value="0.05" /> <!-- Space between joint and end of beam -->
  <xacro:property name="damp" value="0.7" />    <!-- damping coefficient -->

  <!-- Import Rviz colors -->
  <xacro:include filename="$(find ros_robotics)/urdf/materials.xacro" />

  <!-- Default Inertial -->
  <xacro:macro name="default_inertial" params="z_value mass">
    <inertial>
      <origin xyz="0 0 ${z_value}" rpy="0 0 0"/>
      <mass value="${mass}" />
      <inertia ixx="1.0" ixy="0.0" ixz="0.0"
               iyy="1.0" iyz="0.0"
               izz="1.0" />
      </inertial>
  </xacro:macro>

  <!-- Base Link -->
  <link name="base_link">
    <visual>
      <origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
      <geometry>
  <box size="${width} ${width} ${height1}"/>
      </geometry>
      <material name="red"/>
    </visual>

    <collision>
      <origin xyz="0 0 ${height1/2}" rpy="0 0 0"/>
      <geometry>
  <box size="${width} ${width} ${height1}"/>
      </geometry>
    </collision>

    <xacro:default_inertial z_value="${height1/2}" mass="1"/>
  </link>

  <!-- Joint between Base Link and Middle Link -->
  <joint name="joint_base_mid" type="revolute">
    <parent link="base_link"/>
    <child link="mid_link"/>
    <origin xyz="0 ${width} ${height1 - axle_offset}" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
    <dynamics damping="${damp}"/>
    <limit effort="100.0" velocity="0.5" lower="-3.14" upper="3.14" />
  </joint>

  <!-- Middle Link -->
  <link name="mid_link">
    <visual>
      <origin xyz="0 0 ${height2/2 - axle_offset}" rpy="0 0 0"/>
      <geometry>
  <box size="${width} ${width} ${height2}"/>
      </geometry>
      <material name="green"/>
    </visual>

    <collision>
      <origin xyz="0 0 ${height2/2 - axle_offset}" rpy="0 0 0"/>
      <geometry>
  <box size="${width} ${width} ${height2}"/>
      </geometry>
    </collision>

    <xacro:default_inertial z_value="${height2/2 - axle_offset}" mass="1"/>
  </link>

  <!-- Joint between Middle Link and Top Link -->
  <joint name="joint_mid_top" type="revolute">
    <parent link="mid_link"/>
    <child link="top_link"/>
    <origin xyz="0 ${width} ${height2 - axle_offset*2}" rpy="0 0 0"/>
    <axis xyz="0 1 0"/>
    <dynamics damping="${damp}"/>
    <limit effort="100.0" velocity="0.5" lower="-3.14" upper="3.14" />
  </joint>

  <!-- Top Link -->
  <link name="top_link">
    <visual>
      <origin xyz="0 0 ${height3/2 - axle_offset}" rpy="0 0 0"/>
      <geometry>
  <box size="${width} ${width} ${height3}"/>
      </geometry>
      <material name="blue"/>
    </visual>

    <collision>
      <origin xyz="0 0 ${height3/2 - axle_offset}" rpy="0 0 0"/>
      <geometry>
  <box size="${width} ${width} ${height3}"/>
      </geometry>
    </collision>

    <xacro:default_inertial z_value="${height3/2 - axle_offset}" mass="1"/>
  </link>

</robot>

I get the following error on console:

Error: XacroParser: Failed to process expression "$(find ros_robotics)/urdf/materials.xacro". 
XacroParser: Cannot run rospack command "find ros_robotics".
rospackCommands[stem] is not a function
    at evaluateAttribute (XacroParser.js:140:23)
    at XacroParser.js:393:38
    at Generator.next (<anonymous>)
    at asyncGeneratorStep (asyncToGenerator.js:3:1)
    at _next (asyncToGenerator.js:25:1)
    at asyncToGenerator.js:32:1
    at new ZoneAwarePromise (zone.js:1387:1)
    at asyncToGenerator.js:21:1
    at processNode (XacroParser.js:31:23)
    at XacroParser.js:432:35

But it can load in my browser without the line that import Rviz colors (<xacro:include filename="$(find ros_robotics)/urdf/materials.xacro" /> ) .

The problem seems to be the rospack find ros_robotics command.

Is this due to some feature that is not yet implemented ?

gkjohnson commented 2 years ago

The official xacro tool calls out to other ROS cli commands in order to work. Of course "rospack find ros_robotics" cli command is not available in the browser but you can implement it yourself using the "rospackCommands" option with some other approach that will work without cli / file system access.

joaopfg commented 2 years ago

@gkjohnson Thanks for clarification. I thought this syntax ${ find ...} would be interpreted by xacro-parser in a equivalent way it's interpreted on linux shell (doing a pattern mathing on the HTTP server filesystem for what find is looking for and loading the xml following the urdf grammar).

But I solved it in a simpler way for now: I just put all the folders I need in my HTTP server and put absolute paths on everything.

And the import is working fine in typescript now.

gkjohnson commented 2 years ago

doing a pattern mathing on the HTTP server filesystem for what find is looking for

This isn't possible to do generally with static file servers but you can implement it this way yourself if you have control over the file service. It's also possible for the other xacro files to be loaded from other remote servers, then.

And the import is working fine in typescript now.

What changed? Are you still planning to work on PR #78?

joaopfg commented 2 years ago

@gkjohnson I see, thanks!

When I import the package locally I have no errors anymore, so I thought it was solved just by adding the tsconfig.json. Sorry, I'm a newbie in all this (typescript, packaging etc) . I begin working with it very recently for a task on my work :)

But when I run npm run lint -- --fix it seems there is nothing to fix. What do you think the issue can be ?

gkjohnson commented 2 years ago

You need to run npm run lint to see the issues. In the PR the CI runs you can see that what you have submitted fails to pass the lint check:

https://github.com/gkjohnson/xacro-parser/runs/5054933358?check_suite_focus=true

You at least need to make the changes I posted in the PR -- ie install typescript, remove the ts files from the eslint check