Further work to align starNav and netNav functionality

This commit is contained in:
blunty666 2016-12-10 09:03:48 +00:00
parent a373369ba0
commit 0336cdaa2a
6 changed files with 139 additions and 54 deletions

View File

@ -20,9 +20,9 @@ if minZ > maxZ then minZ, maxZ = maxZ, minZ end
-- LOAD NETNAV API -- LOAD NETNAV API
if not netNav then if not netNav then
if not os.loadAPI("netNav") then if not os.loadAPI("netNav") then
error("could not load starNav API") error("could not load netNav API")
end end
end end
-- OPEN REDNET -- OPEN REDNET
@ -42,9 +42,7 @@ if type(mapName) ~= "string" then
printError("mapName must be string") printError("mapName must be string")
return return
end end
if not netNav.getMap() then netNav.setMap(mapName, 15)
netNav.setMap(mapName, 15)
end
local exit = false local exit = false
local returning = false local returning = false

View File

@ -1,16 +1,13 @@
if not remoteMap then local apis = {
if not os.loadAPI("remoteMap") then "remoteMap",
error("could not load remoteMap API") "aStar",
end "location",
end }
if not aStar then for _ api in ipairs(apis) do
if not os.loadAPI("aStar") then if not _G[api] then
error("could not load aStar API") if not os.loadAPI(api) then
end error("could not load API: "..api)
end end
if not location then
if not os.loadAPI("location") then
error("could not load location API")
end end
end end
@ -20,9 +17,10 @@ local SESSION_MAX_DISTANCE_DEFAULT = 32
local SESSION_COORD_CLEAR = 1 local SESSION_COORD_CLEAR = 1
local SESSION_COORD_BLOCKED = 2 local SESSION_COORD_BLOCKED = 2
local SESSION_COORD_DISTANCE = math.huge
local UPDATE_COORD_CLEAR = -1 local UPDATE_COORD_CLEAR = -1
local UPDATE_COORD_BLOCKED = 1 local UPDATE_COORD_BLOCKED = 1
local UPDATE_COORD_DISTANCE = 2
local sessionMidPoint local sessionMidPoint
local sessionMaxDistance local sessionMaxDistance
@ -33,18 +31,18 @@ local serverMap
local function distanceFunc(a, b) local function distanceFunc(a, b)
local sessionMapA, sessionMapB = sessionMap:get(a), sessionMap:get(b) local sessionMapA, sessionMapB = sessionMap:get(a), sessionMap:get(b)
if aStar.distance(a, sessionMidPoint) > sessionMaxDistance then if aStar.distance(a, sessionMidPoint) > sessionMaxDistance then
return math.huge -- first coord is outside the search region return SESSION_COORD_DISTANCE -- first coord is outside the search region
elseif aStar.distance(b, sessionMidPoint) > sessionMaxDistance then elseif aStar.distance(b, sessionMidPoint) > sessionMaxDistance then
return math.huge -- second coord is outside the search region return SESSION_COORD_DISTANCE -- second coord is outside the search region
elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then
return math.huge -- we have found one of these coords to be blocked during this session return SESSION_COORD_DISTANCE -- we have found one of these coords to be blocked during this session
elseif sessionMapA == SESSION_COORD_CLEAR and sessionMapB == SESSION_COORD_CLEAR then elseif sessionMapA == SESSION_COORD_CLEAR and sessionMapB == SESSION_COORD_CLEAR then
return aStar.distance(a, b) -- we have found both of these coords to be clear during this session return aStar.distance(a, b) -- we have found both of these coords to be clear during this session
else else
local serverMapA, serverMapB = serverMap:get(a), serverMap:get(b) local serverMapA, serverMapB = serverMap:get(a), serverMap:get(b)
if serverMapA or serverMapB then if serverMapA or serverMapB then
serverMapA = serverMapA and 2^(serverMapA + 1) or 1 serverMapA = serverMapA and UPDATE_COORD_DISTANCE^(serverMapA + 1) or 1
serverMapB = serverMapB and 2^(serverMapB + 1) or 1 serverMapB = serverMapB and UPDATE_COORD_DISTANCE^(serverMapB + 1) or 1
return math.max(serverMapA, serverMapB) -- the remote server map is indicating one of these coords may be blocked return math.max(serverMapA, serverMapB) -- the remote server map is indicating one of these coords may be blocked
end end
end end
@ -254,16 +252,16 @@ local function _goto(x, y, z, maxDistance)
local goal = vector.new(tonumber(x), tonumber(y), tonumber(z)) local goal = vector.new(tonumber(x), tonumber(y), tonumber(z))
serverMap:check() -- remove timed out data we have received from server serverMap:check() -- remove timed out data we have received from server
sessionMap = aStar.newMap() -- reset the sessionMap
sessionMap = aStar.newMap() -- reset the sessionMap
sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2)) sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2))
sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*aStar.distance(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT) sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*aStar.distance(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT)
local path = aStar.compute(distanceFunc, position, goal) local path = aStar.compute(distanceFunc, position, goal)
if not path then if not path then
return false, "no known path to goal" return false, "no known path to goal"
end end
while not (exit or aStar.vectorEquals(position, goal)) do while not (exit or aStar.vectorEquals(position, goal)) do
local movePos = table.remove(path) local movePos = table.remove(path)
while not move(position, movePos) do while not move(position, movePos) do

View File

@ -1,8 +1,9 @@
local function printUsage() local function printUsage()
print("Usage:") print("Usage:")
print(fs.getName(shell.getRunningProgram()).." <remoteMap_name> <x_pos> <y_pos> <z_pos>") print(fs.getName(shell.getRunningProgram()).." <map_name> <x_pos> <y_pos> <z_pos> <(optional)max_distance>")
print("<remoteMap_name> The name of the remoteMap to connect to and use.") print("<map_name> The name of the map to use.")
print("<x_pos> <y_pos> <z_pos> The GPS coordinates you want to go to.") print("<x_pos> <y_pos> <z_pos> The GPS coordinates you want to go to.")
print("<(optional)max_distance> The farthest distance allowed to travel from start position.")
end end
if not netNav then if not netNav then
@ -40,10 +41,22 @@ for i = 2, 4 do
end end
end end
local maxDistance
if tArgs[5] ~= nil then
if tonumber(tArgs[5]) then
print("setting max_distance to: ", tArgs[5])
maxDistance = tonumber(tArgs[5])
else
printError("max_distance: number expected")
printUsage()
return
end
end
print("going to coordinates = ", tArgs[2], ",", tArgs[3], ",", tArgs[4]) print("going to coordinates = ", tArgs[2], ",", tArgs[3], ",", tArgs[4])
local ok, err = netNav.goto(tArgs[2], tArgs[3], tArgs[4]) local ok, err = netNav.goto(tArgs[2], tArgs[3], tArgs[4], maxDistance)
if not ok then if not ok then
printError("navigation failed: ", err) printError("navigation failed: ", err)
else else
print("succesfully navigated to coordinates") print("succesfully navigated to coordinates")
end end

72
starNav/explore.lua Normal file
View File

@ -0,0 +1,72 @@
local tArgs = {...}
-- FIND AREA BOUNDARIES
local minX, minY, minZ = unpack(tArgs, 2, 4)
minX, minY, minZ = tonumber(minX), tonumber(minY), tonumber(minZ)
local maxX, maxY, maxZ = unpack(tArgs, 5, 7)
maxX, maxY, maxZ = tonumber(maxX), tonumber(maxY), tonumber(maxZ)
local function isInteger(var)
return type(var) == "number" and math.floor(var) == var
end
if not isInteger(minX) then printError("minX must be integer") return end
if not isInteger(minY) then printError("minX must be integer") return end
if not isInteger(minZ) then printError("minX must be integer") return end
if not isInteger(maxX) then printError("maxX must be integer") return end
if not isInteger(maxY) then printError("maxY must be integer") return end
if not isInteger(maxZ) then printError("maxZ must be integer") return end
if minX > maxX then minX, maxX = maxX, minX end
if minY > maxY then minY, maxY = maxY, minY end
if minZ > maxZ then minZ, maxZ = maxZ, minZ end
-- LOAD STARNAV API
if not starNav then
if not os.loadAPI("starNav") then
error("could not load starNav API")
end
end
-- OPEN REDNET
for _, side in ipairs({"left", "right"}) do
if peripheral.getType(side) == "modem" then
rednet.open(side)
end
end
if not rednet.isOpen() then
printError("Could not open rednet")
return
end
-- SET STARNAV MAP
local mapName = tArgs[1]
if type(mapName) ~= "string" then
printError("mapName must be string")
return
end
starNav.setMap(mapName)
local exit = false
local returning = false
local function main()
local startX, startY, startZ = gps.locate(1)
while turtle.getFuelLevel() > 0 and not exit do
local x = math.random(minX, maxX)
local y = math.random(minY, maxY)
local z = math.random(minZ, maxZ)
starNav.goto(x, y, z)
end
returning = true
starNav.goto(startX, startY, startZ)
end
local function control()
while true do
local senderID, message = rednet.receive("explore:return_to_base")
if not exit and not returning then
starNav.stop()
exit = true
end
end
end
parallel.waitForAny(main, control)

View File

@ -1,16 +1,13 @@
if not tinyMap then local apis = {
if not os.loadAPI("tinyMap") then "tinyMap",
error("could not load tinyMap API") "aStar",
end "location",
end }
if not aStar then for _ api in ipairs(apis) do
if not os.loadAPI("aStar") then if not _G[api] then
error("could not load aStar API") if not os.loadAPI(api) then
end error("could not load API: "..api)
end end
if not location then
if not os.loadAPI("location") then
error("could not load location API")
end end
end end
@ -38,13 +35,13 @@ local function distanceFunc(a, b)
elseif aStar.distance(b, sessionMidPoint) > sessionMaxDistance then elseif aStar.distance(b, sessionMidPoint) > sessionMaxDistance then
return SESSION_COORD_DISTANCE -- second coord is outside the search region return SESSION_COORD_DISTANCE -- second coord is outside the search region
elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then elseif sessionMapA == SESSION_COORD_BLOCKED or sessionMapB == SESSION_COORD_BLOCKED then
return SESSION_COORD_DISTANCE -- one of the coords has been found to be blocked this during this session return SESSION_COORD_DISTANCE -- we have found one of these coords to be blocked during this session
elseif sessionMapA == SESSION_COORD_CLEAR and sessionMapA == SESSION_COORD_CLEAR then elseif sessionMapA == SESSION_COORD_CLEAR and sessionMapB == SESSION_COORD_CLEAR then
return aStar.distance(a, b) -- both coords has been found to be clear this during this session return aStar.distance(a, b) -- we have found both of these coords to be clear during this session
elseif mainMap:get(a) or mainMap:get(b) then elseif mainMap:get(a) or mainMap:get(b) then
return MAIN_COORD_DISTANCE return MAIN_COORD_DISTANCE
end end
return aStar.distance(a, b) -- we are assuming both coords are clear return aStar.distance(a, b) -- we dont know anything useful so just calc the distance
end end
local directions = { local directions = {
@ -230,7 +227,9 @@ local function move(currPos, adjPos)
return false return false
end end
local exit = false
local function _goto(x, y, z, maxDistance) local function _goto(x, y, z, maxDistance)
exit = false
if not mainMap then if not mainMap then
error("mainMap has not been specified") error("mainMap has not been specified")
end end
@ -246,7 +245,7 @@ local function _goto(x, y, z, maxDistance)
local goal = vector.new(tonumber(x), tonumber(y), tonumber(z)) local goal = vector.new(tonumber(x), tonumber(y), tonumber(z))
sessionMap = aStar.newMap() sessionMap = aStar.newMap() -- reset the sessionMap
sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2)) sessionMidPoint = vector.new(math.floor((goal.x + position.x)/2), math.floor((goal.y + position.y)/2), math.floor((goal.z + position.z)/2))
sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*aStar.distance(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT) sessionMaxDistance = (type(maxDistance) == "number" and maxDistance) or math.max(2*aStar.distance(sessionMidPoint, goal), SESSION_MAX_DISTANCE_DEFAULT)
@ -255,7 +254,7 @@ local function _goto(x, y, z, maxDistance)
return false, "no known path to goal" return false, "no known path to goal"
end end
while not aStar.vectorEquals(position, goal) do while not (exit or aStar.vectorEquals(position, goal)) do
local movePos = table.remove(path) local movePos = table.remove(path)
while not move(position, movePos) do while not move(position, movePos) do
local blockPresent, blockData = inspect(position, movePos) local blockPresent, blockData = inspect(position, movePos)
@ -293,7 +292,7 @@ local function _goto(x, y, z, maxDistance)
mainMap:saveAll() mainMap:saveAll()
return true return aStar.vectorEquals(position, goal)
end end
local isRunning = false local isRunning = false
@ -311,6 +310,11 @@ function goto(...)
return unpack(passback, 2) return unpack(passback, 2)
end end
function stop()
if isRunning then
exit = true
end
end
function setMap(mapName) function setMap(mapName)
if type(mapName) ~= "string" then if type(mapName) ~= "string" then
error("mapName must be string") error("mapName must be string")

View File

@ -1,7 +1,7 @@
local function printUsage() local function printUsage()
print("Usage:") print("Usage:")
print(fs.getName(shell.getRunningProgram()).." <map_name> <x_pos> <y_pos> <z_pos> <(optional)max_distance>") print(fs.getName(shell.getRunningProgram()).." <map_name> <x_pos> <y_pos> <z_pos> <(optional)max_distance>")
print("<map_name> The name of the remoteMap to connect to and use.") print("<map_name> The name of the map to use.")
print("<x_pos> <y_pos> <z_pos> The GPS coordinates you want to go to.") print("<x_pos> <y_pos> <z_pos> The GPS coordinates you want to go to.")
print("<(optional)max_distance> The farthest distance allowed to travel from start position.") print("<(optional)max_distance> The farthest distance allowed to travel from start position.")
end end
@ -49,4 +49,4 @@ if not ok then
printError("navigation failed: ", err) printError("navigation failed: ", err)
else else
print("succesfully navigated to coordinates") print("succesfully navigated to coordinates")
end end