Mowbot Design & Implementation

User Manual

This section describes how to operate the system.

Raspberry Pi Configuration

Before you can operate the system as described here, you have to configure the Raspberry Pi (rpi4 or rpi zero 2w) board. Follow the instructions in the section "RPi4 and Rpi Zero 2W" to update board firmware, install the Raspberry Pi OS and needed software (including docker) and build the docker image.

Network configuration

The Picostation2 in the robot electronics box is configured for DHCP. Plug the LAN port of its POE injector into any DHCP-enabled network and look on the DHCP server to see which IP device Picostation2-A was given. Send a browser to that IP, log in, and configure the SSID it should connect to. Disconnect from the DHCP-enabled network and power-cycle. The Picostation and rpi should get an IP from DHCP on the wifi network. If the Picostation doesn't show up on the  list of DHCP leases, power-cycle it.

Vnc

rpi4 has tiger-vnc-server installed. It starts automatically. Get access to a GUI on the rpi by running:

xtigervncviewer rpi4

Note that RealVnc doesn't work on Raspberry Pi OS (bookworm version) as of this writing.

ROS_MASTER_URI (ros1-only)

The default .bashrc sets ROS_MASTER_URI to http://rpi4:11311. It can be changed with the master() bashrc function to, for example, localhost, to run simulation

Mower Startup

Before anything can happen, you must start the ROS SW on the rpi.

ssh rpi4roslaunch mowbot_bringup start.launch

Teleoperation

The mower can be driven manually with an X-box compatible game controller. I use a Voyee bluetooth controller. It powers itself off after 5 minutes of inactivity, and the ROS launch must be stopped, gamepad powered back on, and ROS launch restarted.

First, power on the game controller by pressing P3. The red lights on the front of the unit blink then settle with light 1 on. Check laptop bluetooth to ensure the gamepad is communicating. On the laptop, run the xbox launch:

roslaunch mowbot_bringup xbox360_teleop.launch

Press the Deadman button 'X' to enable driving. The left joystick controls forward/back, left/right

Basic Autonomous Movement

The runner.py script runs on the laptop and allows stringing together a bunch of commands that are executed autonomously in sequence. Example to rotate 90 degrees CCW them move 0.5m forward:

rosrun mowbot_bringup runner.py roto 90 movo 0.5

Without arguments, runner.py prints supported commands

Many example scripts that use runner.py are in catkin_ws/scripts. They should work on both the simulation and hardware.

RTK GPS

Manually start the RTK GPS app by running the launch file on rpi

ssh rpiroslaunch mowbot_hardware F9P

Run u-center if needed by plugging the F9P into the dev laptop USB and running it under windows:

Note: I could not get map view to work, despite creating a Google maps API key and installing it into u-center.

Simulation

Set master to localhost. Then run the simulation with the simulation launch file:

master localhostroslaunch mowbot_gazebo gz_mower.launchrosrun mowbot_bringup drive_straight_odom.py 2

Tips & Tricks


Backups

Backups are on laptop in ~/Documents/Robotics/Mowbot/Backups. To back up the /boot and / partitions of the RPi SSD, plug the SSD into laptop and run:

sudo rsync -aAXv /media/bouchier/writable --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found"} writable

ROS 1 Docker Operation

Build the docker container ros1_laptop in ~/Documents/Robotics/Mowbot/Docker/ros1_laptop by running command ./build_it.sh. The container contains the libraries needed to run Mowbot ROS1 SW. It can support a GUI by using vnv

Docker tips & tricks

Engineering Documentation

System Requirements

Use Cases

Requirements



System Description

Mowbot is based on a modified Friendly Robotics RL500 robotic mower. (Friendly Robotics is now Robomow - a division of MTD.) The mower was built and sold around the year 2000, and is a second-generation unit. (Robomow is now on their 5th generation).

The grey battery box in the rear of the unit, which used to house two 12V 18Ah SLA batteries has been repurposed to hold some LiPo batteries and the custom electronics. It is now called "The Electronics Box".

The stock RL500 electronics is used as-is to run the drive motors and blade motors and provide overload/overtemp and other protection. A diagnostic port on the back of the Mower Controller is wired to the electronics box, from where custom software issues drive and blade motor commands and senses robot status. The protocol for talking to the mower is proprietary and has not been released.

The system-design approach taken is to use the OEM mower as-is (as much as possible) to gain the benefits of its mechanical design and low-level motor control HW and FW, and to install smarter, RTK-GPS-based navigation hardware and software to provide improved operation. The goals of the upgraded design are:

The picture below shows the mower with its major components. The mower controller can be used to drive the mower, but apart from the diagnostic port, is otherwise unused. The lid of the electronics box has the GPS antenna and a depth camera on it. RTK-GPS is used for localization, and the depth camera for obstacle detection and remote teleop control. A buck-boost DC-DC converter is powered from a scavenged laptop power brick, and provides shore power and charging power to the mower and electronics box.

Electronics Box Block Diagram

The block diagram is shown below. 

Electronics Box Components Function

The electronics box has a 2-layer architecture: 

The Autonomy layer provides mission planning and execution control, including overall direction control and vision-handling. The Realtime layer provides the interface to the mower, and odometry and other low-level data that should be handled in a realtime manner.

The Raspberry Pi is network connected by a Picostation Wifi device which allows communication to the home Wifi access point and thereon to the internet. RTK GPS corrections are obtained over Wifi from an internet corrections source (rtk2go).

The ESP32 runs the realtime software at a 20Hz loop rate. The realtime software comprises:

HW Configuration

Mobot's HW configuration is:

Compute Subsystem

Sensors

Comms

Power Subsystem

External equipment

Electronics Box

This section shows the construction of the electronics box and associated HW. The picture below shows the electronics box without its lid, wired to the controller. The mower-encoder signals are tapped into inside the mower chassis and brought to the electronics box via a connector under the box.


The rear of the box is a flap that can be opened for maintenance when the box is removed from the mower. Mounted to it are a Raspberry Pi running ROS and ethernet-connected to the wifi station. Beside the Raspberry Pi is a box containing an ESP32 microcontroller running FreeRTOS in the Arduino environment, and a Ublox ZED-F9P GPS receiver. Under the ESP32 is a level-shifter proto board, which converts the 5V encoder pulses to 3.3V

The picture below shows the rear view of the electronics box with its flap open and its lid beside it. Labels identify the RPi, GPS receiver, ESP32 on the flap, as well as the Picostation which provides wifi access, and the powered USB hub which provides power to the high-power devices (camera, SSD). The lid with GPS antenna and the depth camera are identified. 

A clear plastic mid-plane  mounting plate holds the wifi station, POE injector, USB hub and SSD. The wifi station is a Ubiquity pico-station that links to a Ubiquity Rocket M2 access point in the attic of my house. The SSD is mounted to the back side of the midplane. See the picture below.

The front wall of the box is the power plane, with an ideal diode, 24v->5V converter, SSR and terminal strips. See the Power Subsystem section for design details. See the picture below, which is taken with the midplane removed from its mount and folded rearward. The SSD on the midplane can be seen. The antenna for the Picostation can be seen mounted to the front right wall.

Looking down from the top of the electronics box, the BMS and IMU are labeled. They are mounted to the base of the electronics box, below the rear flap and midplane assemblies..

Mowbot is shown below without its cover. The 3 blade motors and two drive motors can be seen, encircling the single large control board which handles the serial protocol from the electronics box and contains the motor drivers..

Power Subsystem Design

See the power wiring diagram below for detailed design. The major features of the design are:

SW Operation

Use Cases

SW Requirements

SW design

The image below shows the block diagram of the SW that runs in the electronics box.

The ROS SW repo is at https://github.com/PaulBouchier/Mowbot

The ESP32 FW is in several repos:

Odometry & Drive Train

Mowbot Drive Train Measurements

Gear Sizes

Hall effect sensor toggles each time a magnet goes by. Two magnet passes/motor revolution. Sensor holds output from last sensor until the one on the opposite side passes over it, when it toggles. i.e. output toggles each half motor rotation, complete cycle each rotation.

At max speed (manual operation on blocks), wheels turned 19 times in 30 sec, i.e. 0.63 rot/s => 0.517m/s => 41 motor revs/sec at max speed. Therefore I will see 41 cycles (80 transitions) per sec at max speed. Each cycle represents 0.817m/65.45 = 0.012m of wheel movement. Each transition represents 0.0062m of wheel movement. At full speed, transitions will happen every 12ms, at 1/4 speed every 48ms. i.e. with a 50ms control loop, only get 4 transitions/cycle at full speed, 1 transition/cycle at 1/4 speed. IOW not enough transitions to control wheel speed. 

Proposal: Control period between transitions

Block diagram and sample timing diagram shown below.

Encoder ISRs place timestamps into queues each time a left or right encoder changes state (each half motor revolution). The MowbotOdometry task pulls the encoder change timestamps out of the queue every 50ms and processes them to develop leftSpeed and rightSpeed, and the robot pose x, y, and theta.

ESP32 Design

The ESP32 embedded computer is mounted on a carrier which contains TTL->3V converter logic, and terminations for other electronics managed by the ESP32. The HW block diagram is shown below.

The ESP32 runs FreeRTOS as shipped from the factory. It is used to ensure that the IP stack gets sufficient run-time on CPU-0. The PlatformIO development environment is used to create the software system, which spawns several tasks when it starts:

The design is highly object-oriented, with each spawned task running in an object which may contain other objects appropriate to its function.

The design uses the mediator pattern, in which a mediator object acts as an interface to each of the other classes, so that none of the other classes (MowbotOdometry, RL500CommsTask, PiLink, TxLog, TxOdometry) need have direct interfaces to each other - they all go through the MowbotMediator object to communicate with each other. This simplifies testing each object by itself - a dummy mediator sufficient for that object's interfaces is all that's needed.

Dev Environment

ESP32 code is developed with the PlatformIO extension to VS-Code. The workspace definition is on Paul's laptop in ~/Documents/PlatformIO/Projects/MowbotEsp32-workspace.code-workspace. There are 4 projects that make up the codebase:

MowbotRealtime Startup

The system follows the Arduino model for startup: the setup() function is called once, then the loop() function is called continuously.

MowbotRealtime/src/main.cpp contains the setup() entrypoint for the software system. The module instantiates the MowbotOdometry, PiLink, and RL500CommsTask classes. The module also instantiates messages used by each module to communicate.  The Arduino setup() entry point calls each object's init() function which spawns the task that does that objects's work. The loop() function does no work.

The module provides a library in MowbotRealtime/lib/MowbotRealtime/src which mediates calls from the three tasks and passes them on to the proper object for servicing.

RL500CommsTask

This task contains messages that are passed between it and the mower. There are two general kinds of message: TxMsg going to the mower, and RxMsg coming from the mower.  It also contains a request queue upon which other tasks can place various kinds of RL500TaskRqst messages. RL500CommsTask pulls requests off the request queue and actions them by interacting with the mower. Requests can be things like motor speed request, BIT-mode request to put the mower into BIT mode, light-mode request to set the light on or off, and so on. A block diagram of the objects used by the task is shown below.

MowbotOdometry task

To be written


RPi4 and Rpi Zero 2W Configuration

This section describes how to install the latest Raspberry Pi OS onto an SSD on a Raspberry Pi and to configure it for developing ROS software.

The overall approach taken is to run Raspberry Pi OS on the RPi, because it is the latest and best suited to RPi hardware, but ROS programs are run inside a docker container, because ROS isn't supported on Raspberry Pi OS. The ROS docker container uses the host's networking stack, and mounts /dev for hardware access. 

User bouchier is the main user account on both laptop and the RPi and inside the ROS docker container, and has ability to commit to github from either laptop or rpi4, and to ssh from laptop to rpi4 without needing to enter a password. 

ROS source code is saved in the recommended places on RPi OS and is edited (generally) on the RPi OS filesystem then built and tested and run in the docker container. Build products are stored on the RPi OS filesystem, so as to persist across container instances. 

Containers are (generally) removed after each use, and re-instantiated from the image each time they're started. See the ROS docker page for more details.

The ROS docker containers are configured with the ROS GUI apps, which can be run either on the rpi or on the laptop. Generally, running on the laptop will be better.

rpi-imager Configuration

In this step we connect the boot media (typically SD-card, but could be SSD) to the laptop, run rpi-imager to install a firmware update image or a Raspberry Pi OS image, then reconnect the boot media to the rpi and boot the rpi from it.

RPi4 SSD Boot Notes

Disk I/O Benchmark results

Insalled and ran the storage benchmark test with the following command:

sudo curl https://raw.githubusercontent.com/TheRemote/PiBenchmarks/master/Storage.sh | sudo bash

which gave the following RPI4-with-SSD performance results, which are about in the middle of the range of reported results:

     Category                  Test                      Result     HDParm                    Disk Read                 322.23 MB/s              HDParm                    Cached Disk Read          308.07 MB/s              DD                        Disk Write                60.8 MB/s                FIO                       4k random read            10773 IOPS (43093 KB/s)  FIO                       4k random write           7864 IOPS (31459 KB/s)   IOZone                    4k read                   23416 KB/s               IOZone                    4k write                  17973 KB/s               IOZone                    4k random read            18942 KB/s               IOZone                    4k random write           21717 KB/s               
                          Score: 5183 

The RPi zero 2W with SD card gave the following performance results:

     Category                  Test                      Result     HDParm                    Disk Read                 22.07 MB/sec             HDParm                    Cached Disk Read          22.10 MB/sec             DD                        Disk Write                12.4 MB/s                FIO                       4k random read            2073 IOPS (8294 KB/s)    FIO                       4k random write           872 IOPS (3488 KB/s)     IOZone                    4k read                   7978 KB/s                IOZone                    4k write                  2964 KB/s                IOZone                    4k random read            6458 KB/s                IOZone                    4k random write           4068 KB/s                
                          Score: 1071

RPi4 Firmware Config

This section describes settings in the boot config files, and associated pins. The only change required is to modify config.txt and cmdline.txt See the table below for the mapping of UARTs to pins, devices, and use. All 5 UARTs are enabled.

# Enable uartenable_uart=1
dtoverlay=uart2dtoverlay=uart3dtoverlay=uart4dtoverlay=uart5

RPi Zero 2W Config

This section describes settings in the boot config files. The only change required is to modify config.txt and cmdline.txt.

# Enable uartenable_uart=1

This causes the OS to present a login on the serial console, and to print boot messages to the serial console.

Verify serial console and networking (RPi4 and RPi Zero 2W)

RPi4 UARTs

Raspberry Pi OS Configuration

These are the steps to configure Raspberry Pi OS on Mowbot's RPi once it has been installed and is bootable. 

Host rpi4    HostName rpi4    User bouchierHost rpiz2w  HostName rpiz2w  User bouchier

Mowbot Ubiquity Config


Package Installation

This section describes installation of packages needed to make ROS on RPi work as desired. Note: some of these steps are no longer necessary if using the 1.8 version of rpi-imager; it does a lot more to pre-configure the system.

VNC

VNC was chosen for graphical use because generally the robot's RPi would run headless, but remote desktop capability is sometimes valuable. 

Observations: the current version of RPi OS doesn't support the RealVNC server which ships with it, owing to it using Wayland and RealVNC using X11. Tigervnc is the recommended alternative

Firefox (Optional)

Install firefox: sudo apt install firefox

miniterm

Configure python for miniterm, (serial port access from python, etc). sudo apt install python-is-python3; sudo apt install python3-pip; Add the following to .bash_aliases: alias miniterm='python -m serial.tools.miniterm --eol LF'

git config file (~/.gitconfig)(

Configure git to use my favorite aliases & tools. Note that git difftool would have to be run in a VNC window, since it uses meld, which is a graphical diff app. Add the following to ~/.gitconfig. Note: the indented lines need to be preceeded by tab, not spaces

[user] email = paul.bouchier@gmail.com name = Paul Bouchier
[alias]s = statusco = checkout
[diff]tool = meld[difftool]prompt = false[difftool "meld"]cmd = meld "$LOCAL" "$REMOTE"
[merge]tool = meld[mergetool "meld"]cmd = meld "$LOCAL" "$MERGED" "$REMOTE" --output "$MERGED"

Make ROS source directories

mkdir -p catkin_ws/srcmkdir -p ros2_ws/src

Mowbot GPS Packages

u-center (dev laptop only)

Install u-center on laptop running Windoze. u-center is a Windoze (x86) tool for checkout and analysis of ublox receivers. 

Download latest version (v22.05) of u-center (not u-center2) from the ublox site. Unzip and run under windows:

UTM conversion

These steps install packages which convert the GPS lat-lon fix to UTM, for easier use with odometry, rviz etc. The GeographicLib which contains conversion routines is built as part of the ROS docker container. The ROS-UTM-LLA package which subscribes to the /gps/fix topic and uses the GeographicLib library to convert the fix to UTM and publishes the UTM fix needs to be cloned. Note: the UTM zone parameter in ROS-UTM-LLA is not used in this application, and can be left as-is.

ROS-UTM-LLA package: https://github.com/PaulBouchier/ROS-UTM-LLA

git clone git@github.com:PaulBouchier/ROS-UTM-LLA.git

rviz_satellite (dev laptop only)

The rviz_satellite package provides an rviz plugin that enables viewing robot position in the context of satellite imagery. You need to create your own Mapbox account and get a mapbox api key (www.mapbox.com) and insert your key into the AerialMapDisplay URI. Note: my URI key has been obfuscated in the git repo to limit unauthorized use of my account.

Reference: https://github.com/nobleo/rviz_satellite

Clone rviz_satellite into the dev laptop ROS src directory

git clone https://github.com/nobleo/rviz_satellite.git

ublox-gps

rtcm_msgs

Docker Installation and Configuration

# Aliases#--------# Docker functions## if ~/.active_docker doesn't exist, create it & set active_docker to ros1_x86_linuxif [ ! -f ~/.active_docker ]then  echo "ros1_rpi" > .active_dockerfiexport ACTIVE_DOCKER=`cat ~/.active_docker`
active_docker () {  if [ $# -eq 1 ]; then    echo ${1} > ~/.active_docker  fi  export ACTIVE_DOCKER=`cat ~/.active_docker`  echo $ACTIVE_DOCKER}
# Docker aliasesexport PATH_TO_ROS_DOCKERS=${HOME}'/ROS_dockers'
alias docker_build='cd ${PATH_TO_ROS_DOCKERS}/${ACTIVE_DOCKER} && docker build -t ${ACTIVE_DOCKER} .'alias dr='cd ${PATH_TO_ROS_DOCKERS}/${ACTIVE_DOCKER} && ./run_it.sh $@'alias dsl='docker start -ai `docker ps -lq`'alias de='docker exec -it `docker ps -lq` bash'
# ROS aliasesalias swri_console='rosrun swri_console swri_console'

Mowbot SW Installation & Test

This section describes how to install Mowbot's ROS SW and related packages onto the RPi.


Test Results and Observations

RPI4 Performance

RPi Zero Performance

Power

Notes

ZED-F9P