3.27. Teaching a Robot to Move

First, we have a neural network watch a teacher. The robot starts at the end of a hallway, and approaches a target location 1 meter from the end of the hall.

In [1]:
from conx import *
from jyro.simulator import *
import math
import time
Using Theano backend.
conx, version 3.5.2
In [2]:
def make_world(physics):
    physics.addBox(0, 0, 8, 2, fill="backgroundgreen", wallcolor="gray")

def make_robot():
    robot = Pioneer("Pioneer", 7.5, 1, math.pi/2) #parameters are x, y, heading (in radians)
    robot.addDevice(PioneerFrontSonar(6))
    robot.addDevice(Camera())
    return robot
In [3]:
robot = make_robot()
robot
Out[3]:
_images/TeacherRobot_3_0.svg
In [4]:
def collect_data(simulator):
    data = []
    simulator.reset() # put robot back to where it is defined
    while True:
        scaled_dist = simulator.robot["sonar"].getData()[0]/6.0
        power = 1.0 - ((1 - scaled_dist)/0.33 * 0.9) # 1.0 to 0.7, power 1.0 to 0
        robot.move(power, 0)
        data.append([scaled_dist, [power]])
        simulator.step()
        time.sleep(.1) # don't overwhelm the network
        if power < 0.05:
            break
    return data
In [5]:
sim = VSimulator(robot, make_world, size=(700, 180))
In [6]:
data = collect_data(sim)
In [7]:
len(data)
Out[7]:
81
In [8]:
train = ["Training Data", [pair[1][0] for pair in data]]
In [9]:
plot(train,
     title="Speed as a Function of Distance",
     xlabel="distance from target",
     ylabel="speed",
     xs=[pair[0] for pair in data], default_symbol="o")
_images/TeacherRobot_9_0.png
In [10]:
net = Network("Go To Target")
net.add(Layer("input", 1))
net.add(Layer("hidden", 10, activation="sigmoid"))
net.add(Layer("output", 1, activation = "linear"))
net.connect()
net.compile(loss="mse", optimizer=SGD(lr=.1, momentum=.5))
net.model.summary()
_________________________________________________________________
Layer (type)                 Output Shape              Param #
=================================================================
input (InputLayer)           (None, 1)                 0
_________________________________________________________________
hidden (Dense)               (None, 10)                20
_________________________________________________________________
output (Dense)               (None, 1)                 11
=================================================================
Total params: 31
Trainable params: 31
Non-trainable params: 0
_________________________________________________________________
In [11]:
net.dataset.load(data)
net.dataset.summary()
Input Summary:
   count  : 81 (81 for training, 0 for testing)
   shape  : [()]
   range  : (0.6511592, 1.0)
Target Summary:
   count  : 81 (81 for training, 0 for testing)
   shape  : [(1,)]
   range  : (0.048616093, 1.0)
In [12]:
net.dashboard()
In [13]:
if net.saved():
    net.load()
    net.plot_loss_acc()
else:
    net.train(400, accuracy=1.0, tolerance=0.05, batch_size=1, save=True, plot=True)
_images/TeacherRobot_13_0.png
In [14]:
test = ["Network", [net.propagate(pair[0], visualize=False)[0] for pair in data]]
In [15]:
plot([train, test],
     title="Speed as a Function of Distance",
     xlabel="distance from target",
     ylabel="speed",
     default_symbol="o",
     xs=[pair[0] for pair in data])
_images/TeacherRobot_15_0.png

3.28. Network-Controlled Robot

In [16]:
outputs = []

def net_brain(robot):
    scaled_distance = robot["sonar"].getData()[0]/6
    output = net.propagate([scaled_distance], visualize=False)[0]
    robot.move(output, 0)
    outputs.append([scaled_distance, output])

robot.brain = net_brain
In [17]:
sim.widget

Run the experiment above before continuing:

  1. press the refresh button to put robot back into initial position
  2. press the play button until robot get’s to target position
  3. press stop
  4. move robot to new position
  5. press play to see what happens
  6. press stop
In [18]:
trained_range = ["Net in Trained Range", [pair for pair in outputs if pair[0] > .66]]
In [19]:
scatter(trained_range,
       title="Network Generalization", xlabel="input", ylabel="output", default_symbol="o")
_images/TeacherRobot_21_0.png
In [22]:
untrained_range = ["Net out of Trained Range", [pair for pair in outputs if pair[0] < .66]]
In [23]:
scatter([trained_range, untrained_range],
        title="Network Generalization", xlabel="input", ylabel="output", default_symbol="o")
_images/TeacherRobot_23_0.png