Archives for category: Robotics

The Radxa Rock Pro, running the Linaro (ubuntu) 14.04 Server image, provides access to the serial console. This can be very handy for troubleshooting if the device isn’t connected to a network.

In order to use the SparkFun FTDI Basic USB-to-serial, you’ll need some jumper wires, in addition to the FTDI device.

DO NOT CONNECT the FTDI 3.3V to the Radxa Rock.

Using the jumpers (because the pins are arranged on the SparkFun device in a different order than on the Rock Pro) connect the three as follows:

FTDI Basic      Rock Pro

Gnd                  GND

TXD                  RX

RXI                    TX

You can then use a Linux terminal emulation program, such as minicom. Set the data rate to 115,200, the protocol to 8, None and 1 and disable hardware flow control. You may have to press the Enter key  when you first connect. If you send a BREAK condition, you’ll enter the FIQ debugger mode. Type “console” and you’ll leave the debugger mode.

Advertisements

Recently, I wanted to play with the latest build of MeeGo on my Nokia N900. I also wanted to try it on a PandaBoard borrowed from a friend. To do that, I needed a better (greater capacity and higher write speed) microSD card than any I had in my collection. That need caused me to learn more about microSD memory cards. The results of learning about microSD and the speed classification were somewhat disappointing.

According to this article on Wikipedia, a Class 10 SD device is supposed to provide a minimum of 10 Megabytes per second in sequential write throughput. What I found is that, in reality, SD Class ratings are on a par with the claims of used car sales.

In order to try and objectively establish the actual throughput of various microSD cards, I needed some software tools. I’ve used two so far. ubuntu distributions include the Disk Utility, which will measure disk speeds. I believe the tool will only measure sequential writes, not random writes. It also doesn’t allow for any configuration of the testing characteristics, such as block size or file size or number of testing threads.

I also used the Linux utility fio. This is a much more comprehensive and capable tool, allowing you to configure essentially every aspect of its operation.

Using both of these tools with the first microSD card I bought for this new project, I was sorely disappointed. I bought a new Lexar 8 gigabyte microSDHC Class 10 card. The Class 10 states that the card is supposed to be capable of a minimum of 10 megabytes per second in sequential write throughput. My test results indicated otherwise.

Using both the ubuntu Disk Utility and fio, the best I was able to achieve was less than 3 megabytes for sequential write throughput. Using fio to execute a random write test, I learned that this Lexar card wasn’t capable of even one megabyte per second for a random write.

Now, I’m on the hunt for microSD cards with at least 8 gigabytes capacity, which will give me at least 5 gigabytes of throughput for random writes.

I firmly believe that every job is easier with the proper tool. Often times, when troubleshooting an issue with one of my hobby robotics projects, the proper tool is an oscilloscope. However, my hobbyist budget doesn’t allow for the purchase of a full-feature benchtop digital ‘scope. I also don’t use it often enough to justify spending a lot of money on a ‘scope. Admittedly, I also don’t know enough about all of the intricate details of fully utilizing all of the capabilities of a ‘scope. Therefore, the best solution for me is one of the many brands of inexpensive ‘scopes which rely on a PC (usually a notebook) for the display and the data capture. Through my employer I was able to get my hands on a BitScope. In this article I’d like to describe the ‘scope and my experience with it.

First off, the BitScope is shipped from Australia so they don’t generally show up overnight, just in case you require instant gratification from your electronics purchases. This ‘scope arrived in about a week, none the worse for wear.

The reason I selected this particular ‘scope was, first and foremost, because it’s officially supported in both the Linux and the Windows environments. I’m a Linux user but my employer is an all-Windows shop.

I ordered a model BS325. The back of the unit I received appears in this photo:

Image

This brought me to the first wrinkle. The sticker makes it seem like I received a BS326N. I extracted the board from the metal case (which is very easy to do and a nice part of the design) and looked closely at the board itself.

Image

The board is clearly labeled “BS325N” but the sticker on one of the modules clearly states “BS326N”. At this point I assumed those two model numbers are equivalent.

As I mentioned earlier, this unit only has an Ethernet interface. BitScope also includes a crossover cable, for a direct connection between the ‘scope and my notebook computer. Herein I encountered the next wrinkle.

I attached the crossover cable to the ‘scope and my Windows notebook. The Data LED lit solid but not the Link LED. I moved the cable to my Linux notebook but saw the same behavior. Through some more experimentation, I’ve since determined that the labels on the LEDs are switched: The LED labeled “Data” is actually the “Link” LED. Again, not really a big deal.

The next thing to do was to actually configure and try the software. BitScope includes a CD with the software for Linux, Macintosh and Windows. Seeing this warmed my heart. I installed the software on my Windows notebook and my Linux notebook. Then I attempted to connect the software to the ‘scope. Yes, next wrinkle.

The page in the included paper manual looks like this:

Image

Since I had ordered a BS325N, the board said BS325N and the stickers said BS326N, I assumed I should use the factory IP address for the BS325N. Nope. The IP address actually assigned to the ‘scope was 192.168.1.73, the one listed for the BS310N. Once again, not a big deal.

I did manage to start the software, connect it to the ‘scope and query the ‘scope. The Windows software identifies the ‘scope as a “BS032600”, by the way. I made a few simple tests and played with the software a bit. I tried the same simple tests on my Linux notebook, but the bitscope-dso software complains and then aborts.

I’m still satisfied with the ‘scope and happy to have it. Obviously, their manufacturing quality control needs some improvement but it’s not keeping me from using the tool. I had also contacted BitScope Technical Support when I was looking at the lack of Link issue. It took them almost two days to respond and I was disappointed to receive the all-too-common Technical Support response. Essentially, I was told “This is almost certainly your problem. Check your firewall and network configuration”. The Technical Support staff apparently either didn’t read my note or doesn’t understand networking issues.

Next, I plan to use the ‘scope to troubleshoot some actual conditions in my lab. I’ll provide some more details on how the device worked for me.

Covariance matrices are a way of describing the relation between a collection of variables. A single covariance value describes the relation between two variables. They are a tool for estimating the possible error in a numerical value and for predicting a numerical value. One of their several applications is in robotics sensor fusion with “regular” and “extended” Kalman filters. In this article I’ll describe how to interpret a covariance matrix and provide a practical example. I’ll leave the formal mathematical and general definition to someone better at that than me.

Let’s begin with the concept of “variance” of a numerical value. That’s the amount by which that value can be expected to vary. For example, if we were to measure the outdoor air temperature with a digital electronic sensor, we may want to know the maximum amount of error to expect in that measurement. That possible amount of error is called the variance and it’s described as a single value. Variance is always positive. For a more in-depth description of variance, please see http://en.wikipedia.org/wiki/Variance.

For the rest of this article I’ll use the terms “value” and “variable” interchangeably. I suppose we could think of a “value” as the current value of a particular “variable”.

Now imagine that there are several properties or conditions or states being measured at the same time and that we’d like to know if there is any relationship between those values. If we could predict in advance how each variable changes, relative to every other variable, that would give us two useful things. First, it would allow us to better identify (and eliminate) outlier values, where one particular value has changed so much that it’s probably not a good measurement. And second, if at one time a measured value was missed, it might be possible to predict what the value should be, based on how all of the other values to which it’s related have changed.

To proceed from a single variance to the idea of covariance and a collection of covariances contained in a matrix, we’ll need an understanding of covariance. Instead of expressing the expected range of possible change in one variable, a covariance expresses the correlation between a change in one variable and a change in another variable. For a much more in-depth explanation, see http://en.wikipedia.org/wiki/Covariance.

To illustrate, we’ll need a more complicated example. Let’s assume we have a mobile robot which can measure both its current position and its orientation. Since this robot can’t levitate or swim we’ll simplify the position and use only the two dimensional X-Y plane. That means the robot’s current position can be adequately described as a position along the X axis and a position along the Y axis. In other words, the robot’s position can be described as (x, y).

The position describes where the robot is located on the surface, which may be a parking lot or the living room floor or the soccer pitch, but it doesn’t describe in which direction it’s pointed. That information about the current state of the robot is called the orientation and will require one dimension. We’ll call this orientation dimension the yaw. The yaw describes in which direction it’s pointing. It’s worth repeating that this is a simplified way of representing the robot’s position and orientation. A full description would require three position values (x, y and z) and also three orientation values (roll, pitch and yaw). The concepts about to be described will still work with a six-dimensional representation of the robot state (position and orientation). Also, yaw is sometimes identified by the lower case Greek letter theta.

Now that we can describe both the position and the orientation of the robot at any point in time and assume that we can update those descriptions at a reasonably useful and meaningful frequency, we can proceed with the description of a covariance matrix. At each point in time, we’ll be measuring a total of three values: the x and y position and the yaw orientation. We could think of this collection of measurements as a vector with three elements.

We’ll start with two sets of measurements, each of which contains three values. Assume the first measurements were taken at 11:02:03 today and we’ll call that time t1. The second set were taken at 11:02:04 and we’ll call that time t2. We’ll also assume that our measurements are taken once per second. The measurement frequency isn’t as important as consistency in the frequency. Covariance itself doesn’t depend upon time, but the timing will become useful further on in this example.

Covariance is a description of how much change to expect in one variable when some other variable changes by a particular amount and in a particular direction. Using the position and orientation example we’ve started, we’d like to know what to expect of the yaw measurement from time t2 when the change in the y measurement between time t1 and t2 was large in the positive direction. Covariance can tell us to expect a similarly large positive change in yaw when y becomes more positive. It could also predict that yaw would become more negative when y became more positive. Lastly, it could state that there doesn’t appear to be any predictable correlation between a change in yaw and a change in y.

Just in case, let’s try a possibly more intuitive example of a correlation. Our initial example measures the position of the robot, with a corresponding x and y value, every second. Since we have regular position updates; since we know the amount of time between the updates (one second); and since we can calculate the distance between the position at time t1 and the position at time t2, we can now calculate the velocity at time t2. We’ll actually get the speed along the x axis and the speed along the y axis which can be combined into a velocity.

Assume the robot is pointed along the x axis in the positive direction and it’s moving. The regular measurements of the position should show a steadily increasing x value and, at least in a perfect world, an unchanging y value. What would you expect the yaw measurement to be – unchanging or changing? Since the robot is not changing its direction the yaw should not be changing. Put in terms of covariance, a change in the x value with no change in the y value is NOT correlated with a change in the yaw value. On the contrary, if we measured a change in yaw with no directional change in the velocity, we would have to suspect that at least one of those measurements, the yaw or the velocity, is incorrect.

From this basic idea of covariance we can better describe the covariance matrix. The matrix is a convenient way of representing all of the covariance values together. From our robotic example, where we have three values at every time t, we want to be able to state the correlation between one of the three values and all three of the values. You may have expected to compare one value to the other two, so please keep reading.

At time t2, we have a value for x, y and yaw. We want to know how the value of x at time t2 is correlated with the change in x from time t1 to time t2. We then also want to know how the value of x at time t2 is related to the values of y and yaw at time t2. If we repeat this comparison, we’ll have a total of 9 covariances, which means we’ll have a 3×3 covariance matrix associated with a three element vector. More generally, an n value vector will have an n×n covariance matrix. Each of the covariance values in the matrix will represent the covariance between two values in the vector.

The first part of the matrix which we’ll examine more closely is the diagonal values, from (1, 1) to (n, n). Those are the covariances of: x to a change in x; y to a change in y; and yaw to a change in yaw. The rest of the elements of the covariance matrix describe the correlation between a change in one value, x for example, and a different value, y for example. To enumerate all of the elements of the covariance matrix for our example, we’ll use the following:

Vector elements at time t:

1st:  x value

2nd:  y value

3rd:  yaw value

Covariance matrix elements:

1,1  1,2  1,3

2,1  2,2  2,3

3,1  3,2  3,3

where the elements correspond to:

1,1 x to x change covariance

1,2 x to y change covariance

1,3 x to yaw change covariance

2,1 y to x change covariance

2,2 y to y change covariance

2,3 y to yaw change covariance

3,1 yaw to x change covariance

3,2 yaw to y change covariance

3,3 yaw to yaw change covariance

Hopefully, at this point, it’s becoming clearer what the elements of a covariance matrix describe. It may also be revealed that there can be certain elements where a correlation is not expected to exist.

It’s important to remember that certain covariance values are meaningful and others don’t provide any directly useful information. A large, positive covariance implies that a large change in the first value, in one direction, will usually correspond with a similarly large change, in the same direction, in the related value. A large negative covariance implies a corresponding large change but in the opposite direction. Smaller covariance values can imply that there either is no correlation between the changes and the values or that the correlation exists but results in a small change.

A large part of developing robotic systems involves measuring the state of the robot and then executing some action, to change the state of the robot. Because there is usually not an exact correspondence between the action and the desired state and because it’s also usually necessary to measure the new state, some method of control is required. It’s helpful if the control method can take into account all of the current state of the robot, the previous changes to the state and their corresponding effect and the new state. One typical method is called PID control.

PID control is useful when the state of some part of the robot can be measured and represented as a numerical value. The actual value is the difference between the actual measurement, called the process variable, and the desired measurement, called the setpoint. The PID control works to bring the difference between the process variable and the setpoint to zero and keep it there. As an example, assume we have a robot which we wish to move at a constant speed. The speed of the robot is based upon the voltage applied to its drive motors. Apply more voltage and it goes faster, apply less voltage and it goes slower. The challenge arises because the change in voltage is not instantaneous and also because the robot is not always travelling over exactly the same surface and with the same load. Sometimes the same voltage will make it go a bit faster and other times a bit slower.

The PID control attempts to reduce the difference between the process variable and the setpoint by calculating a control value and then applying that control value to the process. In our example, the setpoint is the robot speed wanted, the process variable is the actual, current robot speed and the control value is the voltage to apply.

Proportional Gain

The first part of the PID control is the proportional or P adjustment. This is, perhaps, the simplest part of the PID control and responds in proportion to the difference between process value and setpoint. When that difference is large, the P control produces a large control value. When the difference is small the P control produces a small control value. So, let’s say that the voltage range in this example is from 0 to 12. 0 Volts causes the robot to stop (eventually) and 12 Volts causes it to travel at its top speed (again, eventually). We can then write an equation to calculate the control value, based on the setpoint and the process variable:

ControlValue = [P x (SetPoint – ProcessVariable) x (MaxVoltage – CurrentVoltage)] + CurrentVoltage

The ProcessVariable is the current speed of the robot. The SetPoint is the desired speed. The CurrentVoltage is assumed to be what’s causing the robot to move at its current speed. P is the proportional gain, from the P in PID Control, and is used to determine just how much voltage change is applied to the current state of the robot, in order to move the ProcessVariable closer to the SetPoint.

At this point, what we have is a way to adjust the speed of our robot, which responds proportionally to the difference between the actual speed and the desired speed. In other words, if the actual speed is close to the desired speed, this control method will only make a small adjustment. When the difference is great, a large adjustment will be made. This would seem to be a good thing, until we consider latency, in terms of the delay between measuring the speed and responding to the speed and in terms of the delay between applying a new voltage and reaching the full effect of that new voltage. Because of these possible latencies, the system being controlled can have a tendency to oscillate, above and below the desired speed, and never actually reach the desired speed.

Fortunately, the PID control method can deal with that and it’s specifically the D part of the method which I’ll describe next.

Derivative gain

to be continued …

I’ve been using the ROS tf package for a couple of projects recently. As I tried to visualize the coordinate frames and how they would relate to each other, I found myself a bit short on hand and arm joints. I was making the right-handed rule and couldn’t always get my hand into the needed orientation. Because of that, I wanted to create a way to physically visualize the state of the coordinate frame and simultaneously display it with rviz. By creating something like that, I’d get to practice using the tf package and rviz at the same time.

To begin, I needed a physical representation of the coordinate frame. I had some short pieces of wooden dowel in the shop and plenty of small scrap wood blocks. I made a small, nearly cubicle block and then used the drill press to drill three orthogonal holes, one for each of the X, Y and Z axes. To better match the rviz representation of the coordinate frame, I painted the dowels red, green and blue.

Next, I needed a way to measure the orientation of my physical coordinate frame. I had a Sparkfun Serial Accelerometer Tri-Axis – Dongle in my collection of parts. I attached the accelerometer to another face of the block, so that the accelerometer’s axes were aligned with the wooden dowels. This is the end result:

Now that I had the physical coordinate frame, I had to create a class to read the data from the accelerometer and a ROS publisher node to take that data and publish it as a transformation. In order to simplify the design I made a few assumptions and design decisions. First, this coordinate frame is only rotated – I don’t report any translations. The second assumption is that there aren’t any intermediate stages of rotation but only increments of 90 degrees.

In the process of implementing the classes, I learned more about transformations. First, all coordinate frames are tied together into a tree structure. The tree must have a frame named “world” at the top and there can’t be any loops in the tree (which would make it not a tree). Each frame in the tree specifies its current position and orientation relative to its parent frame. Each frame can have zero or more children but can only have exactly one parent. The “world” frame is a special case in that it has no parent.

The position of a frame relative to its parent is specified with a translation from the parent frame and then a rotation in the parent frame. The translation specifies where the origin of the child frame is, relative to the origin of the parent frame, and is stated in meters along each of the three axes. The rotation describes how the child is rotated about each of the parent’s axes and is given in radians. I used Euler angles where a rotation specifies not only the amount but also the direction. A positive rotation about the X axis rotates from the positive Y axis toward the positive Z axis. For the Y axis rotation, positive is from the Z to the X axis and for the Z it’s from the X to the Y. Since ROS wants to represent rotations using quaternions, I had to use the tf.transformations.quaternion_from_euler() method in my publisher node.

The class which reads from the accelerometer is Accelerometer.py and the class which acts as the transform publishing node is TfDemo.py. Including these two files into an appropriate ROS package, running them and then using rviz, it’s possible to change the rotation of the physical frame and see the result in the rvix display.

Several years ago, I decided to enter a robot in the local Robo-Magellan contest. For those not already familiar, Robo-Magellan is a contest defined by the Seattle Robotics Society. I like to describe the contest to friends as “the DARPA Grand Challenge for hobbyists without a 20 million dollar corporate sponsor”. This has been a long, educational project. Here are some of the details.

Robo-Magellan requires a fully autonomous, mobile rover. I started with a mobile rover which I bought from a friend. It was assembled from salvage components, in a frame made from aluminum angle stock. The drive motors are two power window motors with small lawn mower wheels. The motors are controlled by a pair of MotionMind motor controllers from Solutions Cubed. The motors have shaft encoders and the motor controllers, in addition to driving the motors, include PID control capability and the ability to read the shaft encoders.

For the main logic system, I have an old Dell notebook for which I exchanged a $50 Starbucks card. The display was cracked so I removed it. I used the WiFi interface on the notebook for connectivity during development and I bought a four serial port USB dongle to connect to the sensors and actuators.

I plan to use one of my handheld GPS units for part of the navigation system. Depending on which one, it will either use one of the serial ports or connect directly to the USB. I also have a Sparkfun three axis accelerometer and a Parallax gyroscope. The accelerometer has a serial port and the gyroscope is an SPI device.

Before I learned about the Arduino family of microcontroller packages, I used a bare Atmel AVR ATmega32. I use that AVR to read the gyroscope and to also control a pair of Parallax ultrasonic rangefinders. The rangefinders are mounted on the front of the rover, facing forward, and function as the long range collision avoidance system.

Lastly, there is a cheap Logitech webcam mounted on the forward top of the rover. It will be used for a simple color-tracking vision system, to locate and identify the orange traffic cones on the contest field. It connects directly to the USB.

I plan to write the majority of the control software in Python using ROS. The code for the AVR is written in C. I may switch to the Arduino, to simplify development of that part of the software.

In the next article I’ll describe the high-level design of the ROS components.

I accepted a contract to build a remotely controlled, multi-rover planetary exploration simulation for a museum. I decided to use ROS as the communication and control mechanism and to write the software in Python. This article describes the architecture and implementation of the project.

The purpose of the simulation is to allow the visitor to drive the rover around the simulation, looking for artifacts on the planetary surface. There are three artifacts: gypsum, mud and fossils. When the visitor brings the rover within range of these artifacts, the display on the monitor changes to show the visitor additional information about the artifacts.

The design of the simulation has a control console for the visitor. That console includes a large monitor, which displays streaming video from the rover, status information about the rover and some details about what the visitor has “discovered”. The rovers are deployed in a diorama of a planetary surface and can freely roam about that area. They are wheeled rovers using differential steering and, in addition to the HD webcam facing forward, they include fore and aft IR range sensors, battery voltage sensors and an RFID reader. The RFID reader is mounting very low on the front of the rover and is connected via USB.

At the control console, in addition to the monitor, there is a joystick and four push buttons. The joystick is used to drive the rover around the display. One of the buttons is the “start” button and the other three are associated with the artifacts.

The specific hardware components are:

  • CoroWare Corobot classic rover
  • RedBee RFID reader
  • Phidgets motor controller
  • Phidgets 8/8/8 interface board
  • Logitech HD webcam
  • Phidgets voltage sensor
  • Lithium ferrous phosphate batteries
  • Happ UGCI control with daughter board
  • Joystick and four buttons

The software is decided into two parts, one which runs on the control console and another which runs on the rover. The control console is a desktop computer with a wired network connection. It hosts the ROS name server and parameter server. The rovers are mobile ubuntu computers which are battery-powered and have WiFi network connections. They refer to the control console as the ROS master.

On the rover there are N nodes running. The DriveMotors is a service which accepts requests to move the rover. The RfidReader node publishes messages each time it comes within range of an RFID tag. The RoverState node publishes periodic messages about the charge level of the rover’s batteries.

On the control console, there are two ROS nodes. They are the Control node and the DirectionButtons node. The DirectionButtons node is both a Publisher and a Service. It publishes messages each time the state of the joystick or a button changes. The service accepts messages which request a state change for a button lamp. The Control node is all of a Publisher, a Subscriber and a Service requestor. It subscribes to the RfidReader topic to know when the rover has passed over RFID tags. It subscribes to the DirectionButtons topic to know when the visitor has moved the joystick or presses a button. It subscribes to the RoverState topic to monitor the charge level on the batteries. It makes requests to the DriveMotors service to control the rover motion and it makes requests to the ButtonLamp service in order to light the buttons.

The basic flow of the system is a loop with a 120 second run session and then a 15 second delay between sessions. The visitor drives the rover around the diorama, looking for the artifacts. When an artifact is found, the matching button on the control console is lit and pressins that button will cause descriptive information to be displayed on the monitor. If, while the rover is being driven, the battery voltage drops below a pre-set threshold, the rover operation is suspended and a message is sent via E-mail to the Operators. The Operators will then replace the rover with a spare, which has fully charged batteries.

In the next article I’ll describe some of the challenges I faced with this project.

A summary of what we accomplished at the last Workshop, my
understanding of the same and what we’ll do during the next
Workshop.

We’re working out the details and the implementation for the
coordinate navigation frames for the Robomagellan contest. One of
the uses for those frames is to visually search for and locate
the three orange traffic cones in the contest space. At the start
of the contest, we’ll be given the geographic coordinates of the
three cones, as well as of the finish point.

We’ll establish several coordinate frames, conforming
to the naming conventions and orientations outlined in
http://www.ros.org/reps/rep-0103.html and
http://www.ros.org/reps/rep-0105.html.

First, we’ll have a world fixed frame named “map”. Its origin,
(0, 0, 0), will be located at the most northeast corner of the
contest space. The X axis will be aligned with the northern-most
edge of the space and will increase in a westerly direction. The
Y axis will be aligned with the eastern-most edge of the space
and will increase in a southerly direction. The Z axis will point
upward. For the purposes of the contest, the Z coordinate will
always be zero.

As an interim step, we’ll have a camera which is at a fixed
location in the “map” frame. The camera will have both an “odom”
frame and a “base_link” frame, to be consistent with the camera
mounted on the Robomagellan rover. However, since the camera
won’t move initially (mainly because there is no rover yet), the
pose in the odom frame will not change and the two frames will
A summary of what we accomplished at the last Workshop, my
understanding of the same and what we’ll do during the next
Workshop.

By the way, does anyone have a suggestion for a place where we
can collect all of the documentation and designs and discussions
which we create? I think we need something a bit more searchable
and link-able than a collection of files stored in git.

We’re working out the details and the implementation for the
coordinate navigation frames for the Robomagellan contest. One of
the uses for those frames is to visually search for and locate
the three orange traffic cones in the contest space. At the start
of the contest, we’ll be given the geographic coordinates of the
three cones, as well as of the finish point.

We’ll establish several coordinate frames, conforming
to the naming conventions and orientations outlined in
http://www.ros.org/reps/rep-0103.html and
http://www.ros.org/reps/rep-0105.html.

First, we’ll have a world fixed frame named “map”. Its origin,
(0, 0, 0), will be located at the most northeast corner of the
contest space. The X axis will be aligned with the northern-most
edge of the space and will increase in a westerly direction. The
Y axis will be aligned with the eastern-most edge of the space
and will increase in a southerly direction. The Z axis will point
upward. For the purposes of the contest, the Z coordinate will
always be zero.

As an interim step, we’ll have a camera which is at a fixed
location in the “map” frame. The camera will have both an “odom”
frame and a “base_link” frame, to be consistent with the camera
mounted on the Robomagellan rover. However, since the camera
won’t move initially (mainly because there is no rover yet), the
pose in the odom frame will not change and the two frames will
A summary of what we accomplished at the last Workshop, my
understanding of the same and what we’ll do during the next
Workshop.

By the way, does anyone have a suggestion for a place where we
can collect all of the documentation and designs and discussions
which we create? I think we need something a bit more searchable
and link-able than a collection of files stored in git.

We’re working out the details and the implementation for the
coordinate navigation frames for the Robomagellan contest. One of
the uses for those frames is to visually search for and locate
the three orange traffic cones in the contest space. At the start
of the contest, we’ll be given the geographic coordinates of the
three cones, as well as of the finish point.

We’ll establish several coordinate frames, conforming
to the naming conventions and orientations outlined in
http://www.ros.org/reps/rep-0103.html and
http://www.ros.org/reps/rep-0105.html.

First, we’ll have a world fixed frame named “map”. Its origin,
(0, 0, 0), will be located at the most northeast corner of the
contest space. The X axis will be aligned with the northern-most
edge of the space and will increase in a westerly direction. The
Y axis will be aligned with the eastern-most edge of the space
and will increase in a southerly direction. The Z axis will point
upward. For the purposes of the contest, the Z coordinate will
always be zero.

As an interim step, we’ll have a camera which is at a fixed
location in the “map” frame. The camera will have both an “odom”
frame and a “base_link” frame, to be consistent with the camera
mounted on the Robomagellan rover. However, since the camera
won’t move initially (mainly because there is no rover yet), the
pose in the odom frame will not change and the two frames will
always be equivalent.

From the base_link frame, the pan/tilt camera with which we’re
testing and experimenting will have two more coordinate frames.
The first will be called “pan” and will have its origin at a
fixed location in the base_link frame. While its position will
not change, its pose in the frame will change. Specifically, its
pose will pivot in the XZ plane: the direction of the Y axis will
not change but the direction of the X and Z axes will change.

The second camera coordinate frame will be called “tilt”. Its
pose will pivot in the XY plane: the direction of the X axis will
not change but the direction of the Y and Z axes will change.

The process then will be to identify a “traffic cone” in the
field of view of the camera. The location will have a position in
the XY plane of the tilt coordinate frame (the Z coordinate will
have a constant value, the initial measured distance from the
camera to the “traffic cone”). That position will be transformed
to the pan frame, then to the base_link, to the odom and finally
to the map frame.

The location of the “traffic cone” in the map frame can be
published to any subscriber wanting to locate the traffic cone.
In our first experiment and prototype, that subscriber will be a
second camera, with its own odom, base_link, pan and tilt
coordinate frames. The location in the map frame will be
transformed through all of those frames and eventually used by
the second camera’s pan and tilt mechanism to center the location
in the camera’s field of view.

To do all of this, we must:

  •  define the coordinate frames and their relation to each other
  • define the transformations from a frame to its parent and its
    child(ren)
  • write the nodes:
  • locate the traffic cone in the first tilt frame and publish
    that information in the map frame
  • subscribe to the traffic cone location in the map frame and
    use it to aim the second camera

I finally took the time to figure out how to interact with a USB device connected to a Linux computer. I’m working on a robotics project and needed to control a Happ Fighting UGCI. The UGCI has a joystick and four push buttons. The buttons each have a lamp which can be turned off and on. I needed to be able to control the lamps, as well as read the joystick and button events.

I found the PyUSB package at sourceforge. I also found an electronic version of the book “USB Explained” by Steven McDowell and Martin D. Seyer. I found the book to be very useful. I used version 1.0 of the libusb package and version 1.0 of PyUSB.

In short, what I learned was:

  1. USB devices present usually one but at least one configuration
  2. Each configuration can have one or more interfaces
  3. Each interface has one or more endpoints
  4. An endpoint is either an IN or an OUT endpoint, but not both
  5. A device also has a “control” mechanism

Except for the control mechanism, all of these details can be found with “lsusb -vv”.

The configurations, interfaces and endpoints can be shown with something like:

configurations = []
interfaces = []
endpoints = []
for configuration in device:
configurations.append(configuration)
for interface in configuration:
interfaces.append(interface)
for endpoint in interface:
print “Endpoint: %d, direction: %d” % (
endpoint.bEndpointAddress,
usb.util.endpoint_direction(endpoint.bEndpointAddress)
)
endpoints.append(endpoint)

The exchange of data with the USB device is done using the appropriate endpoint. The endpoints have a specific maximum number of bytes which they can exchange at one time. The configuration of the device, when their operation can be configured, is usually done via the control mechanism, not via an endpoint.

Since I didn’t have detailed documentation for the Happ UGCI device, I used a brute-force approach. The button lamps are set and reset using the “control” mechanism. To find the right parameters to use, I ran the following:

for bmRequestType in range(128):
for bRequest in [1,3,5,7,9,11]:
try:
bytesSent = device.ctrl_transfer(
bmRequestType,
bRequest,
0,
0,
payload,
None
)
print bmRequestType, bRequest, bytesSent
time.sleep(0.1)
except:
pass

What I learned was that, to turn on a button lamp, bmRequestType must be 33 (which signifies “host to device”, “class” and “interface”); bRequest must be 9 (which signifies SET_CONFIGURATION); and the payload must have the bit which corresponds to the button set.