Playing with the Player Project
So far, our robot is awake, alert and ready to be told to do something interesting. Let's give it something to do. The CoroBot robot comes with a number of sensors and actuators—probably the easiest of which to interface with are the front- and rear-facing infrared ranging sensors and the mobility base's drive motors. Thus, we can write a small C program to talk to the Player server, read the IR sensors and drive the robot until it is 10cm away from an obstacle in front of the robot.
The first thing we have to do to interface with the Player server is open up a connection to it. For the sake of brevity, we will skip a lot of error checking, but you can download the full version of the code from the LJ FTP server (see Resources).
This code defines the variables we will use to talk to the Player server and the device interfaces in which we are interested:
#include "libplayerc/playerc.h" static playerc_client_t* clientHandle; static playerc_position2d_t* positionProxy; static playerc_ir_t* irProxy;
The clientHandle is used for talking to the Player server itself. The second position2d interface talks to the position2d interface, providing us with encoder information about how the wheels are moving and allowing us to send motor commands to the robot. We'll ignore the encoder information for this example. Lastly, the IR interface gives us information about the distances that the robot's IR sensors are reporting.
The next code snippet uses these proxies to interface with the server and these devices:
playerc_client_connect(clientHandle);
// convert our interface to a PULL interface,
// only updates when we read
playerc_client_datamode(clientHandle, PLAYER_DATAMODE_PULL);
// tell the robot to drop older messages
playerc_client_set_replace_rule(
clientHandle, -1, -1, PLAYER_MSGTYPE_DATA, -1, 1);
// create the position proxy (controls the motors)
positionProxy = playerc_position2d_create(clientHandle, 0);
playerc_position2d_subscribe(positionProxy, PLAYER_OPEN_MODE);
// create the IR proxy (controls the IRs)
irProxy = playerc_ir_create(clientHandle, 0);
playerc_ir_subscribe(irProxy, PLAYER_OPEN_MODE);
We start off by connecting to the Player server and configuring our connection. We want to get new messages from the server only when we are ready for them, so we configure the connection for a pull-type arrangement. And, because we want only the most recent information (we don't care what the IR sensors were indicating a second ago, we care about what they are saying right now), we tell the server to report only the most recent data. If we really wanted, we could let Player ensure that every IR message was delivered, but that might result in getting less-than-fresh data and possibly driving into a wall.
After our connection is configured, we open up the position2d interface on the Player server and subscribe to it. Then, we do the same with the IR interface. So far, so good. Now we need to get the state of the IRs from the robot and tell it how to move the motors:
while (!timeToQuit) {
// attempt to read from the client
if (playerc_client_read(clientHandle) == 0)
continue; // nothing to read, try again.
// read the IR distances and verify we have good data
if (irProxy->data.ranges_count == 2) {
frontIr = irProxy->data.ranges[0];
rearIr = irProxy->data.ranges[1];
}
// figure out how to drive
runController(frontIr, rearIr,
&desiredTranslation,&desiredRotation);
playerc_position2d_set_cmd_vel(
positionProxy, desiredTranslation,
0, desiredRotation, 1);
}
Each time through the loop, we try to read the newest data from the robot. After a little sanity checking, we take the ranges reported by the IR sensors and feed them into a controller function. This controller does some magic processing (we'll talk about that later) and returns information on how we should drive the robot. Finally, we pass these driving commands back to the Player server and start it all over again.
All that's left now is to provide a runController function that maps from IR sensor readings to drive commands. The CoroBot driver accepts numbers in the range of –1.0 to +1.0 to tell how to drive the robot forward and backward: +1.0 means 100% power forward, –1.0 means 100% power in reverse, and 0.0 means stop. It accepts the same range for telling the robot how to turn: –1.0 means turn full power left, +1.0 means turn full power right, and 0.0 means drive straight ahead. Noting that the IR readings are provided in meters, we can use the following P-controller to drive our robot forward until we are 10cm away from a front obstacle. We even get a bonus for free—if we are closer than 10cm away, the robot will back up a bit until it is at the proper distance:
void runController(double frontIr, double rearIr,
double *translation,double *rotation)
{
// convert our IR readings into drive commands
*translation = (frontIr-0.1) * 3.0;
*translation = *translation > 0.9? 0.9: *translation;
*rotation = 0.0;
}
And finally, good programmers always shut down their server connections when they are done:
void shutDownProxies()
{
// close down proxies we have opened
playerc_ir_unsubscribe(irProxy);
playerc_ir_destroy(irProxy);
playerc_position2d_unsubscribe(positionProxy);
playerc_position2d_destroy(positionProxy);
playerc_client_disconnect(clientHandle);
playerc_client_destroy(clientHandle);
}
Building on the design we showed earlier, we can see how our drive-by-IR program interacts with the Player infrastructure. The CoroBot configuration file loads the phidgetIFK driver, which exposes an aio:0 device. This device allows the CoroBot driver to read the robot's onboard infrared sensors. The CoroBot driver also exposes the position2d and IR interfaces, which the drive-by-IR program reads with the help of the libplayerc library (Figure 5).

Figure 5. The Relationship between Several Devices and Interfaces When Using the Drive-by-IR Program
The Player Project offers a lot of functionality that there just isn't room to get into in one article. This includes robot simulation, support for numerous commercial robots of many different prices and qualities, and support for a whole slew of readily available devices. Its plugin system even allows you to build your own drivers for new devices, either to support new hardware or to implement new experimental algorithms. Give it a try, and give your computer a chance to stretch its legs.
Today’s modular x86 servers are compute-centric, designed as a least common denominator to support a wide range of IT workloads. Those generic, virtualized IT workloads have much different resource optimization requirements than hyperscale and cloud applications. They have resulted in a “one size fits all” enterprise IT architecture that is not optimized for a specific set of IT workloads, and especially not emerging hyperscale workloads, such as web applications, big data, and object storage. In this report, you will learn how shifting the focus from traditional compute-centric IT architectures to an innovative disaggregated fabric-based architecture can optimize and scale your data center.
Sponsored by AMD
Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6
Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.
Learn more about catching the bad guy in this free white paper.
Sponsored by DLT Solutions
| Making Linux and Android Get Along (It's Not as Hard as It Sounds) | May 16, 2013 |
| Drupal Is a Framework: Why Everyone Needs to Understand This | May 15, 2013 |
| Home, My Backup Data Center | May 13, 2013 |
| Non-Linux FOSS: Seashore | May 10, 2013 |
| Trying to Tame the Tablet | May 08, 2013 |
| Dart: a New Web Programming Experience | May 07, 2013 |
- RSS Feeds
- New Products
- Making Linux and Android Get Along (It's Not as Hard as It Sounds)
- Drupal Is a Framework: Why Everyone Needs to Understand This
- A Topic for Discussion - Open Source Feature-Richness?
- Home, My Backup Data Center
- Developer Poll
- Dart: a New Web Programming Experience
- May 2013 Issue of Linux Journal: Raspberry Pi
- What's the tweeting protocol?




16 min 31 sec ago
1 hour 3 min ago
2 hours 37 min ago
4 hours 13 min ago
6 hours 11 min ago
6 hours 28 min ago
6 hours 58 min ago
6 hours 59 min ago
7 hours 1 sec ago
10 hours 35 sec ago