Running Blockly On An EV3 Brick

Based on WasabiFan/blockly-ev3dev, it seems we can run blockly from a Lego EV3 brick.

Downloads_—_robot_ev3dev____blockly_—_ssh_—_58×29_and_Hello_World
I managed to see blockly on default port 8000 by copying the following files from WasabiFan‘s repo into the same directory in a EV3 folder (Sharing Files With a Lego EV3 Brick Over Wifi Using Filezilla), and then running python server.py in that directory:

blockly_compressed.js (from .)
blocks_compressed.js (from .)
en.js (from msg/js)
index.html (from server/)
index.js (from server/)
python_compressed.js (from .)
server.py (from server/)

At the moment it only runs a motor command (and note that the speed setting is not a speed setting, it’s a sp_duty_cycle, so needs to be in range 0..100).

Hello_World_ev3_blockly

The run button saves the program as a python file (my_file.py) in the folder user_code and then executes it:

robot@ev3dev:~/blockly$ more user_code/my_file.py 
import ev3dev.ev3 as ev3

outAMotor = ev3.Motor('outA')
outAMotor.reset()

If we can save this as an executable file with a #!/user/bin/python hashbang, the file could then be launched from the brick file browser.

OpenRobertaLab – Simple Robot Programming Simulator and UI for Lego EV3 Bricks

Rather regretting not having done a deep dive into programming environments for the Lego EV3 somewhat earlier, I came across the block.ly inspired OpenRobertaLab (code, docs) only a couple of days ago.

Open_Roberta_Lab

(Way back when , in the first incarnation of the OU Robotics Outreach Group, we were part of the original Roberta project which was developing a European educational robotics pack, so it’s nice to see it’s continued.)

OpenRobertaLab is a browser accessible environment that allows users to use block.ly blocks to program a simulated robot.

Open_Roberta_Lab2

I’m not sure how easy it is to change the test track used in the simulator? That said, the default does have some nice features – a line to follow, colour bars to detect, a square to drive round.

The OU Robotlab simulator supported a pen down option that meant you could trace the path taken by the robot – I’m not sure if RobertaLab has a similar feature?

robotlab

It also looks as if user accounts are available, presumably so you can save your programmes and return to them at a later date:

Open_Roberta_Lab5

Account creation looks to be self-service:

Open_Roberta_Lab6

OpenRobertaLab also allows you to program a connected EV3 robot running leJOS, the community developed Java programming environment for the EV3s. It seems that it’s also possible to connect to a brick running ev3dev to OpenRobertaLab using the robertalab-ev3dev connector. This package is preinstalled in ev3dev, although it needs enabling (and the brick rebooting) to run. ssh into the brick and then from the brick commandline, run:

sudo systemctl unmask openrobertalab.service
sudo systemctl start openrobertalab.service

Following a reboot, the Open Robertalab client should now automatically run and be available from the OpenRobertaLab menu on the brick. To stop the service / cancel it from running automatically, run:

sudo systemctl stop openrobertalab.service
sudo systemctl mask openrobertalab.service

If the brick has access to the internet, you should now be able to simply connect to the OpenRobertalab server (lab.open-roberta.org).

Requesting a connection from the brick gives you an access code you need to enter on the OpenRobertaLab server. From the robots menu, select connect...:

Open_Roberta_Lab3

and enter the provided connection code (use the connection code displayed on your EV3):

Open_Roberta_Lab4

On connecting, you should hear a celebratory beep!

Note that this was as far as I got – Open Robertalab told me a more recent version of the brick firmware was available and suggested I installed it. Whilst claiming I may still be possible to run commands using old firmware, that didn’t seem to be the case?

As we well as accessing the public Open Robertalab environment on the web, you can also run your own server. There are a few dependencies required for this, so I put together a Docker container psychemedia/robertalab (Dockerfile) containing the server, which means you should be able to run it using Kitematic:

kitematic_robertalab

(For persisting things like user accounts, and and saved programmes, there should probably be a shared data container to persist that info?)

A random port will be assigned, though you can change this to the original default (1999):

kitematic_robertalab

The simulator should run fine using the IP address assigned to the docker machine, but in order to connect a robot on the same local WiFi network to the Open RobertaLab server, or connect to the programming environment from another computer on the local network, you will need to set up proter forwarding from the Docker VM:

virtualboxroboertacontainer

See Exposing Services Running in a Docker Container Running in Virtualbox to Other Computers on a Local Network for more information on exposing the containerised Open Robertalab server to a local network.

On the EV3, you will need to connect to a custom Open Robertalab server. The settings will be the IP address of the computer on which the server is running, which you can find on a Mac from the Mac Network settings, along with the port number the server is running on:

So for example, if Kitematic has assigned the port number 32567, and you didn’t otherwise change it, and you host computer IP address is 192.168.1.86, you should connect to: 192.168.1.86:32567 from the Open Robertalab connection settings on the brick. On connecting, you will be presented with a pass code as above, which you should connect to from your local OpenRobertaLab webpage.

Note that when trying to run programmes on a connected brick, I suffered the firmware mismatch problem again.

Sharing Files With a Lego EV3 Brick Over Wifi Using Filezilla

A handy comment on the ev3dev github repository shows how easy it easy to share files between a laptop/desktop computer and a networked Lego EV3 brick over wifi.

For a brick on e 192.168.1.016, from the Filezilla File -> Site Manager… menu

Site_ManagerWe can also set the default directory on the brick (as well as on host):

Site_Manager2

From the Filezilla View -> Filename Filters… option we can hide the display of hidden files:

Directory_listing_filters

To copy files, simply drag them from one machine to the other:

ev3 scp

To run python files on the brick, you need to make them executable. Right-click on a Python file and select the File permissions… option:

permissions

then set the execute file permission as required:

Change_file_attributes

 

See also: Running Python Programmes on the Lego EV3 via the EV3 File Browser for a command line/scp route for file transfer, and Setting Up PyCharm To Work With a Lego Mindstorms EV3 Brick for a guide on file synching via git checkins using the PyCharm Community Edition editor / IDE.

Setting Up PyCharm To Work With a Lego Mindstorms EV3 Brick

Notes based on Setting Up a Python Development Environment with PyCharm for setting up PyCharm editor (I use the free Community Edition) to work with EV3. Requires passwordless ssh into the brick and the brick on 192.168.1.106.

We’re going to go round the houses with git checkins to move stuff from the Mac and the PyCharm editor to the brick.

Get into the brick and do some minimal config stuff:

[Mac] ssh robot@192.168.1.106

[EV3] sudo apt-get update
[EV3] sudo apt-get install git
[EV3] mkdir -p /home/robot/demoproj
[EV3] mkdir -p /home/robot/demoproj/.demoproj.git
[EV3] git init --bare /home/robot/demoproj/.demoproj.git

Now use the nano editor on the brick to populate the demoproj dir with the files we push, setting them to be executable.

[EV3] nano /home/robot/demoproj/.demoproj.git/hooks/post-receive

In the nano editor, change the file to:

#!/bin/sh
git --work-tree=/home/robot/demoproj --git-dir=/home/robot/demoproj/.demoproj.git checkout -f
find /home/robot -iname \*.py | xargs chmod +x

The chmod on the py files makes them executable, so as long as you hashbang the first line of any python files (with #!/usr/bin/python), they should be runnable from the file browser menu on the brick.

Then ctrl-x to exit, saying Yes to save the file on the way out and accepting the default file name. Now make that hook executable:

[EV3] chmod +x /home/robot/demoproj/.demoproj.git/hooks/post-receive

Should we prepend hashbangs as well? This will add one to start of all py files not containing one:

grep -rL '^#!/usr/bin/python$' /home/robot/demoproj/*.py | xargs sed -i '1i #!/usr/bin/python'

In PyCharm, VCS->Check Out From Version Control to create a new project, selecting git as a the checkout target (so you’ll also need git installed on the Mac…).

The VCS Repository URL is: robot@192.168.1.106:/home/robot/demoproj/.demoproj, the Parent Directory (for example, /Users/me/projects) and Directory names (e.g. testProj – note, this must be a new folder) specifying the location on the Mac where you want to keep a local copy of the project files.

Say yes to all the crap PyCharm wants to create, and Yes when it prompts if you want to open the newly created directory. Create a new python file containing the following test program:

#!/usr/bin/python
#The shebang above runs this file with the python shell
from ev3dev.auto import Sound
#Make a short sound
Sound.tone(1000,10)

Save it, press the VCS /UP ARROW/ button top right in PyCharm to commit, add a commit message, then bottom right Commit and Push.

This should commit the file locally and also push it into the git repo on the ev3; the commit hook on the ev3 will copy the file into the demoproj folder and, if it’s a .py file, mark it as executable.

You should now be able to locate it and run it from the ev3dev file browser.

See also: Using IPython on Lego EV3 Robots Running Ev3Dev and Running Python Programmes on the Lego EV3 via the EV3 File Browser.

PS to enable autocompletion in PyCharm, check what Python shell the project is using (in the settings/preferences somehow though I’m damned if I know where to find them; I HATE IDEs with a passion – way to cluttered and over complex…). Then using the same Python shell:

git clone https://github.com/rhempel/ev3dev-lang-python.git
cd ev3dev-lang-python
python setup.py install
cd ..
rm -r ev3dev-lang-python/

Run the programme in PyCharm (or at least, the import lines) and autocompletion should be enabled. The complete code won’t run properly though, because you’re not running it in an ev3dev environment…

Running Python Programmes on the Lego EV3 via the EV3 File Browser

A quick note to self… If we test python scripts on an EV3 brick interactively via a Jupyter notebook and then save the notebook as a python file (eg Untitled1.py), we can get the Python file over to the EV3 brick and into a state we can run it from the file browser by using the following recipe:

echo '#!/usr/bin/python'|cat - Untitled1.py > /tmp/out && mv /tmp/out Untitled1.py
scp Untitled1.py robot@192.168.1.106:/home/robot/
ssh robot@192.168.1.106 'chmod ugo+x /home/robot/Untitled1.py'

Then in the file browser on the brick, just click on Untitled1.py to run it.

It would be easy enough to script this so a single button in the notebook does it automatically? (In which case, it would probably make more sense to modify the template used to generate the Python save file so that it includes the shebang at the start of the file anyway?)

PS see also Setting Up PyCharm To Work With a Lego Mindstorms EV3 Brick and Sharing Files With a Lego EV3 Brick Over Wifi Using Filezilla.

Thinking Around the Edges – Lego EV3 Robots Running Remote Jupyter Kernels

I’ve been pondering the use of Lego EV3 robots on the OU TXR120 residential school again, and after a couple of chats with OU colleagues Jane Bromley (who just won a sci-fi film pitch competition run by New Scientist) and Jon Rosewell (who leads on our level 1 robotics offerings), here’s where I’m at on “visioning” it…?!;-)

The setting for the residential school is 8 groups of 3 students per group working with their own Lego EV3 robot to complete a set of challenges. Although we were hoping to have laptops from which the robots could be programmed wirelessly, it seems as if we might end up with wifi-less desktop machines (which will require tethering the robots to the desktop machine to programme them) with big screens, though I could be wrong.. and we may be able to work around that anyway (a quick trip to Maplin to buy some wifi dongles, for example, or some cables we can plug into a wifi routing switch, for example…) Having laptops would have been a boon for making the room a bit more flexible to work with (but many students have their own laptops…;-) and having a big screen that laptops could be mirror displayed against would possibly improve student experience.

The Lego bricks come with their own firmware, but as described in Pondering New Ways of Programming Lego EV3 Mindstorms Bricks we can also put Linux on them, and make use of a python wrapper library to actually programme the bricks using Python.

In what follows, I’ll refer to the EV3 brick as the client and a laptop or desktop computer that connects to it as the host.

One of the easiest ways to access the Python on the brick is to connect the brick to the network and then ssh in to it – for example (use the correct IP address for the brick):

ssh root@192.168.1.106

Each time you ssh in, you have to provide a password (r00tme is the default on my brick), but passwordless ssh can be set up which makes things quicker (you don’t have to enter the password).

To set up passwordless ssh onto the brick, you need to check that an .ssh folder is available in the home directory (~) on the brick for the ssh key. To do this, ssh in to EV3, cd ~ to ensure you’re at home you home, then ls -a to list the directory contents. If there is no .ssh directory, create one (this post suggests install -d -m 700 ~/.ssh).

If you don’t have an ssh key set up on the host machine you want to get passwordless ssh access from to the brick, follow the above link to find out how to create one. Once you do have ssh keys set up on host, run something along the lines of the following, using the IP address of your connected EV3, to copy the key across to the EV3:

cat ~/.ssh/id_rsa.pub | ssh root@192.168.1.106 'cat > .ssh/authorized_keys'

You will need to provide the password to execute this command (r00tme for the version of Ev3dev I’m running).

You should now be able to ssh in without a password: ssh root@192.168.1.106

Rather than prompting for the password, ssh will use the key provided to log you in.

In my previous post, I described how it was possible to run an old IPython notebook server on the brick that can expose notebooks over the network, although it was a little slow. It’s also possible to ssh in to the brick and run an IPython terminal on the brick:

ssh root@192.168.1.106
ipython

A third way I’d have expected to work is to access a remote IPython kernel on the brick from an IPython console on my laptop: ssh into the EV3 brick, launch an IPython kernel, and pick up the location of the connection file. For example, if the command:

ssh root@192.168.1.106
ipython kernel

to run an IPython kernel on the EV3 responds with something like:

To connect another client to this kernel, use:
    --existing kernel-1129.json

Back on the laptop I’d expect to be able to run:
scp root@192.168.1.106:/root/.ipython/profile_default/security/kernel-1129.json ./
to grab a local copy of the connection file from the brick and copy it over to my host machine (which works) and then use it as an existing connection for a Jupyter console on the laptop host:
jupyter console --existing ./kernel-1129.json --ssh server

But that doesn’t work for some reason? CRITICAL | Could not find existing kernel connection file ./kernel-1129.json

Whatever…

So far, so much noise – the important thing to take away from the above is to get the passwordless ssh set up, because it makes the following possible…

Recall the basic scenario – we want to run code on the brick from a computer. The bricks will run an IPython notebook, but it’s slow. Or we can ssh in to the brick, start an IPython process up, and run things from an IPython command line on the brick.

But what if we could run a Jupyter server on host, making notebooks available via a browser, but use a remote kernel running on the brick?

The remote-ikernel package makes setting up remote kernels that can be accessed from the Jupyter server relatively straightforward to do – install the package on your host machine (eg my laptop) and then run the remote-ikernel command with the settings required:

pip3 install remote_ikernel
remote_ikernel manage --add --kernel_cmd="ipython kernel -f {connection_file}" --name="Ev3dev" --interface=ssh --host=root@192.168.1.106

This creates a kernel.json file and places it in the correct location. (On my Mac this was in the directory /Users/MYUSER/Library/Jupyter/kernels/. )

The kernel.json file created for me (/Users/ajh59/Library/Jupyter/kernels/rik_ssh_root_192_168_1_106_ev3dev/kernel.json) was as follows:

{
  "argv": [
    "/usr/local/opt/python3/bin/python3.5",
    "-m",
    "remote_ikernel",
    "--interface",
    "ssh",
    "--host",
    "root@192.168.1.106",
    "--kernel_cmd",
    "ipython kernel -f {host_connection_file}",
    "{connection_file}"
  ],
  "display_name": "SSH root@192.168.1.106 Ev3dev",
  "remote_ikernel_argv": [
    "/usr/local/bin/remote_ikernel",
    "manage",
    "--add",
    "--kernel_cmd=ipython kernel -f {connection_file}",
    "--name=Ev3dev",
    "--interface=ssh",
    "--host=root@192.168.1.106"
  ]
}

Launching the notebook server using jupyter notebook in the normal way should result in the server picking up the remote kernel from the new kernel file.

To list the kernels available, I launched a Jupyter notebook with the normal (local) Python kernel and ran:

from jupyter_client.kernelspec import KernelSpecManager
list(KernelSpecManager().find_kernel_specs().keys())

My newly created on was there, albeit horribly named (the name was also the directory name the kernel.json file was created in): rik_ssh_root_192_168_1_106_ev3dev.

So here’s where we’re at now:

  • a single desktop or laptop computer with passwordless ssh access to a Lego EV3;
  • the desktop or laptop computer runs a Jupyter server;
  • Jupyter notebooks are available that will start up and run code on a remote IPython kernel on the brick.

Home1

Untitled

Where do we need to be? The most immediate need is to have something that works for residential school. This means we need 8 desktop computers and 8 EV3s.

One thing we’d need to do is find a way of marrying computers and EV3s. Specifically, we need to have known IP addresses associated with specific bricks (can we assign a known IP based on MAC address of the wifi dongle attached to the bricks?) and we need to make sure that passwordless ssh works between the computers and the EV3s. The easiest way of doing the latter would be to use the same ssh keypair in every machine, but this would mean student group A might be able to mistakenly connect to the Student Group B’s machine.

One way round it might be to set up a Jupyterhub server that is responsible for managing connections. The Jupyterhub server is a multiuser hub that will set up a Jupyter server for each logged in user. If we set up the Jupyterhub attached the same wifi network as the EV3 bricks, with 8 users, one per student group, each user/student group could then presumably be assigned to one of the bricks. Students would login to the Jupyterhub, and their Jupyter server would be associated with the remote_ikernel kernel.json file for one of the bricks. Anyone who can connect to the local wifi network can then login to the Jupyterhub as one of the group users, launch a notebook, and run code on one of the bricks. This means that students could write notebooks from their own laptops, connected to the network. Wifi-less desktop machines provided for the residential school could presumably be added into the network via a local ethernet cable?

So we’d have something like this:

robotlab_-_jupyter_pptx2

Does that make sense?