There are two folders under /home/pi: SunFounder_PiCar for controlling motors and steering and SunFounder_PiCar-V for pan/tilt and wireless control. Here look into the code of PiCar-V.
Since too many contents and instructions are involved in the code, we will not cover every detail. For more knowledge about Python 2, Python 3, PyQt, Django, HTML, and CSS in the programs, you can visit related websites or buy books to learn by yourself. In the following part, we will go through the overall structure and the process in brief.
First, let’s check the files in the code folder:
■ .git is a hidden directory to store all the information of a Git repository; it’s generated automatically after you create the repository.
■ client is to store the code of the PC client.
■ datasheet stores the manual of some chips used in the hardware modules.
■ mjpg-streamer is an open source streaming media library, through which the data of the camera is transferred.
■ Remote_control is to store the code of the web server; it controls the motor and servo of the car based on the API request.
■ .gitignore records the requests of file types to be ignored when the Github repository is synchronized.
■ i2cHelper.py is a Python script written by Python 2 to configure and detect the I2C connection.
■ install_dependencies, an executable bash script for simple installation and environment configuration.
■ LICENSE, as the name suggests, is a text file of GNU V2 license.
■ README.md and show record some information normally for statement and prompts.
Server Code
The server code is based on Django 1.10 (adapt to the latest release if needed). If you are interested in this, you can visit the Django website https://www.djangoproject.com/, or read The Django Book to learn more at http://gsl.mit.edu/media/programs/south-africa-summer-2015/materials/djangobook.pdf. Here we will just learn how the web server works. Note: The code may be updated irregularly on Github to fix bugs and release some functions update. So the code here is the initial version. You can view the updates in the Github repository at:
https://github.com/sunfounder/SunFounder_PiCar-V.
Open the code directory and check the file by ls:
pi@raspberry:~ $ cd SunFounder_PiCar-V/pi@raspberry:~/SunFounder_PiCar-V $ lsdatasheet install_dependencies mjpg-streamer remote_controlclient i2cHelper.py LICENSE README.md show |
remote_control is the main code directory of the web server. Open the code directory by cd remote_control, and check the file by ls:
pi@raspberry:~/SunFounder_PiCar-V $ cd remote_controlpi@raspberry:~/SunFounder_PiCar-V/remote_control $ lsdb.sqlite3 manage.py remote_control start static |
- db.sqlite3 is generated when you create a Django project.
- manage.py is the main program of the Django project and is generated when the project is created. It normally does not need to be modified.
- remote_control includes the main code files.
- start is a small script written to run sudo python manage.py runserver 0.0.0.0:8000, and servo installation with attribute install just for convenience.
- static is to store some static pictures on the web.
The Django web server normally runs sudo python manage.py runserver to start. The address 0.0.0.0:8000 means the listening address covers all the addresses on the LAN, and the port number is 8000. Here we will just focus on the code in remote_control folder. Go to the directory via cd remote_control:
pi@raspberry:~/SunFounder_PiCar-V/remote_control $ cd remote_controlpi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control $ lsdriver __init__.py settings.py templates urls.py views.py wsgi.py |
- driver stores the drivers of the car.
- __init__.py is automatically generated when you create a Django project which is a standard necessary document of python package, just leave it there.
- settings.py is automatically generated and stores the related settings.
- templates is a Django app for storing the webs in the html format.
- urls.py is generated automatically to configure the URL to associate with the code.
- views.py is the code for page control which is associated by the URL. It calls the templates to show the page and the driver to control the car.
- wsgi.py is generated automatically and does not need changes. For more, please visit the official website of Django.
So here is how the code works: Run the main program manage.py which will be associated with urls.py automatically, to respond to the URL. When you run the web browser like the Chrome to visit http://<rpi_ip_address>:<port> or visit the configured API via the client, the manage.py will turn to views.py due to the association of the urls.py. Then the views.py processes this and returns the templates to the browser. In addition, it will call the driver package on the basis of the parameters set in the browser to control the car.
Now open the folder driver and check:
pi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control $ cd driver/pi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control/driver $ lscamera.py config __init__.py stream.py |
The driver folder mainly includes the driver modules for controlling the pan and tilt and camera streamer.
camera.py for controlling the pan-and-tilt.
config stores the calibration data.
__init__.py is the essential file of the package and you can just leave it alone.
stream.py is a video streaming service based on the MJPG-streamer.
Exit and open the folder templates to view:
pi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control/driver $ cd ../pi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control $ cd templates/admin.py __init__.py models.py tests.py apps.py migrations templates views.py |
This folder is created by the manage.py startapp just for calling the templates conveniently. Therefore, the files have not been changed except for the templates. Open the templates again:
pi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control/templates $ cd templatespi@raspberry:~/SunFounder_PiCar-V/remote_control/remote_control/templates/templates $ lsbase.html cali.html run.html |
There are three HTML files that also consist of layers. The low level base.html stores contents contained on each page such as the <head> of HTML, the overall layout, and contents of the home page by default. The surface layer: cali.html for calibration and run.html to control the car.
So that’s the code of the server. Next we will come to the code of the client written by PyQt.
Client Code
In Windows, you can check the contents of client directory by grouping files by file type:
- client.py, is the main part of the code of the client.
- icons_rc.py is the python code converted from the UI resource file of Qt, which is the icons.qrc file beside, by pyrcc5 –o icons_rc.py icons.qrc.
- icons.qrc is the Qt resource file and restores the location of the resource pictures.
- .ui is the ui file, or the graphical user interface (GUI) file designed by the Qt tool. Open it by a text editor and you will see the code is written similar to an xml file.
- images stores the picture resources used in designing the UI (user interface). Do not rename or move the folder and the files in it, or else the corresponding content on the UI will be missing because it fails to find the graphic resource.
- _pycache_ not shown in the figure above, is a cache folder automatically generated when you run a .py file of the client. If you’ve just downloaded it and not run yet, it’s not generated.
The code of the client is written in Python 3, and the GUI is designed by the Qt tool. The open source library PyQt is used in the client.py to load the .ui file written by Qt into the python code.
For more information about PyQt, please visit the website:
https://riverbankcomputing.com/software/pyqt/intro
The interfaces go one by one like this:
1. The login page: enter the Raspberry Pi’s IP address and click Log in go to the operation interface.
2. The operation interface will show the view captured by the camera. You can control the movement of the car on this page. You can click the return button, to go back to login, and the settings button to go to calibration interface.
3. The calibration interface: you can control and adjust the car by keyboard. Click OK to save the calibration data, and Cancel to return to the upper level interface.
Now after going through the code, you may wonder actually how to design the graphical interface and use PyQt. So let’s take a closer look!
1. Designing the Interface
Let’s start with the design interface.
In Windows, if you install the PyQt by the .exe package, select the option to install all, so the GUI design tools like the Qt Designer will be installed automatically. Or you can install the entire kit of Qt by yourself. Download the package (may need some setting and registration):
Open the .ui file with a Qt tool after the installation is completed. The Qt designer in Qt tools is a GUI design tool.
Design the first interface (login), with the GUI design tool. In the left column is the Widget Box section. You can just drag the components available here to the edit window in the center to see the effect directly. In the right column, on top is Object Inspector, where you can check the association and category of the added objects. Under this section, the property of the object is shown. You can set the attributes in this part, to differentiate all the widget objects.
Let’s take the picture of the login interface as an example. Drag a Label from Widget Box to the picture, then click on the label and there is a square around, by which you can change its size and position. Then in the property part, select pixmap under text and click the box next to it, and on the pop-up drop-down list, select to read the picture from resource or from file.
If you choose to read from file, find the picture to be used, select it and click OK; to read from resource, create the resource file first. It is very simple – by the pencil icon (edit button) in the window of creating from resource. Click the icon, and select to create a resource and load it.
The setting of other components such as button, line edit and on, is just similar, though the properties are different. The name of the objects whose property has been changed will be marked bold automatically for convenience in next check. You can open those .ui files to see the property details that can be changed, or the widget type by objects in Object Inspector. After editing, you can select Window -> Preview in the Qt Designer to see the effect, or by the shortcut Ctrl + R.
Don’t need to worry if you are not familiar with Qt because great details are given in the Qt document. If you don’t know which property is for what use, you can check Help or the Qt assistant. And those sample sketches of Qt will help a lot for you to learn about Qt.
2. Programing the Functions
Now the interface design is finished. However, the interface files are just some static images and cannot be put into use. So the next step, write the client.py to implement all the interfaces with the corresponding functions as well as redirections. The PyQt is like this:
In Line 5, enter the name of the ui file you designed in the quotation marks.
In Lin 7e, “uic” is the contents in the previously imported PyQt; the built-in function loads the ui files.
In Line 9-13, the class defined is just your GUI window. Define (def) the corresponding functions in the class and write the functions in them. The first def __init __ (self) is the initialization function which is a constructor in C++. It means when the instance is created, the program will run the code and initialize the instance.
Line 15-19 is the entry of the __main__ function, where it starts to execute the whole program.
So here’s how the program goes:
1. Run the __main__ function and create an instance app of QApplication, which is the GUI application.
2. Create an instance window of the MyApp class type. After the creation is done, run the __init__ initialization function of the class.
3. The window instance is displayed.
4. Wait for a while. If the instance app of the GUI application sends an exit signal app.exec_(), then enter sys.exit() to exit Python.
So that’s all for the code. Here we’ve only looked at the entry-level usage. For more detailed code explanation, go to the client.py file. There you can see very detailed comments.