As the name implies, ROS is not just another library to get familiar with. It is an operating system for robots. That is also quite different to a traditional operating system. As I didn’t want to learn a whole bunch of stuff first, I learn about the concepts and facilities as I move along.
After I modeled the robot arm with a urdf xml file, and it moved in the simlator, I wanted to connect ros to the physical arm. I found some tutorials for rosserial on how to connect to an arduino. So, I adapted these examples to the robot arm. The microcontroller board has many similarities to an arduino, but some things are different. First, I compiled the firmware. I had to copy some files from rosserial_arduino, and modified them accordingly. Hooking up the servos as ros subscribers is actually quite easy. The arduino examples use a standard python script on the computer. It looked as if I could use the same. But the robot arm only runs when the RTS level is high. As most libs and programs don’t do that by default, my robot arm did nothing. So, I copied some scripts from rosserial and modified them. In the process I learned about the statserial program that displays the status of the different serial pins. Now, the arm moved to the initial position and waited. Meanwhile I tried to connect to it with the modified python script, but I still got “Lost sync with device, restarting…”.
Now I really wanted to know what the two devices communicated over the serial port. To do so, I used jpnevulator. That’s a serial port sniffer similar to sysinternals portmon which I used in the Windows age.
$ jpnevulator -ra -t /dev/ttyUSB0 0A 5B 52 50 36 42 4F 4F 54 5D 0A .[RP6BOOT]. 0A 5B 52 45 41 44 59 5D 0A .[READY].
… and nothing more. Grumble, did the python script send nothing, or did the sniffer not pick it up… Next thing, I installed boa-constructor and wanted to debug the python scripts, but I couldn’t figure out how to start the debugger with the correct ros commandine.
Next thing I played with simavr, hoping I could debug the code on the device. Simavr started and it seemed to have loaded and run the code, but I could not figure out how to connect the debugger from CodeBlocks.
Browsing the code and some documentation, I found out that the AtMega64 has two UART‘s, but the second one doesn’t seem to be available on the robot arm. This would have been good for debug output. I used the first one for the debug output, but since it’s the communication itself that I want to debug, the additional debug output can be disturbing, and hard to get to.
So I bit the bullet and worked with what I had available. I wrote a python script that sent a ros message to the robot arm, and printed the response along with the debug output to the console. With this, I could narrow down the spots where the firmware crashed. I found the following soar spots:
- The robot arm lib uses char for the serial communication, while rosserial uses uint8_t. No big deal I thought, the types have the same size. It is no big deal for characters in the regular 7bit ASCII range. But rosserial uses 0xFF to indicate message boundaries. By just assigning, it overflowed to something completely different. So I had to explicitly cast for both sending and receiving in the hardware adaptation file ArexxArmHardware.h.
- I assumed, the rosserial code was throughly tested and used a lot. That’s why I didn’t expect and thus didn’t look for uninitialized variables. But the uninitialized arrays publishers and receivers in ros_lib/ros/node_handle.h caused the firmware to crash all the time.
- The Arexx arm examples lib came with a very simplistic implementation of the UART communication. So I ported the ring buffer implementation of the PR6 to the robot arm. Receiving a previously unknown amount of data became a lot more reliable.
Now I could move the joints with commands like this:
rostopic pub ArexxArmServo6 std_msgs/Int16 200
I found a seemingly complete tutorial on what has to be done to integrate a robot arm with ROS. Oh boy, do I really have to do all that stuff? While this one can serve to scare off people, I found another tutorial that explains what to do step by step. And then the tutorial about the “Planning Description Configuration Wizard” really comes in handy for beginners like me.
So a few clicks in the wizard generated a whole load of configuration files by reading my URDF file. With one of the next tutorials, you can run the “Planning Components Visualizer” and see the inverse kinematic and path planning working in the simulator. Here, you move the gripper to a desired position, and the arm bends as required to achieve the position.
But I am still missing the link between the urdf with IK and path planning and the physical robot. Browsing through the ROS tutorials, I found out about the mini_max which seems to have this link implemented. And it’s similar enough that it’s worth having a closer look at the software..