Introduction: STAAR Labs Robotics Group Project

This instructible will describe how to remake the model made to demonstrate the functionality of the food delivery rail system.

Background:

STAAR Labs designed a problem statement to help reduce the number of vehicles on the roads in peak hours at Loughborough University. Freshly made food gets delivered daily to cafes around the university by a company van. We have designed a rail and cart system to eliminate the van, freeing the roads and reducing the carbon footprint.

Our solution was to have a rail system that connects the student union (headquarters) to each on-campus cafe. There would be a robotic arm inside a cart, which would pick up and place boxes of fresh food on the kitchen counter.

We would model this to our client with a makeblock to represent the rail and cart system, and a braccio arm to represent the robotic arm which would be on board the cart.

Step 1: Designing the Solution and Model

Shown above is an open view of our autonomous vehicle model, which consists of the braccio arm, placed on a cart. The vehicle is around the same size as any normal delivery vehicle (vans/cars), so it can travel on the campus roads without disrupting traffic or requiring any new road construction, reducing the total cost of our design’s implementation. The rails can be installed into already available campus roads and as it will be built in ground, it will not disturb the travel of any other vehicles on the same road. Our vehicle also has a set of lights at the front and back to help travel at night, and to make pedestrians aware it is traveling. While traveling, there is a roof that comes over the cart to protect the goods it is transporting. The roof only uncovers when the cart has reached a drop off point. The robotic arm was placed in the corner of the cart to help maximize storage capacity and still allow automation.

Our model consists of multiple sensors like ultrasonic sensors, radar sensors and stereo cameras. It also is equipped with time of flight cameras, which is a highly accurate distance mapping and three-dimension imaging sensor. This helps it run an advanced object detection system, that runs at over 2000 frames per second, which allows the robot to quickly react and brake in case a pedestrian or driver makes a mistake and comes in the way of the traveling vehicle. These sensors also help the cart to map its surroundings and know its location, this allows the customers to track the delivery robot on the online interface where they are also able to order what goods they want, so they can proceed to the counter to collect the goods when the robot is nearby. This ensures that our vehicle, is very pedestrian/ driver safe. The cart also contains an inbuilt air-cooling system, that is powered by the same battery powering the cart, which helps keep the groceries and other perishable items fresh when it is being delivered around campus.

Step 2: Making the Model

Follow the steps provided by the booklet to produce the model for the project using the makeblock ultimate 10-in-1 kit and a braccio robotic arm.

For the makeblock, I used the bartender design to demonstrate the cart, because it had a flat surface at the top, where i could simulate the arm sitting on. I first made the the robot as suggested in the book, and then removed parts that i did not need. This includes the front portion, which would otherwise be used to hold the drink. Then I added an ultrasonic sensor and a colour sensor. The ultrasonic sensor would be used to sense if something obstructs the rails. If sensed, it will come to a stop to prevent an accident. The colour sensor is used for the line following to simulate the cart following the rails on a path. I then cut a piece of recycled cardboard, to use as a surface on top of the makeblock, to place the braccio arm and a container.

For the Braccio arm, i followed the steps provided in the kit, and this did not require very much adjustment as it fulfilled the purpose well. All the wires were tucked away well, to avoid getting in the way of the wheels.

Both the braccio arm and the makeblock were battery powered, and are to be programmed with an arduino.

Step 3: Programming the Robot

Once the braccio arm and makeblock are built, they can be programmed to do what you want it to.

Braccio Arm:

int motor1Pin1 = 8; // pin 2 on L293D IC

int motor1Pin2 = 7; // pin 7 on L293D IC

int enable1Pin = 9; // pin 1 on L293D IC

int motor2Pin1 = 5; // pin 10 on L293D IC

int motor2Pin2 = 4; // pin 15 on L293D IC

int enable2Pin = 6; // pin 9 on L293D IC

int motor3Pin1 = 14; // pin 2 on L293D IC

int motor3Pin2 = 13; // pin 7 on L293D IC

int enable3Pin = 15; // pin 1 on L293D IC

int motor4Pin1 = 11; // pin 10 on L293D IC

int motor4Pin2 = 10; // pin 15 on L293D IC

int enable4Pin = 12; // pin 9 on L293D IC

int state; int flag=0; //makes sure that the serial only prints once the state

void setup() {

pinMode(motor1Pin1, OUTPUT),pinMode(motor1Pin2, OUTPUT),pinMode(enable1Pin, OUTPUT); pinMode(motor2Pin1, OUTPUT),pinMode(motor2Pin2, OUTPUT),pinMode(enable2Pin, OUTPUT); pinMode(motor3Pin1, OUTPUT),pinMode(motor3Pin2, OUTPUT),pinMode(enable3Pin, OUTPUT); pinMode(motor4Pin1, OUTPUT),pinMode(motor4Pin2, OUTPUT),pinMode(enable4Pin, OUTPUT);

Stop();

Serial.begin(9600);

}

void loop() {

if(Serial.available() > 0){

state = Serial.read(); flag=0;

}

if (state == 'F'){

Forward();

if(flag == 0)Serial.println("Go Forward"),flag=1;

}

else if (state == 'B'){

Reverse();

if(flag == 0)Serial.println("Go Reverse"),flag=1;

}

else if (state == 'L'){

Left();

if(flag == 0)Serial.println("Go Left"),flag=1;

}

else if (state == 'R'){ Right();

if(flag == 0)Serial.println("Go Right"),flag=1;

}

else if (state == 'S'){

Stop();

if(flag == 0)Serial.println("STOP!"),flag=1;

}

else if (state == 'P'){

Pick();

if(flag == 0)Serial.println("Pick"),flag=1;

}

else if (state == 'Q'){

Place();

if(flag == 0)Serial.println("Place"),flag=1;

}

else if (state == 'H'){

Hold();

if(flag == 0)Serial.println("Hold"),flag=1;

}

else if (state == 'I'){

Free();

if(flag == 0)Serial.println("Unhold"),flag=1;

}

} v

oid Forward(){

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, HIGH);

digitalWrite(motor2Pin1, HIGH);

digitalWrite(motor2Pin2, LOW);

digitalWrite(enable1Pin, HIGH);

digitalWrite(enable2Pin, HIGH);

}

void Reverse(){

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

digitalWrite(motor2Pin1, LOW);

digitalWrite(motor2Pin2, HIGH);

digitalWrite(enable1Pin, HIGH);

digitalWrite(enable2Pin, HIGH);

}

void Left(){

digitalWrite(motor1Pin1, HIGH);

digitalWrite(motor1Pin2, LOW);

digitalWrite(motor2Pin1, HIGH);

digitalWrite(motor2Pin2, LOW);

digitalWrite(enable1Pin, HIGH);

digitalWrite(enable2Pin, HIGH);

}

void Right(){

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, HIGH);

digitalWrite(motor2Pin1, LOW);

digitalWrite(motor2Pin2, HIGH);

digitalWrite(enable1Pin, HIGH);

digitalWrite(enable2Pin, HIGH);

}

void Pick(){

digitalWrite(motor3Pin1, LOW);

digitalWrite(motor3Pin2, HIGH);

digitalWrite(enable3Pin, HIGH);

}

void Place(){

digitalWrite(motor3Pin1, HIGH);

digitalWrite(motor3Pin2, LOW);

digitalWrite(enable3Pin, HIGH);

}

void Hold(){

digitalWrite(motor4Pin1, LOW);

digitalWrite(motor4Pin2, HIGH);

digitalWrite(enable4Pin, HIGH);

}

void Free(){

digitalWrite(motor4Pin1, HIGH);

digitalWrite(motor4Pin2, LOW);

digitalWrite(enable4Pin, HIGH);

}

void Stop(){ // Stop the motors

digitalWrite(enable1Pin, LOW);

digitalWrite(enable2Pin, LOW);

digitalWrite(enable3Pin, LOW);

digitalWrite(enable4Pin, LOW);

digitalWrite(motor1Pin1, LOW);

digitalWrite(motor1Pin2, LOW);

digitalWrite(motor2Pin1, LOW);

digitalWrite(motor2Pin2, LOW);

digitalWrite(motor3Pin1, LOW);

digitalWrite(motor3Pin2, LOW);

digitalWrite(motor4Pin1, LOW);

digitalWrite(motor4Pin2, LOW);

}

Makeblock

The instructions on how to program this can be found in the booklet along with the kit.

Step 4: Programming the Web Application

The code can be separated into a 'send application' and a 'recieve application'. The program used for this application is called Spyder version 3.8 . The programming language used is Python 3

Send Application

Picture 1: Here I have used the panda library I imported to read data straight out of an excel file. Then I have extracted a list of all the products for input validation later.

Picture 2: Here I defined a function for input validation on locations. In the excel spreadsheet containing some dummy information regarding stock at a few campus café locations, each header is the name of a location, except the ‘product’ header, which contains the names of products. The function checks that the input matches a header in the file, but also checks it is not ‘product’.

Picture 3: While loop repeats until the user enters their café location. This loop does not break unless the ValidateLocation() function returns true or the user exits the program.

Picture 4: The next chunk of code checks to see if the item exists, how many places stock this product, and how many of the product each place has in stock. It first checks through the data structure created by the Pandas library for the index of the row that corresponds to the product. Then it first checks how many the user has in stock, before checking which other cafes have stock and how much. It will only print the stock of stores that have the product, otherwise it will inform the user that no other store has any more.

Then we input in the location we want to request from, which is validated again. Then we input how many we want from that location, which is again validated so that we cannot request more than is already on hand.

Picture 5: Here is the send stock request part of the application, which uses the socket library to utilise a socket to socket connection between computers. Given that stockedCafes and amount variables are instantiated with 0, this next chunk only executes if the program has successfully found a location with stock to request from.

I first create a socket object for other computers to connect to. Then we pass the socket the IP of our user and an available port on the PC. Here I have arbitrarily selected port 1235 because it is a high enough port that it is unlikely to be intercepting / interrupting traffic because it is already in use (I.e. other applications use some of the first ports available). Then we use the listen method of the object to wait for another use to access the port.

Picture 6: This loop runs until the port receives an acknowledgement that a point to point connection has been established and the message has been delivered. Here it prints the IP that the user is sending to when they have connected, which is more for proof of concept than needed. Next, I create the message from the user’s location, product needed and amount and convert it to bytes using the utf-8 encoding. The utf-8 encoding was once again arbitrarily chosen, as there are a number of encoding methods and nearly all can encode the English alphabet and digits 0-9 which is all that is really needed. Finally, there is a conformation that the message has been sent and the program finishes execution.


Receive Application

Picture 7

Here the script is much simpler. We first import the sockets library and create a socket object. Then we attempt to connect to the send user to see if they have a request waiting. Once a connection has been established and we receive a message, it is decoded using the same ‘utf8’ method as before and printed to a console window.

It is worth noting the repeated use of the .gethostname() method, which would not be in the final product as we would be passing the target socket’s IP not our own here. When implementing this system, the PCs running the application will all have to be set up with static IP addresses so that they do not change and can always send and receive messages. Since at home I do not have access to another PC to try this with I have just sent the message to myself, with the applications running on separate consoles. In terms of ports there will likely be a dictionary which functions as a directory for the ports used for each location, and these will need to be different for each application, so they do not overlap.

Picture 8: Here is the dummy spreadsheet I used to represent the backend that the current system already has to track stock levels.