# As a beginner, where to start in coding for driverless car operations?

Hi there,

Sorry to be asking this in advance, but can anyone point me as to how to start coding for driverless car operations (such as steering, object detection, etc.)?

We need to implement a system, as a requirement for our course. Our professor told us he does not expect any complex code. To be quite honest, I have a better understanding of the code AI generates than any other tutorial/code I can find. But if you can lead me to any elementary-level explanation, or if someone is kind enough to guide me through the coding process or developing a simple code, please let me know. I am honestly struggling with coding in generalâ€¦

Sorry if my question is inappropriate.
Thank you for your kind understanding!

I think Iâ€™d start by defining a `Car` class embodying the state of a
car. Initially: position and velocity (direction and speed). Something
like:

`````` class Car:
def __init__(self, *, px, py, dr, vx, vy):
self.px = px    # position X ordinate in metres
self.py = py    # position Y ordinate in metres
self.dr = dr    # direction in radians
self.vx = vx    # speed in metres/second
self.vy = vy    # speed in metres/second
``````

Iâ€™d give it a `tick(t)` method which updates its state for `t` seconds
of time elapsed: update the position according to the direction and
speed if `t` seconds took place.

Then Iâ€™d give it a method `steer(ddr)` to adjust the direction by `ddr`
radians (â€śdelta drâ€ť, the change in direction).

Then Iâ€™d give it an `object_detected(objx, objy)` method called when
some system detects an object. Compute whether the path of the car takes
it too near the object, and adjust the steering andor speed to avoid it
if necessary.

Using metres/seconds/radians makes the math easy.

Iâ€™d write presentation functions to present things in more human
conventional forms like kilometres per hour for speed or degrees for
direction, etc.

2 Likes

Did he say anything about what a) the system; b) the code needs to do?

Hi Cameron,

Thanks for your reply! Would it be helpful to import numpy or matplotlib.pylot or the like? As I see from other autonomous vehicle codes that they import those.

Tick is something I have never encountered before. Thanks for letting me know about it. I think that would help one functionality of the driverless car I want to include as well, which is displaying real time data.

You are correct, using metres, radians, and seconds makes it clearer and simpler. I will try to build on it based on what youâ€™ve given me.

Thanks once more for your guidance!

Hi Karl,

Thanks for taking time to read through my query.

Actually, the first part of the assignment was designing the system using various UML models. This for the object-oriented programming course I am currently taking.

Then this is the second part, which is implementing code that supports the autonomous vehicle operation. I chose three:

1. car control (steering, acceleration, brake),
2. environment perception (mapping and object detection using LiDAR), and
3. vehicle to infrastructure communication (which would display real time data)

We then have to test the code, using assert, and Iâ€™m thinking of using unittest to do that.

Thank you!

matplotlib.pylot or the like? As I see from other autonomous vehicle
codes that they import those.

That might just be habit on their part. I wouldnâ€™t bother unless you
need to do some bulk computation.

Matplotlib is great for making plots. Not what you need.

Numpy is great for computation on large amounts of data, mostly through
its `Series` (like a `list`) and `DataFrame` (like spreadsheet with
columns, each of which is effectively a `Series`). It it useful for
anything with large â€śgridsâ€ť of numbers because it can run bulk
computations on these columns at machine speed. Not what you need (yet).

Tick is something I have never encountered before. Thanks for letting me know about it.

It is just a function name. In my mind it represents â€śwhat happens when
a short period of time elaspesâ€ť, like the tick of a clock.

I think that would help one functionality of the driverless car I want
to include as well, which is displaying real time data.

Matplotlib might help you here, depending on what you really need. If
you had a chunk of data, like a lot of rows saving the `Car` state at
points in time. You might record that state inside the `tick` function,
if thatâ€™s how you end up doing things.

If youâ€™re saving all that state, then you might usefully save it in
a `numpy` `DataFrame` with columns for each piece of state from your car
(its position, speed, direction etc) and using the time as the index.
And now youâ€™re into an area where importing `numpy` might be of help.

Better still, a `numpy` `DataFrame` has methods for drawing plots
directly (they call out to `matplotlib` internally, by default). See the
`DataFrame.plot` method, if you end up with a `DataFrame`.

These are part of Pandas, not Numpy.

2 Likes

Um, indeed. Apologies.

(Pokes around his own codeâ€¦) Yep, Iâ€™ve been using `numpy.array` etc in
a time series module. And also `pandas.DataFrame` in the same module
Youâ€™d think Iâ€™d remember this by now.

Hi Cameron,

Thanks for your explanation. Itâ€™s nice to learn about these things from experts.
Honestly, my brain canâ€™t comprehend all of this at once, but I am trying my best.

I tried writing my code, but just a very simple one. I tried implementing some of your earlier suggestions.

I only imported math, for the steering radius/angle.

Aside from that, I didnâ€™t include any. Since I donâ€™t want to make it very complex, because I know my skill and knowledge is very limited at this point in time.

If you have the time (or anyone else reading this, actually), can you kindly comment on it and let me know how I can further improve on my code? Sorry in advance if it is written badly. Any suggestions are welcome.

``````import math

# System Implementation of the Driverless Car

class Car:

# Front end where user login is authenticated before starting the system
def __init__(self, user, password, model, year, identification):
self.model = model  # car model
self.year = year  # year the car was made
self.identification = identification  # user id
# Welcome message
print(f"Welcome {self.user} with ID {self.identification}. You are using car {self.model} from {self.year}.")

# Operation 1: Car Control
class Control:
speed = 0  # in kilometers per hr (km/ph)
max_speed = 120  # maximum speed before automatic braking
car_on = True  # if car is started
steer_direction = math.radians  # angle of steering
car_controls = ("start", "steer", "accelerate", "brake", "stop", "update")  # a list of car controls
real_time_data = []  # updates about the system will be listed here

def __init__(self, start, steer, accelerate, brake, update):
self.start = start  # car starts once login is authenticated
self.steer = steer  # cruise of the car
self.accelerate = accelerate  # speed of the car
self.brake = brake  # car halts
self.update = update  # real time data is updated

def start(self):
if self.car_on:  # if true
print(f"Car is starting.")
else:  # if false
print(f"Car is stopped.")

def steer(self, steer_left, steer_right,):
assert isinstance(steer_left, object)
print(f"Car is steering left.")
assert isinstance(steer_right, object)
print(f"Car is steering right.")

def accelerate(self, speed):
if speed >= 0:  # possible to speed up if speed is 0
print(f"Accelerating.")  # car is speeding up

def brake(self, speed):
if speed >= 120:  # maximum speed has been reached, car has to break
print(f"Braking.")  # car is slowing down

def stop(self):
if not self.car_on:  # user can control to stop as well
print(f"Car is stopped.")  # car is not moving

def update(self):  # displays real time data about the car
self.car_controls = ()
self.real_time_data = []
print(f"The state of the car is {self.car_controls}. Real time data is {self.real_time_data}")

# Operation 2: Environment Perception
class Perception:
present_location = []
lane = True  # boolean value that states whether the car is driving within the lane
avoid = ("other car", "humans", "animals", "trees", "plants")  # list of objects to avoid using LiDAR
distance = 10  # in meters, maximum distance from object

def __init__(self, location, lane_marking, avoid_object):
self.location = location  # current location
self.lane_marking = lane_marking  # lane marking on the road
self.avoid_object = avoid_object  # objects to avoid to prevent collision

def location(self):
self.present_location = []  # tells the exact location of the car in real time using GS
print(f"Present location is at [].")

def lane_marking(self):  # checks whether the car is driving within the lane, using camera and LiDAR
if self.lane:
print(f"Get back within lane.")
else:
print(f"Continue driving.")

def avoid_object(self, distance):  # detects objects to avoid using LiDAR
self.avoid = ()
if distance <= 10:  # distance of the object is too near, collision possible
print(f"Object {self.avoid} detected. Avoid collision.")  # warning message to avoid collision

# Operation 3: Vehicle to Infrastructure Communication
class V2I:
# list of traffic signs recorded in system using camera
sign = ("stop", "u-turn", "no u-turn", "turn left", "turn right", "no right", "no left")
# dictionary of traffic lights and what car motion they correspond to, using camera
light = {
"red": "stop",
"yellow": "slow down",
"green": "go"
}

def __init__(self, traffic_sign, traffic_light):
self.traffic_sign = traffic_sign  # traffic signs
self.traffic_light = traffic_light  # traffic lights

def traffic_sign(self):
self.sign = ()  # traffic sign is detected and interpreted by the camera and machine learning
print(f"This traffic sign is telling you to {self.traffic_sign}")

def traffic_light(self):
self.light = {}  # traffic light is detected and interpreted by the camera and machine learning
if self.light == "red":  # stop light
print(f"Car should stop.")  # car stops
elif self.light == "yellow":  # slow down
print(f"Car should slow down.")  # car slows down
elif self.light == "green":  # go sign
print(f"Car can move.")  # car drives

``````

Thank you!

``````class Car:

# Front end where user login is authenticated before starting the system
def __init__(self, user, password, model, year, identification):
self.model = model  # car model
self.year = year  # year the car was made
self.identification = identification  # user id
# Welcome message
print(f"Welcome {self.user} with ID {self.identification}. You are using car {self.model} from {self.year}.")
``````

The `print`â€™s good for debug so you get some confirmation that the `Car`
has been initialised correctly. But normally `__init__` is silent (as
are many functions - think of the noise!)

In real systems we try to never store passwords in the clear, or at all
really. Donâ€™t change this now, but a real system will store not the
password but a salted hash of it - this is a string computed from the
matches it, but does not let you compute the password from the hash -
the hash is a one way lossy computation.

``````# Operation 1: Car Control
class Control:
speed = 0  # in kilometers per hr (km/ph)
max_speed = 120  # maximum speed before automatic braking
car_on = True  # if car is started
steer_direction = math.radians  # angle of steering
car_controls = ("start", "steer", "accelerate", "brake", "stop", "update")  # a list of car controls
real_time_data = []  # updates about the system will be listed here
``````

I donâ€™t think the above does what you want.

Youâ€™re defining a set of attribute for the class itself (`Control`), not
each instance.

(Classes are objects too, so you can set attributes on them too.)

Normally youâ€™d be setting some of these up in the `__init__` method as
well, eg:

`````` self.speed = 0  # in kilometers per hr (km/ph)
self.car_on = True  # if car is started
self.steer_direction = math.radians  # angle of steering
self.real_time_data = []  # updates about the system will be listed here
``````

in the `__init__` method.

What we do set on the class itself is attributes defining some common
defaults or other class wide features of the class. So you might start

`````` class Control:
MAX_SPEED = 120  # maximum speed before automatic braking
CAR_CONTROLS = ("start", "steer", "accelerate", "brake", "stop", "update")  # a list of car controls
``````

Think about what these attributes mean: are they attributes for the
class, which apply for every instance and are not changed, or are they
attributes of an instance? The former youâ€™d define as above. The
latter get defined on `self` in the `__init__` method.

You can still refer to the class attributes via `self`, for example
`self.MAX_SPEED` - as long as you havenâ€™t set that attribute on `self`
it will be found on `self`â€™s class. This lets you write:

`````` if self.speed > self.MAX_SPEED:
``````

Another odd item is this line:

`````` steer_direction = math.radians  # angle of steering
``````

`math.radians` is a function accepting a value in degrees and returning
a value in radians. Iâ€™m not sure what you intended to mean here.

`````` def start(self):
if self.car_on:  # if true
print(f"Car is starting.")
else:  # if false
print(f"Car is stopped.")
``````

Whatâ€™s the purpose of this function? Is it to start the car, which I
would expect to affect the value of `self.car_on`, or to report the
current state of the car, which is what it seems to do? i.e. printing
out whether the car is on or not.

`````` def steer(self, steer_left, steer_right,):
``````

The condition in the if-statement is always false. 270 is not <= 90, and
the corresponding values in radians have the same relation. You at least
want the comparison in the other direction: `>=`. Or swap them so that
90 is on the left.

However, youâ€™re comparing two constant values: their relation is always
fixed.

I suspect you actually want to examine the value of
`self.steer_direction`. You can write this test like this:

`````` if math.radians(90) <= self.steer_direction <= math.radians(270):
``````

because Python has this nice chained comparison so you can compare
things in one go as above.

Note that this assumes `self.steer_direction` is always positive, like
the degrees range 0 through 360 - you want your radians direction to be
between 0 and 2 Ď€. This means that if you change direction you need to
make sure that the result is not negative. So if you subtract from it,
if the value goes below 0 you need it to wrap around to 2 Ď€.

At the least, put in an assertion at the start of this function:

`````` assert 0 <= self.steer_direction < 2 * math.pi
``````

That will at least fail if your value gets out of range. If you donâ€™t
know the above to be true, all the if-statements which follow can make
incorrect decisions. Thus the assertion.

`````` assert isinstance(steer_left, object)
``````

The assertion above will never fail. All values in Python are objects
and thus instances of `object`. What do you intend this assertion to
test?

``````    def accelerate(self, speed):
if speed >= 0:  # possible to speed up if speed is 0
print(f"Accelerating.")  # car is speeding up
``````

Is this really what you mean? Acceleration is change in speed. If you
intend to express whether youâ€™re allowed to accelerate, wouldnâ€™t you
test that youâ€™re below the max speed, not >0 ?

``````    def brake(self, speed):
if speed >= 120:  # maximum speed has been reached, car has to break
print(f"Braking.")  # car is slowing down
``````

Ok, here youâ€™re saying â€śtoo fastâ€ť. The `120` is what we cal a â€śmagic
numberâ€ť: a plain value in the code whose meaning isnâ€™t explained.

At the start of the class you defined `max_speed` to be this value. You
should use it here:

`````` if speed >= self.max_speed:
``````

This makes the meaning clear, and has the added benefit that you could
change the value at the top of the class and the approriate thing would
still happen here.

`````` def update(self):  # displays real time data about the car
self.car_controls = ()
self.real_time_data = []
print(f"The state of the car is {self.car_controls}. Real time data is {self.real_time_data}")
``````

This actually sets the attributes on `self`. Did you mean to do that? It
looks like this function should just contain the `print()` call.

`````` # Operation 2: Environment Perception
class Perception:
present_location = []
lane = True  # boolean value that states whether the car is driving within the lane
avoid = ("other car", "humans", "animals", "trees", "plants")  # list of objects to avoid using LiDAR
distance = 10  # in meters, maximum distance from object
``````

Again: which is these attributes are for the class, and which for the
instance? The instance attributes should be set on `self` in the
`__init__` method.

Finally:

`````` def traffic_light(self):
self.light = {}  # traffic light is detected and interpreted by the camera and machine learning
if self.light == "red":  # stop light
print(f"Car should stop.")  # car stops
elif self.light == "yellow":  # slow down
print(f"Car should slow down.")  # car slows down
elif self.light == "green":  # go sign
print(f"Car can move.")  # car drives
``````

what I have a chain of `if`/`elif`/`elif`/â€¦ I like to put a final
clause like this:

`````` else:
raise RuntimeError(f'unhandled value for self.light: {self.light!r}')
``````

This arranges to raise an exception is youâ€™ve missed something in the
earlier `if`s. Shouldnâ€™t happen, but if it does you want to know rather
than have your function silently do nothing when it should have done
something.

1 Like

Iâ€™ll only comment on a little part of the code.

First, itâ€™s good to have a separate class that models the (perception of the) environment.
But the way the code is organized can be improved. The current code has a hotch-potch of class variables (like `present_location`, `lane`) and instance variables (`location`, `lane_marking`). This makes the code very unclear - and you will have huge problems later in changing or debugging the code â€“ especially because the meanings of those variables partially overlap. So, I would advise to either use a dataclass or get rid of all class variables and put the ones you actually want/need inside the `__init__` function.

You may also benefit from having a quick look at how Agent and Environment are modeled in Reinforcement Learning. See for instance how this is done in Python code in Gymnasium.

1 Like

Hi Cameron!

Thanks so much for all your comments! I really appreciate you explaining why my code was wrong, and for telling how I can further improve on it.

I will try to redo the code, and implement whatever changes you recommended. Hopefully I can do it!

Alright, this is noted. Thanks for the information.

Okay, I will try to apply this to the other classes as well.

I just wanted to command the car to inform the direction of steering, based on the angle.

The purpose is to report the current state of the car. Should I include this in a separate function, such as update then?

You are correct, that is what I want to do. I have never applied the chained comparison, though I did read on it before. Thanks for the reminder.

``````   def accelerate(self, speed):
if speed >= 0:  # possible to speed up if speed is 0
print(f"Accelerating.")  # car is speeding up
``````

Is this really what you mean? Acceleration is change in speed. If you
intend to express whether youâ€™re allowed to accelerate, wouldnâ€™t you
test that youâ€™re below the max speed, not >0 ?

Yes, I wanted the system to accelerate if its speed is between 0-120.

It is indeed something I never use, so I will try to incorporate this more in order to describe things clearer.

It is incomplete, I should keep in mind to end them with an else always.

Thank you so much, I will try my best to fix the code based on your comments, Cameron!

I have an additional question, is it possible to test this code with assert and unittests?

Cheers.

Hi Hans,

You are right, looking at them now, they are unclear. I should fix that, cause we are required to test the code using assert and unittest. And it might be a problem for me. seeing as I am already struggling as is now. But I will keep your comment in mind, as I will fix the code based on everyoneâ€™s suggestions here. Thank you, all!

I have never encountered data classes before. Iâ€™ll try using them in the code.

Thank you!

I will try to redo the code, and implement whatever changes you
recommended. Hopefully I can do it!

Most changes should be doable.

Okay, I will try to apply this to the other classes as well.

Thereâ€™s a style feature here, too. Python doesnâ€™t have â€śconstantsâ€ť like
some languages, but we share a convention that things we would treat as
constants we given UPPERCASE names. This doesnâ€™t change any behaviour,
it just reminds us what kind of value weâ€™re looking at.

I just wanted to command the car to inform the direction of steering, based on the angle.

Right. Normally an attribute is just like a variable - itâ€™s a named
thing referring to a value. So youâ€™d use it to store the sterring
direction. Having it command the car can be done (thereâ€™s a thing
called a property which can have side effects, but put that off for
now).

There are two ways to look at â€ścommandingâ€ť the car:

• just store the steering angle, in which case youâ€™re arguably
â€śinformingâ€ť the car of the sterring direction, and for it to have an
effect something has to pay it some attention, such as the `tick()`
method
• have a method to set the angle, and the method could do other
things; in a sense that would be a command to do something. If
youâ€™re just changing the steering angle I donâ€™t see much use for doing

It just occurred to me: is the steering angle the carâ€™s current
direction, or the angle on the steering wheel, causing change in the
current direction over time?

The purpose is to report the current state of the car. Should I include this in a separate function, such as update then?

Iâ€™d just give it a different name, like `show_start()`. Methods and
functions do things (even if itâ€™s just printing) so they tend to have
verbs for names.

So a method named `start()` I would expect to actually start the car.
Try to have methods named after what they do.

``````  def accelerate(self, speed):
if speed >= 0:  # possible to speed up if speed is 0
print(f"Accelerating.")  # car is speeding up
``````

Is this really what you mean? Acceleration is change in speed. If you
intend to express whether youâ€™re allowed to accelerate, wouldnâ€™t you
test that youâ€™re below the max speed, not >0 ?

Yes, I wanted the system to accelerate if its speed is between 0-120.

Then you probably want to check both ends of the range, eg:

`````` if 0 <= speed < self.max_speed:
``````

I have an additional question, is it possible to test this code with
assert and unittests?

Definitely.

â€śdesign by contractâ€ť, which involves specifying what functions may be
given, and what they achieve. If you know these things you can reason
about whether your final outcome is achieved by the functions. The flip
side is that you can embed these constraints in the code as assertions.

Example:

`````` def square_root(x):
assert x >= 0, f'negative x not supported (x={x})'
result = math.sqrt(x)
assert result * result == x, f'result:{result} is not the square root of x:{x}'
return result
``````

This functionâ€™s contract would say that it accepts nonnegative values
and returns their square root.

At the beginning of the function you can test the requirements for `x`
and at the end of the function you can test that the `result` you
computed satisfies the contract.

You can do this with most functions.

Aside: note that with `float` values the above assert isnâ€™t reliable.
`float`s are effectively fractions, so a square root is really the
closest such fraction to the real square root and the reverse
multiplication will thus be slightly off too. We test floating point
things like this with an â€śalmost equalâ€ť test.
The `unittest` module has an `assertAlmostEqual` method for just this
kind of thing:

Note that these are run-time tests - they check that youâ€™re using the
function correctly, and that the results were good when called.

Theyâ€™re not unit tests.

Unit tests call functions with a set of test cases you define, planned
to exercise that function in important ways and to ensure that it
behaves as you expect. Theyâ€™re designed to test your functions in
isolation and small combinations without running your programme as a
whole.

Thereâ€™s a variety of unit test frameworks available, but standard Python
ships with a module called `unittest` which is where you should start:

A file containing unit tests using this module looks like this:

`````` import unittest

class TestSomething(unittest.TestCase):

def setUp(self):
...

def test_this(self):
...

def test_that(self):
...
``````

You can have a few `TestCase` classes (for example, one for `Car`s, one
for each other class), and each class can have many `test*` methods, one
for each unit test. These are normally quite small.

The `setUp()` method (optional) sets things on `self` important to all
tests. For simple things you might not need this. For a test case
covering a bunch of related things it would do some common setup. For
you, maybe it makes a `Car` (or one of your other classes):

`````` def setUp(self):
self.car = Car(......)
``````

Now you can use `self.car` as a ready made `Car` in each test without
repeating yourself in each test method. It gets called for each test
method, so you have a pristine new `Car` for every test.

Inside a test method you would do things with the car and make various
assertions. Instead of just using the `assert` statement, youâ€™d use
various `assert*` methods defined in the module. Example (totally made
up):

`````` def test_speed(self):
# assuming the Car is set up to move in the X direction
self.car.speed = 10
px0 = self.car.px
self.car.tick(2)
# check that the car move the expected distance
self.assertEqual(self.car.px, px0 + 2 * 10)
``````

If youâ€™re going to run the file directly:

`````` python3 test_file.py
``````

youâ€™ll also want the standard boilerplate at the bottom:

`````` if __name__ == '__main__':
unittest.main(__name__, None, argv)
``````

which will run the tests if you invoke the file directly. There are
tools like `pytest` which will scan your code looking for tests and run
them for you.

Anyway, the point of unit tests is to test functions and classes in
isolation, outside running your programme as a whole.

Theyâ€™ve got two primary purposes:

• test that the function behaves according to your expectations for
various important values
• test that the functions continue to pass the tests after youâ€™ve
changed them! So useful when you modify your programme!

Remember that testing helps you find bugs. It doesnâ€™t prove that you
have no bugs.