Proxy Robot Model

The proxy robot model is a simplification of the wobbly two-wheeled robot intended for displaying the position of a remote robot using the delegate robot model. The body has no actuators, sensors, or physics. It does participate in collisions, acting like a fixed rigid body.

The model appears in the ‘party’ project available as a zip file party.zip.

../_images/proxy-sim.jpg

Screenshot of Webots model of a diff-drive ‘proxy’ robot.

proxy.proto

The robot model has been encapsulated in a .proto file for easy reuse. The model includes user-accessible scaling and color parameters.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
#VRML_SIM R2020b utf8
# Proxy robot body to represent a remote robot, based on the wobbly robot body.
# This robot has no physics but is positioned by a delegate in response to
# position data reported over the network.
# documentation url: https://courses.ideate.cmu.edu/16-375
# license: No copyright, 2020 Garth Zeglin.  This file is explicitly placed in the public domain.
PROTO proxy [
  field SFVec3f    translation  0 0 0
  field SFRotation rotation     0 1 0 0
  field SFString   controller   ""
  field SFString   name         "proxy"
  field SFFloat    wheelRadius  0.1
  field SFFloat    axleLength   0.14
  field SFColor    bodyColor    0.8 0.8 0.8
  field SFColor    wheelColor   0.3 0.3 0.3
  field SFString   customData   ""
]
{
  Robot {
    # connect properties to user-visible data fields
    translation IS translation
    rotation IS rotation
    controller IS controller
    name IS name
    customData IS customData

    # calculate derived parameters
    %{
      local counterweightHeight = fields.wheelRadius.value
      local counterweightOffset = 0.75*fields.wheelRadius.value
      local counterweightTop    = 1.25*fields.wheelRadius.value
      local sensorHeight        = 3*fields.wheelRadius.value
      local stalkHeight         = sensorHeight - counterweightTop
      local stalkOffset         = counterweightTop + 0.5*stalkHeight
    }%

    children [
      # The body group contains three cylinders: the massive counterweight at
      # bottom, a thin stalk rising above it, topped by the sensor disc.
      # All these shapes participate in collision; the axle is kept separate
      # as it is just for rendering.
      DEF bodyShape Group {
        children [
          # counterweight
          Transform {
            translation 0 0 %{= counterweightOffset }%
            rotation 1 0 0 1.5708
            children [
              Shape {
                appearance DEF bodyAppearance PBRAppearance {
                  baseColor IS bodyColor
                  roughness 0.5
                  metalness 0.5
                }

                geometry Cylinder {
                  height %{= counterweightHeight }%
                  radius 0.05
                }
              }
            ]
          }
  	  # sensor disc
          Transform {
            translation 0 0 %{= sensorHeight }%
            rotation 1 0 0 1.5708
            children [
              Shape {
                appearance USE bodyAppearance
                geometry Cylinder {
                  height 0.01
                  radius 0.025
                }
              }
            ]
          }
	  # stalk
          Transform {
            translation 0 0 %{= stalkOffset }%
            rotation 1 0 0 1.5708
            children [
              Shape {
                appearance USE bodyAppearance
                geometry Cylinder {
                  height %{= stalkHeight }%
                  radius 0.01
                }
              }
            ]
          }
        ]
      }
      # Visible axle shape, not part of the boundingObject.
      DEF axleShape Transform {
        translation 0 0 %{= fields.wheelRadius.value }%
        children [
          Shape {
            appearance USE bodyAppearance
            geometry Cylinder {
              height %{= fields.axleLength.value + 0.02 }%
              radius 0.005
            }
          }
        ]
      }
      # Define the left wheel axis, pointing in the +Y direction along the axle.
      HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 1 0
          anchor 0 0 %{= fields.wheelRadius.value }%
        }
	# Define the left wheel solid, offset along +Y along the axle.
        endPoint DEF leftWheel Solid {
          translation 0 %{= 0.5*fields.axleLength.value }% %{= fields.wheelRadius.value }%
          rotation 0 -1 0 0
          children [
            # Define the left wheel shape and appearance, which is used by the right wheel solid.
            DEF wheelShape Transform {
              rotation 0 0 1 0
              children [
                Shape {
                  appearance PBRAppearance {
                    baseColor IS wheelColor
                    roughness 0.5
                    metalness 0.5
                  }
                  geometry Cylinder {
                    height 0.01
                    radius %{= fields.wheelRadius.value }%
                  }
                }
              ]
            }
          ]
          name "left wheel"
          boundingObject USE wheelShape
        }
      }
      # Define the right wheel axis, also pointing in the +Y direction along the axle
      # so positive wheel rotations will move forward.
      HingeJoint {
        jointParameters HingeJointParameters {
          axis 0 1 0
          anchor 0 0 %{= fields.wheelRadius.value }%
        }
	# Define the right wheel solid, offset along -Y along the axle.
	# The wheel shape is inherited from the left wheel.
        endPoint DEF rightWheel Solid {
          translation 0 %{= -0.5*fields.axleLength.value }% %{= fields.wheelRadius.value }%
          rotation 0 0 1 3.14159
          children [
            USE wheelShape
          ]
          name "right wheel"
          boundingObject USE wheelShape
        }
      }
    ] # close children list of Robot
    boundingObject USE bodyShape
  } # close Robot
}