461 lines
14 KiB
Lua
461 lines
14 KiB
Lua
|
-- Problem: Program si? wiesza przy zapisywaniu zdj?? i wysy?aniu requesta do API
|
||
|
http = require('socket.http')
|
||
|
json = require('json')
|
||
|
|
||
|
COLOR_WHITE = {255, 255, 255}
|
||
|
COLOR_RED = {255, 0, 0}
|
||
|
COLOR_GREEN = {0, 255, 0}
|
||
|
COLOR_BLUE = {0, 0, 255}
|
||
|
|
||
|
OBSTACLE_AVOID_DISTANCE = 3
|
||
|
MOVING_VELOCITY = 20
|
||
|
TURNING_VELOCITY = 15
|
||
|
PROXIMITY_STOP_DISTANCE = 1
|
||
|
CONFIDENCE = 0
|
||
|
IMAGE_COUNTER = 0
|
||
|
CAMERA_FIELD_OF_VIEW = 60
|
||
|
PHOTO_WIDTH = 1920
|
||
|
BATERY_VALUE = 10
|
||
|
|
||
|
function sysCall_init()
|
||
|
|
||
|
os.execute("rm -r robot")
|
||
|
os.execute("mkdir robot")
|
||
|
|
||
|
ModelHandle = sim.getObject(".")
|
||
|
ModelName = sim.getObjectAlias(ModelHandle)
|
||
|
|
||
|
RatHandles = {} -- List of rats on the scene
|
||
|
local i = 0
|
||
|
while true do
|
||
|
local rat_handle = sim.getObject("/Rat*", {index=i, noError=true})
|
||
|
if rat_handle < 0 then
|
||
|
break
|
||
|
end
|
||
|
table.insert(RatHandles, rat_handle)
|
||
|
i = i + 1
|
||
|
end
|
||
|
|
||
|
DuckHandles = {} -- List of ducks on the scene
|
||
|
local i = 0
|
||
|
while true do
|
||
|
local duck_handle = sim.getObject("/Duck*", {index=i, noError=true})
|
||
|
if duck_handle < 0 then
|
||
|
break
|
||
|
end
|
||
|
table.insert(DuckHandles, duck_handle)
|
||
|
i = i + 1
|
||
|
end
|
||
|
|
||
|
RightWheel = sim.getObject("./RightWheel")
|
||
|
LeftWheel = sim.getObject("./LeftWheel")
|
||
|
Camera = sim.getObject("./Camera")
|
||
|
VisionSensor = sim.getObject("./Vision_sensor")
|
||
|
SonarRight = sim.getObject("./Proximity_sensor_right")
|
||
|
SonarLeft = sim.getObject("./Proximity_sensor_left")
|
||
|
|
||
|
Diodes = { -- LED_strip has to be ungrouped
|
||
|
D2 = sim.getObject("./diode_2"),
|
||
|
D3 = sim.getObject("./diode_3"),
|
||
|
D4 = sim.getObject("./diode_4"),
|
||
|
D5 = sim.getObject("./diode_5"),
|
||
|
D6 = sim.getObject("./diode_6"),
|
||
|
D7 = sim.getObject("./diode_7")
|
||
|
}
|
||
|
|
||
|
sim.setShapeColor(sim.getObject("./diode_1"), nil, 0, COLOR_WHITE)
|
||
|
sim.setShapeColor(sim.getObject("./diode_8"), nil, 0, COLOR_WHITE)
|
||
|
|
||
|
sim.setObjectInt32Param(RightWheel,2000, 1) -- Enable velocity control
|
||
|
sim.setObjectInt32Param(LeftWheel,2000, 1)
|
||
|
sim.setObjectInt32Param(Camera,2000, 1)
|
||
|
|
||
|
Set_wheel_velocity(5, 5)
|
||
|
sim.setJointTargetVelocity(Camera, 0)
|
||
|
|
||
|
sim.setJointTargetForce(LeftWheel, 5)
|
||
|
sim.setJointTargetForce(RightWheel, 5)
|
||
|
|
||
|
Last_Color_Change_Time = sim.getSimulationTime()
|
||
|
Last_Camera_Rotation_Time = sim.getSimulationTime()
|
||
|
Last_Photo_Time = sim.getSimulationTime()
|
||
|
Last_Turn_Time=sim.getSimulationTime()
|
||
|
Turning = false
|
||
|
Seeing_Another_Rat = 0
|
||
|
Close_To_Rat = false
|
||
|
CameraAngle = Get_angle(VisionSensor)
|
||
|
ModelAngle = Get_angle(ModelHandle)
|
||
|
Rat_Degrees_Offset_From_Photo_Center = 0
|
||
|
|
||
|
DEBUG_Sensor_Time = sim.getSimulationTime()
|
||
|
|
||
|
--sim.addBanner("Bateria = 100", 2, sim_banner_fullyfacingcamera, nil, ModelHandle, nil, nil)
|
||
|
|
||
|
Camera_Rotate_Counter = 0
|
||
|
--IMAGE_COUNTER = 0
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
function sysCall_actuation()
|
||
|
-------------------- photo test --------------------
|
||
|
if (sim.getSimulationTime() - Last_Photo_Time) > 0.5 then
|
||
|
if BATERY_VALUE > 0 then
|
||
|
BATERY_VALUE = BATERY_VALUE - 1
|
||
|
UpdateBatery(BATERY_VALUE)
|
||
|
end
|
||
|
if not Close_To_Rat then
|
||
|
Take_photo()
|
||
|
end
|
||
|
Last_Photo_Time = sim.getSimulationTime()
|
||
|
end
|
||
|
|
||
|
-------------------- camera test -------------------
|
||
|
if (sim.getSimulationTime() - Last_Camera_Rotation_Time) > 1.7 then
|
||
|
if Camera_Rotate_Counter == 0 then
|
||
|
sim.setJointTargetVelocity(Camera, 2)
|
||
|
Camera_Rotate_Counter = 1
|
||
|
else
|
||
|
sim.setJointTargetVelocity(Camera, -2)
|
||
|
Camera_Rotate_Counter = 0
|
||
|
end
|
||
|
Last_Camera_Rotation_Time = sim.getSimulationTime()
|
||
|
end
|
||
|
|
||
|
-------------------- moving test -------------------
|
||
|
if Turning == true and Angle_difference(Get_angle(ModelHandle), Desired_angle) < 10 then
|
||
|
Finish_turning()
|
||
|
Stop_if_close(RatHandles)
|
||
|
end
|
||
|
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
function sysCall_sensing()
|
||
|
local _, _, _, detected_handle_left, _ = sim.readProximitySensor(SonarLeft)
|
||
|
local _, _, _, detected_handle_right, _ = sim.readProximitySensor(SonarRight)
|
||
|
if Has_Value(RatHandles, detected_handle_left) or Has_Value(RatHandles, detected_handle_right) then
|
||
|
if detected_handle_left > 0 and Has_Value(RatHandles, detected_handle_left) then
|
||
|
Handle = detected_handle_left
|
||
|
else
|
||
|
Handle = detected_handle_right
|
||
|
end
|
||
|
Close_To_Rat = true
|
||
|
Change_strip_color(COLOR_RED)
|
||
|
SensorMovement(Handle)
|
||
|
elseif BATERY_VALUE > 0 then
|
||
|
Close_To_Rat = false
|
||
|
VisionMovement()
|
||
|
else
|
||
|
Set_wheel_velocity(0, 0)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
function sysCall_cleanup()
|
||
|
-- do some clean-up here
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
------------------------------ non-sysCall functions below ------------------------------
|
||
|
function VisionMovement()
|
||
|
if Seeing_Another_Rat == 1 then
|
||
|
local adjusted_angle = Calculate_desired_angle(CameraAngle, Rat_Degrees_Offset_From_Photo_Center)
|
||
|
local angle_diff = Angle_difference(ModelAngle, adjusted_angle)
|
||
|
if angle_diff > 5 then
|
||
|
if math.abs(ModelAngle - adjusted_angle) < 180 then
|
||
|
if ModelAngle < adjusted_angle then
|
||
|
print(string.format("[%s] Rat detected on the left", ModelName))
|
||
|
else
|
||
|
print(string.format("[%s] Rat detected on the right", ModelName))
|
||
|
angle_diff = -angle_diff
|
||
|
end
|
||
|
else
|
||
|
if ModelAngle > adjusted_angle then
|
||
|
print(string.format("[%s] Rat detected on the left", ModelName))
|
||
|
else
|
||
|
print(string.format("[%s] Rat detected on the right", ModelName))
|
||
|
angle_diff = -angle_diff
|
||
|
end
|
||
|
end
|
||
|
DEGREES_TO_TURN = angle_diff
|
||
|
Start_turning(angle_diff)
|
||
|
ModelAngle = 0
|
||
|
CameraAngle = 0
|
||
|
Rat_Degrees_Offset_From_Photo_Center = 0
|
||
|
end
|
||
|
if not Turning then
|
||
|
Go_Forward()
|
||
|
end
|
||
|
elseif not Turning then
|
||
|
Random_Walk()
|
||
|
end
|
||
|
if not Turning then
|
||
|
Stop_if_close(RatHandles)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function SensorMovement(handle)
|
||
|
Follow(handle)
|
||
|
end
|
||
|
|
||
|
|
||
|
function RatCallPredictionAPI(filename)
|
||
|
local response = http.request(string.format("http://127.0.0.1:5000/detectRat1?img=%s", filename))
|
||
|
return json.decode(response)
|
||
|
end
|
||
|
|
||
|
function RobotCallPredictionAPI(filename)
|
||
|
local response = http.request(string.format("http://127.0.0.1:5000/detectRobot1?img=%s", filename))
|
||
|
return json.decode(response)
|
||
|
end
|
||
|
|
||
|
function UpdateBatery(batery_value)
|
||
|
sim.addBanner(batery_value, 0.4, sim_banner_fullyfacingcamera, {1.0, 0, 0, 0, 0, 0}, ModelHandle, nil, {1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})
|
||
|
end
|
||
|
|
||
|
function Has_Value (tab, val)
|
||
|
for index, value in ipairs(tab) do
|
||
|
if value == val then
|
||
|
return true
|
||
|
end
|
||
|
end
|
||
|
return false
|
||
|
end
|
||
|
|
||
|
|
||
|
function Change_strip_color(rgb_vals)
|
||
|
for _, v in pairs(Diodes) do
|
||
|
sim.setShapeColor(v, nil, 0, rgb_vals)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function Set_wheel_velocity(left_vel, right_vel)
|
||
|
sim.setJointTargetVelocity(LeftWheel, left_vel)
|
||
|
sim.setJointTargetVelocity(RightWheel, right_vel)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Take_photo()
|
||
|
CameraAngle = Get_angle(VisionSensor)
|
||
|
ModelAngle = Get_angle(ModelHandle)
|
||
|
local img = sim.getVisionSensorImg(VisionSensor)
|
||
|
local filename = "img"..IMAGE_COUNTER..".png"
|
||
|
local path = "robot1/"..filename
|
||
|
sim.saveImage(img, {1920,1080}, 0, path, -1)
|
||
|
print(string.format("[%s] Photo taken 1", ModelName))
|
||
|
local res = RatCallPredictionAPI(filename)
|
||
|
local res_robot = RobotCallPredictionAPI(filename)
|
||
|
print(CONFIDENCE)
|
||
|
if BATERY_VALUE > 0 then
|
||
|
if table.concat(res['0']) == 'None' then
|
||
|
--print(CONFIDENCE)
|
||
|
if CONFIDENCE > 0 then
|
||
|
CONFIDENCE = CONFIDENCE - 1
|
||
|
end
|
||
|
Seeing_Another_Rat = 0
|
||
|
if not Close_To_Rat and CONFIDENCE == 0 then
|
||
|
Change_strip_color(COLOR_GREEN)
|
||
|
print(string.format("[%s] No rats detected!", ModelName))
|
||
|
else
|
||
|
print(string.format("[%s] Chase the rat!", ModelName))
|
||
|
end
|
||
|
|
||
|
else
|
||
|
local frame_width = res['0'][1]
|
||
|
local rat_pos = res['0'][2] + frame_width / 2
|
||
|
Rat_Degrees_Offset_From_Photo_Center = (rat_pos - (PHOTO_WIDTH / 2)) / (PHOTO_WIDTH/CAMERA_FIELD_OF_VIEW)
|
||
|
if table.concat(res_robot['0']) == 'None' then
|
||
|
Seeing_Another_Rat = 1
|
||
|
Change_strip_color(COLOR_RED)
|
||
|
CONFIDENCE = 3
|
||
|
print(string.format("[%s] Another rat detected on camera", ModelName))
|
||
|
elseif res_robot['0'][1] == 'red' then
|
||
|
Seeing_Another_Rat = 0
|
||
|
print(string.format("[%s] I'm looking for another rat. This robot doesn't need my help", ModelName))
|
||
|
if CONFIDENCE == 0 then
|
||
|
Change_strip_color(COLOR_GREEN)
|
||
|
end
|
||
|
|
||
|
elseif res_robot['0'][1] == 'white' then
|
||
|
Seeing_Another_Rat = 1
|
||
|
print(string.format("[%s] Robot need my help. I'm on my way!", ModelName))
|
||
|
Change_strip_color(COLOR_RED)
|
||
|
CONFIDENCE = 3
|
||
|
end
|
||
|
end
|
||
|
IMAGE_COUNTER = IMAGE_COUNTER + 1
|
||
|
else
|
||
|
Change_strip_color(COLOR_WHITE)
|
||
|
print(string.format("[%s] I have to charge my battery", ModelName))
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
|
||
|
function Orientation_to_angle(orientation)
|
||
|
-- returns a value between [0, 360]
|
||
|
local angle = math.deg(orientation[2]) + 90
|
||
|
if orientation[1] < 0 then
|
||
|
angle = 360 - angle
|
||
|
end
|
||
|
return angle
|
||
|
end
|
||
|
|
||
|
|
||
|
function Get_angle(handle)
|
||
|
local orientation = sim.getObjectOrientation(handle, sim.handle_world)
|
||
|
return Orientation_to_angle(orientation)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Calculate_desired_angle(old_angle, angle_delta)
|
||
|
local desired = old_angle + angle_delta
|
||
|
if desired > 360 then
|
||
|
return desired % 360
|
||
|
elseif
|
||
|
desired < 0 then
|
||
|
return desired + 360
|
||
|
else
|
||
|
return desired
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function Angle_difference(actual_angle, desired_angle)
|
||
|
-- returns a value between [0, 180]
|
||
|
local diff = math.abs(desired_angle - actual_angle)
|
||
|
return diff < 180 and diff or 360 - diff
|
||
|
end
|
||
|
|
||
|
|
||
|
function Turn_Left()
|
||
|
Set_wheel_velocity(0, TURNING_VELOCITY)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Turn_Right()
|
||
|
Set_wheel_velocity(TURNING_VELOCITY,0)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Go_Forward()
|
||
|
Set_wheel_velocity(MOVING_VELOCITY, MOVING_VELOCITY)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Stop_Moving()
|
||
|
Set_wheel_velocity(0, 0)
|
||
|
end
|
||
|
|
||
|
|
||
|
function Start_turning(degrees)
|
||
|
FULL_CIRCLE_PERIOD = 2.8 -- at 2.5 speed
|
||
|
print(string.format("[%s] Starting to turn %.2f degrees", ModelName, degrees))
|
||
|
Turning = true
|
||
|
Desired_angle = Calculate_desired_angle(Get_angle(ModelHandle), degrees)
|
||
|
if degrees > 0 then
|
||
|
Turn_Left()
|
||
|
else
|
||
|
Turn_Right()
|
||
|
end
|
||
|
Last_Turn_Time = sim.getSimulationTime()
|
||
|
end
|
||
|
|
||
|
|
||
|
function Finish_turning()
|
||
|
Go_Forward()
|
||
|
Last_Turn_Time = sim.getSimulationTime()
|
||
|
Turning = false
|
||
|
After_turning = Get_angle(ModelHandle)
|
||
|
print(string.format("[%s] Finished turning; Angle deviation from desired: %.2f (Desired: %.2f vs Actual: %.2f)",
|
||
|
ModelName,
|
||
|
Angle_difference(After_turning, Desired_angle),
|
||
|
Desired_angle,
|
||
|
After_turning))
|
||
|
end
|
||
|
|
||
|
|
||
|
function Random_Walk()
|
||
|
local _, obstacle_left_distance, _, _, _ = sim.readProximitySensor(SonarLeft)
|
||
|
if obstacle_left_distance == 0 then
|
||
|
obstacle_left_distance = math.huge
|
||
|
end
|
||
|
|
||
|
local _, obstacle_right_distance, _, _, _ = sim.readProximitySensor(SonarRight)
|
||
|
if obstacle_right_distance == 0 then
|
||
|
obstacle_right_distance = math.huge
|
||
|
end
|
||
|
|
||
|
if obstacle_right_distance < obstacle_left_distance and obstacle_right_distance < OBSTACLE_AVOID_DISTANCE then
|
||
|
Turn_Left()
|
||
|
elseif obstacle_left_distance < obstacle_right_distance and obstacle_left_distance < OBSTACLE_AVOID_DISTANCE then
|
||
|
Turn_Right()
|
||
|
else
|
||
|
Go_Forward()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function Follow(object_handle) -- Use with flat sensors with no blind zone in the middle
|
||
|
local left_detected, left_distance, _, _, _ = sim.checkProximitySensor(SonarLeft, object_handle)
|
||
|
local right_detected, right_distance, _, _, _ = sim.checkProximitySensor(SonarRight, object_handle)
|
||
|
|
||
|
if (sim.getSimulationTime() - Last_Photo_Time) > 0.5 then
|
||
|
if not Close_To_Rat then
|
||
|
local img = sim.getVisionSensorImg(VisionSensor)
|
||
|
local filename = "img"..IMAGE_COUNTER..".png"
|
||
|
local path = "robot1/"..filename
|
||
|
sim.saveImage(img, {1920,1080}, 0, path, -1)
|
||
|
end
|
||
|
Last_Photo_Time = sim.getSimulationTime()
|
||
|
IMAGE_COUNTER = IMAGE_COUNTER + 1
|
||
|
end
|
||
|
|
||
|
if left_detected == 1 and right_detected == 1 then
|
||
|
Go_Forward()
|
||
|
elseif left_detected == 1 then
|
||
|
Turn_Left()
|
||
|
elseif right_detected == 1 then
|
||
|
Turn_Right()
|
||
|
else
|
||
|
Go_Forward()
|
||
|
end
|
||
|
|
||
|
if (left_distance > 0 and left_distance < PROXIMITY_STOP_DISTANCE) or (right_distance > 0 and right_distance < PROXIMITY_STOP_DISTANCE) then
|
||
|
Stop_Moving()
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
function Stop_if_close(handle_table)
|
||
|
-- Przy szczurach jest ok przy robotach z jakiegos powodu nie wykrywa jesli patrzy na kolo zamiast chassisa (kolo pewnie ma inny objecthandle?)
|
||
|
local left_detected, left_distance, _, left_detected_object_handle, _ = sim.readProximitySensor(SonarLeft)
|
||
|
local right_detected, right_distance, _, right_detected_object_handle, _ = sim.readProximitySensor(SonarRight)
|
||
|
if Has_Value(handle_table, left_detected_object_handle) or Has_Value(handle_table, right_detected_object_handle) then
|
||
|
if (left_distance > 0 and left_distance < PROXIMITY_STOP_DISTANCE) or (right_distance > 0 and right_distance < PROXIMITY_STOP_DISTANCE) then
|
||
|
Stop_Moving()
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
|
||
|
|
||
|
------------------------------ DEBUG functions below ------------------------------
|
||
|
function DEBUG_What_Do_I_See(sensor_handle)
|
||
|
local detected, distance, detected_point, detected_object_handle, detected_surface_normal_vector = sim.readProximitySensor(sensor_handle)
|
||
|
if detected == 1 then
|
||
|
print(string.format("[%s] Object detected by %s; Handle: %d, Name: %s, Distance: %.2f",
|
||
|
ModelName,
|
||
|
sim.getObjectAlias(sensor_handle),
|
||
|
detected_object_handle,
|
||
|
sim.getObjectAlias(detected_object_handle, 1),
|
||
|
distance))
|
||
|
end
|
||
|
end
|