Here is my code. I have walls in the colors grey and brown, which turtles should avoid when moving. I have to move my turtles when Eat = 1 toward the door with the color green and enter the room if Eat =0 turtle has to move in black patches only.
I have an issue as turtles are not moving through the door and also when facing the wall they stop there instead of
to go
ask students [
pd
set heading 90
forward 1
if (eat = 1)
[
if (([pcolor] of patch-left-and-ahead 90 1 = green) or ([pcolor] of patch-left-and-ahead 90 2 = green) or
([pcolor] of patch-left-and-ahead 90 3 = green) or ([pcolor] of patch-left-and-ahead 90 4 = green) or
([pcolor] of patch-left-and-ahead 90 5 = green) and pycor <= -10 )
[
set heading towards one-of patches with [pcolor = green]
forward 1
]
if ([pcolor] of patch-ahead 1 = green)
[
set heading 0
forward 3
]
if (pycor >= -9 and [pcolor] of patch-ahead 1 = black)
[
set heading 270
forward 1
]
]
while [ any? patches in-radius 1 with [ pcolor = grey ] or any? patches in-radius 1 with [ pcolor = brown - 2]] [
bk 1
lt (random 180) - 90
fd 1
]
]
tick
end
Your code looks quite chaotic to me so it is hard to give immediate pointers. Instead, let me describe what happens at each part:
let new-patch patch-ahead 2
You define new-patch as the patch in the direction your student is currently facing
if ([pcolor] of patch-here = black ) [
ifelse (eat = 0)
[set heading random 360
forward 1]
[
set heading random 360
forward 1
set heading towards one-of patches with [pcolor = green]
forward 5
]
When a turtle is standing on a black patch, it has two options, depending on whether or not it has any eat. If it has no eat, it faces a random direction and takes a step forward. If it has eat, it also faces a random direction and takes a step forward. After that it chooses a random door and moves 5 steps towards it.
The immediate problems I see with this part are:
What is the purpose of turning in a completely random direction and stepping forward?
Since both the turtles with eat and those without eat have the random walk it, it should not be inside the ifelse blocks.
The random step could make your turtle step onto a grey or brown patch, which I assume you don't want
The students with eat != 1 move towards a random green patch but this green patch they choose can be a different one each tick, causing them to move back and forward between two doors. I suggest either having them pick one door as destination and storing it as a turtle variable, always moving towards that one until they reach it (set my-door one-of patches with [pcolor = green]) or having them move towards the closest door (set heading towards min-one-of (patches with [pcolor = green]) [distance myself])
Here as well, your turtle could walk onto a wall if it is in the direct line towards your door
Onto the next part
if ([pcolor] of new-patch = grey or [pcolor] of new-patch = brown - 2 ) [
right 180
forward 1
]
Here you have the turtle turn around and take a step in the other direction, if the patch that was 2 in front of them at the start was grey or brown.
This part of the code is executed regardless of whether or not the first part was executed, meaning that if the turtle stood on a black patch before, it first chose new-patch as the patch that was 2 in front of it, then it did some random turning and a step forward, and now it checks what color the patch they initially defined as new-patch had, even if they are now looking in a completely opposite direction. This could actually make them turn back towards the patch you are trying to avoid
I'm just wondering, why have new-patch be the patch that is 2 steps ahead and not 1 step ahead?
And finally
if ( pxcor >= -9 and [pcolor] of patch-here = grey or [pcolor] of patch-here = brown - 2)[
left 180
forward 1
]
Here you have a turtle turn around if the patch they are standing on is grey or brown. Not necessarily a bad way of solving them walking into walls but it does not solve all of those instances and furthermove provides problems once you are stuck in those walls
Let's assume you are standing on a grey patch while facing the door. This means that there is generally grey in front and grey behind. Since the student is not standing on black, there is no random walk. The patch 2 ahead is grey so you turn around and take a step. Now you are standing on another grey patch so you turn back and take a step, ending right where you started this tick.
Of course for this to happen you first need to actually end up in the wall. For that we have the forward 5 from earlier to blame. A turtle that is close to the wall and moves 5 steps toward a door can do so through part of a wall. It gets deep enough for both of your 180° turns not to be able to get them out.
Instead of all this turning around, I suggest you add in a local variable called destination let destination patch-ahead 1, let it check whether or not that patch is a wall and only start randomly turning if it is a wall. Then set destination patch-ahead 1 and check again. Only let it move towards destination after all the checking is done.
In general, I suggest you let the turtles put their pen down to more accurately trace their movement ask turtles [pd], reduce the number of turtles and see what happens from step to step
As to your final question of why they don't move through the door: well, in the code there is no command that tells them what to do if the patch they are standing on is green so once they step onto the green they will simply stop. (or if they manage to move through the door, they will turn back towards it (or another door) and with the random walks added in, they will eventually end up either in a wall or on top of the door, both of which make them stop)
Last but certainly not least: start a bit smaller. Use just one or a few turtles, a short wall and a single door. Make sure your movement works on that before scaling up to all those different rooms
I hope this points you in the right direction and will be glad to further elaborate if you have questions
Related
I'm trying to model predators hunting prey through a world filled with obstacles. In an obstacle free world, the predators go on random walks until prey fall within a certain detection radius (react-D), and then move towards the prey to capture. I guess there may be several ways to handle obstacles that block line of sight, but my initial efforts are along the following lines:
ifelse any? prey in-radius react-D
[let target min-one-of prey in-radius react-D [distance myself]
face target
...move towards target if it's closer than the nearest obstacle (blue patch) ahead
]
[continue to random walk, avoiding obstacles
]
The first condition of ifelse may need another ifelse. In any case I think I just need a distance of the nearest blue patch ahead to compare with the target distance, but it's not clear to me how I can get that from patch-ahead.
It would be nicer if I could put all this into the test of the first ifelse, but something like the following doesn't allow for patches that aren't blocking line of sight to the prey:
ifelse any? prey in-radius react-D and min-one-of (patches in-radius react-D with [pcolor = blue])[distance myself] > min-one-of (prey in-radius react-D) [distance myself]
Line of sight is actually really tricky to model in NetLogo. At the moment I do it by creating a turtle (invisible, separate breed called crawler) where the agent is that is looking and have the crawler move ahead in small steps checking the colour of the patch that it is on. That goes inside a while loop and the crawler stops when it finds the wrong colour or when it gets to the target distance. the crawler has to take small steps because crossing over the corner of a patch should still block it and it's a trade-off between resolution (how small the crawler step is) against efficiency.
You can almost certainly do the same thing by creating a patch-set as the union of patches found with patch-ahead of multiple distances like 0.1, 0.2, .... and then checking any? over that patch-set
My current solution, giving patches-own [ ob ] values of 1 to all obstacle patches, then using while to detect obstacles ahead:
to detect-ahead
let dist 1
let last-patch patch-here
while [dist <= react-D] [
let p patch-ahead dist
if p != last-patch and [ob] of p = 1 [
ask p [ sprout-markers 1 [ set color yellow ] ]
set last-patch p
]
set dist dist + 1
]
end
Then it should simply be a case of comparing min-one-of the marker agent set with the target. Obviously smaller increments would be good, as JenB says.
I'm trying to add a condition that doesn't allow an agent to cross over a road. The road patches are set to color red. I can't seem to figure out how to get this condition to work. I ultimately want the agent to turn around if the road is in the patch ahead. Here is my net logo code so far.
to go
ask turtles [
move
]
tick
if ticks >= 60 [stop]
end
to move
ifelse random-float 1 < q
[
ifelse random-float 1 < w
[let target-patch max-one-of neighbors [veg-suitability]
face target-patch]
[let target-patch max-one-of neighbors [pelev]
face target-patch]
]
[
ifelse [pcolor] of patch-ahead 1 = red
[lt random-float 180]
move-to one-of neighbors
ldd-normal
]
end
to ldd-normal
let ldd-distance (ldd-scale)
fd ldd-distance
end
The logic of your move procedure is a bit confused I think. First you have a random chance to either move to a patch with a higher value of a variable of interest (with the uphill primitive) or, if the random draw fails, it moves to a random neighbour. If you don't want it to move onto a red patch then you need to test if the patch that is chosen is red, but you just move it without checking.
After you have moved the turtle, you then check the colour of patch-ahead. Your problem here is that patch-ahead depends on the direction the turtle is facing, which has nothing to do with the direction it has already been moving. You either make it turn (though it may not turn enough) OR move forward. So it never actually moves away.
I can't give you an actual answer because I don't know what your logic is supposed to be. But you could look at structures like:
move-to one-of neighbors with [pcolor != red]
Or, if there are enough red patches that it is possible that there aren't any non-red neighbours (which would cause an error if you tried to move to one), you could use:
let okay-patches neighbors with [pcolor != red]
if any? okay-patches [move-to one-of okay-patches]
Another option is that you only meant to face rather than move to the patch in the first sections of code, then test whether it is facing a red patch and turn around if it is.
My code is about 2 car in one road, where both cars will change their heading (turn to left) if they meet head-to-head, and go back to the center of the road (which is pycor = 0) and turtles can't walk outside the road,
My problem is I don't know how to make the turtles move back to the center, I tried to use cohesion from flocking, but I don't know the right way. Here is my code:
globals
[initialHead too-close-distance]
turtles-own
[speed
top-speed]
to setup
clear-all
ask patches [setup-road]
setup-cars
reset-ticks
end
to go
move
end
to setup-road
if pycor < 2 and pycor > -2 [ set pcolor white
]
end
to setup-cars
create-turtles 1
[
setxy -15 0
set color red
set size 1.2
set initialHead 90
set speed 0.5
set top-speed 0.5 + random-float 0.5
]
create-turtles 1
[
setxy 15 -0
set color blue
set size 1.2
set initialHead 270
set speed 0.5
set top-speed 0.5 + random-float 0.5
]
end
to move
ask turtles
[
speed-up-car
avoid
forward speed]
end
to avoid
slow-down-car
let visibility (patches in-cone 7 50)
let center pycor = 0
let too-near one-of other turtles-on visibility
ifelse too-near != nobody
[turn-away ([heading] of too-near) max-separate-turn
[;need to turn back to center]
[ fd speed]
end
to turn-away [new-heading max-turn]
turn-at-most (subtract-headings heading new-heading) max-turn
end
to turn-at-most [turn max-turn] ;; turtle procedure
ifelse abs turn > max-turn
[ ifelse turn > 0
[ rt max-turn ]
[ lt max-turn ] ]
[ rt turn ]
end
to speed-up-car
set speed (speed + acceleration)
if speed > top-speed [ set speed top-speed ]
end
to slow-down-car
set speed (speed - deceleration)
if speed < 0 [ set speed deceleration ]
end
Here's some basic logic that I think will work for passing for the case of 2 cars heading opposite directions. The logic gets much more complex if you have many cars.
I'll leave it to you to write NetLogo code.
Basically, you need a state-transition plans which keeps track of what state each car is in, so it can decide what to do next and what state that will put it in.
Suppose you have states ["driving", "turning-away", "passing", "turning-back" ], and you know if you have conflicting traffic. You also know your y-position so you know how far off the center you are.
You need to figure out logically what all the possible and relevant transitions are and the rules that determine which one to take given what state you are currently in.
It would be interesting (!) to model the states as nodes and the transitions as links, but let's leave that for another time.
Basically you will end up with a long list of if-else clauses, which you can evaluate to decide what the next-state will be, and then after everything is evaluated, you can do what it takes to move to that state. Rather than building a full dynamic model of motion, let's simplify to say that passing involves turning to 10 degrees from the original heading for a bit, then by 30 degrees for a while, then by 10 degrees for a while longer, then back to 0 degrees when happily off the road. Returning to the center-line is just the reverse process. This would probably look ok to a user.
Here's some pseudocode:
if driving and there's no conflict, keep driving.
if driving [
if there's a conflict
[ set next-state "turning-away"
if off-road by short distance [set offset-angle 10]
if off-road by medium distance [ set offset-angle 30]
if off-road by large distance [ set offset-angle 10]
if off-road entirely [ set offset-angle 0 set state "passing"]
]
otherwise [ set next-state "driving"]
and move forward based on speed and heading.
if in the middle of turning away the conflict goes away, i don't know what you want to do. Probably completing move to the passing location is simplest to code.
if passing and there's still a conflict, keep on passing
if passing and there's no conflict anymore, reverse the moves based on distance off-road to get back on the road.
if in the middle of turning back there is a new conflict, i don't know what you want to do. Probably change to turning-away and pick a heading based on distance from the centerline as above.
Anyway, let me know what you think of that approach. I don't see how to make it much simpler.
Im struggling to get turtles to avoid certain patches with a colour green while still pathing towards a target patch.
my netlogo model simulates a countries ocean fishing with boats (turtle) leaving from ports into the sea and returning. Each boat currently sets a target patch in the ocean based on underlying GIS fishing effort data points (patch variables).
Currently, on the way to their target, some boats have to travel out of their semi enclosed ports and if using line of site will travel across land (green patches). I cannot figure out how to get the boats to choose a path which avoids green patches while still pathing towards the same target patch?
Most answers I have found here only accommodate relatively random movement where the heading is changed if a green patch is within a cone X or in front. I am trying to figure out a pathing technique which doesnt involve head towards X until you hit green then go random left or right but this model needs to be able to determine whether heading left or right after hitting green patch (in the cone) is the right way to go. very confused!!
Patches-own
land
vessels-own
home-port ; patch of the home port
target ; target patch for fishing
ask patches ; sets the color of land and sea patches
[ ifelse (land = 1)
[set pcolor green]
[set pcolor blue]
]
to choose-target
set target one-of patches in-radius 60 with [(fishing-
effort > 100) and (fishing-effort < 1010)] ; sets the
fishermen target to one of the patches with a fishing
effort score
end
to movement
ifelse distance target < 1
[stop] ;
[ face target
forward 1
set fuel fuel - 1] ; uses one fuel per movement forwards
if distance target < 1 [ stop]
end
Thanks!
I have built the road shapefile which already intersected with patches. I want the turtle to move on the road that I had assigned.
to go
ask turtles
[
step
avoid-wall
]
tick
end
to-report coinflip?
report random 2 = 0
end
to avoid-wall
if [pcolor] of patch-ahead 3 = black [set heading heading - 180]
end
to step
ifelse coinflip? [rt random 60] [lt random 60]
fd random 3
end
Actually, I intend to let the turtle move out of the assigned patches. But I still want them to come back in the next tick or just the few tick later. Some turtles come back and some do not (according to my code). How should I fix the code?
I have tried to use this code in Turtles moving in a pattern (Netlogo) but it does not work (I think that it does not work because my patches are a narrow road, not an area.)