classdef Vehicle < handle
properties
id;
withInfo;
% defines if the robot will follow with knowledge mechanism or without knowledge mechanism
shaftLength = 0.1; % 0.1
wheelRadius = 0.02; % 0.02
distanceBetweenSensors = 0.1; % 0.1
position; % [x; y; bearing]
positionHistory;
positionLeftSensor; % [x; y]
positionRightSensor;
healthPoints;
alive;
speed;
fearFactor;
room; % the room which it is in
rooms;
doors;
costs;
target;
roomsWithFire;
hasExited = false;
lastDoor = 0; % last door it came through, arbitrary 0 when it just initialised
leftLineHandle; %left side of vehicle
rightLineHandle; %right side of vehicle
frontLineHandle; %front of vehicle
backLineHandle; %back of vehile
leftWheelHandle; %wheel left
rightWheelHandle; %wheel right
leftSensorHandle; %sensor left
rightSensorHandle; %sensor right
historyPlotColour;
positionHandle; % only use it to draw a blob instead of the full
%left/right/front/back and wheels of the vehicle
% ------only relevant if withInfo is false---------
roomsSeen;
% the rooms the vehicle has been to. The vehicle does not know the
% layout of the building.
% ------only relevant if withInfo is false---------
end
methods
function obj = Vehicle(id, position, rooms, doors, withInfo, historyPlotColour)
obj.id = id;
obj.withInfo = withInfo;
obj.position = position;
obj.positionHistory = (position);
obj.positionLeftSensor = position(1:2) + obj.shaftLength/2*[cos(position(3));sin(position(3))] + ...
obj.distanceBetweenSensors/2*[-sin(position(3));cos(position(3))];
obj.positionRightSensor = position(1:2) + obj.shaftLength/2*[cos(position(3));sin(position(3))] + ...
obj.distanceBetweenSensors/2*[sin(position(3));-cos(position(3))];
obj.healthPoints = 30000;
obj.alive = true;
% set the speed and risk taking factor randomly
obj.speed = 0.5 + 1*rand(1,1);
% cost increments by 10*fearFactor when encountering fire
obj.fearFactor = rand(1,1)*0.4 + 2.8;
% obj.fearFactor = 30;
obj.rooms = rooms;
obj.room = obj.getRoom(rooms);
obj.doors = doors;
if (~obj.withInfo)
obj.roomsSeen = [obj.room.id];
end
obj.initialiseCosts();
obj.target = obj.getTarget(obj.room);
obj.faceDoor([obj.target.x, obj.target.y]);
obj.roomsWithFire = [];
% initialise room with fire for the current room
if (obj.room.hasFire())
obj.roomsWithFire = [obj.roomsWithFire, obj.room.id];
end
obj.leftLineHandle = line(0,0,'color','k','LineWidth',2); %left side of vehicle
obj.rightLineHandle = line(0,0,'color','k','LineWidth',2); %right side of vehicle
obj.frontLineHandle = line(0,0,'color','k','LineWidth',2); %front of vehicle
obj.backLineHandle = line(0,0,'color','k','LineWidth',2); %back of vehicle
obj.leftWheelHandle = line(0,0,'color','k','LineWidth',5); %wheel left
obj.rightWheelHandle = line(0,0,'color','k','LineWidth',5); %wheel right
% set the robot to red if it has information, to green if it
% does not
if (obj.withInfo)
obj.leftSensorHandle = line(0,0,'color','r','Marker','.','MarkerSize',25); %sensor left
obj.rightSensorHandle = line(0,0,'color','r','Marker','.','MarkerSize',25); %sensor right
else
obj.leftSensorHandle = line(0,0,'color','g','Marker','.','MarkerSize',25); %sensor left
obj.rightSensorHandle = line(0,0,'color','g','Marker','.','MarkerSize',25); %sensor right
end
obj.historyPlotColour = historyPlotColour;
obj.positionHandle = line(0,0,'color','k','Marker','.','MarkerSize',20);
%position. only use it to draw a blob instead of the full
%left/right/front/back and wheels of the vehicle
end
function updatePosition(self, omegaLeftWheel, omegaRightWheel)
velocity = (omegaLeftWheel*self.wheelRadius + omegaRightWheel*self.wheelRadius)/2; %this might be the velocity of car
dphi = (omegaRightWheel*self.wheelRadius - omegaLeftWheel*self.wheelRadius)/2/(self.shaftLength/2); % Remove minus sign to switch polarity, now it goes away from fire
% minus sign is changing going towards/away from lightsource
dt = 5 * self.speed; % how fast the animation is (the faster the animation, the less accurate the computation)
self.position = self.position + [velocity*cos(self.position(3));velocity*sin(self.position(3));dphi]*dt;
self.positionLeftSensor = self.position(1:2) + self.shaftLength/2*[cos(self.position(3));sin(self.position(3))] + self.distanceBetweenSensors/2*[-sin(self.position(3));cos(self.position(3))];
self.positionRightSensor = self.position(1:2) + self.shaftLength/2*[cos(self.position(3));sin(self.position(3))] + self.distanceBetweenSensors/2*[sin(self.position(3));-cos(self.position(3))];
self.positionHistory = [self.positionHistory, self.position];
end
function distance = getDistanceToFire(self, positionFire)
% distances = [distance to left sensor, distance to right
% sensor]
distance = [norm(self.positionLeftSensor - positionFire), norm(self.positionRightSensor - positionFire)];
end
function distance = getDistanceToDoor(self, positionDoor)
% distances = [distance to left sensor, distance to right
% sensor]
distance = [norm(self.positionLeftSensor - positionDoor), norm(self.positionRightSensor - positionDoor)];
end
function faceDoor(self, positionDoor)
angle = self.getAngleToDoor(positionDoor);
if (angle > 0)
while (abs(angle) > 0.05)
self.updatePosition(-0.1, 0.1);
angle = self.getAngleToDoor(positionDoor);
end
else
while (abs(angle) > 0.05)
self.updatePosition(0.1, -0.1);
angle = self.getAngleToDoor(positionDoor);
end
end
end
function vehiclesInRoom = getVehiclesInRoom(self, vehicles)
% argument vehicles is all vehicles on the map apart from
% itself
vehiclesInRoom = [];
for i = 1: numel(vehicles)
if (vehicles(i) ~= self)
if (vehicles(i).room == self.room)
vehiclesInRoom = [vehiclesInRoom, vehicles(i)];
end
end
end
end
function angle = getAngleToDoor(self, positionDoor)
u = [positionDoor(1) - self.position(1), positionDoor(2) - self.position(2)];
v = [(self.positionLeftSensor(1) + self.positionRightSensor(1)) / 2 - self.position(1), (self.positionLeftSensor(2) + self.positionRightSensor(2)) / 2- self.position(2)];
cosTheta = dot(u,v)/(norm(u)*norm(v)