One of the benefits of being on sabbatical is that I don’t have to rush back to work
after ROSCon - and so I can sit around and write up some thoughts and themes
from the show.
Don’t expect me to tell you what the best talks were - I didn’t actually attend any talks.
You are not alone if that seems strange to you, my reasoning is that all the talks get
recorded and will be posted in a week or two but walking around talking with people can
only be done in person.
Getting New Contributors into Open Source Robotics Software
On the Tuesday prior to ROSCon, PickNik Robotics hosted MoveItCon with more than fifty
community members in attendance. The most interesting takeaway came from the opening
presentation slides:
Over the past year, 29 of 66 contributors to MoveIt2 were FIRST TIME contributors.
This stands in stark contrast to many of the more core ROS packages. I had
numerous discussions at both MoveItCon and ROSCon about why MoveIt2 has been so
successful in luring new contributors. The consensus was really around how little
friction new contributors encounter.
MoveIt2 has a large group of very active maintainers - who especially take the
time to help new contributors run through the gauntlet they might encounter. There are
a number of maintainer strategies at play for MoveIt2, but here are a few you could apply
to your own projects:
Actively maintain the list of tickets/issues on a project, culling out of date ones.
Instead of spending time tackling some of the easier issues, tag them “Good First Issue”
and then spend that time to help a new contributor to solve the bug or implement
a new feature.
Respond quickly to new PRs. Make sure feedback is constructive.
Have great documentation, especially around how to setup the development environment.
Be a cool/glamorous project. Ok, this is a bit harder for some of the essential open
source packages - but it is hard to deny that MoveIt2 and Nav2 aren’t both benefitting
at least a bit from this glamour.
During the closing at ROSCon, the audience was asked to raise their hand if this was their
first year at ROSCon - and I would say a majority of hands went up. I’m sure some of them
might be long time users or developers of ROS - but I wonder how many more of those people
we could help to contribute to ROS over the next year?
The Kids Are, Well, No Longer Kids
There have been 12 ROSCon/ROSWorld events. The folks that have been there from the beginning
are getting a bit older. We don’t stay out as late after the conference, and some of us
have likely forgotten what it was like just starting out in ROS or robotics. If you have
been around in ROS and robotics for a while, here’s some ideas for you:
Mentor some junior engineers. Connect them to people working on similar problems.
Point them at all that documentation you wrote years ago - you wrote documentation,
didn’t you?
You don’t have to just write code - review some code. Help junior developers get
their contributions merged.
Don’t burn out - take care of yourself physically and mentally - there were more than
a few people I talked to who aren’t actually as old as they feel - but much of robotics
is still taking place in fast-paced startups, and they can take a toll on you…
I certainly wish I had better paid attention to that last point when I was at Fetch
Robotics. Since leaving Fetch, I’ve lost 85 pounds and am probably in the best shape
of my life - and know I could have been a much better leader and mentor at Fetch
if I had not been burnt down most of the time.
What About Those New Faces?
If you are relatively new to ROS or robotics, you’re not alone - the community is still
growing fast. I had a number of people at both MoveItCon and ROSCon ask about what
they should be studying or learning. My answer evolved a bunch over the course of the
week - here’s what I landed on:
Find some really good mentors. ROS, and robotics in general, moves quicker than most
university programs can evolve. I’ve been fortunate to have some really great
mentors throughout my career, it is probably the biggest benefit from my
Willow Garage days.
Contribute some open source. Help out an existing project, or even find something that
is missing and go make it exist. At Cobalt Robotics, I encouraged my younger colleagues
to get involved and in addition to various bug fixes to ROS packages, they have also
published some pretty cool work - including an
image assembler for Livox lasers and
AR visualization of what your robot sees.
We Are So Back
I cannot even count how many people I talked to who have moved back to the greater
Boston area, or even the East Coast in general. Further, so many of them talking about
work-life balance. I really want to organize a “ROSCon In The Woods” next summer where we
just go for a hike and have a BBQ in like southern New Hampshire. Drop me a message if
you’d be interested in such a thing.
The Elephant In The Room
Finally, at ROSCon there was the elephant in the room - the acquisition of Open Robotics
by Intrinsic. Not much has really changed in how ROS is operating since the acquisition,
but there were still certainly discussions of “what if the level of support and funding goes
down?”.
We in the ROS Community can’t actually do anything about that - so instead we should focus
on what we can do. Having a large open source project so largely maintained and funded by a
single organization is never great - just look at the struggle after the demise of Willow
Garage. Instead of worrying about what might happen, this is a great opportunity to
convince whomever you work for to contribute more to ROS, with both developer time and
money. Everyone can be an advocate for open source robotics software.
There was a shortage of entries in the
tablebot competition
shortly before the registration window closed for RoboGames 2023. To make sure the
contest would be held, I entered a robot. Then I had to build one.
What’s A Tablebot?
A tablebot lives on the table. There are three “phases” to the competition:
Phase I: Build a robot that goes from one end of a table to the other and back.
Phase II: Have the robot push a block off the ledge of the table.
Phase III: Have the robot push the block into a shoebox mounted at the end of the table.
There is also an unofficial Phase IV - which is to fall off the table and survive.
I did not attempt this phase.
The majority of tablebots are quite simple - a couple of sonar or IR sensors and they
kind of wander around the tabletop in hopes of completing the different phases. My
tablebot is decidedly different - and it paid off as the robot won the gold medal at
RoboGames 2023.
Robot Build
The entire robot is built of 3d printed parts and random things I had on hand.
I’ve had one of those $99 LD-06 lidars sitting around for a while, and decided this was
a great project to use it on. I used a Dynamixel AX-12 servo to tilt the laser so I can
find the table, the cube, or the goal.
All of the code runs on an STM32, on my custom Etherbotix board which was designed
for my Maxwell robot
a number of years ago. The robot uses
differential drive with some 30:1 12V gear motors, which were purchased from
Lynxmotion in 2008 and used in various fire fighting robots over the years.
A set of small digital Sharp IR sensors are used as cliff sensors. These can
be moved up or down to calibrate for different table surfaces using a pair of
adjustment screws. While the sensors are very accurate and stop the robot,
they don’t see far enough ahead when going at full speed, and so I also
use the laser to detect when the table edge is approaching.
Phase 1 Software
Phase 1 is pretty straight forward - and mostly based on dead reckoning odometry:
The laser is angled downwards looking for the table. This is done by projecting to
the scan to 3d points, and filtering out anything not in front of the robot at
roughly table height. When the table disappears (number of points drops too low),
we reduce our maximum speed to something that is safe for the cliff sensors to
detect.
While the laser sensors look for the end of the table, the robot drives forward,
and a simple feedback loop keeps the robot centered on the table using odometry.
When the cliff sensors eventually trigger, the robot stops, backs up 15 centimeters,
and then turns 180 degrees - all using dead reckoning odometry.
The maximum speed is then reset and we take off to the other end of the table with
the same behavior.
Phase 2 Software
The movements of Phase 2 are basically the same as Phase 1 - we drive forward,
staying centered with odometry. The speed is a bit lower than Phase 1 because the
laser is also looking for the block:
The laser scan is projected to 3d, and we filter out any points that are part
of the table based on height. These remaining points are then clustered and
the clusters are analyzed for size.
If a cluster is a good candidate for the block, the robot turn towards the block
(using, you guessed it, dead reckoning from odometry).
The robot then drives towards the block using a simple control loop to keep
the heading.
Once the block is arrived at, the robot drives straight until a cliff sensor
trips.
At that point, the robot stops the wheel on the side of the tripped cliff sensor
and drives the other wheel very slowly forward so that we align the front of
the robot with the edge of the table - ensuring the block has been pushed off
the table.
Phase 3 Software
The final phase is the most complex, but not by much. As with the earlier phases,
the robot moves down the table finding the block:
Unlike in Phase 2, the robot actually approaches a pose just behind the block.
Once that pose has been reached, the robot tilts the laser back to level and
finds the goal.
The robot then turns towards the goal in the same way it first turned towards
the block.
The robot then approaches the goal using the same simple control loop, and in
the process ends up pushing the block to the goal.
All of the software for my Tablebot is availble on
GitHub.
Robogames Video
Jim Dinunzio, a member of the Homebrew Robotics Club, took a video during the
actual competition at Robogames so you can actually see the winning set of runs:
Visualization
To make development easier, I also wrote a Python GUI that renders the table,
the robot odometry trail, the laser data, and detected goals and cubes.
Fun with Math
Along the way I actually ran into a bug in the ARM CMSIS DSP library. I used the
arm_sin_cos_f32() function to compute my odometry:
This function takes the angle (in degrees!) and returns the sine and cosine of the
angle using a lookup table and some interesting interpolation. With the visualization
of the robot path, I noticed the robot odometry would occasionally jump to the
side and backwards - which made no sense.
Further investigation showed that for very small negative angles,
arm_sin_cos_f32 returned huge values. I dug deeper into the code and
found that there are several different versions out there:
The version from my older STM32 library, had this particular issue at very
small negative numbers. The same bug was still present in the official CMSIS-DSP
on the arm account.
The version in the current STM32 library had a fix for this spot - but that fix
then broke the function for an entire quadrant!
The issue turned out to be quite simple:
The code uses a 512 element lookup table.
For a given angle, it has to interpolate between the previous and next
entry in the table.
If your angle fell between the 511th entry and the next (which would be
the 0th entry due to wrap around) then you used a random value in the next
memory slot to interpolate between (and to compute the interpolation).
At one point, this resulted in sin(-1/512) returning outrageous values of
like 30.
With that bug fixed, odometry worked flawlessly afterwards. As it turned out,
I had this same function/bug existing in some brushless motor control code at
work.
Robogames Wrap Up
It is awesome that RoboGames is back! This little robot won’t be making another
appearance, but I am starting to work on a RoboMagellan robot for next year.
It has been a while since I’ve posted to the blog, but lately I’ve actually been working
on the UBR-1 again after a somewhat long hiatus. In case you missed the earlier posts in
this series:
The latest ROS2 release came out just a few weeks ago. ROS2 Humble targets Ubuntu 22.04
and is also a long term support (LTS) release, meaning that both the underlying Ubuntu
operating system and the ROS2 release get a full 5 years of support.
Since installing operating systems on robots is often a pain, I only use the LTS releases
and so I had to migrate from the previous LTS, ROS2 Foxy (on Ubuntu 20.04). Overall, there
aren’t many changes to the low-level ROS2 APIs as things are getting more stable and mature.
For some higher level packages, such as MoveIt2 and Navigation2, the story is a bit different.
Visualization
One of the nice things about the ROS2 Foxy release was that it targeted the same operating
system as the final ROS1 release, Noetic. This allowed users to have both ROS1 and ROS2
installed side-by-side. If you’re still developing in ROS1, that means you probably don’t
want to upgrade all your computers quite yet. While my robot now runs Ubuntu 22.04, my
desktop is still running 18.04.
Therefore, I had to find a way to visualize ROS2 data on a computer that did not have the
latest ROS2 installed. Initially I tried the Foxglove Studio, but didn’t have any luck
with things actually connecting using the native ROS2 interface (the rosbridge-based
interface did work). Foxglove is certainly interesting, but so far it’s not really
an RVIZ replacement - they appear to be more focused on offline data visualization.
I then moved onto running rviz2 inside a docker environment - which works
well when using the rocker tool:
If you are using an NVIDIA card, you’ll need to add --nvidia along with
--x11.
In order to properly visualize and interact with my UBR-1 robot, I needed to add the
ubr1_description package to my workspace in order to get the meshes and
also my rviz configurations. To accomplish this, I needed to create my own docker
image. I largely based it off the underlying ROS docker images:
The image derives from humble-desktop and then adds the build tools and clones
my repository. I then ignore the majority of packages, install dependencies and
then build the workspace. The ros_entrypoint.sh script handles
sourcing the workspace configuration.
The full source of these docker configs is in the
docker folder
of my ubr_reloadedrepository. NOTE: The updated code in the
repository also adds a late-breaking change to use CycloneDDS as I’ve had
numerous connectivity issues with FastDDS that I have not been able to debug.
Visualization on MacOSX
I also frequently want to be able to interact with my robot from my Macbook. While I previously
installed ROS2 Foxy on my Intel-based Macbook,
the situation is quite changed now with MacOSX being downgraded to Tier 3 support and the new
Apple M1 silicon (and Apple’s various other locking mechanisms) making it harder and harder
to setup ROS2 directly on the Macbook.
As with the Linux desktop, I tried out Foxglove - however it is a bit limited on Mac. The
MacOSX environment does not allow opening the required ports, so the direct ROS2 topic
streaming does not work and you have to use rosbridge. I found I was able to visualize
certain topics, but that switching between topics frequently broke.
At this point, I was about to give up, until I noticed that Ubuntu 22.04 arm64 is a Tier 1
platform for ROS2 Humble. I proceeded to install the arm64 version of Ubuntu inside Parallels
(Note: I was cheap and initially tried to use the VMWare technology preview, but was unable
to get the installer to even boot). There are a few tricks here as there is no arm64 desktop
installer, so you have to install the server edition and then upgrade it to a desktop. There
is a detailed description of this workflow on askubuntu.com.
Installing ros-humble-desktop from arm64 Debians was perfectly easy.
rviz2 runs relatively quick inside the Parallels VM, but overall it was not
quite as quick or stable as using rocker on Ubuntu. However, it is really nice
to be able to do some ROS2 development when traveling with only my Macbook.
Migration Notes
Note: each of the links in this section is to a commit or PR that implements the discussed
changes.
In the core ROS API, there are only a handful of changes - and most of them are actually
simply fixing potential bugs. The logging macros have been updated for security purposes
and require c-strings like the old ROS1 macros did. Additionally the macros are now
better at detecting invalid substitution strings. Ament has also gotten better at
detecting missing dependencies. The updates I made to
robot_controllers
show just how many bugs were caught by this more strict checking.
image_pipeline has had some minor updates since Foxy, mainly to improve
consistency between plugins and so I needed to
update some topic remappings.
Navigation has the most updates. amcl model type names have been
changed
since the models are now plugins. The API of costmap layers has changed significantly,
and so a number of
updates were required
just to get the system started. I then made a more detailed pass through the
documentation and
found a few more issues and improvements with my config,
especially around the behavior tree configuration.
I also decided to do a proper port of
graceful_controller to ROS2,
starting from the latest ROS1 code since a number of improvements have happened in the
past year since I had originally ported to ROS2.
Next Steps
There are still a number of new features to explore with Navigation2, but my immediate
focus is going to shift towards getting MoveIt2 setup on the robot, since I can’t easily
swap between ROS1 and ROS2 anymore after upgrading the operating system.