For minimum latency and maximum bandwidth, or just to free your robot from reliance on the network, you can install run-time software directly to the on-board processor P3. There are three development pathways to choose from. We provide an example of each approach, below.

Interpreted software

The easiest route is to write your control software in some interpreted language, which probably means python. There is no requirement to compile.

Compile on-board

You can build your software in a compiled language and build it on-board using the installed toolchain. To do this, you have only to login to P3, write your code, compile it and run it.


However, the compile time will be much less if you use your workstation to cross-compile for the "target" (P3) and transfer the resulting binary to P3 for execution.



Whichever route you choose, you must start by configuring MIRO to seek the ROS master locally, i.e. running on the P3. To do this, login to MIRO, open up ~/.profile, and uncomment the two lines indicated at the top of the file.

... # uncomment these values to configure MIRO to run encapsulated # "on-board", so the ROS master runs here as do ROS nodes. ROS_IP= ROS_MASTER_IP=localhost ...

Restart MIRO before continuing so that this change takes effect.

This is the modification made if you pass the option --onboard to the programmer when you Reprogram P3.

Run the master node

The ROS master node, aka roscore, must be running on-board MIRO before you attempt to create your ROS network. It will make sense to start it from ~/bin/user_ready.sh eventually, but to begin with we can just start it manually.

Login to MIRO, and start roscore in the terminal window.

root@miro:~> roscore ... logging to /home/root/.ros/log/b9a7d42a-f788-11e6-aee0-7cdd90ddd329/roslaunch-miro-833.log Checking log directory for disk usage. This may take awhile. Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server ros_comm version 1.12.6 SUMMARY ======== PARAMETERS * /rosdistro: kinetic * /rosversion: 1.12.6 NODES auto-starting new master process[master]: started with pid [844] ROS_MASTER_URI= setting /run_id to b9a7d42a-f788-11e6-aee0-7cdd90ddd329 process[rosout-1]: started with pid [857] started core service [/rosout]

The ROS master node is now running, and we can proceed to build our ROS network.

Run the bridge

The MIRO bridge, miro_bridge, is so named because it "bridges" between the USB link to the platform itself (down to P2, actually) and the network. Running on-board, we won't be using the physical network, but we still use the bridge because we are treating the localhost ( as a "network", and using the same network tools.

To run the bridge, login to MIRO in a second terminal window, and do the following.

root@miro:~> run_bridge_ros.sh ________________________________________________________________ MIRO tools [miro_bridge] Copyright (C) 2019 Consequential Robotics ________________________________________________________________ device: /dev/P2 network: ROS (/miro/rob01) sync_interval: (do not change) frame: (do not change) sound: /home/root/sound mdk: R170209 ________________________________________________________________ [000.000] enter threadproc [000.001] interf opening (FLAGS=0x8)... [000.002] start thread [000.012] open() /dev/P2 OK [000.015] opened [000.021] initializing ROS... [000.054] attempting to contact ROS master... [000.059] upstream connection validated [000.194] loading sound from: /home/root/sound [000.309] finished: total RAM used is 1171 kiB [000.310] advertising main topics... [005.324] hooking SIGINT [005.330] received: PLATFORM_READY [005.331] sending P2_W_SYNC [n_hi=0]... [MIRO_USB_OK] [005.334] read model_pars persist file... NOT FOUND! [005.335] sending SET_MODEL_PARS... [MIRO_USB_OK] [005.336] sending SET_RTC (16:25:08)... [MIRO_USB_OK] [005.356] received (in msg_id=57445): ACK_SET_MODEL_PARS [005.357] received (in msg_id=57445): ACK_SET_RTC
For clarity, all WARNINGs have been stripped from the trace, above—a handful of warnings whilst the bridge starts up and settles are to be expected, and can safely be ignored.
If you want to start the bridge in the background, instead, you can use start_bridge.sh instead—make sure it is configured to use MODE=normal first, and stop it using stop_bridge.sh.

The bridge is now running in that window so you should leave it open.


Login to MIRO in a third terminal window, and use rostopic to see if everything seems to be up and running. You should see a list of topics published by the bridge that expose the Interfaces to the network.

root@miro:~> rostopic list /miro/rob01/bridge/config /miro/rob01/bridge/stream /miro/rob01/core/config /miro/rob01/core/control /miro/rob01/core/state /miro/rob01/log /miro/rob01/platform/caml /miro/rob01/platform/caml/compressed /miro/rob01/platform/caml/compressed/parameter_descriptions /miro/rob01/platform/caml/compressed/parameter_updates /miro/rob01/platform/caml/compressedDepth /miro/rob01/platform/caml/compressedDepth/parameter_descriptions /miro/rob01/platform/caml/compressedDepth/parameter_updates /miro/rob01/platform/caml/theora /miro/rob01/platform/caml/theora/parameter_descriptions /miro/rob01/platform/caml/theora/parameter_updates /miro/rob01/platform/camr /miro/rob01/platform/camr/compressed /miro/rob01/platform/camr/compressed/parameter_descriptions /miro/rob01/platform/camr/compressed/parameter_updates /miro/rob01/platform/camr/compressedDepth /miro/rob01/platform/camr/compressedDepth/parameter_descriptions /miro/rob01/platform/camr/compressedDepth/parameter_updates /miro/rob01/platform/camr/theora /miro/rob01/platform/camr/theora/parameter_descriptions /miro/rob01/platform/camr/theora/parameter_updates /miro/rob01/platform/config /miro/rob01/platform/control /miro/rob01/platform/mics /miro/rob01/platform/sensors /miro/rob01/platform/state /rosout /rosout_agg

Interpreted software

We provide an example interpreted Python Command-line Client on-board MIRO for you to use as a starting point. It also works to test that the preparations, above, have been performed correctly. Open a third terminal window, login to MIRO, and proceed as follows to start the python client.

MIRO is going to move! Support it with its wheels off the ground, or ensure that it can move around safely.
root@miro:~> run_client_ros.sh initialising... 2.7.12 (default, Feb 19 2017, 23:34:26) [GCC 6.2.0] turn left tick drive forward tock tick turn right tock tick drive forward tock tick turn left ...

The client's main thread produces tick, tock, periodically. Meanwhile, each time a message arrives from the bridge with updated platform_sensors data, a message is sent back down, and the robot is driven in a forward-turn-forward-turn pattern, indefinitely.

Build on-board

An example compiled-language C++ Command-line Client is provided, namely miro_ros_client, and it is pre-compiled. You can now run this to test the control of the robot. Open a third terminal window, login to MIRO, and proceed as follows.

root@miro:~> miro_ros_client robot=rob01 show=f drive=lean ________________________________________________________________ MIRO tools [miro_ros_client] Copyright (C) Consequential Robotics ________________________________________________________________ open log... initializing ROS... subscribing to "/miro/rob01/platform/sensors"... subscribing to "/miro/rob01/platform/state"... subscribing to "/miro/rob01/core/state"... subscribing to "/miro/rob01/platform/caml"... subscribing to "/miro/rob01/platform/camr"... publishing on "/miro/rob01/platform/control"... publishing on "/miro/rob01/core/config"... publishing on "/miro/rob01/core/control"... entering loop... lean left... lean left... lean left... lean left... lean left... C0:48 [320x240] @ 5.93 lean left... ...

The argument show=f is causing each camera frame received by the client to be reported. The argument drive=lean causes control signals to be sent to drive MIRO's joint to move.

Re-compile example client

The final step is to re-compile the client so that you can use it as a starting point for your own controller. To do this, change into the source directory and run make, as follows.

root@miro:~> cd mdk/src root@miro:~/mdk/src> make ... compiling object: /tmp/miro1/mdk/deb64/miro_ros_client/miro_ros_client.o linking executable: ../../bin/deb64/miro_ros_client ...


Compiling the client on-board is really rather slow, even with a reduced level of optimization, so if you intend to do much development in a compiled language for on-board deployment, cross-compiling from your workstation will probably be a must. To prepare for this, you'll need to build the cross-compiler on your workstation, which takes a long while but only has to be done once.

Build the cross-compiler

The cross-compiler for MIRO is prepared along with the on-board Linux system. Therefore, to make it available on your workstation, you should build the on-board Linux system from source. Instructions for doing this are found at ~/mdk/extern/yocto/source/BUILD.txt. Follow the instructions there, now—the job is fairly straightforward, but the actual build will take a couple of hours. It will also require around 20 gigabytes of hard drive space. Make sure to complete the step "Build the cross-compiler" at the end, after building the system itself.

Compile example client

Exactly how you run the cross-compile on your workstation will depend on exactly where you installed the cross-compiler, so you may need to tweak the build; if so, you will probably want to modify the file ~/mdk/config/make/makefile.am335x-deb64. If you followed the recommendations in BUILD.txt to the letter, that makefile should work as is.

You should change into the MDK source directory, and run make for the target, as follows.

~/mdk/src $ make TARGET=am335x ... compiling object: /tmp/miro1/mdk/am335x/miro_ros_client/miro_ros_client.o linking executable: ../../bin/am335x/miro_ros_client ...

That step creates the executable at ~/mdk/bin/am335x/miro_ros_client.

Install executable

The final step is to install that executable to your P3. You can do this using your preferred tools. One way is as follows.

$ scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ~/mdk/bin/am335x/miro_ros_client root@ ...

Replace the token with the IP address of your P3.

If you have set a password on your P3, use the following mouthful.

$ sshpass -p 1234 scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no ~/mdk/bin/am335x/miro_ros_client root@ ...

Replace the token 1234 with the required password.