Force Torque Sensor - modulabs/gazebo-tutorial GitHub Wiki

Introduction

์ด๋ฒˆ ํŠœํ† ๋ฆฌ์–ผ์€ ๊ด€์ ˆ(joint)์— ์ž‘์šฉํ•˜๋Š” forcre/torque sensor์˜ ์‚ฌ์šฉ๋ฒ•์„ ์„ค๋ช…ํ•œ๋‹ค. ์ด ์„ผ์„œ๋Š” force, torque ์ฝ์€๊ฐ’์„ topic์œผ๋กœ publish ํ•œ๋‹ค.

Quick Start

Part 1: See the sensor in action

Create a world with a force/torque sensor

force_torque_tutorial.world ์ด๋ฆ„์œผ๋กœ world๋ฅผ ์ €์žฅํ•œ๋‹ค.

<?xml version="1.0"?>
<sdf version="1.6">
  <world name="default">
    <physics name="default_physics" default="0" type="ode">
      <max_step_size>0.001</max_step_size>
      <real_time_factor>1</real_time_factor>
      <real_time_update_rate>1000</real_time_update_rate>
      <ode>
        <solver>
          <type>quick</type>
          <iters>50</iters>
          <sor>1.0</sor> <!-- Important, see issue #2209 -->
          <use_dynamic_moi_rescaling>false</use_dynamic_moi_rescaling>
        </solver>
      </ode>
    </physics>
    <include>
      <uri>model://ground_plane</uri>
    </include>
    <include>
      <uri>model://sun</uri>
    </include>
    <model name="model_1">
      <link name="link_1">
        <pose>0 0 2.0 0 0 0</pose>
        <inertial>
          <inertia>
            <ixx>0.100000</ixx>
            <ixy>0.000000</ixy>
            <ixz>0.000000</ixz>
            <iyy>0.100000</iyy>
            <iyz>0.000000</iyz>
            <izz>0.100000</izz>
          </inertia>
          <mass>10.000000</mass>
        </inertial>
        <visual name="visual_sphere">
          <geometry>
            <sphere>
              <radius>0.100000</radius>
            </sphere>
          </geometry>
        </visual>
        <visual name="visual_cylinder">
          <pose>0 0 -0.75 0 0 0</pose>
          <geometry>
            <cylinder>
              <radius>0.0100000</radius>
              <length>1.5</length>
            </cylinder>
          </geometry>
        </visual>
        <collision name="collision_sphere">
          <max_contacts>250</max_contacts>
          <geometry>
            <sphere>
              <radius>0.100000</radius>
            </sphere>
          </geometry>
        </collision>
      </link>
      <joint name="joint_01" type="revolute">
        <parent>world</parent>
        <child>link_1</child>
        <pose>0 0 -1.5 0 0 0</pose>
        <axis>
          <limit>
            <lower>-1.57079</lower>
            <upper>1.57079</upper>
          </limit>
          <dynamics>
            <damping>0.000000</damping>
            <friction>0.000000</friction>
          </dynamics>
          <xyz>1.000000 0.000000 0.000000</xyz>
        </axis>
        <sensor name="force_torque" type="force_torque">
          <update_rate>30</update_rate>
        </sensor>
      </joint>
    </model>
  </world>
</sdf>

Launch the world

terminal์„ ์—ด๊ณ , ์ด ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•œ๋‹ค. (--verbose)

gazebo --verbose force_torque_tutorial.world

View the output of the force/torque sensor

์ƒˆ๋กœ์šด terminal์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๋ช…๋ น์–ด์™€ ํ•จ๊ป˜ topic viewer๋ฅผ ์—ฐ๋‹ค:

gz topic --view /gazebo/default/model_1/joint_01/force_torque/wrench

Apply forces and torques in gazebo

Y๋ฐฉํ–ฅ์œผ๋กœ 500N์˜ ํฌ๊ธฐ๋กœ link_1์— Apply a force. topic viewer (ctrl-t)๋กœ ๊ฒฐ๊ณผ๊ฐ’์„ ๋ณด์ž.

Part 2: Explanation of the above steps

At the start of the world

์ด world๋Š” ํ•˜๋‚˜์˜ ๋งํฌ์™€ ํ•˜๋‚˜์˜ ๊ด€์ ˆ์„ ๊ฐ–๋Š”๋‹ค. ๋งํฌ๋Š” ๊ด€์ ˆ๋กœ๋ถ€ํ„ฐ 1.5m offser์„ ๊ฐ–๋Š” 10kg, ๊ตฌ ๋ชจ์–‘์ด๋‹ค. ๊ด€์ ˆ์€ ๋งํฌ(child)์™€ world(parent)๋กœ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ๊ณ , x๋ฐฉํ–ฅ์œผ๋กœ ํšŒ์ „์ด ๊ฐ€๋Šฅํ•˜๋‹ค. ์‹œ๋ฎฌ๋ ˆ์ด์…˜์ด ์ฒ˜์Œ ์‹œ์ž‘ํ• ๋•Œ๋Š” ๋งํฌ๋Š” ๊ด€์ ˆ ์œ„์—์„œ ํ‰ํ˜•์„ ์ด๋ฃจ๊ณ  ์žˆ๋‹ค. ์ด๋•Œ torque๋Š” ์—†๋‹ค. ๊ด€์ ˆ์— ์ž‘์šฉํ•˜๋Š” ํž˜์€ ์ค‘๋ ฅ(-z ๋ฐฉํ–ฅ)์œผ๋กœ๋ถ€ํ„ฐ ์˜จ๋‹ค.

forceJointZ = mass * g
            = 10 kg * -9.8 m/s^2
            = -98 N

After applying a force to the link

link_1์— ์™ธ๋ ฅ์„ ๋„ฃ์–ด์ฃผ๋ฉด, ๋งํฌ๋ฅผ ๋„˜์–ด์ง€๊ณ , ๊ด€์ ˆ ํ•œ๊ณ„์ธ 90๋„์—์„œ ๋ฉˆ์ถ”๊ฒŒ ๋œ๋‹ค. ๊ด€์ ˆ ํ•œ๊ณ„๋Š” ๋งํฌ๊ฐ€ ground plane ์œ„์—์„œ ๋ฉˆ์ถœ ์ˆ˜ ์žˆ๋„๋ก ์œ ์ง€ํ•ด์ฃผ๋Š” ์—ญํ• ์ด๋‹ค. ๊ด€์ ˆ์˜ +Y๋ฐฉํ–ฅ์€ ground plane๋กœ ๋“ค์–ด๊ฐ€๋Š” ๋ฐฉํ–ฅ์ด๋‹ค. ๋งํฌ์— ์ž‘์šฉํ•˜๋Š” ์ค‘๋ ฅ์€ x๋ฐฉํ–ฅ์œผ๋กœ ํ† ํฌ๋ฅผ ๋งŒ๋“ ๋‹ค.

์งˆ๋Ÿ‰์€ ๋™์ผํ•˜๊ณ , ํž˜์˜ ํฌ๊ธฐ๋„ ๋™์ผ. ํž˜์˜ ๋ฐฉํ–ฅ์€ Y๋ฐฉํ–ฅ์œผ๋กœ +98N๋˜๋„๋ก ๋ณ€ํ™”ํ•œ๋‹ค. ๊ตฌ๋Š” Joint์˜ z๋ฐฉํ–ฅ์œผ๋กœ 1.5m ๋–จ์–ด์ ธ์žˆ๊ธฐ์—, x๋ฐฉํ–ฅ์˜ ํ† ํฌ๋Š”:

torqueJoint01_x = r X R
                = ||r|| * ||F|| * sin(theta)
                = distanceZ * (massLink * g) * sin(theta)
                = 1.5 m * (10 kg * 9.8 m/s^2) * sin(-90)
                = -147 Nm

Note: ๊ด€์ ˆ limit ๊ทผ์ฒ˜ ๊ตฌ๊ฐ„์˜ ์ธก์ •๊ฐ’์€ ๋ฌผ๋ฆฌ ์—”์ง„์˜ ํŒŒ๋ผ๋ฏธํ„ฐ์— ๋”ฐ๋ผ ํŠˆ ์ˆ˜ ์žˆ๋‹ค. issue #2209๋ฅผ ๋ณด์•„๋ผ

Understanding the Force/Torque Sensor

SDF parameters

Generic parameters

๋ชจ๋“  ์„ผ์„œ๋Š” SDF sensor schema์•ˆ์—์„œ ๊ณตํ†ต๋œ ํŒŒ๋ผ๋ฏธํ„ฐ set์„ ๊ฐ–๋Š”๋‹ค.

<always_on>

๋งŒ์•ฝ true๋ผ๋ฉด ์„ผ์„œ๋Š” ํ•ญ์ƒ force์™€ torque๋ฅผ ์ธก์ •ํ•œ๋‹ค. ๋งŒ์•ฝ false๋ผ๋ฉด ์„ผ์„œ๋Š” subscriber๊ฐ€ sensor's topic์— ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์„๋•Œ๋งŒ ์—…๋ฐ์ดํŠธ๊ฐ€ ๋œ๋‹ค. ์ด๋Ÿฌํ•œ ์„ค์ •์€ code๋ฅผ ํ†ตํ•ด ์„ผ์„œ๋ฅผ ์ ‘๊ทผํ• ๋•Œ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค. ๋งŒ์•ฝ subscriber๊ฐ€ ์—†๋‹ค๋ฉด ForceTorqueSensor::Torque() or ForceTorqueSensor::Force()๋ฅผ ๋ถ€๋ฅด๋Š” ๊ฒƒ์€ ์•ˆ์ •ํ™”๋œ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•  ๊ฒƒ์ด๋‹ค. ์ด๋Ÿฌํ•œ ๋ฌธ์ œ๋Š” IsActive()๊ฐ€ false๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š”์ง€๋ฅผ ํ™•์ธํ•˜๋Š”๊ฒƒ์œผ๋กœ ๋ฐœ๊ฒฌํ•  ์ˆ˜ ์žˆ๋‹ค. ์ฝ”๋“œ๋Š” SetActive(true)๋ฅผ ๋ถ€๋ฆ„์œผ๋กœ์จ, ์„ผ์„œ๊ฐ€ subscriber๊ฐ€ ์—†๋Š” ์ƒํ™ฉ์—์„œ ์—…๋ฐ์ดํŠธ ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•œ๋‹ค.

<update_rate>

์ด๊ฒƒ์€ ์„ผ์„œ๊ฐ€ ์Šค์Šค๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” rate (Hz)๋ฅผ ๋งํ•œ๋‹ค. ์ด๊ฒƒ์€ simulated second ๋งˆ๋‹ค ์„ผ์„œ์— ์˜ํ•ด published๋˜๋Š” ๋ฉ”์„ธ์ง€์˜ ์ˆ˜์ผ ๊ฒƒ์ด๋‹ค.

<visualize>

๋งŒ์•ฝ ture๋ผ๋ฉด, gazebo client๋Š” ๊ด€์ ˆ์— ์ž‘์šฉํ•˜๋Š” force์™€ torque๋ฅผ visualizationํ•˜๋Š”๊ฒƒ์„ ๋ณด์—ฌ์ค„ ๊ฒƒ์ด๋‹ค.

<topic>

force/torque ์„ผ์„œ๋Š” ํ˜„์žฌ ์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์›ํ•˜์ง€ ํ•ž๋Š”๋‹ค.

<frame>

force/torque ์„ผ์„œ๋Š” ํ˜„์žฌ ์ด ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์ง€์›ํ•˜์ง€ ํ•ž๋Š”๋‹ค.

<pose>

๊ณต๊ฐ„์ƒ์—์„œ 'x y z roll pitch yaw (position + orientation)'์˜ ์ˆœ์„œ์˜ Floating point number ์˜๋ฏธํ•œ๋‹ค. ์ด๊ฒƒ์€ parent joint๋กœ๋ถ€ํ„ฐ ์„ผ์„œ frame์„ ๋ฌ˜์‚ฌํ•œ๋‹ค.

Force/Torque specific parameters

force/torque sensor๋Š” <sensor> tag with the attribute type set to force_torque๋ฅผ ์ถ”๊ฐ€ํ•จ์œผ๋กœ์จ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค. ์•„๋ž˜์—๋Š” ์œ„ ๋ฐฉ๋ฒ• ์™ธ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด 2๊ฐ€์ง€ ๋” ์ œ์‹œ๋˜์–ด์žˆ๋‹ค.

<sensor name="my_cool_sensor" type="force_torque">
  <force_torque>
    <frame>child</frame>
    <measure_direction>child_to_parent</measure_direction>
  </force_torque>
</sensor>

<frame>

The value of this element may be one of: child, parent, or sensor. It is the frame in which the forces and torques should be expressed. The values parent and child refer to the parent or child links of the joint. The value sensor means the measurement is rotated by the rotation component of the <pose> of this sensor. The translation component of the pose has no effect on the measurement.

Regardless of this setting, the torque component is always expressed about the origin of the joint frame.

<measure_direction>

This is the direction of the measurement. Try changing the example above to parent_to_child. After being toppled the sensor reports a force of -98 N on the Y axis and a torque of +147 Nm about the X axis. This is the same magnitude as before but opposite direction.

Adding a force/torque sensor to a link

While the SDF schema allows a <sensor> tag to be placed on either a link or a joint, the force/torque sensor only works on joints. If the sensor is added to a link, running gazebo with --verbose shows the following error:

[Err] [Link.cc:114] A link cannot load a [force_torque] sensor.

Modeling a Real Force/Torque Sensor

The above example places a force/torque sensor on a revolute joint. However, real force/torque sensors are typically rigidly mounted to another rigid body. A real sensor could not measure the force and torque exactly at the revolute joint origin. Modeling this way is reasonable if the real sensor is close enough to the joint that the error from the offset is negligible.

If this error is not negligible, the rigid body can be split into two links with a fixed joint at the location of the real sensor.

โš ๏ธ **GitHub.com Fallback** โš ๏ธ