In the last few days I started some serious coding. The first for 20 years, in fact, when I built the software for the BRL LinuxBots. (The coding I did six months ago doesn't really count as I was only writing or modifying small fragments of Python).
My coding project is to start building an ethical black box (EBB), or to be more accurate, a module that will allow a software EBB to be incorporated into a robot. Conceptually the EBB is very simple, it is a data logger - the robot equivalent of an aircraft Flight Data Recorder, or an automotive Event Data Recorder. Nearly five years ago I made the case, with Marina Jirotka, that all robots (and AIs) should be fitted with an EBB as standard. Our argument is very simple: without an EBB, it will be more or less impossible to investigate robot accidents, or near-misses, and in a recent paper on Robot Accident Investigation we argue that with the increasing use of social robots accidents are inevitable and will need to be investigated.
Developing and demonstrating the EBB is a foundational part of our 5-year EPSRC funded project RoboTIPS, so it's great to be doing some hands-on practical research. Something I've not done for awhile.
Here is a block diagram showing the EBB and its relationship with a robot controller.
As shown here the data flows from the robot controller to the EBB are strictly one way. The EBB cannot and must not interfere with the operation of the robot. Coding an EBB for a particular robot would be straightforward, but I have set a tougher goal: a generic EBB module (i.e. library of functions) that would - with some inevitable customisation - apply to any robot. And I set myself the additional challenge of coding in Python, making use of skills learned from the excellent
online Codecademy Python 2 course.
There are two elements of the EBB that must be customised for a particular robot. The first is the data structure used to fetch and save the sensor, actuator and decision data in the diagram above. Here is an example from my first stab at an EBB framework, using the Python dictionary structure:
# This dictionary structure serves as both
# 1 specification of the type of robot, and each data field that
# will be logged for this robot, &
# 2 the data structure we use to deliver live data to the EBB
# for this model let us create a minimal spec for an ePuck robot
epuckSpec = {
# the first field *always* identifies the type of robot plus # version and serial nos
"robot" : ["ePuck", "v1", "SN123456"],
# the remaining fields are data we will log,
# starting with the motors
# ..of which the ePuck has just 2: left and right
"motors" : [0,0],
# then 8 infra red sensors
"irSensors" : [0,0,0,0,0,0,0,0],
# ..note the ePuck has more sensors: accelerometer, camera etc,
# but this will do for now
# ePuck battery level
"batteryLevel" : [0],
# then 1 decision code - i.e. what the robot is doing now
# what these codes mean will be specific to both the robot
# and the application
"decisionCode" : [0]
}
Whether a dictionary is the best way of doing this I'm not 100% sure, being new to Python (any thoughts from experienced Pythonistas welcome).
The idea is that all robot EBBs will need to define a data structure like this. All must contain the first field "robot", which names the robot's type, its version number and serial number. Then the following fields must use keywords from a standard menu, as needed. As shown in this example each keyword is followed by a list of placeholder values - in which the number of values in the list reflects the specification of the actual robot. The ePuck robot, for instance, has 2 motors and 8 infra-red sensors.
The final field in the data structure is "decisionCode". The values stored in this field would be both robot and applications specific; for the ePuck robot these might be 1 = 'stop', 2 = 'turn left', 3 = 'turn right' and so on. We could add another value for a parameter, so the robot might decide for instance to turn left 40 degrees, so "decisionCode" : [2,40]. We could also add a 'reason' field, which would save the high-level reason for the decision, as in "decisionCode" : [2,40,"avoid obstacle right"] noting that the decision field could be a string as shown here, or a numeric code.
As I hope I have shown here the design of this data structure and its fields is at the heart of the EBB.
The second element of the EBB library that must be written for the particular robot and application, is the function which fetches data from the robot
# Get data from the robot and store it in data structure spec
def getRobotData(spec):
How this function is implemented will vary hugely between robots and robot applications. For our Linux enhanced
ePucks with WiFi connections this is likely to be via a TCP/IP client-server, with the server running on the robot, sending data following a request from the client
getRobotData(ePuckspec) For simpler setups in which the EBB module is folded into the robot controller then accessing the required data within
getRobotData() should be very straightforward.
The generic part of the EBB module will define the class EBB, with methods for both initialising the EBB and saving a new data record to the EBB. I will cover that in another blog post.
Before closing let me add that it is our intention to publish the specification of the EBB, together with the model EBB code, once it had been fully tested, as open source.
Any comments or feedback would be much appreciated.