Required Knowledge and Parts:
Application:
The digital EV3 Colour Sensor can distinguish between seven different colours and detect the iabsence of colour. It also serves as a light sensor by detecting light intensities. Students can experiment with light reflection of different colours and gain experience with a technology widely used in ndustries to programme robots to function using sorting and line-following with colours.
The Colour Sensor allows the robot to measure reflected red light and ambient light from darkness to very bright sunlight and detect seven colours plus the absence of colour. It can tell the difference between colour or black-and-white or among blue, green, yellow, red, white, and brown.
This is an introductory video on how to use the EV3 colour sensor in 3 different modes:-
This project use color/light sensor to recognise the position of the cube and pass the data to the cube solving algorithm to calculate the actions of solving the cube. The complete product works as below video.
Items required for this project:
Follow the instruction of this link to setup your development environment.
The robot MindCub3r can be assembled with the following guide from David Gilday - MindCub3r Assembly Guide using EV3 Home Set
In order to utilize and program the robot in Python, MicroPython is needed. MicroPython is Python for Microcontrollers, In this case, MicroPython for EV3 is needed. The MicroPython image and guide for EV3 can be seen in the following link - MicroPython image and flashing to SD card guide
Internet connection is needed to update the software as well as to install the dependencies and Python code. The guide can be found here, Internet Connection via USB Guide
Using a SSH client such as PuTTY to connect to the EV3 Brick to install additional software and run the program. In our case, PuTTY is used as our SSH client. PuTTY is an open source SSH and telnet client. PuTTY can be downloaded here, Download PuTTY. The steps to connect PuTTY to the EV3 Brick can be found here, SSH connection to EV3 Brick.
ev3dev
for the “host name”. Then click the Open button to connectrobot
) and the password (maker
) if you haven’t changed it yet and then you should be logged in.robot
maker
The Python program for the Rubik's cube solver that we will be using is here, Mindcuber Code Program. In that link, there is a guide to the installation and running of program. With the internet connection connected at the EV3 Brick and SSH terminal established, use the SSH terminal to perform the below steps.
kociemba is a two-phase algorithm for solving of 3x3x3 Rubik's cube, created by Herbert Kociemba. The algorithm is briefly explained here, Herbert Kociemba's Algorithm This algorithm is then ported to a Python package with two equivalent implementations in C and Python. The library that we are using is from here, dwalton76's kociemba python library, which was originally created by muodov. Firstly, update of the operating system and installation of the dependencies of kociemba is performed before installing kociemba.
In your SSH terminal, perform the below steps:
sudo apt-get update
sudo apt-get install build-essential libffi-dev
cd ~/
git clone https://github.com/dwalton76/kociemba.git
cd ~/kociemba/kociemba/ckociemba/
make
sudo make install
This library is found here, dwalton76 rubiks-color-resolver python library. The purpose of this library is to resolve the detected Red, Green, Blue (RGB) values to the six cube colors of Rubik's cube. This library analyzes all RGB values and assign one of the six colors of the cube to each square. It then uses the Traveling Salesman algorithm to sort the colors. It is intended to work with kociemba. Firstly, pip for Python 3 will be installed, also known as pip3. Using pip3, rubiks-color-resolver package is then installed from its git repository.
In your SSH terminal, perform the below steps:
sudo apt-get install python3-pip
sudo pip3 install git+https://github.com/dwalton76/rubiks-color-resolver.git
Installing MINDCUB3R program
The program is mentioned at the download and installation of software section. There are two different code programs, namely calibrate_white.py and mindcuber.py. The purpose of the calibrate_white.py is to allow the robot to measure and calibrate its color sensor by measuring the RGB values of the white center of the Rubik's cube. It is a good idea to run calibrate_white.py whenever you move to a room with different lighting. The mindcuber.py is the main program where it controls the robot, scans the colors of the 6 different faces of the Rubik's cube, performs algorithms to solve the Rubik's cube, and controls the robot to turn the Rubik's cube to the solved state. Firstly, the MINDCUB3R repository is cloned from Github. Then a command to kociemba will be made to initialize the kociemba program.
In your SSH terminal, perform the below steps:
cd ~/
git clone https://github.com/ev3dev/ev3dev-lang-python-demo.git
cd ~/ev3dev-lang-python-demo/robots/MINDCUB3R/
kociemba DRLUUBFBRBLURRLRUBLRDDFDLFUFUFFDBRDUBRUFLLFDDBFLUBLRBD
The fourth step is essentially to run the kociemba program by giving a series of string representation of the colors of each of the 54 squares of a 3x3x3 cube. The letters represents different moves which is known as the Rubik's Cube Notation. An explanation of the notation can be found here, Rubik's Cube Notation. With the first run of the kociemba program, it takes some time to process, ~30 seconds, where it build a series of tables that caches to the filesystem. After the first run, the kociemba program will then run faster.
As mentioned previously, this program is to calibrate the robot's color sensor by measuring the RGB values of the white center of the Rubik's cube. It is advised to run this program if you move to a room with different lighting. It would be more accurate if a piece of white paper is attached on the white center of the Rubik's cube for this calibration section. This is because the white center of the Rubik's cube contains other colors which can affect the reading of the color sensor.
To run this program, perform the following steps in your SSH terminal:
cd ~/ev3dev-lang-python-demo/robots/MINDCUB3R/
./calibrate_white.py
As mentioned previously, this is the main program where it controls the robot to compute and solve the Rubik's cube. It takes some time for it to start as well as the computation of the solution of the Rubik's cube. Before starting the program, if you have attached a white paper on the white center of the Rubik's cube for the calibrate_white.py, remove the paper as this affects the flipping of the cube.
To run this program, perform the following steps in your SSH terminal:
cd ~/ev3dev-lang-python-demo/robots/MINDCUB3R/
./mindcuber.py
Do note that the MINDCUB3R drains battery quickly and is not perfect as some issues can arise. Some issues detected were:
It was discovered that the default program sometimes fail due to the flipper not able to flip the Rubik's cube. An adjustment to the flipper speed was made and it shows an improvement to the flipping of the cube. The robot was tested three times and it successfully flips the Rubik's cube til completion of every trial.
To change the speed of the flipper, perform the following steps in your SSH terminal:
cd ~/ev3dev-lang-python-demo/robots/MINDCUB3R/
nano mindcuber.py
flip_speed = 300
and flip_speed_push = 400
. Change the value of both to flip_speed = 700
and flip_speed_push = 800
The calibrate_white.py code can be found here, calibrate_white.py code.
Imported Libraries | Purpose |
---|---|
from mindcuber import MindCuber |
This library uses the code from the mindcuber.py found in the MINDCUB3R program repository, specifically the MindCuber class |
import logging |
Logging purposes of events, logging documentation |
import sys |
Provides various functions and variables that are used to manipulate different parts of the Python runtime environment. This program uses this library to exit the program if an error occurred. sys documentation |
With the imported MindCuber class, the program uses its functions to perform following tasks:
wait_for_cube_insert
, where it uses the robot's infrared sensor to detect if the Rubik's cube is present on the robot's Rubik's cube holder. The infrared sensor detects based on the distance of the cube. Once the Rubik's cube is detected, it uses the robot's flipper arm to position the Rubik's cube for the color sensor to scan and moves the flipper arm away afterwards.calibrate_white()
method of the ColorSensor library from ev3dev as seen from here, calibrate_white() method. This method determines the maximum RGB raw values of the white square of the Rubik's cube and assigns the RGB values to red_max, green_max, and blue_max variables, which helps to scale future RGB raw values.The mindcuber.py code can be found here, mindcuber.py code.
With the start of this program, a MindCuber()
class object is created that initializes various variables and methods. Python class and instance variables are present in the MindCuber()
class. These are object-oriented programming concepts which you can read it in more details in this link, Python Class Variables vs. Instance Variables.
After initializing the variables and methods, the program perform following tasks:
scan_order
list. The program then uses the imported RubiksColorSolverGeneric
method and input the scanned information. With the scanned information, the program utilizes kociemba and algorithms to derive the solution of the Rubik's cube.Below is the explanation of each class and variable in this program.
Imported Libraries | Purpose |
---|---|
from ev3dev2.motor import LargeMotor, MediumMotor, OUTPUT_A, OUTPUT_B, OUTPUT_C, SpeedDPS |
Utilizes the various motor classes and methods of the robot, ev3dev motor classes documentation |
from ev3dev2.sensor.lego import ColorSensor, InfraredSensor |
Utilizes the various sensor classes and methods of the robot, ev3dev sensor classes documentation |
from pprint import pformat |
Short for Pretty Printer, this library helps to format print output where it notably helps to print more complex data types such as dictionary and list, pprint documentation |
from rubikscolorresolver import RubiksColorSolverGeneric |
Utilizes rubiks-color-resolver library that was installed previously |
from subprocess import check_output |
Allows the production and management of processes to perform various tasks, subprocess documentation |
from time import sleep |
The library time offers many different time-related methods. For this program, it utilizes the sleep method where it helps to delay the robot for timing purposes, sleep() method documentation |
import json |
Short for JavaScript Object Notation, JSON is a lightweight data-interchange format to allow humans to easily read and write as well as to allow machines to easily parse and generate, json documentation |
import logging |
Logging purposes for events, logging documentation |
import os |
Provides operating system dependent functionalities such as file path retrieval and file creation. Hence, it can run smoothly in different operating systems. os documentation |
import signal |
This library is similar to a notification of an event. When an event occurs in the system, a signal is generated to notify programs about the event. For this program, signal is used to stop and shutdown the program and robot if an event happened that causes the program to be terminated or interrupted. signal documentation |
import sys |
Provides various functions and variables that are used to manipulate different parts of the Python runtime environment. This program uses this library to exit the program if an error occurred. sys documentation |
import time |
As mentioned above, this program only uses the sleep() method. In this instance, time.sleep() is written instead. |
Class Variables | Purpose |
---|---|
scan_order |
A list of numbers determining the order to scan the Rubik's cube |
hold_cube_pos |
Sets a value to have the Rubik's cube to be in the targeted position of the turntable |
rotate_speed |
Sets a value on the speed of rotating the cube |
flip_speed |
Sets a value on the speed of pulling back the cube |
flip_speed_push |
Sets a value on the speed of pushing back the cube |
Class Instance Variables | Purpose |
---|---|
self.shutdown |
Default value is False . When robot is shutting down, this becomes True to stop further action from the robot |
self.flipper |
The flipper uses the large motor arm of the lego set and is connected to port A of the EV3 Brick. Hence, this detects whether the connected motor is a large sized motor and assign its operation to port A |
self.turntable |
The turntable uses the large motor arm of the lego set and is connected to port B of the EV3 Brick. Hence, this detects whether the connected motor is a large sized motor and assign its operation to port B |
self.colorarm |
The colorarm uses the medium motor arm of the lego set and is connected to port C of the EV3 Brick. Hence, this detects whether the connected motor is a medium sized motor and assign its operation to port C |
self.color_sensor |
Assigns the various operations of the color sensor |
self.color_sensor.mode |
Sets the mode of the color sensor to read the raw values of RGB components |
self.infrared_sensor |
Assigns the various operations of the infrared sensor |
self.init_motors() |
Initializes the various motor arms by turning them on and off, as well as resetting them |
self.state |
A list of Rubik's cube notations |
self.rgb_solver |
Default value is None. When program runs, the result of the imported RubiksColorSolverGeneric() method will be assigned to this variable |
signal.signal(signal.SIGTERM, self.signal_term_handler) |
Initializes a signal handler to stop the program and the robot if a termination event has occurred |
signal.signal(signal.SIGINT, self.signal_int_handler) |
Initializes a signal handler to stop the program and the robot if an interrupt event has occurred |
filename_max_rgb |
Filename of the txt file generated after running of the calibrate_white.py |