This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
PhyscoKillerMonkey's profile picture

Wireless Goto Program (for GPS turtles!)

Started by PhyscoKillerMonkey, 03 November 2012 - 12:10 AM
PhyscoKillerMonkey #1
Posted 03 November 2012 - 01:10 AM
So for the past few days I have been working on a GPS program for my turtles, firstly setting up a GPS tower and then writing a program that can make use of being able to find out it's exact location and act on that. It worked ok but I needed something better so after re-writing the original program (you tend to make the code a lot shorter and tidier the second time around) I added rednet functionality. This allows for the player to sit at a command terminal and order around turtles (as long as you know the co-ordinates of where to send them!) So here it is, you will need a working and properly configured GPS system in your world (I recommend taking a look at this post if you require some help)

[media]http://youtu.be/ZJenRoUVMLo[/media]

Firstly the code for the turtles, there are two files. The goto file (which can be used on it's own if you want, just use goto x y z or shell.run("goto", x, y, z) if you require it inside of a program. The program has go-around (or over) as well as good old block breaking fail safes so that it should hopefully not get stuck (in basic terrain, if you run it near buildings with overhangs and caves etc. it will get stuck, this isn't a path finding program. You will have to add those features yourself) It also auto-refuels when needed, the fuel goes in slot 1.

Spoiler

rednet.open("right") --Open rednet and clear the console
term.clear()
term.setCursorPos(1,1)
local tArgs = { ... } --Get the coordinates from alongside the program launch (goto x y z)
local gox = tonumber(tArgs[1])
local goy = tonumber(tArgs[2])
local goz = tonumber(tArgs[3])
if #tArgs ~= 3 then --Make sure there are 3 coordinates entered else the program will return an error
print("Usage: goto <x> <y> <z>")
end
local digBlocks = false --Extra parameters: whether to dig blocks or attempt to go over
local goneUp = 0 --dir and goneUp are used to keep track of position
local dir = 0
function forward()
while not turtle.forward() do --If turtle cannot go forward (either out of fuel or block blocking)
print("Can't move, checking fuel")
  if turtle.getFuelLevel() == 0 then
   turtle.select(1)
   turtle.refuel(1)
  end
  if digBlocks then --If digBlocks var was true the turtle will dig thorugh the blockage otherwise will go over
   turtle.dig()
  else
   turtle.up()
   goneUp = goneUp + 1
  end
end
while goneUp > 0 and not turtle.detectDown() do --Make sure to compensate for going up and over blocks by going down when next possible
  turtle.down()
  goneUp = goneUp - 1
end
end
function up() --Same as forward, for up
while not turtle.up() do
print("Can't move, checking fuel")
  if turtle.getFuelLevel() == 0 then
   turtle.select(1)
   turtle.refuel(1)
  end
  if digBlocks then
   turtle.digUp()
  end
end
end
function down() --Same as forward, for down
while not turtle.down() do
print("Can't move, checking fuel")
  if turtle.getFuelLevel() == 0 then
   turtle.select(1)
   turtle.refuel(1)
  end
  if digBlocks then
   turtle.digDown()
  end
end
end
function getPos() --Gets the position of the turtle from local GPS towers
print("Getting position")
cx, cy, cz = gps.locate(10)
print(cx, cy, cz)
end
function getDir() --Gets the heading of the turtle by taking position, moving forward 1 and comparing the 2 positions
print("Getting direction")
getPos()
ox, oy, oz = cx, cy, cz
forward()
getPos()
if oz > cz then dir = 0
elseif oz < cz then dir = 2
elseif ox < cx then dir = 1
elseif ox > cx then dir = 3 end
print(dir)
turtle.back()
getPos()
end
function turn(d) --Turns to heading "d", uses getDir() to calculate how many turns are needed
getDir()
print("Aligning")
print(dir, d)
while dir ~= d do
  turtle.turnRight()
  dir = dir + 1
  if dir == 4 then dir = 0 end
end
end
function moveX() --Combine the past functions to move along the x axis
print("Moving X")
getPos()
if gox > cx then --The current and destination coordinates are compared to decide which heading is needed and distance to move
  turn(1)
  for x = 1, gox - cx do
   forward()
   cx = cx + 1
  end
elseif gox < cx then
  turn(3)
  for x = 1, cx - gox do
   forward()
   cx = cx - 1
  end
end
end
function moveZ() --The same as moveX() but for the Z axis
print("Moving Z")
getPos()
if goz > cz then
  turn(2)
  for z = 1, goz - cz do
   forward()
   cz = cz + 1
  end
elseif goz < cz then
  turn(0)
  for z = 1, cz - goz do
   forward()
   cz = cz - 1
  end
end
end
function moveY() --The same as moveX() but for the Y axis, as the movement is vertical no turn calcuations are needed so this function is shorter
print("Moving Y")
getPos()
if goy > cy then
  for z = 1, goy - cy do
   up()
   cy = cy + 1
  end
elseif goy < cy then
  for z = 1, cy - goy do
   down()
   cy = cy - 1
  end
end
end
getPos()
if goy > cy then --If the turtle has to move upwards to get to the destination if moves up first, if it needs to move down if moves down last
moveY()
moveX()
moveZ()
else
moveX()
moveZ()
moveY()
end

Then there is the listening program on the turtle which constantly sends out requests for a command to all computers in the area (this can be tweaked if you want only one computer to hear it's shouts :D/>/>). Once it hears the "goto" command it readies for the co-ordinates transmission and goes off on its way.

Spoiler

--Open rednet, make clearing the screen a single function
rednet.open("right")
function clear() term.clear() term.setCursorPos(1, 1) end
while true do
clear()
print("Connected, ID: ", os.computerID(), ". Listening for requests.")
rednet.broadcast("Listening") --Tell all other computers in the area that this turtle is ready and waiting for orders
local id, msg = rednet.receive(10) --Wait for a return message for 10 seconds, then repeat
if msg == "goto" then --If the incoming message is a goto request then prepare for coordinates (other commands can be added in this if statement in the future
  print("Goto request from ", id, ", getting coordinates...")
  local id, msg = rednet.receive()
  gox = tonumber(msg) --Because only strings can be send over rednet the coordinates are changed to and from strings on each side of the message
  local id, msg = rednet.receive()
  goy = tonumber(msg)
  local id, msg = rednet.receive()
  goz = tonumber(msg)
  print("Coordinates recived, going to ", gox, " ", goy, " ", goz)
  shell.run("goto", gox, goy, goz) --Run the goto program with the recived coordinates
end
end

And finally there is the code for the control terminals. This just listens for a turtle to broadcast "Listening" and sends a message back with the command (just goto at the moment although I plan to use this for other wireless operations in the future) and the co-ordinates required.

Spoiler

rednet.open("right") --Open rednet, make clearing the screen a single function
function clear() term.clear() term.setCursorPos(1, 1) end
while true do
clear()
print("Connected, ID: ", os.computerID(), ". Listening for turtles")
id, msg = rednet.receive() --Wait for a turtle to say it is "Listening"
if msg == "Listening" then
  rednet.send(id, "goto") --When a waiting turtle is found send the command (goto) to its ID so it can ready for the transmision of coordinates
  clear()
  print("Turtle found, enter goto coordinates")
  print("Enter X")
  local gox = tonumber(io.read()) --Get the coordinates from the player, they could be aquired by another means if needed
  clear()
  print("Enter Y")
  local goy = tonumber(io.read())
  clear()
  print("Enter Z")
  local goz = tonumber(io.read())
  clear()
  print("Coordinates are: ")
  print("X: ",x)
  print("Y: ",y)
  print("Z: ",z)
  print("Sending coordinates")
  rednet.send(id, tostring(gox)) --Convert the coordinates to strings (as rednet only sends strings) and send them to the waiting turtle
  sleep(0.5)
  rednet.send(id, tostring(goy))
  sleep(0.5)
  rednet.send(id, tostring(goz))
end
end

All the code is commented so it should be understandable (not that lua is a very hard language to read anyways, as long as you use logical variables)
If you have any questions or improvements please leave a comment, feedback is always nice :)/>/>
Sodapop98 #2
Posted 06 December 2012 - 04:32 PM
This works great. Thanks.
beeproductions #3
Posted 13 December 2012 - 11:16 AM
well..got all this setup but the problem it's that the turtle won't move…

It's getting the coords..it's saying that it's going to those specific coords but won't move:(.

the fuel level it's ok..no objects in front of it..
AngelMalus #4
Posted 27 December 2012 - 08:02 PM
Why does it bounces fwd and back before every turn?
Seems like is trying to know what direction is facing.
If that is what it is, why does it need to do it, on every turn?
Mikeyhun #5
Posted 28 December 2012 - 02:30 AM
Just on more idea to shorten your code:
You should send 1 rednet message rather then 4
You can achive this by using tables like

terminal:
message = {cmd = "goto", x = gox, y = goy, z = goz}
textutils.serialize(message)
rednet.send = (id,message)

turtle:
message = textutils.unserialize(message)
if message.cmd == "goto" then
move…
elseif message.cmd == "gohome" then
move…
end

And you can get the variables the same way message.x,message,y …

this will shorten your code big time
cheers :D/>