üApp: picar-s: refactor bang-bang controller uobject

This task will refactor the existing picar-s bang-bang controller to house the controller logic within the uobject that operates on the HMAC sensor data buffer.

The proposed sub-tasks follow:

  1. We will be working with forks and respective branches of the following repositories:

    • uberspark/uberxmhf.git on branch develop
    • uberspark/uberspark.git on branch develop
    • uberspark/uapp-SunFounder_PiCar-S.git on branch uobjcoll
    • uberspark/uobjcoll-SunFounder_Line_Follower.git on branch uobjcoll
    • uberspark/uobjcoll-raspberrypi-linux-i2c-bcm2835.git on branch uobjcoll-4.4.y

    Ensure the aforementioned forks/branches are upto date with the upstream repositories. The following gives an example of how to sync your fork of uberspark/uberxmhf.git ; the same can be applied to other repositories. Note these commands have to be applied on a local checkout of your fork.

    git remote add upstream https://github.com/uberspark/uberxmhf.git
    git fetch -a upstream  
    git checkout develop 
    git pull upstream develop 
    git push origin develop
    
  2. Build and install micro-hypervisor and I2C drivers i2c-bcm2708 from the above forks/branches and ensure baseline line-following functionality works

  3. Create a new folder within uapp-SunFounder_PiCar-S.git, branch uobjcoll, folder example/bangbang_shared. This will house our refactored bang bang controller based on the existing line-following controller.

  4. Move existing uapp-SunFounder_PiCar-S.git, branch uobjcoll, example/line_follower_clib.py into example/bangbang_shared/ folder and refactor the logic to match how things are done with example/pid_shared. i.e., we need to have bangbang.c, bangbang.h, bangbang_line_follower.py, README.md, and Makefile. The bangbang_line_follower,py will be existing line_follower_clib.py.

  5. Now rework bangbang_line_follower.py logic to match what is found in example/pid_shared/pid_line_follower.py using the template of lines 37–45 as here: uapp-SunFounder_PiCar-S/pid_line_follower.py at uobjcoll · uberspark/uapp-SunFounder_PiCar-S · GitHub

  6. The idea with the above is that we implement the bangbang controller logic within bangbang.c which will include lines 94–174 of bangbang_line_follower.py re-implemented in C such that all servo output routines are left outside the logic, just like how it is done with the pid controller.

  7. Test bangbang_line_follower. This should follow the line as before.

The above will allow us to move bangbang.c into a uobject as the next task.

PR(s):

Merge(s):

I tested the branches up to step 3 and it all worked fine. Now moving into analyzing how to refactor the code as described in the task.

I have two questions:

  1. Do we need the logic of pid_shared also in this refactoring? This would include the calls to the pid library?
  2. Lines 94-174 depend on Python files for controlling front_wheels.py and back_wheels.py. These Python modules depend on some lower-level Python modules and they depend on others, PCF8591.py, TB6612.py, Servo.py, etc. Reimplementing all this properly in C does not seem straightforward starting from the Python code. In addition this code is installed only on the Raspberry Pi in a separate folder by running a script. All these are located in ~/SunFounder_PiCar/picar folder on the Raspberry Pi.

The sensors and the PID portions were way easier to isolate compared to actuation, because of the implementation of the code.

No, just the vanilla bang-bang controller

Yes, we need to move it out of the logic so we dont bring it into the C implementation. See the existing PID controller implementation and how it separates the wheel movement and keeps the wheel/servo logic in python while implementing the controller in C.

I understand the pid_shared logic, because I was in the discussions when it was implemented. So what portion do we want to be implemented in C in this case?

The portion that takes in the line-following sensor readings (with HMAC) as input and produces the appropriate turn angle and speed to drive servos as output.

What about the control of the wheels? This is the real issue that I see after looking at the Python code?
For example:
w = front_wheels.Front_Wheels(db=‘config’)
bw = back_wheels.Back_Wheels(db=‘config’)
fw.wheel.write(tmp_angle)
bw.forward()

These are intermixed in the logic everywhere.

Precisely the point of this task, to attempt to disentangle them so that we can cleanly separate out the angle/speed computations and the wheel APIs :slight_smile:

ok, I see. Let me see how this could be disentangled, because now it is entangled pretty well. Stay tuned. Ha ha.

1 Like

I started by refactoring the Python script, because it was impossible to figure out how to move code to C when the Python was so poorly structured.
The changes are in my fork, branch uobjcoll :

After working with Python and refactoring it I am so unhappy with this language, especially when used for safety-critical embedded systems. Its variable scoping and runtime error checking could make you insane if you come from C/C++ and even Java.
Now that we have things in different functions do we want both of the functions to go into a C library ?
Please take a look at my updated script in the bagbang_shared folder under examples

Hmmm. I dont see the bang bang folder in the repo you linked above…

It is part of the uobjcoll branch in this fork:

Ok thanks. Below is my proposal, please see if this is feasible to implement:

Refactor current lines 132-159 in the current bang bang controller python implementation so that you essentially replace that block with a call to a single python function compute_speed_angle or something similar which in turn uses calculate_speed and calculate_angle functions within it without the usage of the servo functions like bw.xxx and fw.xxx (as in lines 149-154). Then bring in current functionality of lines 149–154 after that call to compute_speed_angle. So bascially the high-level structure that will replace current lines 132–159 will be:

var1,var2, var3,... = calculate_speed_angle(p_var1, p_var2, ...);
current lines 149-154 functionality

The above pattern will enable use of lt_status_now sensor data variable only within calculate_speed_angle and its children functions (calculate_speed and calculate_angle). We can then move calculate_speed_angle and children functions into a C implementation.

Let me know if you have any further clarifications

Thanks!

ok, sounds good. I should be able to change the python as proposed and implement the C routines.

1 Like

I have created a C library with the required functionality and tested with the Python calling and the car following the line fine.

Sounds great! Can you submit a PR so we can review together and merge?
Thanks @antonhristozov !

I also added a README.md and submitted a pull request:

PR merged upstream. Added PR and merge info to OP. Closing task thread. Thanks @antonhristozov !