robot arms in Robot Overlord
News

Friday Facts 11: How to add a robot arm to Robot Overlord (2022)

Robot Overlord is going to be the inkscape, the VLC, the Steam of robot arms – the one vendor-agnostic interface everyone teaches, knows, and loves. In order to get there it has to support every robot arm under the sun. This post is for robot arm makers that want to save time by not writing all their own code.

Some of the arms already available

Did you know Robot Overlord speaks natively to Marlin 3D printer firmware? Save even more time by using the same firmware.

You will need

  • A 3D CAD model of your robot arm
  • The D-H parameters of the arm in the same pose as it appears in your CAD file
  • The ability to write Java code for the Robot Overlord project
  • Some familiarity with git (forks, commits, pull requests)

Prepare your CAD file

It is easiest to export your arm into discrete moving sections, all of which with the same origin at the bottom center of the base of the arm (see slide 1). This is the same origin as the D-H parameters.

A meca500 robot, color coded with the base and six parts. the origin would be in the red part, on the same axis of rotation as the pink part

To help Robot Overlord run smoothly and to protect your IP it is recommended that you decimate the model by removing all hidden internal structures and components. Consider leaving screw heads while removing the threaded sections to save many megabytes of file size.

Each discrete section should be exported as an OBJ or STL file. (more on this later.)

The exported files should be located in /src/main/resources/[your robot folder]/. So if your robot is named Foo then it would be /src/main/resources/foo/. It would be consistent to name them base, j0, j1, etc.

Prepare your Robot Overlord class

In Robot Overlord’s /src/main/java/com/marginallyclever/robotOverlord/robots/robotArm/implementations you will find the collection of currently supported robot arms. It may be easiest to copy one of these classes and modify it for your purposes. Here is the minimum needed to code your arm. Every instance of Foo should be replaced with your class name.

public class Foo extends RobotArmIK {
	private static final long serialVersionUID = 1L;

	public Foo() {
		super();
		setName("Foo v1");  // the name that appears to users.
	}
	
	@Override
	protected void loadModel() {
		setBaseShape(new Shape("Base","/Foo/j0.obj"));

		// The DH parameters and the model file, added in order from J0 ... J5.  
		// angles are degrees, distances are centimeters.
		// name d r alpha theta thetaMax thetaMin modelFile
		addBone(new RobotArmBone("X", 7.974,     0,270,  0,170,-170,"/Foo/j1.obj"));
		addBone(new RobotArmBone("Y", 9.131,17.889,  0,270,370, 170,"/Foo/j2.obj"));
		addBone(new RobotArmBone("Z",     0,12.435,  0,  0,150,-150,"/Foo/j3.obj"));
		addBone(new RobotArmBone("U",     0,     0,270,270,440, 100,"/Foo/j4-6.obj"));
		addBone(new RobotArmBone("V",15.616,     0, 90, 90,270,-90,"/Foo/j5-6.obj"));
		addBone(new RobotArmBone("W",  5.12,     0,  0, 180,360,   0,"/Foo/j6-6.obj"));

		adjustModelOriginsToDHLinks();
		setTextureFilename("/Foo/texture.png");
	}
}

Now that the arm can be loaded by the app it needs to be on the menu of things that can be created by the user. In /src/main/java/com/marginallyclever/robotOverlord/EntityFactory.java add your new class:

public class EntityFactory {
	private static Class<?> [] available = {
		// ...
		com.marginallyclever.robotOverlord.robots.robotArm.implementations.Mantis.class,
		com.marginallyclever.robotOverlord.robots.robotArm.implementations.Sixi2.class,
		com.marginallyclever.robotOverlord.robots.robotArm.implementations.Sixi3_5axis.class,
		com.marginallyclever.robotOverlord.robots.robotArm.implementations.Sixi3_6axis.class,
		com.marginallyclever.robotOverlord.robots.robotArm.implementations.Thor.class,
		com.marginallyclever.robotOverlord.robots.robotArm.implementations.Foo.class,  // "Foo" must be your class name.
	};
	// ...
}

Now when you run the application and open the Add menu your robot name will appear.

‘Foo v1’ will appear on this list

Model size and orientation fixes

It is possible that your model appears in Robot Overlord too large, too small, or the parts are rotated in a strange way. My solution is to use a modelling program like Blender to rotate, scale, decimate, and even texture the model.

Forward and Up will control the rotation. +Z is always up in a Robot Overlord scene.

Selection Only will simplify your exporting from Blender. In the image above it will only export J2.

Scale will control the size. For models that appear in meters instead of centimeters, choose 0.1. If your model is imperial, you’ll probably want 2.54.

Now share it with …the world!

You’ve changed the code, you’ve massaged the model, it runs on your machine. Now to share it with everyone else! A pull request from you to the Robot Overlord project will tell the dev team that your stuff is ready. This is the best way to make sure your model gets in the way you want it.

No time? Let us do it for you.

We can add your model(s) to our system. Contact us! We’re looking to collaborate and work with everyone. Writing the class is free; preparing the CAD files is specialized work we outsource and will quote.

What about URDF files?

URDF is the Unified Robot Description Format, part of ROS, the Robot Operating System. ROS is a nice system but much harder to get running – part of the reason I work on Robot Overlord. Join the Robot Overlord github project and help make it happen? Imagine what we could do together!

News

Friday Facts 9: Daisy Stepper Driver 1.0

Daisy Stepper Driver is a closed-loop stepper controller that can be daisy-chained.

A stepper controller is a dual h-bridge circuit for controlling a stepper motor. You may be familiar with the A4988 stepper driver common in 2020s 3D printers. This board includes a more advanced model of the same. It can drive any one stepper motor at 24V up to 2A.

Closed-loop means that the board has a brain chip (MCU) that can read the motor position as well as direct. This way it can tell if it missed a step, bumped into something, is being driven, etc.

Daisy-chained means that they can be hooked sequentially. Sequential wires are much shorter. Shorter wires make for easier construction and repair. They are designed for up to 6 Daisies in a row. The Daisies talk to each other via the CANopen protocol.

The MCU is an STM32F103. In speaks CANopen natively while driving the stepper and listening to the sensor.

The CANopen master at the base of the robot can be any MCU that speaks CANopen. It synchronizes each motor and provides a single USB or bluetooth serial connection to the world.

What does this have to do with robots?

This board is designed to fit inside each gearbox of the Sixi 3 robot arm.

The old way a wire from every part had to run all the way through the arm and out the base. To replace the second joint from the bottom you would have to dismantle the entire arm. In the daisy chain model you only need to remove the elbow and disconnect the two cables to the next link in the chain.

Here’s a video of the arm moving IRL. Note the large cable hanging off the side – this version does not have the board in yet. It is the “outside” version of the wiring. I live in constant anxiety that they will get caught on something while moving.

Editor’s note – in this video one motor misbehaves. It was later found that the motor was negative 400-steps per turn instead of the expected 200-steps-per-turn.

Why isn’t the board in already?!

To test the board I have to be able to program it. To program the STM32F103 MCU I need to flash it with a bootloader via the programming pin J6. I have an STLINK V3 MINI to flash the bootloader BUT the MINI has male pins at 1.25mm pitch and my board’s J6 is 2.5mm pitch.

Editor’s note – I believe the larger connector is also a reversible connector.

Do you want to see this board get done? Say something nice on Discord.

What comes next?

Assuming this board is good and can be programmed… the next tasks are:

  • mount the board in the actuator
  • attach the disc to the output of the gearbox
  • run wires from one to the next and test the daisy chain
  • get an appropriate brain board and drive everything synchronously
  • make more boards

At the last stage it will be time to go to Kickstarter to scale production and bring the price down.

Did you design this board yourself?

No, and I’m proud of it! I have played with KiCAD in the past and done a few but this was beyond my skill. I found a great EE on Fiverr, gave him my specs, and he routed everything in a couple of days. Truly blown away by his skill. He even had a PDF step-by-step guide for ordering from PCBWay so I didn’t have to assemble the board or nothing.

Sadly, he closed his account and I have no way to reach him any more. Electroniikka! If you’re out there, know that I want to work with you again. I love working with talented people, it’s fun, easy, and it helps me scale up to the speed I long for.

News

Friday Facts 3: Sixi 3 Java GUI

This week I’ve done a lot to make driving the Sixi 3 arm easier.

You’ll recall from FF1 that I had build a Panel to talk to a robot in Javax Swing.

TextInterfaceToListeners (at the bottom) was the starting point. Then I made a ConversationHistoryList (in the middle). The two are tied togeter in a TextInterfaceWithHistory, such that hitting send copies the message to the history and clicking a line in the history copies it to the input field. Next I made a ChooseConnectionPanel (at the top) and attached that to the TextInterfaceWithHistory inside a TextInterfaceToNetworkSession. Sure, it could have all been in one giant class… but that’s hard to manage, debug, or reuse.

Having made all that, I found it was no better than the existing Arduino serial interface for talking to the robot. My biggest worry is that I make a typo and send the robot crashing through the table before I can hit the emergency stop. So to address this pain point, I needed a way to drive more intuitively.

The Dial

The Dial is drawn to scale whatever size you need. It listens for scrolling of the mouse wheel. Other classes can subscribe to get ActionEvents when the dial moves. This way the dial is loosely coupled and can be reused all over the place. For example,

Angle Driving

Using the dial I built a panel that is initialized with a virtual sixi3 robot.

The radio buttons on the left are pulled from the robot model. The AngleDriving system listens to the dial. When the Dial moves then AngleDriving looks at the selected button, finds the robot joint, and tweaks it by 1 degree.

Cartesian Driving

Moving the arm one joint at a time is fine some of the time, but sometimes I need to move in a straight line. I improved the look of the Dial a little bit and made this tool to move the end effector (finger tip) of the robot arm.

XYZ are straight line moves. Roll is a twist around Z, pitch a twist around X, and yaw a twist around Y. Each of these moves happens relative to the reference frame. The options for now are world, the first joint of the robot, and the end effector itself.

Read-only panels

Once I had that I needed more ways to visualize what the system was doing. The two types I made are the AngleReportPanel,

And the various matrix reports.

Each of these listens to the robot reporting a change to the end effector position.

Cartesian Driving with Jacobians

Big shout out to https://akintokinematics.com/ for the excellent Jupyter notebooks that helped me improve cartesian driving to work. For some time now I’ve been telling everyone how much I love Gradient Descent for moving the robot arm. Well… it turns out Gradient Descent is hard to tune and slow AF to converge on a solution, sometimes taking 30 seconds per millimeter. So, instead, based on Greer’s notes, I used the approximate Jacobian.

The approximate Jacobian is a matrix describing the relationship between joint velocity and cartesian velocity at a position. So from position A to position B have the cartesian difference {x,y,z,roll,pitch,yaw}, dAB.

  • I get the approximate Jacobian at A, aj.
  • I get the inverse or pseudoinverse of the Jacobian, aji,
  • Multiply aji * dAB to get is the amount to move each joint in the arm.
  • Apply the joint change and measure the error term.

I set up a loop to run (at most) 20 times. In practical terms it never seems to run more than 2 or 3 per step, and feels blazing fast.

Putting it all together

If you run the development version of Robot Overlord today and use Demos > Sixi 3 you’ll get this view and be able to drive the virtual robot by playing with the controls. Tweaking the dials moves the virtual robot. Sixi 3 UI listens for those changes and sends them through the RobotUI.chatInterface so they show up in the history and they move the real machine (if connected).

My next Thing is figuring out a nice way to run programs: loops, sequences, patterns, wait for signal, send signal, conditionals, and so on. The virtual robot does not know anything about gcode and my gut says it would be a really big mess to spread gcode around the app. I would love to jazz with you about this and find a Good Way to achieve the Thing.

News

Friday Facts 2: Makelangelo Java GUI

This last week there has been work on Makelangelo software to make it work with the new firmware.

I spent a lot of time using design patterns to decouple classes so they can be independently tested. Usually this means an Observer pattern common in Java: a visible Panel on the screen has a list of registered Listeners and when something interesting happens in the Panel it calls notifyListeners(interestingEvent). This way Panel can be run and tested without needing any specific Listener.

A single sub-panel

I’d like to change up the code for a MakelangeloRobot to be decoupled from the NetworkSession – the source of data from the real machine. Then data could come from, say, a piece of code reading from a file. That way the state of the machine could be recorded and played back for testing things like “is the machine connecting to you a Makelangelo 5, a 3, a 2, or something else?”

I’m also plagued by ideas about how a Turtle path is used by a MakelangeloRobot. Turtle is a class that contains TurtleMoves, which describe the movement of the pen over the paper. One Turtle per color! Based on the old Commdore 64 turtle, one of the first procedural drawing programs I used as a kid.

Many classes in the Makelangelo app read and manipulate the history of TurtleMoves in a Turtle.

Drawing speed vs quality testing

In a cartesian plotter the velocity, acceleration, and jerk have the same effect everywhere across the work area. Testing such a machine to find ideal speeds is not onerous. I would draw a grid of squares and on the x axis each square would have more velocity while on the y axis each square would have greater acceleration. In this way the sweet spot is easy enough to find.

In a polargraph plotter the challenge is much greater. What works at the top doesn’t work at the bottom, what works in the center might not work on the sides. Simply drawing a set of squares isn’t enough! Long story short I need your help to find the sweetest of sweet spots. Together we can do it. Right? Right??

Spiral improvements

before
after

…and that’s all I have to say about that.

Final thoughts

These changes can be downloaded from the Makelangelo project on Github.

Did you know you can add bars to your timing belt? I didn’t.

Join our Discord to talk more about this post.