Blossom

2023-07-14 This page is a work-in-progress. This page covers the build and use of a Blossom robot, specifically:

  • Building the robot hardware

  • Setting up the software

  • Controlling the robot using the mobile interface

Build

The total component cost for the base Dynamixel-powered configuration is less than $200. The platform also supports a cheaper configuration using micro servos and an Arduino for approximately $50.

Parts

The parts to print in *.stl format are available here. Each directory contains the whole runner (e.g. blsm_A ) or individual parts (e.g. A1). I printed the parts on an entry-level Creality Ender 3 and sliced the files in Cura using this profile. The instructions are available here.

Part

D escription

Quantity

Method

A pprox imate total cost

blsm_A

Part runner

1

Print

NA

blsm_B

Part runner

2

Print

NA

blsm_C

Part runner

2

Print

NA

blsm_D

Part runner

1

Print

NA

blsm_E

Part runner

3

Print

NA

blsm_F

Part runner

3

Print

NA

blsm_M

Part runner

4

Print

NA

blsm_SR

Slip Ring for rotating the upper body

1

Print the static non-rotating ‘dummy’ mo del, or use the actual 12-wire slip ring to enable continuous rotation beyond 360 degrees

NA or $ 22.00

String

String for actuating the head

1

Purchase ( e.g. fishing line, twine)

$ 5-$20

Rubber bands, 4mm diameter

Rubber bands for hanging the head platform

6

Purchase e.g. black rubber bands

$8

Motors and electronics

The standard full-featured configuration uses Dynamixel ‘smart’ servos. Dynamixels have a lot of nice features built in, such as different operating modes (position- or velocity-control modes), velocity and acceleration profiles, and PID tweaking.

Part

D escription

Quantity

Method

A pprox imate total cost

D ynamixel XL 330-M288

Motor

4

Purchas e

$100 ($2 5/ea)

D ynamixel X3P Cable

Cables (included with XL330 motors)

6

Purchase

NA (inc luded with XL330 m otors — only buy if need sp ares)

D ynamixel U2D2

Motor controller

1

Pur chase

$ 32.00

The Arduino-powered configuration is much cheaper (around the cost of just one Dynamixel) and more hackable, though the movement is noisier and less smooth. The left-right yaw rotation is also limited to ±90°.

Part

D escription

Quantity

Method

A pprox imate total cost

Arduino (or clone)

Micro controller and cable

1

Purc hase

$15

Micro servo

Small servos with basic position control

4

Pur chase

$10

Wiring

For the Dynamixel-powered configuration, refer to the wiring documentation to set up the U2D2 controller with an external power supply. For the Arduino-powered design, refer to this Fritzing diagram. Either configuration will require USB breakouts for power and some cables.

Pa rt

Description

Quantity

M ethod

Approximate total cost

U SB br ea ko ut

Breaks out power connections to ease supplying power

1

Purc hase

$6

M al e- Fe ma le a nd M al e- Ma le w ir es

Connects components

Several

Purc hase , or use spare c ables and b readb oards

$7

Hardware

The minimal M2 hardware required is all available in this set for $10.

Part

Quantity

Notes

M2x8mm

14

M2x10mm

12

M2 nuts

12

Only necessary if using SG90 servos

Tools and miscellaneous

Part

Description

Quantity

Notes

Wire cutters

Cutting parts from the runners, cutting wires

1

El ectrical wire

Connecting motors

A couple meters worth

USB wall adapter

Powering the motors

1

Id eally 15W (5 V/3A) or gr eater to s upply suffi cient power to the m otors

Wiring

Follow the wiring instructions.

Software

Environment setup

Set up conda, then set up a conda environment and install some other dependencies with pip (because of issues with mouse). Docker maybe coming soon (maybe).

conda env create -f env.yaml
conda activate r0b0
pip3 install -r req.txt

To enable https for the control page, generate some keys with openssl. Since this is self-signing(?), you can safely hit ‘Enter’ to accept the defaults for all fields.

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout r0b0/key.pem -out r0b0/csr.pem

ngrok setup

This has only been tested on iOS. Phone-based motion control is enabled through ngrok. ngrok opens a tunnel to a local port (e.g. localhost:8080) through a URL. Tunneling enables sending data transmission even from non-local networks — this enables telepresence by sending phone orientation data and WebRTC handshaking through the tunnel. If you’re not interested in motion control, you can skip this section.

Sign up for ngrok. Continue on with the guides until you can run ngrok as a terminal command - this will probably require some sudo apting (Linux) or brewing (macOS) and some authtokening. Start a tunnel to https://{hostname}:{port} that the blsm rig is running on, e.g. with the defaults of hostname=localhost and port=8080:

ngrok http https://localhost:8080

The terminal will show you the forwarding URL, e.g.:

...
Forwarding http://someRandomLettersAndNumbers.ngrok.app -> https://localhost:8080
Forwarding https://someRandomLettersAndNumbers.ngrok.app -> https://localhost:8080
...

This next part is a kludge. We need to update this address in three files: r0b0/rigs/static/controller.js, r0b0/rigs/static/player.js, and r0b0/rigs/host.py. This address is stored as socketAddr and SOCKET_ADDR towards the top of each file — modify these to https://someRandomLettersAndNumbers.ngrok.app: In controller.js and player.js:

const socketAddr = "https://someRandomLettersAndNumbers.ngrok.app"

In host.py:

SOCKET_ADDR = "https://someRandomLettersAndNumbers.ngrok.app"

Note that ngrok must be running in a separate terminal — start it, then open another terminal to continue the instructions.

If you have a paid ngrok subscription, you can add a --subdomain argument to the tunnel command to maintain a consistent forwarding URL. For example, to set the forwarding URL to https://mysubdomain.ngrok.io:

ngrok http https://localhost:8080 --subdomain=mysubdomain

Motor calibration (Dynamixel models only)

Next, we will calibrate the motors. This is only necessary for Dynamixel motors First, we need to figure out the USB port that the motor controller (e.g. U2D2, USB2AX) is connected to. Run ls /dev/tty* twice, once with the motor controller connected and again with it disconnected, and take note of the port that disappeared, e.g. /dev/tty.usbserial-FT1SF1UM. Open r0b0/scripts/motor_calib.py and modify the parameters (motor model, USB port, baud rate) towards the top for your robot’s configuration (XL330 for the new version of the robot, XL320 for the old version):

# an example for XL330 motors
MOTOR_MODEL,USB_PORT,BAUD_RATE = 'xl330-m288','/dev/tty.usbserial-FT1SF1UM',57600
# an example for XL320 motors
MOTOR_MODEL,USB_PORT,BAUD_RATE = 'xl320','/dev/tty.usbmodem212401',1e6

With one motor connected at a time, run this calibration script:

python3 -m r0b0.scripts.motor_calib

This will scan for connected motors, and should find the connected motor, usually with ID 1 if it has not yet been set. The script will pause at (Pdb) — this means that the script has started successfully and is now in a debugging loop. To set the ID, for example from 1 to 2:

m1 = dxl_mgr.dxl_dict['1']
m1.set_torque_enable(False)
m1.set_id(2)
m2 = dxl_mgr.dxl_dict['2']
m2.set_torque_enable(True)

To test if the ID was changed successfully, we can toggle the LED.

m2.set_led(True)
m2.set_led(False)

To set the motor to the default position:

# for XL330
m2.set_goal_position(1000) # for the towers:1000; for the base: 2000
# for XL320
m2.set_goal_position(700) # for the towers:700 ; for the base: 500

To stop the script, type Ctrl+D. Repeat this for motor IDs 3 and 4.

Starting the blsm rig

Dynamixel

Start the blsm rig configuration, which contains the blsm_dxl robot as a DynamixelRobot and the bslm_phone browser-based interface as a Page. The rig uses the motion2motor cable to translate device_motion events from the page (when accessed from a mobile browser) into position events for the motor.

In /config/gadgets/blsm_dxl.yaml (here), modify usb_port with the port we found during the motor calibration step:

type: DynamixelRobot
usb_port: /dev/tty.usbserial-FT1SF1UM   # modify this

In a separate terminal window from the ngrok tunnel script,

python3 start.py --config blsm

Arduino

We must first flash the Arduino with the pyFirmata firmware, which enables the Arduino to be controlled from Python through the Arduino gadget class. Connect the Arduino to the computer. Open r0b0/gadgets/Standardfirmata.ino in the Arduino IDE. To find the port that the Arduino is connected to, use the Arduino IDE (Tools > Port). Upload the firmware to the board (Sketch > Upload).

Next, we need to modify the configuration at /config/gadgets/blsm_ard.yaml (here) with the usb_port and motor ids. For the motor IDs, refer to the Fritzing diagram and modify according to your specific build:

type: ArduinoRobot
usb_port: /dev/cu.usbserial-ADAQDbKpQ # modify this to the port that the Arduino is connected to
baud_rate: 57600
timeout: 2
motors:
- name: base
  id: 9         # modify this to the pin that the BASE motor is connected to
- name: tower_1
  id: 10        # modify this to the pin that the FRONT head motor is connected to
- name: tower_2
  id: 6         # modify this to the pin that the LEFT head motor is connected to
- name: tower_3
  id: 5         # modify this to the pin that the RIGHT head motor is connected to

Telepresence

Video (optional)

Connect a USB webcam to your computer. With the prior scripts running (start.py and the ngrok tunnel), on the desktop/laptop computer controlling the robot, navigate to https://localhost:8080/broadcaster. This page contains the controls for WebRTC media sources. Select the connected webcam in the dropdown, which should begin a video feed on the page.

Control

In a mobile browser (e.g. Safari), navigate to the forwarding URL (https://someRandomLettersAndNumbers.ngrok.app in the above example). Note: since the ssl certificates were self signed, you will probably run into a privacy warning on your browser. Here’s a guide on how to bypass this, which should be safe since this is being developed locally anyways.

You should see video feed from the webcam selected in https://localhost:8080/broadcaster. Hold the phone straight out, as if you were taking a picture of something directly in front of you. Toggle the ‘head’ switch to turn on control and begin transmitting the phone orientation to the robot. The motor controller should start blinking blue to indicate that it is sending motor commands. The robot’s head should be moving in response to the phone motion.

Recording movements

To begin recording a movement, ensure that the control switch is on and click the large red recording button in the center. Move the phone to control the robot, then click the recording button again to stop. This will save the motion as a Tape in the /tapes directory (more documentation here).

Player

In either the desktop or mobile browser, navigate to the Player page at https://someRandomLettersAndNumbers.ngrok.app/player. Click ‘Update’ to populate the dropdown with the tape files in tapes. Select a tape and click ‘Play’ to begin playback. If you create new movement recordings using the controller interface, you can repopulate the dropdown by clicking ‘Update’ without having to refresh the page. Note that tapes are only loaded once in the backend, so if you manually rename files, you must restart the whole start.py script to override the cached tape.

You can also call this function from the command line. For example, to play tapes/demo_tape.json:

rig.play('demo_tape')

Troubleshooting

Motor settings

Setting motor info e.g. IDs needs torque to be disabled. For example, to set the ID of motor 1 to 7 in using r0b0.scripts.motor_calib.py:

set_param('torque_enable',{1:False})
set_param('id',{1:7})

Interface issues

On the mobile interface, turning on the control switch should first prompt a request for access to the device orientation. If this is not popping up, ensure that socketAddr/SOCKET_ADDR are defined appropriately in r0b0/rigs/static/controller.js, r0b0/rigs/static/player.js, and r0b0/rigs/host.py. They should be set to the ngrok address tunnelling to https://localhost:8080, e.g. https://104e-32-221-140-83.ngrok-free.app.

Slow control

There is a bit of lag between the phone control and the robot control, which is to be expected considering the data passing through the network. Try the following if the lag is too large for your application.

Networking

Ensure that the phone controller is connected to the same network as the robot’s computer.

Motor parameters

The robot configuration at /config/gadgets/blsm_dxl.yaml (here) contains parameters for the motor movement, such as the goal/profile velocity/acceleration. On startup, /r0b0/gadgets/dxl_robot.py (here) configures these parameters during startup. You can tune these values, and refer to the motor documentation for available parameters.

To set motor parameters, add values as entries in the configuration file. Any writable parameter can be set in the configuration file — just add the entry as lower cased and underscored (e.g. ‘Profile Velocity’ -> profile_velocity) For example, in /config/gadgets/blsm_dxl.yaml (here), to set tower_1’s Profile Velocity and Profile Acceleration to 300 and 100, respectively:

- name: tower_1
  model: xl330-m288
  id: 1
  operating_mode: 3
  profile_velocity: 300
  profile_acceleration: 100

Setting operating_mode: 3 sets the motors to position control mode, per the documentation. Faster velocity and acceleration will yield snappier movements at the risk of jerkiness.