Further software and hardware updates

Over the last few weeks I have been thinking about the overall controller architecture, 3D printing some test Raspberry Pi cases, and updating the Python test software.

Plotter updates

Timed operations

After refactoring the giant single-file script from the previous post, I noticed the script was actually running very inefficiently, partly down to the fact that the 2D canvas had to redraw the whole robot on every frame, but also because of the way some of the threaded classes (e.g. input handler, serial handler) were inadvertently constantly interrupting the main thread, because they were relying on use of the root window’s after() method. The timing loops are cleaned up now and the code runs much more efficiently.

Here is an example I figured out, of how to create a class to run a function in a separate thread, with a defined time interval, that is pausable/stoppable. It subclasses the Thread class, and uses the help of an Event object to handle the timing functionality. After creating an object of this class, you call its start() method, which invokes the run() method in a separate thread. The pause(), resume() and stop() methods perform the respective actions. The example is a stripped-down version of an input handler, which applies the equations of motion to user inputs, as shown in a past post.

import threading
from time import time
import math
class InputHandlerExample(threading.Thread):
    def __init__(self):
        # Threading/timing vars
        self.event = threading.Event()
        self.dt = 0.05  # 50 ms
        self.paused = False
        self.prevT = time()
        self.currT = time()
        self.target = 0.0
        self.speed = 0.0

        # Input vars
        self.inputNormalised = 0.0

    def run(self):
        while not self.event.isSet():
            if not self.paused:

    def pause(self):
        self.paused = True

    def resume(self):
        self.paused = False

    def stop(self):

    def pollInputs(self):
        # Upate current time
        self.currT = time()

        # Get user input somehow here, normalise value
        #self.inputNormalised = getInput()

        # Update target and speed
        self.target, self.speed = self.updateMotion(
            self.inputNormalised, self.target, self.speed)

        # Make use of the returned target and speed values
        #useResults(target, speed)

        # Update previous time
        self.prevT = self.currT

    def updateMotion(self, i, target, speed):
        m = 1.0
        u0 = speed

        # Force minus linear drag
        inputForceMax = 1000
        dragForceCoef = 5
        F = inputForceMax*i - dragForceCoef*u0
        a = F/m
        t = self.currT - self.prevT

        # Zero t if it's too large
        if t > 0.5:
            t = 0.0
        x0 = target

        # Equations of motion
        u = u0 + a*t
        x = x0 + u0*t + 0.5*a*math.pow(t, 2)

        return x, u

3d plot

So far the 2D representation of the robot worked OK, but it has its limitations. So I finally decided to put some effort into updating the representation of the robot. I went with matplotlib and its 3D extensions with the mplot3d toolkit.

The joints are simply represented using the scatter() function, while the lines are simply drawn with plot(). The text() function overlays the number of the joints over the joint positions. The leg target widgets use a combination of the above functions. The 3D plot is updated using the FuncAnimation class.

Since this designed for Matlab-style plotting rather than a simulator, the performance is still somewhat lacking (not as fast as the 2D canvas), but I wanted to be able to get something working fairly quickly and not waste too much time with something like OpenGL, since my aim is to have a test program and not build a 3D simulator from scratch. There’s always ROS and Gazebo if I need to take this further!

As a side note, I have added the option in the main program to be able to select between 2D or 3D drawing mode, as well as no drawing, which should be useful for speeding up execution when running on the Raspberry Pi in headless mode (no screen).

Here is a screenshot and a video of the results:

Quadbot 17 3D Drawing 002

Canvas redrawing

Another efficiency issue was the fact that previously the canvas was cleared an then redrawn from scratch on every frame update. To improve efficiency, both for the 2D and the 3D cases, the drawing classes now have structs to keep track of all element handles, and the redraw functions move the elements to their updated positions. For the 2D case (TkInter canvas), this is done with the coords() method. For the 3D case (matplotlib) it was a bit trickier, but I managed it with a combination of methods:

  • For lines (plot): set_data() and set_3d_properties()
  • For points (scatter): ._offsets3d = juggle_axes()
  • For text overlay (text): set_position and set_3d_properties()

Updated class diagram

The interaction between the different elements is cleaned up and now looks like this:

QB17QuadKinematics Class Diagram 02

Hardware architecture

Not, to make a switch and talk a bit more about the hardware, here is the current plan of how all the components will probably look like:

Hardware Components Diagram 01

I have in fact got two Raspberry Pis now, a Pi 3 Model B as well as a Pi Zero W. Both now have built-in WiFi, but I am going with the larger Pi 3 as the current choice for main controller, favouring the quad-core CPU over the Zero’s single core.

I tried 3D printing some cases from Thingiverse for each Pi, and here are the results. A great plus point of the Pi 3 case is that it has mounting points which will be easy to locate on the main robot body.

You can find my builds and their sources on Thingiverse:

Software updates

Here is a quick update on current progress with the software:

  • The robot spine can now be fully translated and rotated w.r.t. the world frame. Although I mentioned in the past that this isn’t really needed until the issue of localisation is faced, it is actually useful as a testing method for the IK, as all the legs can are moving w.r.t. the base – imagine e.g. the robot moving from a crouching to standing position.
  • The spine RPY orientation in space and its two joints are temporarily set up to influence each other, such that they emulate how the robot would behave if we wanted the spine/body orientation to change while keeping the feet flat – assuming the robot is standing on a perfectly flat surface. This should all make sense once I test the body orientation kinematics on the real robot soon!
  • As the controller I have been using does not work wirelessly, it’s not convenient to always have plugged in, so I added the ability for the test program to read the keyboard input as an alternative for moving the foot target positions. The Python module used is pynput. On this issue of the controller, if anyone knows how to get an XBox One controller’s wireless adaptor to work in Linux and Python, please let me know!
  • The monolithic Python test script was becoming a bit out of hand in terms of size and use of globals, so I’ve broken up into a few separate files and classes with better encapsulation than originally. It’s not perfect or optimised, but a bit more manageable now.

Quadbot 17 Spine XYZ and KB Input

Latest test program, with keyboard input and full spine control.


Simple class diagram of the Python program, after refactoring the original single-file script.

On the hardware side, I have some new controllers to explore various ideas, namely a Robotis OpenCM9.04 and a Raspberry Pi 3. The Raspberry could be mounted to the robot with a 3D-printed case like this.

Magnetic Encoders VS Optical Encoders

Enrique del Sol - Robotics, Mechatronics & Control Research

Encoders, whether rotary or linear, absolute or incremental, typically use one of two measuring principles—optical or magnetic. While optical encoders were, in the past, the primary choice for high resolution applications, improvements in magnetic encoder technology now allow them to achieve resolutions down to one micron, competing with optical technology in many applications. Magnetic technology is also, in many ways, more robust than optical technology, making magnetic encoders a popular choice in industrial environments.

Parameter Optical Sensor Characteristics Magnetic Hall Sensor Characteristics
Principle  coded disc/scale, through beam arrangement  magnet/tape/polewheel opposed to sensor
Incremental accuracy of target  100 nm – 1 μm

(lithography process)

 5 μm – 30 μm

(magnetisation process)

Energising by external LED (20 mW)  by target (Br>220 mT)
Signal Frequency  > 1 MHz possible  < 50 kHz
Benefits  high code density, high code accuracy  robust
Disadvantages  sensitive to contamination, high alignment requirements  raw code density, medium code…

View original post 513 more words

Chassis assembled

After 3D printing a few more plastic parts and cutting all the aluminium plates, the custom chassis is finally complete! Below are some quick notes on the progress over the last weeks.

More 3D printed parts and painting

I printed off some of the remaining parts of the chassis. The battery compartment was best printed upright with minimal support structure needed. The rear bumper was trickier than the front bumper, because of the additional hole space for the battery, so I found it was best to print upright, with a raft and curved supports at the bottom.

Once all parts were printed, and some more sanding, I spray-painted all the parts with plastic primer, then blue paint, and finally clear sealer.

Metal parts

I was initially thinking of finding an online service to cut out the aluminium chassis parts, but then decided it would be faster and cheaper to just get some sheets 1.5 mm thick aluminium sheets from eBay and cut them on a jigsaw table.
I used Fusion 360’s drawing tool to export to PDF the parts I needed to cut out: four chassis plates and four foot plates. I then printed them in actual scale and glued them on the aluminium to uses as traces.


I threaded the holes on all the 3D parts, which were either 3 mm wide where the aluminium plates attach, or 2 mm at the leg and spine bracket attachment points.
Using a tap for the 3 mm holes worked pretty well, but the 2 mm holes were more prone to being stripped or too loose, so manually threading the holes with the bolts worked better. Another issue was the infill surrounding the internal thread cylinder sometimes being a bit too thin. In retrospect, I’d try designing the 3D parts to use heat-set or expandable inserts, especially for the smaller threads.

The servo brackets attaching to the chassis have a large number of holes (16 for each leg and one of the spine brackets, and 12 for the other spine bracket) so the screws so far seem to secure the brackets well enough. The spine section is under a lot of stress from the wight of the whole chassis and legs, so it will not be able to withstand much twisting force, and the servos may not be strong enough at this area, but I will have to test this in practice with new walking gaits.


The custom chassis has finally made it from a 3D design to a reality, with relative success so far. Some of the threaded holes on the 3D parts are not as strong as I’d like, the AX-12 may be under-powered for the spine connection, and the brackets anchoring the spine may be the first to give way due to twisting forces. Also the chassis as a whole would benefit form weight-saving exercise and perhaps being thinned down. But this has only been the first iteration of the main chassis, and the robot design has now become a reality and seems to stand up well. The next step will see how it performs some of the basic walking gaits!


From paper to plastic

… or more correctly, from CAD to reality, as it is time for 3D printing!

I’ve recently got a new 3D printer in the form of a FlashForge Creator Pro 2017, which means I can start printing some of the structural components for the quadruped now, leaving the decorative pieces for later. In fact, some of them have already been printed, as you can see in the images below.

Chassis parts

All the parts were recently updated from their previous iteration slightly, by adding fillets around the edges, and decreasing nut hole diameters by 0.2 mm in order to provide some material for self-tapping threads. On the other hand, I increased the tolerance of some slots by the same amount, to allow a tolerance for their connection to interlocking plastic tabs.

The rear section has also been modified: the underside aluminium base will have a tab at 90° that connects to the rear, to provide more rigidity to the central connection with the spine servo bracket.

Here are the CAD models of the chassis parts:

Foot base

Front body assembly

Rear body assembly



All parts were printed in PLA plastic.

The first part I started with was the foot base. I printed it with a 20% honeycomb infill. I didn’t add any intermediate solid layers, but might do so in other parts. I have so far printed two out of the four bases.

Each leg will connect to a leg base bracket, which is the same design for all legs. The part was printed “upside-down” because of the orientation of the interlocking tabs. This meant that some support structure was needed for the holes. For the first print attempt I also added supports around the overhang of the filleted edge, along with a brim, but for the subsequent prints I didn’t bother with these, as the fillet overhang held fine without supports, and saved from extra filing/sanding down. These parts also used 20% infill.

For the front and rear “bumpers”, I reduced the infill to 10%.

For the larger part comprising of the central section of the front, the spine front bracket, I also used an infill of 10%. Due to the more complicated design that would have included many overhangs, I found it easier to cut the part lengthwise and print it as two separate pieces. These will be super-glued together after sanding.

Time-lapse GIFs and images of the printing process:


The parts so far

In terms of printing times, the foot bases and leg base brackets took about 3 hours each, the bumpers took around 4 hours each, and the two spine front bracket halves took about 7 hours combined, so total printing time is going to be fairly large!

The 0.2 mm clearance seems to work fine for self-threading the plastic with M2 size metal nuts, but was too large for some of the plastic-to-plastic interlocking tabs, possibly since this tolerance is close to the resolution limits of the printer (theoretically a 0.4 mm nozzle and 0.18 mm layer height). However after some filing and sanding down, all the plastic parts fit together nicely.

The resulting 3D prints before and after sanding:

The assembly so far

Finally, here are some images of how the chassis assembly is shaping up, as well as the foot bases shown attached to the foot metal brackets. These fitted snug without any sanding, and all the holes aligned perfectly with the metal brackets, which was reassuring!

The next step is to glue the front bracket halves together, and maybe spray paint all the parts, as they lose all their original shine and end up looking very scratched after sanding.


Four legs built – New videos and images

With the hardware for all four legs gathered, I have assembled the first standalone version of the quadruped. The MakerBeam XL aluminium profiles were adopted as before, to create a temporary chassis.

The fact that the robot can now stand on its four feet meant I could quickly give the walking gaits a test on the real hardware: The Python test software reads the up/down and forward/back position of each leg for a number of frames that make up a walking gait, the IK is solved, and the resulting joint values are streamed via serial over to the Arbotix-M, which simply updates the servo goal positions. No balancing or tweaking has been done whatsoever yet, which is why in the video I have to hold on to the back of the robot to prevent it from tipping backwards.

I took some time to make a video of the progress so far on this robot project:

A chance for some new photos:

Finally, here is an older video showing the Xbox One controller controlling the IK’s foot target position, and a simple serial program on the ArbotiX-M which receives the resulting position commands for each motor (try to overlook the bad video quality):

In the next stage I will start building the robot’s body, as per the CAD design, which is for the most part 3D printed parts and aluminium sheets, combined with the 2 DoF “spine” joints.