As you saw in the previous section, once you load (or connect to) a robot, the variable robot provides a handle on the robot and its attributes. In Pyro, a robot's properties, sensors, and other devices are accessible through a common abstraction called attributes. Each robot instantiated in a Pyro session has its own set of attributes depending on the type of robot and the number and kind of devices available on the robot. You can view these attributes by clicking on the robot's "View" button in the Pyro console window. For example, if we are connected to a simulated robot in the Pyrobot simulated world, clicking on View might display the following robot attributes:
Reading from the top of the attribute list above, we can see that the robot has 2 built-in devices: light and sonar. Some of the other attributes have specific values associated with them. For example, radius (0.75), stall (0), etc. Thus, the radius of the robot is 0.75 and it is not stalled (a value of 0 or false as opposed to 1 or true). Other attributes of the robot appear as a UNIX-like directory name (for example, light and sonar which are shown as folders). This means that these are aggregate attributes. Actually, the robot itself is an aggregate containing all of the subattributes shown above. You can go ahead and explore the structure of each (sub)aggregate by clicking in the expand slot of the folders. The methods available on each of these aggregates are available in the methods folder. In Python terminology, what you are looking at is the dictionary of each object. This makes every object in the system self documenting. By simply having the view window open, you can examine the specific current values of these attributes, as well as learn their structure (subattributes) and their behaviors (methods). These attributes can then be used in your robot control programs in whatever way you may wish. For example, if you wanted to access the radius of the robot, you could enter the following in the command line:
>>> self.robot.radius 0.75
As it should be the case, several attributes (for example, those corresponding to sensory devices) are read only while others are modifiable. You can also create new attributes, if you wanted. For example, the robot above does not have a name attribute. You could create it by entering (or if were already defined and modifiable):
>>> robot.name = 'C3PO' Ok >>> self.robot.name C3PO
Aggregate attributes are attributes that contain more attributes themselves. Aggregates are generally associated with devices available on a robot. Depending on the kind of device (sonar, laser, infra-red, etc.) the attributes on each device will vary. The attribute robot.builtinDevices contains a list of all the devices available on robot. When you instantiate a robot in Pyro, some of these devices are activated by default while others will be activated by the programmer when needed. Thus, in the above example, the devices light, and sonar are already activated (notice that they are listed as subfolders in the attribute list).
Let us explore the sonar device on a simulated Pioneer robot in a Stage world. Start pyrobot, use the server StageSimulator with the world file room.cfg, and the robot Player6665. To get all the sub-attributes of sonar, we can try the following command:
>>> dir(robot.sonar) ['__doc__', '__getitem__' ... 'updateDevice', 'updateWindow', 'value', 'visible', 'window']
A sonar device has lots of attributes! Some of these are methods, and some are properties. To get a better sense of which of these properties are useful for us you can use the Python builtin program help. You can pass any object to help:
>>> help(robot.sonar) Help on instance of PlayerSonarDevice: <pyrobot.robot.player.PlayerSonarDevice instance>
This attempts to find help on this instance of the sonar device. We would really like help on the code behind the instance. You can do that by getting help on the class of the sonar. That can be accessed in Python using robot.sonar.__class__:
>>> help(robot.sonar.__class__) Help on class PlayerSonarDevice in module pyrobot.robot.player: class PlayerSonarDevice(PlayerDevice) | Method resolution order: | PlayerSonarDevice | PlayerDevice | pyrobot.robot.device.Device | | Methods defined here: | | __init__(self, client) | | __len__(self) | ... | | ---------------------------------------------------------------------- | Properties inherited from pyrobot.robot.device.Device: | | geometry | <get> = getGeometry(self) ... | | value | <get> = getValue(self) | # Properties to make getting all values easy:
While you are typing in the command entry field in Pyro, you may also press the TAB key which will provide additional bits of information on what is possible to complete.
For example, if you were typing in the command field:
and then pressed the TAB key (when your cursor is right after the period and before you hit enter), then you will see something like the following the the message window:
Completion data: ----------------------------------------- active addWidgets() angle() arc count data destroy() distance() geometry getActive() getDeviceData() getDeviceState() getGroupNames() getMaxvalue() getPose() getSensorValue() getVisible() groups index makeWindow() maxvalueraw noise pos radius rawToUnits() rawValue rawunits setActive() setMaxvalue() setPose() setTitle() setVisible() setup() startDevice() state stopDevice() title type units updateDevice() updateWindow() value visible window ----------------------------------------------------------
These are all of the methods and attributes that you can refer to after the period. Let us explore some of these properties and methods.
>>> robot.sonar.type sonar >>> robot.sonar.value [1.577893512115228, 1.9876466568573361, 2.9193383789120246, 2.6569077503698515, 2.5433940728758198, 3.1246711481876299, 2.1186971638104173, 1.5358810231437758, 1.5203534828814835, 0.76560741984948599, 0.53682969476323295, 0.48285799199783824, 0.505026591691631, 0.58749707513599214, 0.77367888648663208, 1.5761551637612889]
The first is obvious, giving us the type of the sonar device. The second one gives us the current readings of all the sonars on the robot. The robot we are illustrating above is a Pioneer2 robot with 16 sonars. Note that it is possible for a single robot to have multiple sonar devices. In this case there is only one sonar device, which is sonar. However, if there were additional sonar devices, they would be referred to by sonar, sonar, and so on.
Start pyrobot, load the StageSimulator, the world room.cfg, and then load the Player6665.py robot. Try out the commands above. Move the robot around so that some of its sonar sensors are close to a wall. Observe the sonar values. Then move the robot to a new location and see how the values have changed. Sonar sensors report an estimated distance to an obstacle. So smaller values indicate a closer obstacle.
The attribute abstraction enables a programmer to access all the features of a robot using a single, uniform interface. This makes short work of sensor intricacies and enables you to focus directly on the robot behavior or the robot task at hand.
In later sections, we will see additional examples of other devices like cameras and other range sensors, such as IRs or lasers. Devices that are available, but not yet activated, can be activated explicitly enabling access to their attributes in a similar fashion. We will see examples of these in later sections as well. For now, it would be a good idea to review the material in this section and make sure that you have tried the features presented here. Since this way of accessing attributes is self-documenting, feel free to explore other attributes that are available.