New Project: Computer Control via USB Serial

Since I’ve started this blog I’ve explored several problem domains with a common thread: equipment automation by computer control. Most recently my CNC project running GRBL needed a computer G-code sender. 3D printers are similar, though most modern printers can run independently using G-code stored on a memory card. And finally the aborted thermoforming machine project that had ambition to use a Raspberry Pi as its brain.

In all of these cases, we had a piece of equipment that could communicate with a PC via a USB serial adapter, so we can let the hardware focus on low level tasks and the PC could perform higher level tasks. It would be useful to dig deeper into this world and get a better feel of the tools available for solving problems.

For this initial pass my focus will be on PC software that interfaces with arbitrary pieces of equipment that communicate via USB serial, and the primary motivation for PC involvement would be its ability to display data on a full sized computer monitor. These two considerations will be my “North Star” for prioritization.

As a starting point, I thought I’d look over a few examples from an existing ecosystem: that of computer controlled hardware for electronics measurement and testing automation. I didn’t think they would be directly applicable, but I didn’t know how to articulate why until I learned a little more.

As of this writing, my understanding is that such software’s value to professional engineers are in two areas that are near, but not quite, my own priorities for this investigation:

  • They are built around the IEEE-488 standard, a formalized version of GPIB interface that started as a proprietary solution (HP-IB) for Hewlett-Packard equipment but has grown into a de facto standard in this industry. This standard encompasses the physical connector, electrical interface, and software protocol. Recently, the popularity of USB meant USB has taken over the physical and electrical portions. But the GPIB communication protocol lives on as USB488, which I understand to be a part of USB TMC. This is different from USB serial adapters, which usually identify as USB CDC and/or ACM.
  • They offer an extensive collection of data analysis and visualization tools specialized to the field of electronics test and measurement. This does not necessarily mean they support custom rendering of arbitrarily large data sets.

As a first example of how those differences manifest in practice, let’s do a quick window-shopping pass of Keysight VEE.

Preparing Retired Laptops For Computing Beginners

I’ve just finished looking over several old laptop computers with an eye for using them as robot brains running ROS, a research project made possible by NUCC. Independent of my primary focus, the exercise also gave me some ideas about old laptops used for another common purpose: as cheap “starter” computers for people getting their feet wet in the world of computers. This intent involves a different set of requirements and constraints than robot building.

In this arena, ease of use becomes paramount which means most distributions of Linux are excluded. Even Raspbian, the distribution intended for people to learn in a simplified environment on a Raspberry Pi, can get intimidating for complete beginners. If someone who receives a hand-me-down computer knows and prefers Linux, it’s a fair assumption they know how to install it themselves as I had done with my refurbished Dell Latitude E6230.

Next, a hand-me-down laptop usually includes personal data from its previous owner. Ideally it is inaccessible and hidden behind password protection, but even if not, the safest way to protect against disclosure is to completely erase the storage device and reinstall the operating system from scratch.

Historically for Windows laptops such cleaning also meant the loss of the Windows license since the license key has almost certainly been separated from the computer in its lifespan. Fortunately, starting from Windows 8 there is a Windows license key embedded in the hardware, so a clean install will still activate and function properly. For these Windows laptops and MacOS machines, it is best to preserve that value and run its original operating system. This was the case for the HP Split X2 I examined.

If a Windows or MacOS license is not available, the most beginner-friendly operating system is Chrome OS. It is available for individuals to install as Neverware CloudReady: Home Edition. Putting this on a system before giving it to a beginner will allow them to explore much of modern computing while also sparing them much of the headaches. And if they dig themselves into a hole, it is easy to restart from scratch with a “Powerwash”. This was what I had done with the Toshiba Chromebook 2 I examined.

But modern computing has left 32-bit CPUs behind, limiting options for older computers lacking support for 64-bit x86_64 instruction set. It meant Neverware CloudReady is not an option for them either. It is possible the user can be served by a machine that is a stateless web kiosk machine, in which case we can install Ubuntu Core with the basics of web kiosk.

And if we have exhausted all of those options, as was the case for the HP Mini netbook I examined, I believe that means the machine is not suitable as a hand-me-down starter computer for a beginner. Computers unable to meet minimum requirements for all of the above would only be suitable for basic command-line based usage. And whether computing veterans like it or not, current convention wisdom says a command line is not the recommended starting point for today’s computing beginners.

So in order of preference, the options for a beginner-friendly laptop after wiping a disk of old data are:

  1. Windows (if license is in hardware) or MacOS (for Apple products)
  2. Either original Chromebook/Chromebox or Chrome OS via Neverware CloudReady.
  3. Ubuntu Snappy Core in Web Kiosk mode.
  4. Sorry, it is not beginner friendly.

A Tale of Three Laptops

This is a summary of my research project enabled by the National Upcycling Computing Collective (NUCC). Who allowed me to examine three retired laptop computers of unknown condition, evaluating them as potential robot brain for running Robot Operating System (ROS).

For all three machines, I found a way to charge their flat batteries and get them up and running to evaluate their condition. I also took them apart to understand how I might mechanically integrate them into a robot chassis. Each of them got a short first-pass evaluation report, and all three are likely to feature in future projects both robotic and otherwise.

In the order they were examined, the machines were:

  1. HP Split X2 (13-r010dx): This was a tablet/laptop convertible designed for running Windows 8, an operating system that was also designed for such a dual-use life. Out of the three machines, this one had the longest feature list including the most modern and powerful Intel Core i3 CPU. But as a tradeoff, it was also the bulkiest of the bunch. Thus while the machine will have no problem running ROS, the mechanical integration will be a challenge. Its first pass evaluation report is here. For full details query tag of 13-r010dx for all posts relating to this machine, including future projects.
  2. Toshiba Chromebook 2 (CB35-B3340): This machine was roughly the same age as the HP, but as a Chromebook it had a far less ambitious feature list but that also gave it a correspondingly lighter and slimmer profile. It is possible to run a form of Ubuntu (and therefore ROS) inside a Chromebook, but there are various limitations of doing so. Its suitability as a robot brain is still unknown. In the meantime, the first pass evaluation report is here, and all related posts (past and future) tagged with CB35-B3340.
  3. HP Mini (110-1134CL): This was a ~10 year old netbook, making it the oldest and least capable machine of the bunch. A netbook was a simple modest machine when new, and the age meant this hardware lacks enough processing power to handle modern software. While technically capable of running ROS Kinetic, the low power processor could only run the simplest of robots and unable to take advantage of the more powerful aspects of ROS. The first pass evaluation report is here, and all related posts tagged with 110-1134CL.

While not the focus of my research project, looking over four old laptops in rapid succession (these three from NUCC plus the refurbished Dell Latitude E6230 I bought) also gave me a perspective on preparing old laptops for computing beginners.

Learning About Airflow From Three Years Of Dust

Three years ago I started this custom computer case project to build something tailored to run FreeNAS. The primary purpose was to get some hands-on time working with laser-cut acrylic, and I learned a lot building it. Now that I’ve decided to upgrade my home server to a different configuration, there will be too much hardware to fit in this box. I’ll start with a commodity PC tower case but I might build another custom case later. Either way, this little acrylic box will be retired.

Since the computer has been sitting in a corner unobtrusively serving up files for my home network, it has also collected three years of dust. The top layer is not particularly interesting, as they were deposited by gravity. The remainder, though, serve as indicator for airflow through the system and serves as a record of comparison against my intended airflow design for the box.

The biggest lesson for me was that convection played a much smaller role than I had expected. Most of the dust indicating flow was proportional to the size of their air channels, there’s no visible sign of convection altering the flow. The most visible example is the ring of dust near the CPU fan on my front panel. I had expected it to be slightly teardrop-shaped to reflect heat rising, but it is almost a perfect circle.

The most unexpected cluster of dust is on the auxiliary CPU power cable, running to the right side of the CPU fan alongside the USB wires. It appears most of the dust there were carried by air drawn in through the front panel gap. I hypothesize that, since it is a very narrow gap, airflow through that route is slowed and thus more likely to deposit dust on that cable bundle.

There were a few minor smudgest of dust whose origins are a mystery. Two up top near the PSU fan, and one on the bottom at the rear end of the PSU. I’m curious what they were, but their fine dust particle size implies they were not a significant factor, so I’m content to leave them as mysteries for now. Maybe they’ll make sense for me in the future once I learn more about designing for airflow. In order to preserve this information (all this dust will be disturbed and cleaned up when I disassemble this box) I shot a video for future reference:

(Cross-posted to Hackaday.io)

FreeNAS Box Decommissioned After Three Years

I’ve decided to retire my current home server running FreeNAS. It has worked well for three trouble-free years and will likely continue working for a few more. But I have enough motivations for an upgrade beyond its current capabilities.

First, I learned that FreeNAS has been making more and more use of its boot drive in its recent releases. At one point all the SATA ports on a FreeNAS box could be dedicated to storage devices, because FreeNAS itself is happy to boot from a USB flash drive, load to RAM, and run from there. Thus the boot drive is touched very little, minimizing wear on flash memory. However, FreeNAS documentation explained this has not been the case for several years. I have yet to run into any problems with the USB flash drives I’ve been using as mirrored boot volumes, but after three years of service I decided not to wait until problems crop up.

When looking at a boot drive for a modern operating system, my default choice is to use a solid state drive. SSDs were still an expensive luxury when I first started playing with FreeNAS, but they are now quite affordable and there’s been enough hardware churn for a few of my own SSDs to drop out of circulation and thus available for use. My first two Intel X25-M SSDs still report over 85% of wear life remaining. Their modest 80GB capacity is pretty cramped for modern desktop use, but quite spacious for a FreeNAS system drive. That capacity also means a lot of elbow room for flash wear-leveling.

The downside, of course, is that I need a SATA port on the motherboard to connect to my old but still functional X-25M. In order to have a X-25M as my FreeNAS system drive, I had to upgrade beyond this MSI AM1I motherboard with only two SATA ports.

Another motivation was an interest in hosting more functionality on the home server. While code with FreeBSD support can run in a jail, I needed virtual machines to run non-FreeBSD code such as ROS. When I started looking at FreeNAS, virtual machine support via bhyve was an experimental new feature. It has since grown to be a mature part of the feature set. With virtualization I can use the same physical box to host other software projects.

But a virtual machine also locks out a portion of system memory as any RAM allocated to the virtual machine is not available to the rest of FreeNAS. I have many 8GB DDR3 memory modules, but there were only two memory slots on an AM1I motherboard for 16GB. Moving to a motherboard with 4 memory slots will double the available memory to 32GB, plenty of room for playing with VMs.

With these points in mind, I powered off my homebuilt FreeNAS box built of laser-cut acrylic. The two storage drives will be moved to a commodity PC tower case. But before I take it all apart, I wanted to make note of a few observations from this computer’s three years of sitting on a shelf quietly running FreeNAS.

Mars-Bound Rover Perseverance

NASA has just announced the winner of their Name the Rover Contest: Perseverance. The contest invites K-12 students within the United States to submit names for the Mars 2020 rover along with an essay explaining why it is the best name. Sadly, not one of them suggested naming Mars 2020 rover “Sawppy” but I’ll just have to get past that personal disappointment somehow.

I’ve already seen a few people calling it “Persie”, “Percy”, and variants thereof. The official Twitter handle is @NASAPersevere and judging by the first few tweets, this account will follow the trailblazing Phoenix PR effort and tweet from the first person. I’m doing the same for Sawppy, and @SawppyRover has followed @NASAPersevere for future updates. If all goes well, Perseverance wouldn’t even be the only Mars-bound robotic explorer: the European Space Agency has designed one of their own. ExoMars 2020 is an interesting engineering marvel in and of itself, but that’s for another blog post.

Back to the naming contest: I really like the cartoony rover they used. I’ve spent a lot of time analyzing photos, videos, and CAD models of Curiosity and Mars 2020 Perseverance when building Sawppy. I see a lot of technical accuracy represented in the illustration. From the robot arm joints to the rocker-bogie suspension components, I’m very impressed at how well it blends technical details with classic cartoon techniques for appealing character animation. I’m definitely keeping this guy in mind for my future rover work.

In the meantime I have to get on various parts of Sawppy’s online documentation and update mentions of Mars 2020 to Perseverance. I’ll definitely update greeting pages, but I probably won’t bother to update every past project log. The rule of thumb: If it has a date, people can tell it was written before the announcement, so I will probably let it slide. If it doesn’t have a date, I should probably fix it.

Toshiba Chromebook 2 (CB35-B3340): Hardware Internals

While I contemplate buying a replacement screen to bring this Chromebook back to function, I removed the bottom panel as well, just for a look. Ten screws held the bottom panel in place, two of which were hidden under two rubber feet. (Top two as shown in this picture):

Toshiba Chromebook 2 CB35-B3340 bottom

Once removed, we could see the surprisingly roomy interior.

Toshiba Chromebook 2 CB35-B3340 internals

This was a relatively thin laptop for its age and screen size, so I had expected components to be packed densely. The battery, a single large module in the center, dominated the volume as expected. On either side are speakers, each with the luxury of the largest enclosures than I’ve ever seen in laptop speakers. Far larger than the volume allocated to speakers within the HP Split. I’ve read that interior volume for audio tuning is at an extreme premium, with sound designers fighting for millimeters, so it was a surprise to see this. And even with that use of volume, there are still room left unused near the corners.

Electronics occupied the area close to the hinge. They covered less than half of the available surface area and far less than half of the available volume within this laptop. Most of the main circuit board was covered by a metal shield, so I removed it to see components underneath. (In this picture, the machine was rotated 180 degrees relative to previous picture.)

Toshiba Chromebook 2 CB35-B3340 internals without EM shield

I see the CPU, RAM, and flash storage are all tightly integrated and soldered on board. No RAM or storage upgrades for this machine, which is consistent with the Chromebook ethos. About the only core component not soldered down is the commodity WiFi card, which I interpret to mean there was little to no cost savings to integrate an unit.

I had known about Chromebook’s concept of reduced complexity, but it was mostly in terms of software and maintenance. Since Chrome OS was running a Linux kernel under the hood, I expected the hardware to be just as complex as any other laptop. But apparently not this one, which I found very interesting. Now I’m curious if all Chromebooks have electronics guts simpler than equivalent full PC laptops. If I have the opportunity to take apart more Chromebooks in the future, I’ll keep an eye open to see if this is actually common across all Chromebooks or maybe the simplicity of this model is just good work on the part of the Toshiba Dynabook team which designed this Chromebook.

This was an interesting and instructive look inside the machine, time to put it back together and take stock of the current situation.

HP Split X2 (13-r010dx): Hardware Specifications

The first of three old laptops from NUCC to be examined stumped me at first. I found very little information printed on the device and it took a while before I realized it was a convertible tablet. All the information labels were hidden while the tablet was docked. Once I separated the pieces, I could read all the identifiers including its model number 13-r010dx. From there it was easy to find HP’s product page for this machine.

While in laptop mode, the device has a full size SD memory card slot, one HDMI port, and two USB ports. By detaching the base turning it into a tablet, we also expose a duplicate charging jack, a headphone jack, and a microSD memory card slot. I find it odd that the headphone jack is a tablet mode exclusive, and even more odd that they felt it was important to have two flash memory slots.

For robot brain purposes I would have preferred to have a physical Ethernet jack but I can do without. USB Ethernet adapters are plentiful, though the ones I’ve tried had problems with long term reliability. On the upside, both memory card slots are full depth slots so cards sits flush against exterior and would not jut out. So for example, I could keep a microSD card in the tablet and still dock it to the keyboard base without mechanical interference. For robot brain purposes, memory cards are useful for data transfer and logging.

Keyboard feel is decent and the accompanying touchpad is satisfactorily large. Sadly the screen resolution was a disappointing 1366×768. It was accompanied by tablet style features like a touchscreen and a portrait/landscape orientation sensor. None of these would be critical as a robot brain but might be pertinent for other uses.

A sticker proclaimed its processor to be a Core i3, the spec sheet elaborated it is a Core i3-4012Y that I expect to be capable but not super speedy. 4GB of RAM should be sufficient for most purposes, and storage is a SATA hybrid hard drive with 500GB of spinning magnetic platter storage backed by 8GB of NAND Flash memory cache. I don’t recall any prior experience with these hybrid drives and looking forward to seeing one in action. The charge port LED changed from orange to white indicating full charge by the time I was ready to turn it on.

Dell Latitude E6230: Working Too Well To Be Dismembered, NUCC to the Rescue

The previous few blog posts about my refurbished Dell Latitude E6230 was written several months ago and had sat waiting for a long-term verdict. After several months of use I’m now comfortable proclaiming it to be a very nice little laptop. Small, lightweight, good battery life, and decently high performance when I need it. (At the cost of battery life when doing so, naturally.)

The heart of this machine is a third generation Intel Core i5, which covers the majority of computing needs I’ve had while away from my desk. From the basics like 64-bit software capability to its ability to speed itself up to tackle bigger workloads. When working away from a wall plug and running on battery, the E6230 slows only minimally. Unlike my much newer Inspiron 7577 which slows drastically while on battery to the extent that it occasionally felt slower than the E6230. I can run my 7577 for perhaps two to four hours on battery, never far from a reminder of its limited on-battery performance. Whereas I can run the E6230 for around four to six hours on battery, without feeling constrained by reduced performance.

The E6230 has several other features I felt would be good for a robot brain. Top of the list is an Ethernet port for reliable communication in crowded RF environments. Several “SuperSpeed” USB 3 ports are useful for interfacing with hardware. And when I want more screen real estate than the built-in screen can offer, I have my choice of VGA or HDMI video output.

That built-in screen, with its minimal 1366×768 resolution, is about the only thing standing between this machine and greatness. Originally I did not care, because I had planned to tear the case apart and embed just the motherboard in a robot. But this laptop is working too darned well to be subjected to that fate! For the near future I plan to continue using the E6230 as a small laptop for computing on-the-go, and kept my eyes open for other old laptops as robot brain candidates.

An opportunity arose at Sparklecon 2020, when I mentioned this project idea to NUCC. They had a cabinet of laptops retired for one reason or another. I was asked: “What do you need?” and I said the ideal candidate would be a laptop with a broken screen and/or damaged keyboard, and have at least a Core i3 processor.

We didn’t find my ideal candidate, but I did get to bring home three machines for investigation. Each representing a single criteria: one with a busted screen, one with a busted keyboard, and one with a Core i3 processor.

Close enough! And now it’s time for me to get to work on a research project: determine what condition these machines are in, and how they can be best put to use.

Successful Polycarbonate Plastic Engraving Session

The first test run for CNC engraving was done on a piece of MDF. Mainly because the piece was already in the machine, surfaced, and ready to go. It was also a forgiving material in case of mistakes, but MDF doesn’t show engraved details very well.

The next session increased the difficulty level: now we have a piece of scrap polycarbonate plastic (“Lexan”) for our next engraving test. This material is interesting because it has different properties than PMMA (a.k.a. acrylic.) The latter is a popular material for laser cutting but also very brittle, very vulnerable to cracking under stress. Polycarbonate plastics are much more robust and a better choice when physical strength is important in a project.

Acrylic is also popular for laser engraving projects, but polycarbonates do not engrave or cut easily under laser power due to its different properties. It is not particularly friendly to CNC machining, either, but we’ll start with an engraving project before we contemplate milling them.

Thankfully the first session was a success, and illustrates some of the challenges of working with such materials. The toughness of the material also meant the little strings of cut chips want to remain attached to the stock, making cleanup a hassle. Upon close examination, we saw the engraved groove is slightly deeper on the left side than the right. Proof our scrap MDF working surface is not flat which was not a surprise, but “flat enough” within 4-8 thousands of an inch (1-2 sheets of normal office paper) which was better than expected.

Even with its imperfections, performance on this test indicates the machine is capable of engraving on materials we can’t use in the laser cutter. That might be useful, and a good example of how we can still learn lessons on this machine despite its flawed Z-axis and other problems. We should still fix them, of course, but the machine can already be useful while we work on those improvements.

Preparing For ROS 2 Transition Looks Complicated

Before I decided to embark on a ROS Melodic software stack for Sawppy, I thought about ignoring the long legacy of ROS 1 and going to the newer ROS 2 built on more modern infrastructure. I mean, I told people to look into it, so I should walk the walk right? Eventually I decided against putting Sawppy on ROS 2, the deal breaker was that the Raspberry Pi is not a tier 1 platform for ROS 2. This means there’s no guarantee on regular binary releases for it, or that it will always function. I may have to build my own arm32 binaries for Raspbian from source code, and I would be on my own to verify functionality. I’ve done a superficial survey of other candidates for a Sawppy brain, but for today Sawppy is still thinking with a Raspberry Pi.

But even after making that decision I wanted to keep ROS 2 in mind. Open Robotics has a  ROS 2 migration guide for helping ROS node authors navigate the transition, and it doesn’t look trivial to me. But then again, I don’t have the ROS expertise to accurately judge the effort involved.

The biggest headache for some nodes will be the lack of Python 2 support. Mainly impact ROS nodes with a long legacy of Python 2 code, it does not impact a new project written against ROS Melodic which is supposed to support Python 3.

The next headache is the fact that it’s not possible to write if/else blocks to allow a single ROS node to simultaneously support ROS 1 and 2. The recommendation is to put all specialized logic into generic non-ROS-specific code in a library that can be shared. Then have separate code tailored to the infrastructure paradigms of ROS and ROS 2. This way all the code integrating with a ROS platform can be separated, but calling into a shared library.

And it also sounds like the ROS/ROS 2 build systems conflict so they can’t even coexist side by side at the same time. Different variants of a node have to live in separate branches of a repository, with the shared library code merged across branches as development continues. Leaving ROS/ROS 2 specific infrastructure code live in their separate branches.

I can see why a vocal fraction of ROS developers are unhappy with this “best practice”. And since ROS is open source, I foresee one or more groups joining forces to keep ROS 1 alive and working with old code even as Open Robotics move on to ROS 2. Right now there are noises being made from people who proclaims to do a similar thing, saying they’ll keep Python 2 alive past official EOL. In a few years we can look back and see if those Python 2 holdouts actually thrived, and we can also see how the ROS 1/ROS 2 situation has evolved.

Wish List: Modular Sawppy Motor Controllers

One of the goals for my now-abandoned ROS Melodic Sawppy software project is something I still believe to be interesting. In contrast with the non-rover specific goals I outlined over the past few days, this one is still a rover item: I would like Sawppy motor control to be encapsulated in modules that can be easily swapped so Sawppy siblings are not required to use LX-16A servos.

My SGVHAK rover software had an infantile version of this option, and it was written in extreme time pressure to support our hack of using a RC servo controller to steer the right-front corner during SGVHAK rover’s SCaLE debut. In SGVHAK rover software, all supported motor controller code are all loaded, an unnecessary amount of complexity and overhead. It would be nice for a particular rover to bring in just the code it needed.

The HBRC crew up in the SF Bay Area (Marco, Steve, and friends) have swapped out the six drive wheels for something faster while keeping the servos for steering, so a starting point is to have options for different controls for steering and driving. But keeping in mind the original scenario was using a RC servo to hack a single steering corner, we want to make it possible to use heterogeneous motor controllers for each of ten axis of motion.

I need to better understand Rhys code to know if this is something I can contribute back to the Curio ROS Melodic software project. Rhys has stated an intent to bring in ros_control for Curio software stack. Primarily for the reasons of better Gazebo simulation, but it would also abstract Sawppy motor control logic: generic velocity controllers for driving wheels and position controllers for steering. And from there, we can have individual implementations responding to those controllers. Is that how it will work? I need to ramp up on Gazebo and ros_control before I can speak knowledgeably about it.

Learning Github Actions For Automating Verification

Once I wrote up some basic unit tests for my Sawppy rover Ackermann math, I wanted to make sure the tests are executed automatically. I don’t always to run the tests, and a test that isn’t getting executed isn’t very useful, obviously. I knew there were multiple tools available for this task, but lacking the correct terminology I wasted time looking in the wrong places. I eventually learned this came under the umbrella of CI/CD tools. (Continuous integration/continuous deployment.) Not only that, a tool to build my own process has been sitting quietly waiting for me to get around to using it: GitHub Actions.

The GitHub Actions documentation was helpful in laying out the foundation for me as a novice, but I learn best when the general foundation is grounded by a concrete example. When looking around for an example, I realized again one was sitting right in my face: the wemake Python style guide code analysis tool is also available as a prebuilt GitHub Action.

Using it as a template, I modified my YAML configuration file so it ran my Python unit tests in addition to analyzing my Python code style. And that it would do this upon every push to the repository, or whenever someone generates a pull request. Now we have insight into the condition of my code style and basic functionality upon every GitHub interaction, ensuring that nobody can get away with pushing (or create a pull request) with code that is completely untried and fundamentally broken. If they should try to get away with such a thing, GitHub will catch them doing it, and deliver proof. It’s not extensive enough to catch esoteric problems, but it provides a baseline sanity check.

I feel like this is something good to keep going and put into practice for all my future coding projects. Well, at least the nontrivial ones… I’ll probably skip doing it for simple Arduino demo sketches and such.

First Foray Into Python Unit Tests

When a Sawppy community member stepped up and released a ROS Melodic rover software stack, I abandoned my own efforts since there was little point in duplicating effort. But in addition to rover control, that project was also a test run for a few other ideas. I used a Jupyter notebook to help work through the math involved in rover geometry, and I started using a Python coding style static analysis tool to enforce my code style consistency.

I also wanted to start writing a test suite in parallel to my code development. It’s something I thought would be useful in past projects but never put enough focus into it. It always seemed so intimidating to build test suites that are robust enough to catch all the bugs, when it takes effort to climb the learning curve to even verify the most basic functionality. What would be the point of that? Surely basic functionality would have been verified before code is pushed to a Github repository.

Then I had the misfortune to waste many hours on a different project, because another developer did not even verify the code was valid Python syntax before committing and pushing to the repository. My idealism meant I wasted too many hours digging for another explanation, because “surely they’ve at least ran their code” and I was wrong. This taught me there’s value in unit tests that verify basic functionality.

So I brought up the Python unit test library documentation, and started writing a few basic tests for rover Ackermann geometry calculation. The biggest hurdle was that binary floating point arithmetic is not precise enough to use the normal equality comparison, and we don’t even need that much precision anyway. Calculating Sawppy steering geometry isn’t like calculating orbital trajectory for an actual mission to Mars. For production code using Python 3.5 onwards, there’s a math.isclose() available as a result of PEP 485. And for the purposes of Python unit tests, we can use assertAlmostEqual(). And how did I generate my test data? I used my Jupyter notebook! It’s a nice way to verify my wemake-compliant code would generate the same output as the original calculations hashed out in Jupyter notebook.

And finally, none of this would do any good if it doesn’t get executed. If someone is going to commit and push bad code they didn’t even try to run, they’re certainly not going to run the unit tests, either. What I need is to learn how to make a machine perform the verification for me.

Reworking Sawppy Ackermann Math in a Jupyter Notebook

The biggest difference between driving Sawppy and most other robotic platforms is the calculation behind operating the six-wheel-drive, four-wheel-steering chassis. Making tight turns in such a platform demands proper handling of Ackermann steering geometry calculations. While Sawppy’s original code (adapted from SGVHAK rover) was functional, I thought it was more complex than necessary.

So when I decided to rewrite Sawppy code for ROS Melodic (since abandoned) I also wanted to rework the math involved. I’ve done this a few times, most recently to make the calculations in C for an Arduino implementation of Sawppy control code, and it always starts with a sketch on paper so I can visualize the problem and keep critical components in mind.

Once satisfied with the layout on paper, I translate them into code. And as typically happens, that code would not work properly on the first try. The test/debug/repeat loop is a lot more pleasant in Python than it was in C, so I was happy to work with the tools I knew. But if the iterative process was even faster, I was convinced I could write even better code.

Thus I had my first real world use of a Jupyter notebook: my Sawppy Python Ackermann code. I could document my thinking in Markdown right alongside the code, and I could test ideas for simplification right in the notebook and see their results in numerical form.

But I’m not limited to numerical form: Jupyter notebooks can access a tremendous library of data visualization tools. It was quite overwhelming to wade through all of my options, I ended up using matplotlib‘s quiver plot. It plots a 2D field of arrows, and I used arrow direction to represent steering angle and arrow length to represent rolling speed. This plot gave a quick visual confirmation those numbers made sense.

In the Jupyter notebook I could work freely without worrying about whether I was adhering properly to style guides. It made the iterative work faster, but that did mean spending time to rework the code to satisfy wemake style guides. The basic logic remains identical between the two implementations.

I think this calculation is better than what I had used on SGVHAK rover, but it feels like there’s still room for improvement. I don’t know exactly how to improve just yet, but when I have ideas, I know I can bring up the Jupyter notebook for some quick experiments.

Inviting wemake to Nitpick My Python Code Style

I’m very happy Rhys Mainwaring released a ROS Melodic software stack for their Curio rover, a sibling of my Sawppy rover. It looks good, so I’ve abandoned my own ROS Melodic project, but not before writing down some notes. Part 1 dealt with ROS itself, many of which Rhys covered nicely. This post about Python Style is part 2, something I had hoped to do for the sake of my own learning and I’ll revisit on my next Python project. (Which may or may not be a robotic project.)

The original motivation was to get more proficient at writing Python code that conforms to recommended best practices. It’s not something I can yet do instinctively, so every time I tackle a new Python project I have to keep PEP8 open in a browser window for reference. And the items not explicitly covered by PEP8 are probably covered by another style guide like Google’s Python style guide.

But the rules are useless without enforcement. While it’s perfectly acceptable for a personal project to stop with “looks good to me” I wanted to practice going a step further with static code analysis tools called “linter“s. For PEP8 rules, the canonical linter is Flake8 which is a Python source code analysis tool packaged with a set of default rules for enforcing PEP8. But as mentioned earlier, PEP8 doesn’t cover everything, so Flake8 has option for additional modules for enforcing even more style rules. While browsing these packages, I was amused to find the wemake Python style guide which called itself “the strictest and most opinionated python linter ever.”

I installed wemake packages so that I can make Python code in my abandoned ROS Melodic project compliant with wemake. While I can’t say I was thrilled by all of the rules (it did get quite tedious!) I can confirm it does result in very consistent code. I’m glad I’ve given it a try, and I’m still undecided if I’m going to commit to wemake for future Python projects. No matter the final decision, I’ll definitely keep running at least plain flake8.

But while consistent code structure is useful for ease of maintenance, during the initial prototyping and algorithm design it’s nice to have something with more flexibility and immediate feedback. And I’ve only just discovered Jupyter notebooks for that purpose.

Original Goals For Sawppy ROS Melodic Project

Since a member of the Sawppy builder community has stepped up to deliver a ROS Melodic software stack, I’ve decided to abandon my own effort because it would mean duplicating a lot of effort for no good reason. I will write down some thoughts about the project before I leave it behind. It’s not exactly a decent burial, but it’ll be something to review if I ever want to revisit the topic.

Move to ROS Melodic

My previous ROS adventures were building the Phoebe Turtlebot project, which was based on ROS Kinetic. I wanted to move up to the latest long term service release, ROS Melodic, something Rhys has done as well in the Curio project.

Move to Python 3

I had also wanted to move all of my Python code to Python 3. ROS Kinetic was very much tied to Python 2, which reached end-of-life at the beginning of 2020. It was not possible to move the entire ROS community to Python 3 overnight, but a lot of work for this transition was done for ROS Melodic. Python 2 is still the official release for Melodic, but they encourage all Python modules to be tested against Python 3 and supposedly all of the core infrastructure has been made to be compatible with Python 3. Looking over the Curio project, I saw nothing offhand indicating a dependency on either Python version, so I’m cautious optimistic it is Python 3 compatible.

Conform to ROS Project Structure

I originally thought I could create a Sawppy ROS subdirectory under Sawppy’s main Github repository, but decided to create a new repository for two reasons:

  1. ROS build system Catkin imposes its own directory structure, and
  2. Existing name “Sawppy_Rover” does not conform to ROS package naming recommendations. Name must be all lowercase to avoid ambiguity between case-sensitive and case-insensitive file systems. https://www.ros.org/reps/rep-0144.html

Rhy’s Curio project solves all of these concerns.

Conform to ROS Conventions

Another motivation for a rewrite of my Sawppy code was to change things to fit ROS conventions for axis orientation and units:

  • Sawppy had been using +Y as forward, ROS uses +X as forward.
  • Sawppy had been using turn angle of positive degrees as clockwise, ROS uses right hand rule along +Z axis meaning counter-clockwise.
  • Math functions prefer to work in radians, but older code had been written in terms of degrees. Going with ROS convention of radians would skip a lot of unnecessary conversion math.
  • One potential source of confusion: “angular velocity” flips direction from “turn direction” when velocity is negative, old Sawppy code didn’t do that.

Rhy’s Curio project appears to adhere to ROS conventions.

All of that looks great! Up next on this set of notes, my original intent to practice better Python coding style with my project.

Rhys Mainwaring’s ROS Melodic Software and Simulator for Sawppy

When I created Sawppy, my first goal was to deliver something that could be fun for robotics enthusiasts to play with. The target demographics were high school students and up, which meant creating a software stack that is self-contained and focused enough to be easy to learn and modify.

To cater to Sawppy builders with ambition for more, one of the future to-do list was to write the necessary modules to drive Sawppy via open source Robot Operating System. (ROS) It is a platform with far more capability, with access to modules created by robotics researchers, but not easy for robotics beginners to pick up. I’ve played with ROS on-and-off since then, never quite reaching the level of proficiency I needed to make it happen.

So I was very excited to learn of Rhys Mainwaring’s Curio rover. Curio is a Sawppy sibling with largely the same body but running a completely different software stack built on ROS Melodic. Browsing the Curio code repository, I saw far more than just a set of nodes to run a the physical rover, it includes two significant contributions towards a smarter rover.

Curio Rover in Simulation

There’s a common problem with intelligent robotics research today: evolving machine learning algorithms require many iterations and it would take far too long to run them on physical robots. Even more so here because, true to their real-life counterparts, Sawppy and siblings are slow. Rhys has taken Sawppy’s CAD data and translated physical forms and all joint kinematics to the Gazebo robot simulator used by ROS researchers. Now it is possible to work on intelligent rovers in the virtual world before adapting lessons to the real world.

Rover Odometry

One of the challenges I recognized (but didn’t know how to solve) was calculating rover wheel odometry. The LX-16A servos used on Sawppy could return wheel position, but only within an approximately 240 degree arc out of the entire 360 degrees circle. Outside of that range, the position data is noisy and unreliable.

Rhys has managed to overcome this problem with an encoder filter that learned to recognize when the servo position data is unreliable. This forms the basis of a system to calculate odometry that works well with existing hardware and can be even faster with an additional Arduino.

ROS Software Stack For Sawppy

Several people have asked me for ROS software for Sawppy, and I’m glad Rhys stepped up to the challenge and contributed this work back to the community. I encourage all the Sawppy builders who wanted ROS to look over Rhys’ work and contribute if it is within your skills to do so. As a ROS beginner myself, I will be alongside you, learning from this project and trying to run it on my own rover.

https://github.com/srmainwaring/curio

(Cross-posted to Sawppy’s Hackaday.io page)

Sparklecon 2020: Sawppy’s First Day

I brought Sawppy to Sparklecon VII because I’m telling the story of Sawppy’s life so far. It’s also an environment where a lot of people would appreciate the little miniature Mars rover running amongst them.

Sparklecon 2020 2 Sawppy near battlebot arena

Part of it was because a battlebot competition was held at Sparklecon, with many teams participating. I’m not entirely sure what the age range of participants were, because some of the youngest may just be siblings dragged along for the ride and the adults may be supervising parents. While Sawppy is not built for combat, some of the participants still have enough of a general interest of robotics to took a closer look at Sawppy.

Sparklecon 2020 3 Barb video hosting survey

First talk I attended was Barb relaying her story of investigating video hosting. Beginning of 2020 ushered in some very disruptive changes in YouTube policies of how they treat “For Kids” video. But as Barb explains, this is less about swear words in videos and more about Google tracking. Many YouTube content authors including Barb were unhappy with the changes, so Barb started looking elsewhere.

Sparklecon 2020 4 Sawppy talk

The next talk I was present for was my own, as I presented Sawppy’s story. Much of the new material in this edition were the addition of pictures and stories of rovers built by other people around the country and around the world. Plus we recorded a cool climbing capability demonstration:

Sparklecon 2020 5 Emily annoying things

Emily gave a version of the talk she gave at Supercon. Even though some of us were at Supercon, not all of us were able to make it to her talk. And she brought different visual aids this time around, so even people who were at the Supercon talk had new things to play with.

Sparklecon 2020 6 8 inch floppy drive

After we gave our talks, the weight was off our shoulders and we started exploring the rest of the con. During some conversation, Dual-D of NUCC dug up an old school eight inch floppy drive. Here I am failing to insert a 3.5″ floppy disk in that gargantuan device.

Sparklecon 2020 7 sand table above

Last year after Supercon I saw photographs of a sand table and was sad that I missed it. This year I made sure to scour all locations to make sure I can find it if it was present. I found it in the display area of the Plasmatorium drawing “SPARKLE CON” in the sand.

Sparklecon 2020 8 sand table below

Here’s the mechanism below – two stepper motors with belts control the works.

Sparklecon 2020 9 tesla coil winding on lathe

There are full sized manual (not CNC) lathe and mill at 23b shop, but I didn’t get to see them run last year. This year we got to see a Tesla coil winding get built on the lathe.

For last year’s Sparklecon Day 2 writeup, I took a picture of a rather disturbing Barbie doll head transplanted on top of a baseball trophy. And I hereby present this year’s disturbing transplant.

Sparklecon 2020 WTF

Sawppy has no idea what to do about this… thing.

Sawppy Servo Experiment: Standard Servo with Metal Horn

From birth my Sawppy has been running around with LX-16A servos made by LewanSoul (also seen sold under the Hiwonder brand *) but that is not an explicit requirement. From the onset I designed Sawppy to accommodate multiple different servo types, primarily the three I investigated. In theory any servo would work, as long as they physically fit within the available space and someone puts in the effort to design a servo-specific mounting bracket and output adapter.

In an exploration to lower cost of rover building, today’s experiment is to validate my design goal of flexibility, putting theory into practice by adapting standard RC servos. This servo was also interesting because it has a metal horn, which would replace the common plastic servo horns that have been a common point of failure. This particular pairing of servo and horn came from now-defunct Roboterra (as of writing, the link shows up as a Squarespace site whose subscription has expired.) But the same concepts should apply to other servos and their horns.

Roboterra servo with metal horn

An adapter bracket was quickly whipped up to bolt to Sawppy. The bracket surrounds the entire perimeter of the servo including the four empty mounting points. The servo is not mounted as RC servos usually are, because Sawppy was designed so the servo only needs to provide twisting force. They are free to slide along axis of rotation, letting 608 bearings built elsewhere into Sawppy take care of handling the forces of a rover on the move.

Roboterra servo bracket and coupler

The metal horn on this servo is much larger in diameter than LX-16A servos, allowing a larger 3D-printed coupler. The metal horn was tapped to accept screws with M3 thread. The larger coupler held with M3 machine screws is far more sturdy than the LX-16A solution of coarse threads cut by self-tapping screws.

This is a promising first step into using commodity RC servos on a rover build. A large selection of RC servos are out there for every budget and power, making them a tempting option for some rover builders. But there’s still work ahead as the wiring will get more complicated as well as requiring a revamp of the electronics control system.