Suitcase Robot Model

The suitcase robot model simulates a testbed for mounting actuation inside a suitcase. It corresponds closely to the physical prototype. It is intended as a basis for exploring hardware to add into the suitcase.

This model is demonstrated in the suitcase-demo.wbt world.

This model makes use of several objects defined in proto files: suitcase.proto, suitcase-actuators.proto, pedestal.proto, and ball_array.proto. These make use of embedded Lua scripting to parametrically generate world objects.

../_images/suitcase-demo.png

Screenshot of Webots model of actuated suitcase sitting on a gallery pedestal.

Sample Performance Script

 1# script.py
 2# Sample abstract performance script for operating the suitcase and lighting hardware on either
 3# the Webots simulation or the physical hardware.
 4# No copyright, 2023, Garth Zeglin.  This file is explicitly placed in the public domain.
 5
 6print("loading script.py...")
 7
 8# Standard Python imports.
 9import math, random
10
11# Define the abstract performance interface.
12from performance import Performance
13
14# Define an abstract performance controller which can run either the Webots simulation or a physical machine.
15class SuitcasePerformance(Performance):
16    def __init__(self):
17
18        # Initialize the superclass which implements the abstract robot interface.
19        super().__init__()
20
21        # Initialize the controller state machine
22        self.last_t = 0.0
23        self.event_timer = 0.0
24        self.state_index = 'rest'
25
26    # Entry point for periodic updates.
27    def poll(self, t):
28        dt = t - self.last_t
29        self.last_t = t
30
31        # Change the target velocity in a cycle with a two-second period.
32        self.event_timer -= dt
33        if self.event_timer < 0:
34            if self.state_index == 'rest':
35                self.set_spotlight('right', 1.0)
36                self.set_spotlight('left', 0.0)
37                self.state_index = 'moving'
38                self.event_timer += 1.5
39                for j in range(self.num_motors):
40                    pos = math.pi * (1 - 2*random.random())
41                    self.set_motor_target(j, pos)
42
43            else:
44                self.state_index = 'rest'
45                self.set_spotlight('right', 0.0)
46                self.set_spotlight('left', 1.0)
47                self.event_timer += 0.5
48                for j in range(self.num_motors):
49                    self.set_motor_target(j, 0)
50
51            print(f"Switched to state {self.state_index}")

Abstract Performance Interface

 1# performance.py
 2
 3# Abstract performance interface for operating the suitcase and lighting hardware on either
 4# the Webots simulation or the physical hardware.
 5
 6# No copyright, 2023, Garth Zeglin.  This file is explicitly placed in the public domain.
 7
 8print("loading performance.py...")
 9
10# Standard Python imports.
11import math, random
12
13################################################################
14# Define the superclass for controller objects which can drive either a Webots
15# simulation or a physical machine.
16
17class Performance:
18    def __init__(self):
19        self.lights = {'left' : 1.0, 'right' : 1.0 }
20        self.num_motors = 4
21        self.target = [0, 0, 0, 0]
22
23    def set_spotlight(self, name, intensity):
24        self.lights[name] = intensity
25
26    def set_motor_target(self, motornum, pos):
27        self.target[motornum] = pos
28
29    # Entry point for periodic updates.
30    def poll(self, t):
31        pass

Webots Robot Controller

 1# suitcase.py
 2#
 3# Sample Webots controller file for driving the four-motor suitcase actuator insert.
 4# The robot also includes two controllable spotlights.
 5# No copyright, 2021-2023, Garth Zeglin.  This file is explicitly placed in the public domain.
 6
 7print("loading suitcase.py...")
 8
 9# Import the Webots simulator API.
10from controller import Robot
11
12# Define the time step in milliseconds between controller updates.
13EVENT_LOOP_DT = 50
14
15# Load the abstract performance script which will drive this simulated show.
16import script
17
18################################################################
19# The sample controller is defined as an class which is then instanced as a
20# singleton control object.  This is conventional Python practice and also
21# simplifies the implementation of the interface which connects this
22# code to physical hardware.
23
24class Suitcase(Robot):
25    def __init__(self):
26
27        # Initialize the superclass which implements the Robot API.
28        super().__init__()
29
30        robot_name = self.getName()
31        print("%s: controller connected." % (robot_name))
32
33        # Fetch handle for the four stepper motors.
34        j1 = self.getDevice('motor1')
35        j2 = self.getDevice('motor2')
36        j3 = self.getDevice('motor3')
37        j4 = self.getDevice('motor4')
38
39        # Convenience list of all actuators.
40        self.motors = [j1, j2, j3, j4]
41
42        # Connect to the spotlights.
43        self.right_spotlight = self.getDevice('right_spotlight')
44        self.right_spotlight.set(255)
45        self.left_spotlight = self.getDevice('left_spotlight')
46        self.left_spotlight.set(255)
47
48        # Current light state used for smoothing changes.
49        self.spot_intensity = [0.0, 0.0]
50
51        # Create the abstract controller object implementing the performance.
52        self.controller = script.SuitcasePerformance()
53
54        return
55
56    def run(self):
57        # Run loop to execute a periodic script until the simulation quits.
58        # If the controller returns -1, the simulator is quitting.
59
60        while self.step(EVENT_LOOP_DT) != -1:
61            # Read simulator clock time.
62            t = self.getTime()
63
64            # Update the controller object.
65            self.controller.poll(t)
66
67            # Apply output values to the simulated hardware.
68            for motor, pos in zip(self.motors, self.controller.target):
69                motor.setPosition(pos)
70
71            self.spot_intensity[0] += 0.2 * (self.controller.lights['left'] - self.spot_intensity[0])
72            self.spot_intensity[1] += 0.2 * (self.controller.lights['right'] - self.spot_intensity[1])
73            self.left_spotlight.set(int(255 * self.spot_intensity[0]))
74            self.right_spotlight.set(int(255 * self.spot_intensity[1]))
75
76
77################################################################
78# If running directly from Webots as a script, the following will begin execution.
79# This will have no effect when this file is imported as a module.
80if __name__ == "__main__":
81    robot = Suitcase()
82    robot.run()

Suitcase Actuators Proto

  1#VRML_SIM R2023b utf8
  2# documentation url: https://courses.ideate.cmu.edu/16-375
  3# Four actuators mounted to a block intended to fit inside the suitcase body.
  4# The visible actuator geometry is defined using STL files.
  5# license: No copyright, 2021-2023 Garth Zeglin.  This file is explicitly placed in the public domain.
  6
  7PROTO suitcase-actuators [
  8  field SFVec3f    translation          0 0 0
  9  field SFRotation rotation             1 0 0 0
 10  field SFString   name                 "actuators"
 11  field SFString   controller           "suitcase"
 12  field SFColor    baseColor            0.21529 0.543008 0.99855
 13  field SFString   contactMaterial      "default"
 14]
 15{
 16  Robot {
 17    # connect properties to user-visible data fields
 18    translation IS translation
 19    rotation IS rotation
 20    name IS name    
 21    controller IS controller    
 22    contactMaterial IS contactMaterial
 23    
 24    children [
 25      # define a box to represent the base surface and motor housing block
 26      DEF baseObject Transform {
 27        translation 0.0045 0 0.04
 28        children [
 29          Shape {
 30            appearance PBRAppearance {
 31              baseColor IS baseColor
 32              metalness 0
 33            }
 34            geometry Box {
 35              size 0.296 0.438 0.064
 36            }
 37          }
 38        ]
 39      }
 40      # wrap the motor1 definitions within a translated coordinate frame
 41      Pose {
 42        translation -0.0695 -0.1095 0.072
 43        children [
 44          HingeJoint {
 45            jointParameters HingeJointParameters {
 46              axis 0 0 1
 47            }
 48            device [
 49              RotationalMotor {
 50                name "motor1"
 51                maxVelocity 5
 52                maxTorque 1
 53              }
 54            ]
 55            endPoint Solid {
 56              translation 0 0 0.01
 57              children [
 58                # define the disc used for physics and collision
 59                DEF actuator1Disc Pose {
 60                  rotation 1 0 0 0
 61                  children [
 62                    Shape {
 63                      appearance DEF woodAppearance PBRAppearance {
 64                        baseColor 0.992157 0.893126 0.601785
 65                        metalness 0
 66                        roughness 0.5
 67                      }
 68                      geometry DEF actuatorDisc Cylinder {
 69                        height 0.006
 70                        radius 0.025
 71                      }
 72                    }
 73                  ]
 74                }
 75                # define the visible object on top of the disc
 76                DEF actuatorObject Pose {
 77                  translation -0.003 0 0.018
 78                  children [
 79                    Shape {
 80                      appearance USE woodAppearance
 81                      geometry DEF tagGeometry Mesh {
 82                        url [
 83                           "../stl/tag375.stl"
 84                        ]
 85                      }
 86                    }
 87                  ]
 88                }
 89              ]
 90              name "link1"
 91              boundingObject USE actuator1Disc
 92              physics DEF actuatorPhysics Physics {
 93                density -1
 94                mass 0.2
 95              }
 96            }
 97          }
 98        ]
 99      }
100      Pose {
101        translation -0.0695 0.1095 0.072
102        children [
103          HingeJoint {
104            jointParameters HingeJointParameters {
105              axis 0 0 1
106            }
107            device [
108              RotationalMotor {
109                name "motor2"
110                maxVelocity 5
111                maxTorque 1
112              }
113            ]
114            endPoint Solid {
115              translation 0 0 0.01
116              children [
117                DEF actuator2Disc Pose {
118                  rotation 1 0 0 0
119                  children [
120                    Shape {
121                      appearance USE woodAppearance
122                      geometry USE actuatorDisc
123                    }
124                  ]
125                }
126		USE actuatorObject		
127              ]
128              name "link2"
129              boundingObject USE actuator2Disc
130              physics USE actuatorPhysics
131            }
132          }
133        ]
134      }
135      Pose {
136        translation 0.0785 -0.1095 0.072
137        children [
138          HingeJoint {
139            jointParameters HingeJointParameters {
140              axis 0 0 1
141            }
142            device [
143              RotationalMotor {
144                name "motor3"
145                maxVelocity 5
146                maxTorque 1
147              }
148            ]
149            endPoint Solid {
150              translation 0 0 0.01
151              children [
152                DEF actuator3Disc Pose {
153                  rotation 1 0 0 0
154                  children [
155                    Shape {
156                      appearance USE woodAppearance
157                      geometry USE actuatorDisc               
158                    }
159                  ]
160                }
161		USE actuatorObject		
162              ]
163              name "link3"
164              boundingObject USE actuator3Disc
165              physics USE actuatorPhysics	      
166            }
167          }
168        ]
169      }
170      Pose {
171        translation 0.0785 0.1095 0.072
172        children [
173          HingeJoint {
174            jointParameters HingeJointParameters {
175              axis 0 0 1
176            }
177            device [
178              RotationalMotor {
179                name "motor4"
180                maxVelocity 5
181                maxTorque 1
182              }
183            ]
184            endPoint Solid {
185              translation 0 0 0.01
186              children [
187                DEF actuator4Disc Pose {
188                  rotation 1 0 0 0
189                  children [
190                    Shape {
191                      appearance USE woodAppearance
192                      geometry USE actuatorDisc                               
193                    }
194                  ]
195                }
196		USE actuatorObject
197              ]
198              name "link4"
199              boundingObject USE actuator4Disc
200              physics USE actuatorPhysics	      	      
201            }
202          }
203        ]
204      }
205      # define first controlled spotlight
206      LED {
207        name "right_spotlight"
208        color [ 1 1 1 ]
209        gradual TRUE
210        children [
211	  SpotLight { 
212	    attenuation 0 0 1
213	    beamWidth 0.3
214	    cutOffAngle 0.4
215	    direction -1 -2 -1
216	    intensity 5
217	    location 1.0 1.5 1.0
218	    castShadows TRUE
219          }
220        ]
221      }
222      # define controlled spotlight
223      LED {
224        name "left_spotlight"
225        color [ 1 1 1 ]
226        gradual TRUE
227        children [
228	  SpotLight { 
229	    attenuation 0 0 1
230	    beamWidth 0.3
231	    cutOffAngle 0.4
232	    direction -1 2 -1
233	    intensity 5
234	    location 1.0 -1.5 1.0
235	    castShadows TRUE
236          }
237        ]
238      }
239    ] # close children of Robot
240    boundingObject USE baseObject
241    physics Physics {
242    }
243  } # close Robot
244}