Skip to content

Visuals and collision transforms match the wrong link #175

Description

@Hugo-Suricate

Description

World transforms of the visuals and collisions attached to a chain are incorrectly computed. Their transform is computed relative to the parent link instead of the current one.

Example using a simple URDF and k::Chain::from_urdf_file() shows each link's visual geometry has the wrong parent transform. Visuals are systematically offset by one link in the hierarchy.

Environment

k crate version: 0.32.0
Platform: [Win 10]
Rust version: [1.97.1]

Minimal Reproduction Files:

minimal_test.urdf

<?xml version="1.0"?>
<robot name="test_robot">
  <link name="base_link">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <box size="0.1 0.1 0.1"/>
      </geometry>
    </visual>
  </link>

  <!-- First Joint: base_link -> link_1 with Z offset -->
  <joint name="joint_0" type="revolute">
    <parent link="base_link"/>
    <child link="link_1"/>
    <origin xyz="0 0 0.2" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14" upper="3.14" effort="100" velocity="1.0"/>
  </joint>
  
  <link name="link_1">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <cylinder radius="0.05" length="0.1"/>
      </geometry>
    </visual>
  </link>
  
  <!-- Second Joint: link_1 -> link_2 with Z offset -->
  <joint name="joint_1" type="revolute">
    <parent link="link_1"/>
    <child link="link_2"/>
    <origin xyz="0 0 0.3" rpy="0 0 0"/>
    <axis xyz="0 0 1"/>
    <limit lower="-3.14" upper="3.14" effort="100" velocity="1.0"/>
  </joint>
  
  <link name="link_2">
    <visual>
      <origin xyz="0 0 0" rpy="0 0 0"/>
      <geometry>
        <sphere radius="0.05"/>
      </geometry>
    </visual>
  </link>
  
</robot>

src/main.rs

use k::{Chain};

fn main() {
    let chain = Chain::<f32>::from_urdf_file("minimal_test.urdf").unwrap();
    chain.update_link_transforms();
    
    println!("{}\n", chain);
    
    // Local translations
    println!("Joints: ");
    for joint in chain.iter_joints() {
        println!("{} joint local translation : {:?}", joint.name, joint.local_transform().translation);
        println!("{} joint world translation : {:?}", joint.name, joint.world_transform().unwrap().translation);
    }

    println!("\nLink visuals: ");
    for link in chain.iter_links() {
        println!("{} visual world translation : {:?}", &link.name, &link.visuals.first().unwrap().world_transform().unwrap().translation);
    }
}

link_1 visual should match link_1 world position (i.e. joint_0) but doesn't : matches base_link instead
link_2 visual should match link_2 world position (i.e. joint_1) but doesn't : matches joint_0 instead

Probable root cause and fix

In src/chain.rs in the update_link_transforms(), line 491, the transform is computed with parent_world_transform(). Replace with world_transform() and rename the variable to avoid confusion.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions