The robots are coming (virtually)

Yes, it’s several years since I last posted anything. But I think this might conceivably be useful for somebody, in a very specific set of circumstances.

Install ROS and baxter emulator on WSL

This is a fairly detailed set of steps to install ROS Noetic and the Baxter SDK and its 3d graphical emulator on a Ubuntu system running in Windows, to allow development of ROS applications for Baxter without a real robot. It’s mostly written down to help me remember the steps I had to go through to get everything working with WSL and Noetic even though the Baxter SDK has been prtty much abandoned and doesn’t support newer versions of ROS. It’s actually not that hard, but there area a lot of steps. I hope you find it useful.

Some of this comes from Setting up ROS in Windows through WSL2, and some from Baxter workstation setup, and more from Github. Other bits I’ve worked out through trial and error and a number of web searches.

Preparation

I’m assuming you already have the Windows Subsystem for Linux version 2 (WSL2) installed on your windows PC. If not, then this won’t be much use. I’m also assuming you have a Ubuntu distro installed (I’m using 20.04) and the Windows Terminal as an interface to it.

Install X VxXsrv server to allow gui apps

VxXsrv is an XWindows server program which runs in windows, so the WSL Ubuntu instance can use it as a front end for graphical applications. It works really well.

NB: This bit is done in Windows.

From sourceforge download the installer and run it. When the install is complete, run VxXsrv and on its first run make sure ‘Native OpenGL’ is not selected, and ‘Disable access control’ is selected. Save the config for future runs.

Use ifconfig to find the ip v4 address of the the windows machine, because you’ll need it for the next step (in WSL)

From here on, work in your Ubuntu instance through the Windows Terminal

Configure display in WSL to use X server

Add the display config to your bash script

echo 'export DISPLAY=999.999.999.999:0.0' >> ~/.bashrc

Replace 999.999.999.999 with the ipv4 address you found in the previous step. Note that this may change if you are on a wifi network, and it will need to be reconfigured every time it does.

Make the config active

source ~/.bashrc

Optional: test the x server

sudo apt update
sudo apt install x11-apps
xcalc

If all is well, you’ll see the xcalc running in an X window on your windows desktop

Install ROS

Make sure everything is up to date

sudo apt update
sudo apt upgrade

Add ROS package information to sources list

sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'

Add the keys to allow these extra sources to be used. Install curl if it’s not already present, then use it to download keys

sudo apt install curl

curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo 
apt-key add -

sudo apt update

Install ROS Noetic:

sudo apt install ros-melodic-desktop-full

Prepare for ROS use by configuring bash script

echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc
source ~/.bashrc

Install development packages

sudo apt install python3-rosdep python3-rosinstall python3-rosinstall-generator python3-wstool build-essential

When it’s done

sudo rosdep init
rosdep update

test it!

roscore & rosrun rviz rviz

Create ROS workspace

mkdir -p ~/ros_ws/src

Source ROS and build

source /opt/ros/noetic/setup.bash

Build and Install

cd ~/ros_ws
catkin_make
catkin_make install

Install Baxter SDK

cd ~/ros_ws/src
wstool init .
wstool merge https://raw.githubusercontent.com/RethinkRobotics/baxter/master/baxter_sdk.rosinstall
wstool update

Source ROS setup

source /opt/ros/noetic/setup.bash

Build and install

Be prepared for this to fail with errors!

cd ~/ros_ws
catkin_make

Don’t worry. Because we are now using Python 3, some of the scripts need a bit of tweaking because they are using Python 2 syntax.

in file ~/ros_ws/src/baxter_interface/src/baxter_interface/robot_enable.py, find a line which says

except OSError, e:

and change it to

except OSError as e:

Then try again:

cd ~/ros_ws
catkin_make
catkin_make install

Set up ROS workspace

Download the baxter.sh script. This will set the right parameters for ROS to communicatwe with the (emulated) robot.

$ wget https://github.com/RethinkRobotics/baxter/raw/master/baxter.sh
$ chmod u+x baxter.sh

Customize the baxter.sh script

Edit the baxter.sh shell script making the necessary modifications to describe your development environment. In WSL, th linux system will probably have a different IP address to the windows PC hosting it. This is absolutely fine for the baxter simulator, but you need to know what it is. The hostname comand will tell you:

hostname -I

Using your favorite editor (you’ve got an X server now, so you could use xedit) edit ~/ros_ws/baxter.sh and make the following changes:

Edit the ‘baxter_hostname’ field

baxter_hostname="baxter_hostname.local"

Edit the ‘your_ip’ field. Modify where ‘your_ip’ is the IP address of your PC.

your_ip="192.168.XXX.XXX"

Modify ‘ros_version’ to noetic:

ros_version="noetic"

Save the file.

Initialize your SDK environment

From this point forward, your ROS environment setup should be as simple as sourcing the baxter.sh script from the root of your Catkin workspace:

cd ~/ros_ws
. baxter.sh

"Should". What a great word.

Getting it all to work

Install the baxter simulator

cd ~/ros_ws/src
git clone https://github.com/RethinkRobotics/baxter_simulator.git
wstool merge baxter_simulator/baxter_simulator.rosinstall
wstool update

Install other dependent packages:

cd ~/ros_ws/src
git clone https://github.com/ros/xacro.git -b noetic-devel
git clone https://github.com/ros/roslint.git

Build everything

Expect this to fail!

source /opt/ros/noetic/setup.bash
cd ~/ros_ws
catkin_make

The emulator uses the Qt4 user interface library, but this has been superseded by Qt5 and is not installed by default. So it needs to be manually added (unless you fancy editing all the files which use it and converting them to Qt5). We need to use a third party PPA to do this:

sudo add-apt-repository ppa:rock-core/qt4
sudo apt update
sudo apt install qt4-default

Then try catkin_make again:

catkin_make

And once again, it will fail. There appear to be loads of errors, but in fact there are only two files which need to be edited:

1. ~/ros_ws/src/baxter_simulator/baxter_sim_kinematics/src/arm_kinematics.cpp

Edit the lines which says

boost::shared_ptr<const urdf::Link> link = robot_model.getLink(tip_name);
boost::shared_ptr<const urdf::Joint> joint;

to read as follows (i.e. replace the reference to the boost libraries with the std one).

std::shared_ptr<const urdf::Link> link = robot_model.getLink(tip_name);
std::shared_ptr<const urdf::Joint> joint;

2: ~/ros_ws/src/baxter_simulator/baxter_sim_hardware/src/baxer_emulator.cpp

Edit the lines which says

cv_ptr->image = cv::imread(img_path, CV_LOAD_IMAGE_UNCHANGED);

to read as follows (updateing to match changes in the OpenCV library).

cv_ptr->image = cv::imread(img_path, cv::IMREAD_UNCHANGED);

Then try catkin_make again, and assuming it works (you might get some warnings, but you can ignore them) do catkin_make install

catkin_make
catkin_make install 

Time to try it out

Use the baxter.sh script with the ‘sim’ parameter to set up parameters for simulation rather than a real robot.

cd ~/ros_ws
.\baxter.sh sim
roslaunch baxter_gazebo baxter_world.launch

And it fails again. This time it’s a ROS launch file which needs modifying to use xacro instead of the old xacro.py. Edit the file ~/ros_ws/src/baxter_simulator/baxter_gazebo/launch/baxter_world.launch and change the section below

<param if="$(arg load_robot_description)" name="robot_description" command="$(find xacro)/xacro.py --inorder $(find baxter_description)/urdf/baxter.urdf.xacro gazebo:=true"/>

removing the ".py" from the xacro command:

<param if="$(arg load_robot_description)" name="robot_description" command="$(find xacro)/xacro --inorder $(find baxter_description)/urdf/baxter.urdf.xacro gazebo:=true"/>

That’s it. You sould be good to go, now. Run the following command

roslaunch baxter_gazebo baxter_world.launch

And you should see Gazebo fire up, with a model of Baxter in it, and also a window showing emulations of the arm and body control dials and buttons. Note that these are running alongside any other Windows apps! It’s a bit like magic.

You can now open otehr Windows terminal sessions to the same Ubuntu instance and run other ROS nodes to control the simulated robot. As with a real robot, you need to enable it using the enable_robot script fromt eh baxter_tools package before it will do anything. You can also run the standard sample demos, e.g. the arm wobbler:

./baxter.sh sim
rosrun baxter_examples joint_velocity_wobbler.py

Though you might need to edit the first lines of python files to ue Python3 instead of python or python2. And in enable_robot.py you’ll need to correct the syntax of an exception handler and a print statement. But they are left as simple exercises for the reader 🙂

The sons of Martha

Rudyard Kipling wrote a poem called ‘The sons of Martha‘ which is a gentle hymn of praise to those in society whose graft keep things going while others enjoy themselves. I like to think it’s about engineers. It contains a line which I really like: ‘They do not preach that their God will rouse them a little before the nuts work loose‘. If I’d paid a little more heed to that, I wouldn’t now have a pile of wreckage rather than a working drone. I failed to properly tighten the propeller nuts, and sure enough one came loose at altitude. It makes for an amusing video (I hope I haven’t given away the ending), but it may be a little while before the drone flies again.

Making things to make things to make things

I recently acquired a woodturning lathe. Unfortunately, it was missing a rather important part – the centre drive head, which grips the wood being turned. It’s not huge or complex. It just looks like an elongated nut with spikes on one end which grip the wood being turned. At the other end is an internal screw thread, which fits on to the drive shaft of the lathe:
drive_centre 1
Because the lathe is old (you can tell from the black and white picture), the manufacturer doesn’t sell the spare part any more. They don’t seem to appear on eBay, presumably because anyone with a lathe isn’t going to sell such an important component. If I had any significant metalworking machinery, I could make one – but I don’t (yet). I do have a 3D printer, however.

I didn’t do any stress analysis on the component, but my instinct told me that a printed part wouldn’t going to be strong enough for this job. The centre has to hold a largish lump of wood spinning at up to 3000rpm. It has to do this while the wood is carved by a chisel, and most importantly it has to do this while I am standing very close to it. It’s not allowed to break. The body of the part needs to be reasonably strong, and the spikes on the end doubly so. It’s not really printable unless you have a SLS metal printer. If I could afford one of those, I wouldn’t be buying an old second-hand lathe.

My solution was to cast a new component, and to 3D print the mould for it. Some years ago I came across Plastic Padding Chemical Metal, which is a two-part polyester resin filled with metal powder. It’s designed for repairing things, and it’s very strong when it sets. I’ve mended various things with it over the years, and none of them have ever failed. I thought I might be able to use it to cast a new part. My wholly unscientific feeling was that it ought to be strong enough for the body of the thing, but probably not for the spikes. For that purpose, some hardened steel masonry nails might do the job. Casting would allow me to embed the nails in the part, and to create the required femall screw thread by simply casting around the male one.

I used OpenSCAD to design a three part mould, and printed it:
mould_01

This is actually the Mark III version. The first two did not have a separate end piece, and I eventually realised that once I had filled the mould with resin and put the nails in, I would not be able to separate it. Doh! One thing to bear in mind is that Plastic Padding is sticky. It’s designed as a repair material, so it’s intended to stick to things. I didn’t want it to stick to the mould, or to the screw thread on the drive shaft. To stop this, I lined the mold with sellotape, and covered the shft’s screw thread with a layer of PTFE plumber’s tape. You can’t beat a good bodge. Here’s how the mould looks, half assembled and almost ready for filling:

mould_02

And here it is fully assmbled and filled with sticky goo, waiting for it to set:

mould_03

After 20 minutes, I opened up the mould (you’ll have noticed the carefully-planned slots on the mould join line, for levering it apart) to reveal this mess:

mould_04

Which eventually delivered a component which clearly needed a bit of cleaning up:

mould_05

But it works! Just for entertainment, I mounted a 2″ square section block of cheap pine, and turned it into one of the roughest spindles you’ll ever see – but the Plastic Padding component worked fine:

mould_06

Now I just need to learn how to turn wood properly…

Incidentally, I’m not sponsored by Plastic Padding. I’m not averse to them sending me a free pack, either 😉

Happiness is a clean head

I’ve not posted much about 3D printing for a while, largely because I haven’t ben able to get my printer to make a decent print without a lot of fiddling. Prints were rough, structurally weak, and generally unsatisfactory. I Tried all sorts of kludgy fixes, but nothing seemed to work reliably. I was beginning to think that the filament I was using was beginning to degrade (some of it is a year or more old). Then I had a conversation with a colleague about the 3D printers (Ultimaker II’s) at work. They were suffering similar problems, and were returned to good operation by replacing the print heads. It turns out that with sufficient usage, the tiny hole in the hot squirty nozzle (that’s a technical term) becomes both worn and partially blocked with overcooked filament residue. It’s a bit like the virtually indestructible stuff which accumulates on the the tins in which you roast vegetables. You do roast vegetables, don’t you? This (blocked nozzles, not ineffectually-cleaned roasting tins) results in a number of problems:

  1. Low extrusion rates
  2. Filament feed skipping, because it can’t push the filament hard enough
  3. Erratic extrusion

At work, we’ve started to think of the print head (or at least the extrusion nozzle) as a consumable item, to be replaced routinely after an as-yet undetermined quantity of filament has been extruded.

Why, I thought, couldn’t I try this at home? No reason at all. Apart from anything else, hotend technology has improved since I bought mine. It seems the generally-accepted best DIY print head is the e3dv6. It’s cleverly designed to separate the hot part from the rest by as small a thermal bridge as possible, and also has a built-in fan to keep the cool part cool. And unlike my old hotend, it’s got a separately-replaceable nozzle. So if (when) it does clog or wear out, it will be cheap to replace.

e3dv6

I bought one. Naturally, it needed a new part printing to fit it on to Richmond, but that was easy. And guess what? It works brilliantly. In a stroke, I’m back to creating smooth, accurate prints. Indeed, I’m tempted to say that the quality is better than the J-Head generated when it was new. I’m really quite chuffed.

Printed lathe parts online

Since I posted a video of my 3D printed lathe on YouTube, the video has now been viewed over 100,000 times. If a typical working day is 8 hours, and the working year is 250 days or so, then it’s the equivalent of about two solid years of someone watching it. That’s not a job I’d want.

assembly2

Anyway, a number of people have asked for the STL files so they could make one themselves. I’ve finally got them in some sort of order, and you can now download a zip file with them all from here [wpdm_package id=’423′].

If you haven’t seen the video, here it is:

Cracking the cube

I can’t take any credit for this.

Earlier this summer, I built a Rubik’s cube solver from a Lego Mindstorms set. I simply followed the plans for the Mindcuber design. It seemed to work quite well, but my Rubik’s cube had one face which was much stiffer to rotate than others, and the power available from the Lego motors was insufficient to reliably turn it. So it’s been sitting in my office for a while doing nothing. Today, however, Rob lent me a speed cube he bought from Amazon. It’s designed to take as little torque as possible to rotate, and has nicely chamfered edges so it doesn’t jam if it’s slightly out of alignment when you try to turn it. In the picture, the speed cube is the one on the left.

rubiks_cubes

The cube-solver robot loves it. I’ve posted a video of it on the YouTubes at http://youtu.be/iDMrePmmNA0 .

The whole thing is a supremely pointless exercise, but it is rather hypnotic to watch.

…and we’re back!

As a close follower of my blog, you will doubtless have noticed that it has been off the air the last few days. I didn’t. Rob drew my attention to its non-existence. It turns out that there were hosting troubles, and to cut a dull story short I’ve had to move the blog to a different hosting provider.

It’s more or less fixed now, but still has a few niggles to sort out. Sorry for any inconvenience.

More tiny WiFi success

As I have posted before, I have been playing with the super-cheap WI07C WiFi module based on the ESP8266 chip. I’ve now had sufficient success with it that I can publish a post on a working project. This simple setup uses an Arduino nano to read temperatures from to 18BS20 sensors, formats the data as JSON and then sends it over WiFi to a server on my home network. It’s cheap and simple. Here’s the fritzing diagram:

WI07C_bb

You may notice the Adafruit level shifter board in there too. That’s because the digital IO from the arduino is 5V, but the WiFi module needs 3.3V. The Adafruit module is a dead easy way of joining the two. The temperature sensors use a three-wire protocol which allows you to connect many in parallel and address each one individually. there’s a software library which takes care of this.

Here’s the Arduino sketch. It uses Miles Burton’s temperature control library to read from the sensors, so you’ll need to download that. NB: this code is not a shining exaple of style or completeness. It’s a quick hack to get something working. It does no error checking or reconnection if there are problems. You may find yourself pressing the reset button a lot.

You might also note that the hardware serial port is required for the WiFi module, which needs 115200 baud. This means that you can’t upload a new sketch to the arduino while it’s connected to the WiFi module. I just whip out the wires to the TXD and RXD pins on the arduino while I’m uploading, and all is well.

The sketch tries to join the WiFi network, and then tries to establish a simple TCP connection to a server IP address and port of your choice. Once the connection is established, it checks the temperature sensors every 10 seconds or so and sends the temperatures to the server in JSON format, thus: {"temp":[22.63,22.81]}. That’s all it does. You’ll need a TCP server listening on your chosen IP address and port, of course. It seems to work quite reliably for me.

#include <SoftwareSerial.h>
#include <OneWire.h>
#include <DallasTemperature.h>

#define SSID        "MyHomeSSID"
#define PASS        "MyPassword"
#define TARGET_IP   "192.168.1.xx"
#define TARGET_PORT 5000
#define TEMPERATURE_PIN 9

SoftwareSerial dbgSerial(10,11); // RX,TX
OneWire wire(TEMPERATURE_PIN);
DallasTemperature sensors(&wire);

void setup()
{
   // WiFi module needs fast serial, so must use the hardware port which is also used for
   // uploading sketches
   Serial.begin(115200);
   Serial.setTimeout(5000);

   // For debugging, we therefore need a software serial port.  This can be much slower.
   dbgSerial.begin(9600);
   dbgSerial.println("Starting");

  delay(1000);

  // Connect to the wirelsess network
  dbgSerial.println("Joining network...");
  Serial.print("AT+CWJAP="");
  Serial.print(SSID);  
  Serial.print("","");
  Serial.print(PASS);
  Serial.println(""");
  receive();

  // Just check that the WiFi module is joined to the network
  dbgSerial.println("Check connection...");
  Serial.println("AT+CWJAP?");
  receive();

  dbgSerial.println("Initialising sensors...");
  sensors.begin();


  dbgSerial.println("Connecting to server...");
  Serial.print("AT+CIPSTART="TCP","");
  Serial.print(TARGET_IP);
  Serial.print("",");
  Serial.print(TARGET_PORT);
  receive();
  delay(5000);

  dbgSerial.println("Ready to rumble!");
}

int incomingByte=0;
bool echoLocal = true;

// Get the data from the WiFi module and send it to the debug serial port
void receive(){
  delay(500);
  while (Serial.available() >0) {
    incomingByte = Serial.read();
    dbgSerial.write(incomingByte);
  }
  dbgSerial.println();
}

char temp1[10];
char temp2[10];

void loop()
{

  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  dbgSerial.print("Requesting temperatures...");
  sensors.requestTemperatures(); // Send the command to get temperatures
  dbgSerial.println("DONE");

  dtostrf(sensors.getTempCByIndex(0),1,2,temp1);
  dtostrf(sensors.getTempCByIndex(1),1,2,temp2);  

  String json="{"temp":[" + String(temp1) + "," + String(temp2) + "]}";
  dbgSerial.print("Sending ");
  dbgSerial.println(json);

  // Send the data to the WiFi module
  Serial.print("AT+CIPSEND=");
  Serial.println(json.length());
  delay(500);
  Serial.print(json);
  receive();


  delay(10000);
}

This is a work in progress. I’ll be updating it soon. But for now, I’m very pleased with the simplicity of the WiFi modules, and even more pleased with their low cost (I am a Yorkshireman, after all).