Wild Thumper based ROS robot

My ROS (Robot Operating System) indoor & outdoor robot

Similar projects worth following
I've build a few robots before, but never was able to do real navigation with them, e.g. drive successfully from living room to kitchen. Reason was that a few infrared and sonar sensors are not enough to do 'real' navigation. You can avoid obstacles with them, but not much more. My Software was not much better suited for this until I discovered ROS (Robot Operating System) with the rviz GUI a few years ago. Since ready available robots with ROS are a little bit expensive I decided to build a new robot in spring 2015 around the wild thumper 4wd chassis. The hardware and electronics were almost completed in a few weeks. Since then I've spent some time with tuning..

The goal is to be able to navigate indoor doing SLAM (simultaneous localization and mapping) and outdoor with GPS.

The free space on the back is supposed to host a robot arm somewhere in the future.


  • Wild Thumper 4wd chassis
  • Motors upgraded with encoders
  • Total weight: 3.3kg

Power supply:

  • Battery: 2x 7.2V NiMh, fused with 30A (slow)
  • 5V via voltage regulator D24V50F5 (5A), fused with 3A (fast)

The two batteries are connected in parallel using a LM5050-2 active ORing circuit each. Another LM5050-2 can be connected in parallel for docking station supply.


  • Solid Run Hummingboard (i.MX6 ARM Cortex-A9 Dual Core 1GHz, 2GB RAM)
  • AVR Atmega32 for motor control
  • AVR Atmega328 (Arduino Nano) for I/O


  • Hummingboard: GPS (uart), IMU (USB), 3D-Camera (USB), 2xAVR over I2C, PCA9517 "Level translating I2C-bus repeater" to bridge the 3.3V with the 5V I2C.

Motor control:

  • Motors driven by 4x VNH2SP30, one for each on a 20kHz PWM
  • Speed control (PID) and Odometry from wheel encoders are calculated on Atmega328 (yes, doing float on it).

Inputs/Outputs on Atmega328:

  • 3x distance sonar sensors, 2x infrared distance sensors, battery voltage

Odometry calculation:

  • Odometry from wheels corrected with Tinkerforge IMU Brick 2.0 with Kalman filtering


  • Xtion Pro Live depth camera
  • 2x IR 2D120X (1x left, 1x right)
  • 3x sonar SRF05 (2x front, 1x aft).

The point of the sonar sensors is to correct the dead zone of the depth camera in less then 0.5m


  • Debian Stretch
  • Robot Operating System (ROS) Kinetic

Object following:

With ultra-wideband (UWB) modules the robot can follow a target, in the following video a R/C car:

Details in the corresponding log "Follow me - part 4".

GPS test video:

The following videos shows the robot automatically driving a square by four GPS waypoints. The front camera is shown on the lower left, the rviz map video is shown on the upper left.

LED stripe demo:

  • 1 × Wild Thumper 4wd
  • 2 × Battery NiMh 7.2V 5000mAh
  • 2 × LM5050-2 board active ORing Custom board
  • 1 × D24V50F5 5V/5A voltage regulator
  • 1 × Solid Run HummingBoard-Pro + i.MX6 Quad SoM with W-Lan & Bluetooth

View all 10 components

  • Checking I2C pull-ups

    Humpelstilzchen10/03/2018 at 08:06 0 comments

    TL;DR: Always check your signals with an oscilloscope!

    Long version:

    I wanted to try out rosruby, a ROS wrapper for the ruby programming language, so I decided to port the ROS node for the LPD8806 LED strip of this robot to it. This strip uses a somewhat crippled SPI with only MOSI and SCK to control the lights. While testing the new node the I2C bus immediately and repeatable fails. Since I2C is used as the connection to e.g. the motor controller, the bus is critical for operation. This has not happened before. After ruling out power issues this smelled like a problem with electromagnetic interference, which is why I checked the SPI signals (yellow: SCK, green: MOSI) with an oscilloscope:

    While there are some spikes in the SPI signal and I'm certainly missing the line impedance matching resistors for termination of the bus I don't consider the signal bad enough to disrupt a healthy I2C.

    So I looked at the I2C bus instead which resulted in the following horrific picture (yellow: SCL, green: SDA)

    This by any means is matching more a saw tooth then a clean rectangular signal. It is obvious that the value of 5k Ohm for the pull-up is way too high in this robot. After replacing both resistors with 1k ones the signal is now much better (yellow: SCL, green: SDA):

    Also the I2C no longer fails when sending data on the LPD8806 SPI.

  • Follow me - part 4

    Humpelstilzchen09/09/2018 at 07:58 0 comments

    In the last attempt to make my robot follow me, I used a radio frequency of 433MHz with a small bandwidth of 90kHz. The major problem with this approach were reflections resulting in multipath interference. A technology immune against this issue is ultra-wideband (UWB), which is using a large bandwidth with more then 500MHz. The DWM1000 Module by Decawave is one implementation of UWB, quote:

    "DWM1000 is an IEEE802.15.4-2011 UWB compliant wireless transceiver module based on DecaWave's DW1000 IC.  DWM1000 enables the location of objects in real time location systems (RTLS) to a precision of 10 cm indoors, high data rate communications, up to 6.8 Mb/s, and has excellent communications range of up to 300 m thanks to coherent receiver techniques."

    Originally designed for 2d/3d localization, the DWM1000 modules basically enable the measuring of the distance between a "tag" and an "anchor". To test the DWM1000 I bought three Localino v1.3 boards. One board includes a DWM1000 and an AVR Atmega328 where I installed an open source dw1000 library on. Two DWM1000 are mounted on my Wild Thumper robot, one on each side between the front and the aft wheel about 29cm apart.

    Both DWM1000 on the robot are configured as anchors. The third DWM1000 is configured as a tag and is the beacon that is to be followed:

    Given the two distances dist_left, dist_right from both anchors to the tag and the distance between both anchors dist_left_right we get two right-angled triangles that share a side. With them the beacon position (x, y) from the center of the robot can be calculated using the Pythagorean theorem:

    There are two solutions for these equations, one in front of the robot, one behind. Since the beacon is initially set up to be in front of the robot and is expected to stay there, only this one solution is taken. The calculated relative position of the beacon is then smoothed with a simple Kalman filter [1]. The prediction of the Kalman filter assumes a stationary object and is only adjusted when the robot itself moves. The prediction is corrected by the calculated x & y values from the equations above. The working code can be seen in the following video where the Wild Thumper robot follows a DWM1000 beacon which is mounted on a R/C car.

    [1] The simple Kalman filter is based on the Matlab code in Xilinx Xcell Journal Issue 53, p. 74.

  • Light demo

    Humpelstilzchen08/12/2018 at 07:11 0 comments
  • Follow me - part 3

    Humpelstilzchen06/18/2018 at 10:55 0 comments

      Since using a beam antenna wasn't as accurate as I hoped for direction finding (see previous log) I was looking for other alternatives, so I tried using the phase difference between two antennas, sometimes named tdoa. This method basically uses the doppler effect, but instead of rotating the antenna physically, the antenna is rotated virtually, by switching between one or more antennas. The idea is 

      1. when one antenna is closer to the transmitter, there is an audible glitch in the signal
      2. when the transmitter is equidistant to the antennas, there is no change in the signal

      My phase difference receiver is using two antennas. Switching between two Lambda/2 antennas is done using RF Pin Diodes:

      The diodes are driven with a PWM from an AVR Attiny. Using a capacitor the amplitude of the PWM is shifted to -2,5/+2.5V. The HF is connected to an rtl sdr, decoding is done with GNU Radio. The whole setup looks like this:

      The transmitter has to be FM, the closest thing to that in my inventory was an RFM12 (433MHz), which does Frequency Shift Keying (FSK). I programmed the RFM12 to send a few zeroes so I can easily identify the signal. The result looks like this when the left antenna is closer:

      As one can see I use a PWM with a ratio of 30% : 70% to distinguish between both phases. When the right antenna is closer the spikes are inverted. When both antennas are equidistant distance from the transmitter the signal is not disturbed:

      So the setup basically works, the robot can distinguish if the transmitter is closer to the left, closer to the right or equidistant to both antennas. But there are still a lot of problems, mostly from reflections which do make the robot drive to the wrong direction...

  • Updating the AVRs over I2C

    Humpelstilzchen01/19/2018 at 07:12 0 comments

    The wild thumper has an AVR Atmega32 and an Atmega328 microcontroller. Normally to flash a new firmware onto them I have to open the upper panel and attach my ISP. To workaround that I developed an I2C bootloader. After setting the fuse bits "Boot Reset vector Enabled" and "Boot flash section size"=1024 words the bootloader is programmed into the AVR.

    On start the bootloader checks if the first byte in the flash is 0xff. If it is 0xff it assumes that the memory is erased and there is no valid program. Else it starts the main program by jumping to address 0x00. There is also the option to force the bootloader to run by writing the magic number 123 into the first address of the eeprom. When the bootloader runs it accepts commands from I2C (defaults to address 0x50/0x28). Commands include

    • read memory
    • write memory
    • erase memory
    • erase all
    • and jump to address

    I also wrote the corresponding client program which runs on the Linux computer. With this python script programming an AVR becomes to

    ./ 0x52 main.hex -j

     First argument is the target address 0x52 (0x29), second argument is the program file to flash, -j tells the bootloader to start (jump to) program after flashing.

    From now on I can update the firmware of all microcontrollers in the field without taking everything apart or attaching an extra programmer.

  • Follow me - part 2

    Humpelstilzchen01/14/2018 at 09:46 0 comments

    FInally got a HB9CV antenna, a BNC cable and a corresponding adapter to my RTL-SDR. I've put the antenna onto a servo and 3d printed an adapter, the whole setup looks like this:

    The beacon was quickly wired on a breadboard. The antenna does not have the correct length, but this was enough to receive a signal in a first test:

    On the software side the beacon simply transmits "MO" in Morse code every 5s with currently 50ms for a dit and 150ms for a dah. I have to speed it up later. The first reception was done with multimon-ng. Minimum frequency of the transmitter is 433.82MHz, maximum is 434.02MHz, so I used the center frequency of 433.92MHz with a bandwidth of 200kHz. Gain was set to maximum and everything piped to multimon-ng:

    rtl_fm -g 19 -f 433.92e6 -M am -s 200e3 -r 22050 - | multimon-ng -a MORSE_CW -t raw /dev/stdin

    After verifying that multimon-ng prints "MO" every 5s I wrote a small python script to decode the same output of rtl_fm. The data is sampled 45 times a second as short int:

    frames =*2) # Two bytes per value
    data = np.array(struct.unpack("<%dh" % (len(frames)/2), frames))

     and then the average is used to detect if this is a high or low level:

    avg = np.average(data)
    cur_level = avg > HIGH_THRES

    With help of the Internet decoding the morse code was very. In the end every time I detected a "MO" I printed the average high level on the terminal.

    Using the average level I placed the beacon every 30° around the antenna with a distance of 1.5m to a get a radiation pattern of the antenna. My setup was not very accurate but it does give a first idea:

    As one can see the maximum is not quite in front of the antenna, it does squint about 30°. But the decrease of values to 0° and 60° degree is clearly visible. The exact values in this area need more investigation.

  • Follow me - part 1

    Humpelstilzchen12/31/2017 at 09:25 0 comments

      The goal for 2018: Getting my robot to follow me. How can this be done? I checked a few options for this:

      1. Visually e.g. with OpenCVs Find-Object or OpenCVs camshift. However after playing with them I haven't found them robust enough. Maybe my camera or illumination could have been better?
      2. Ultrasonic as implemented by e.g. Robo-Dog. Seems to work good, but with limited range (few meters?) and you have to point the beacon towards the robot, that is not what I plan.
      3. Radio: The ham radio people have a game called "Amateur radio direction finding" (also known as fox hunting) where the hams are trying to locate a small beacon by using a direction finding receiver. There is a small howto on a cheap self made Transmitter & Receiver "Foxy" available (german) that should provide a good starting point. However I plan do use a AVR with a 434 mhz ook transmitter as beacon and my old RTL-SDR as receiver. Antenna will probably be a HB9CV. On ISM 433MHz the reception antenna will probably end up as big as my robot, so moving to a higher frequency (868MHz to 2.4GHz) might be obvious.

  • GPS test

    Humpelstilzchen12/16/2017 at 17:59 0 comments

    Doing a GPS test by automatically driving a square with four GPS waypoints. The front camera is shown on the lower left, the rviz map video is shown on the upper left.


  • Rework

    Humpelstilzchen12/09/2017 at 19:57 0 comments

    Currently doing some rework and moving the single-board computer from the top to the interior, thought I share a picture from the inside:

  • Sonar sensor (here SRF05) tuning

    Humpelstilzchen07/09/2017 at 08:31 0 comments

    ROS supports sonar and infrared sensors with the sensor_msgs/Range Message. Using it is pretty straightforward, but there are two values that I have spend quite some time on tuning: field_of_view and max_range.

    1. max_range:

    The SRF05 has a maximum range of about four meter. But that is not what I have set as max_range value because of the high field of view of this sensor (see below) with a maximum of about 55°. That means in an area of four meter and 55° a table leg is enough to mark the full area as occupied. To avoid this situation I set the max range value to only 0.5 meter.

    2. field_of_view:

    The field of view is not constant. For the details hobbizine has a good article which I highly recommend to read, quote:

    "The beam width (or beam angle) of ultrasonic range finders is typically described as being a cone of a certain angle (...) The conclusion of this logic would be that the detection zone extends from the sensor in an even, steadily expanding arc until it reaches the 4 meter limit of the SRF05 range. In reality the detection zone expands at about 55° for the first meter and then the rate of expansion starts to decay. At about 2 meters distance from the sensor the angle of the detection zone is closer to 40° with the zone reaching a maximum width of about 80-100 centimeters. From this point the detection zone will begin to narrow, ultimately reaching zero when the distance from the sensor is a little more than 4 meters."

    I currently use 30° for the 0.5m max range

View all 13 project logs

Enjoy this project?



Rud Merriam wrote 08/06/2018 at 16:40 point

Would like to see the code for this. Can you share it, please?

  Are you sure? yes | no

Humpelstilzchen wrote 08/06/2018 at 16:57 point

The project is based on the Robot Operating System, so most code comes from there, everything else (e.g. the ROS configuration files, the AVR code) is in my git repository

  Are you sure? yes | no

Rud Merriam wrote 08/06/2018 at 18:52 point

How can I clone it from that URL?

  Are you sure? yes | no

Humpelstilzchen wrote 08/06/2018 at 19:18 point

  Are you sure? yes | no

Tegwyn☠Twmffat wrote 07/03/2018 at 08:27 point

Have you thought of burying RFID tags under your carpet for indoor navigation? I wonder if it would work?

  Are you sure? yes | no

Humpelstilzchen wrote 07/04/2018 at 07:30 point

Havn't thought of that yet, I'm using SLAM for indoor navigation. Also I'm currently testing DWM1000 modules.

  Are you sure? yes | no

Tegwyn☠Twmffat wrote 07/04/2018 at 08:12 point

Searching with google I only find one instance of it being used:

  Are you sure? yes | no

evansgp wrote 07/01/2018 at 05:45 point

Hi! Your project is awesome and I'm inspired to do something similar as my next project. One question: I was looking at the Wild Thumper chassis and it says the motors that have built in encoders aren't supported. Which ones are you using? Did you have to do anything special for them to fit?

Edit: Oh, I think I found an answer to my own question:

  Are you sure? yes | no

Humpelstilzchen wrote 07/04/2018 at 07:28 point

Thanks and the pdf is correct, you will need an  additional hole. Btw if you get the 6wd base you will only need encoders for the 2 center motors.

  Are you sure? yes | no

Similar Projects

Does this project spark your interest?

Become a member to follow this project and never miss any updates