Problem
This is a prototype for sending commands to an Arduino Uno. The program will allow the user to receive all the logged data such as GPS data and stuff like that. Since I haven’t written the Arduino code to get actual data, the random_log function creates random data.
I have not yet written all the code for returning to home and all that jazz above, but I would first like feedback on what I have so far and how I can better organize or simplify it. (FYI the code works perfectly for me.)
import random
import time
print ('PROTOTYPE COMMAND PROMPT FOR TRANS COM')
print ('')
def random_log():
for i in range(1, 50):
right = random.randint(-10, 10)
left = random.randint(-10, 10)
r_time = random.randint(1, 15)
l_time = random.randint(1, 15)
log = [left, l_time, right, r_time]
print (log)
def rth_dir():
print ('RETURNING TO HOME POINT VIA DIRECT PATH')
return trans_com()
def rth_log():
print ('RETURNING TO HOME VIA PATH LOGS')
return trans_com()
def abort():
print ('EMERGENCY RTH HAS BEEN AUTHORIZED.')
print ('URGENT: "u" LOW BATTERY: "low bat"')
a_type = input('SELECT ABORT TYPE')
if a_type == 'u':
print ('RETURNING ASAP')
return trans_com
elif a_type == "low bat":
print ('RETURNING BECAUSE OF LOW BATTERY')
return trans_com()
else:
print ('ERROR! NOT VALID ABORT TYPE')
return abort()
def trans_com():
trans_com_in = input('COMMAND COM: ')
if trans_com_in == 'get log':
random_log()
return trans_com()
elif trans_com_in == 'rth dir':
rth_dir()
return trans_com()
elif trans_com_in == 'rth log':
rth_log()
return trans_com()
elif trans_com_in == 'a':
abort()
return trans_com()
elif trans_com_in == 'coms':
print ('=================================================================')
print ('rth_dir ---> Return To Home by direct path')
print ('rth_log ---> Return To Home by logged data')
print ('a ---> imediatly returns to home medium speed: EMERGENCY ONLY!')
print ('get log ---> prints all travel log since home point')
print ('=================================================================')
print ('')
return trans_com()
else:
print ('Unknown command, type "coms" for list of all commands')
print ('')
return trans_com()
trans_com()
trans_com is the user input for executing the different functions
Solution
Fixing minor errors
There are 2 minor errors you should fix and they are related to the commands to type:
print ('=================================================================')
print ('rth_dir ---> Return To Home by direct path')
print ('rth_log ---> Return To Home by logged data')
print ('a ---> imediatly returns to home medium speed: EMERGENCY ONLY')
print ('get log ---> prints all travel log since home point')
print ('=================================================================')
Actually typing rth_dir
and rth_lo
g lead to errors. What you actually meant was rth dir
and rth log
respectively (removed the underscore).
Handling the keyboard interrupt exception
When the user aims to exit your application and presses Ctrl + C, this exception is thrown but not handled:
...
trans_com_in = input('COMMAND COM: ')
KeyboardInterrupt
You can handle the KeyboardInterrupt
exception by running a sys.exit()
this way:
def trans_com():
try:
# The previous function body here
except KeyboardInterrupt:
sys.exit()
Better command line approach
You can make your code much cleaner and more efficient if you rely on a parser for command-line options such as the one that comes with Python itself and called argparse
. With that in mind, your in addition to cleanness and efficiency of the code mentioned before, this module will help you to get rid of several other lines of code. I
What I mean is that you can substitute these lines:
elif trans_com_in == 'coms':
print ('=================================================================')
print ('rth_dir ---> Return To Home by direct path')
print ('rth_log ---> Return To Home by logged data')
print ('a ---> imediatly returns to home medium speed: EMERGENCY ONLY!')
print ('get log ---> prints all travel log since home point')
print ('=================================================================')
print ('')
return trans_com()
else:
print ('Unknown command, type "coms" for list of all commands')
print ('')
return trans_com()
by using argparse accordingly; for example:
import argparse
# ...
# ...
parser = argparse.ArgumentParser(description="Prototype for sending commands to an Arduino Uno.")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument("--rth dir", help="Return To Home by direct path.")
group.add_argument("--rth log", help="Return To Home by logged data.")
group.add_argument("--a", help="Imediatly returns to home medium speed: EMERGENCY ONLY!")
group.add_argument("-- get log", help="Prints all travel log since home point.")
args = parser.parse_args()
This approach will automatically lead several other lines of your code , such as these ones, to be useless:
else:
print ('Unknown command, type "coms" for list of all commands')
print ('')
and:
trans_com_in = input('COMMAND COM: ')
Because when the user tries to run your code this way: python3 solution.py
, the Python interpreter will trigger this exception that is self expressing:
python3 solution.py
usage: solution.py [-h]
(–rth dir RTH DIR | –rth log RTH LOG | –a A | — get log GET LOG)
solution.py: error: one of the arguments –rth dir –rth log –a — get log is required
By typing the --help
(or -h
) option, the user can see the information you already wanted to display in your current code:
python3 solution.py -h
usage: solution.py [-h]
(--rth dir RTH DIR | --rth log RTH LOG | --a A | -- get log GET LOG)
Prototype for sending commands to an Arduino Uno.
optional arguments:
-h, --help show this help message and exit
--rth dir RTH DIR Return To Home by direct path.
--rth log RTH LOG Return To Home by logged data.
--a A Imediatly returns to home medium speed: EMERGENCY ONLY!
-- get log GET LOG Prints all travel log since home point.
Now with this approach, you need to change your code accordingly, and I think that will be easy for you to do by checking the content of args
variable instead of that of trans_com_in
.
Other notes
-
You can type:
print ('PROTOTYPE COMMAND PROMPT FOR TRANS COMn')
instead of:
print ('PROTOTYPE COMMAND PROMPT FOR TRANS COM') print ('')
- Choose better names: Functions’ names like
rth_dir()
,trans_com()
andlog_dir()
do not tell much about their purpose unless the maintainer of your code digs into their bodies. You should choose names that express right away the purpose of those functions. The same observation is valid when it comes to other variables (such astrans_com_in
,r_time
,l_time
,left
,right
. - Leave only one blank line between the definitions of your functions. Please check PEP8 for more details.