Friday 9 May 2008

Using Repast to move agents along a road network

Introduction

Some people have asked how I have used Repast Simphony to create a virtual city in which agents’ movements are restricted to a road network. So here I’ll briefly outline the method I used. I was still very new to Repast when I worked this out so I'm sure there’ll be much more efficient methods, comments/criticisms are welcome.

The basic idea is to create a GIS projection to hold the spatial locations of all the roads and a Network projection to store the topographical relationships between the roads. So if an agent needs to get to a destination we ask the Network projection which roads it has to travel along, then actually plot a course using the GIS projection.

Firstly I’ll outline a bit more about the contexts and projections and then briefly discuss how the agents move around the city.

Creating the city – contexts and projections

There are two types of objects I use to represent the road network: Roads and Junctions (or “Intersections” if you prefer). Junctions are created at the points where two roads meet and will form the Nodes in a Network projection. I used two separate contexts to store these objects called: RoadContext and JunctionContext. I also created two GIS projections and a Network projection from these contexts:



I have used separate contexts because I only want Junction objects in the RoadNetwork projection (they will form the nodes of the network) and couldn't see a way of doing this if Roads and Junctions were kept in the same context.

To read in the road data and add them to the context I saved the road network as an Arc Shapefile and then used ShapefileLoader. Simphony has made this really easy, it only takes a few lines of code.

To create the Junction objects I iterate over all the Road objects and create a Junction wherever two roads meet. Then I add the Junctions to the JunctionContext (so they are also automatically added to the RoadNetwork projection) and create an edge between them (setting the weight as the distance of the road segment). So now there are Road objects in the RoadGeography and repast edges in the RoadNetwork. It's important to keep a list of roads and edges so we know which road each edge corresponds to, this is how we can link the GIS projection to the Network projection.

That’s all that is required to create the city road network. Now we have the spatial information (the RoadGeography) and topographical information (the RoadNetwork) about the roads. In the next section I’ll outline how to move agents around the city.

Moving around the city

I will assume that the agent is starting on a road segment. If the agent isn’t on a road (they could be at home for example) then a few extra steps will be needed to move them onto the nearest road first. The routing algorithm works by firstly building a list of coordinates which the agent must pass through to get to their destination and then moving along the planned route.

Planning the route

The following diagram illustrates a hypothetical route and the junctions which the agents will pass through to get between their origin and destination.



The following steps briefly outline how to create a route:
  1. Find the nearest Junctions to the agent’s starting position and the destination.
  2. Calculate a list of edges (in the RoadNetwork projection) which make up the bulk of the route (I use the repast.simphony.space.graph.ShortestPath.getPath() function).
  3. Create a list of coordinates which the agent must pass through to get from the origin to the destination. This is done by:
    1. Iterating over all the edges which make up the route and:
    2. Finding the Road object (in the RoadGeography GIS projection) which corresponds to the edge (this is why it is necessary to keep a list of edges and their corresponding road when building the city).
    3. Adding all the coordinates which make up the geometry of the road to the list.
(If the road network is a true manhattan grid then there are a number of ways of improving the efficiency of the routing algorithm. This is rarely the case in European cities though so I assume the road network is much less ordered and that roads have bends in them. Also, I assume that the agent will want to get to destinations which are part-way along a road segment, if this restriction is removed (so the agent only travels to Junctions) then the algorithm can be made even simpler.)

So now the agent will have a list of coordinates which will take the agent from an its origin to its destination, restricted to roads.

Moving

My agents are only allowed to move a certain distance each turn, so the last step which is required is to calculate whether or not the agent can make it all the way to the next coordinate in it’s list and if not, where it will end up. This is fairly straightforward using a vector.



If the agent cannot make it all the way from coordinate (b) to coordinate (a), you can move it the maximum remaining distance it is allowed to travel in the direction of (a). Then in the next iteration it can continue on towards (a) as normal.


That's it, I’m sorry if that isn’t very clear but I hope it will help. Please email me if you have any questions.

21 comments:

Anonymous said...

Fantastic! I think you might have just saved me a month's worth of work and more than a few sleepless nights.
Crile from NZ

Martin said...

Thanks for a very relevant post. Would you be able to point to any more concrete resources, such as in your introductory tutorial to Repast/GIS? A couple of lines of code would be extremely helpful.
Martin (CH)

Nick Malleson said...

Martin, the Repast mailing list has quite a lot of information on it, but I can't think of anything more specific. Over the next few days I'll try to make my code a bit more understandable and then publish it, that might help a bit.
Cheers,
Nick

Lily said...

Nick,

You have done a great job. I have tried your tutorial with my own shapefiles and it was really easy to follow. Thank you for your guidance!! I totally agree that it will be great if you may be able to post the code to make possible to move the agents trough the road network, I bet that it will be a first big step for many students in order to develop other kind of models and you will have the very well earned credits!!

Anonymous said...

Hello Nick:
Thanks for this work.
Haow I can make my Shapefile?
Tahnks

Nick Malleson said...

A shapefile is a geographic data file used by the ArcGIS software. If you don't have access to ArcGIS there is free software available that you can use to create these files, have a look at QuantumGIS or uDig (or google for 'open source gis'.

kakald said...

Hi Nick, i have a problem when i get the position of people(agent). I try to print out the position of agent, then the result as following:
Charlie is at: (-1.5416054025675636,53.76233761532447)
Ed is at: (-1.5351642215901398,53.7591775067917)
Ben is at: (-1.547286024883547,53.75552702133503)
Andy is at: (-1.5529309275054117,53.75933862993736)
Jenny is at: (-1.5495796564669024,53.76255502964699)
....

Can you tell me the reason of this result

Nick Malleson said...

Hi Kakald,
That is correct, it the agents' positions in lat/long decimal format (the default projection used by Simphony).
Cheers,
Nick

kakald said...

Hi Nick,
I have a question. I suppose that i have a line and the agent is out of the line. My goal is to move the agent to an extrimity and after that agent will move to end point. I did as following but it can not run
- Use movebyVector() function to allow agent move to first extrimity (with angle of first one) and after that i also use this function to move agent from first one to end point.
But it can not run. Can you explain me the reason?
Thanks

kakald said...

Hi Nick, i see that in your source code, there is a function which is to convert from long/lat to meters. But when i compare it with a tool, it's not correct. Can you explain more?
Thanks

Nick Malleson said...

Hi Kakald,

For your first question about moveByVector() please could you be more specific about what the problem is? It might be easier to email me directly.

For the convertToMeters function, have a look at this code:

http://dl.dropbox.com/u/299787/convertToMeters.txt

Cheers,
Nick

nilesh anand said...

Hi, Nick,

Great work!!

I am following each documents of yours to understand ABM.

I would like to know whether it is possible to use google map for GIS so that you can make it like real city.

Thanks,

nilesh anand

david said...

Hello Nick,

First and foremost i would like to complement you on the model you have developed, it is really usefull.

I have been using it as of lately and have modified the shapefiles for some of the contexts. I have modified the vehicle and house shapefiles. The latter i have actually replaced with another shapefile called customers. I have incorporated these new shapefiles in the "GLOBAVARIABLES" and when running the model it does not take the new customer.shp but still takes the old house.shp.

Can you tell me if i am overlooking something?


Kind regards,

David Watson

Nick Malleson said...

Hi David,
Sorry for not replying sooner. I'm going to spend most of next week redesigning the software to make it easier to use so if you can hold off for another week then the problem might have gone. Without more details

Otherwise the only thing I can suggest is that the software is actually reading the new customers file but still displaying the old one. To do this you need to edit the display in the GUI.

Nick

Nij said...

Hello Nick,

First of all, thank you very much for sharing your excellent work.

I am trying to input the road shapefile into RepastCity2. The location of this road network is in Bangkok, Thailand, and it covers around 5 sq.km. areas. I have also created shapefiles for agents and houses.

Once I run the model, only agents appear on the GUI, and the agents seem to move along the (invisible) road network. In addition, I was able to export the road shapefile from the GUI. So, it seems like the road shapefile has been included in the model but did not show up.

I was wondering if I have overlook anything in the model. And I would be very much grateful if you could please give my some pieces of advice on how to get around this problem.

Thank you very much.
Nij from NY

Nick Malleson said...

Hi Nij,

I'm glad you have found the software useful. The only reason I can think that the roads aren't being displayed is because you haven't added them to the display again (so they're in the model but not being displayed). It would be nice if this was done automatically but I couldn't work out how to at the time (maybe in the new version of the Repast software this will be possible).

Try editing the Person Display (under the 'Person Context' list on the left). You should get the option to add a shapefile to the display, use this to add your road network. If you're not sure about anything, I'd highly recommend the Repast tutorial ('Repast Java Getting Started') here: http://repast.sourceforge.net/docs.html

Nij said...

Hi Nick,

Thank you so much for your reply. I will try to edit the code as you suggested, and will certainly let you know how it goes.

Thank you once again,
Nij

Anonymous said...

Hi! Nick! this is student from Japan.In my case, my reseach background is a parking area.Without GIS map how to import the map of a parking area into REPAST and is it need to be identified by X and Y? Or it also can be worked out by drawing map with each lot in the excel and import into Repast? I really want to know the related the code now! Thank you very much! Vero

Nick Malleson said...

Hi Vero,
I think you will need to import it using a GIS Shapefile (that's the easiest way to do it). There should be a good way to convert your Excel spreadsheet into a GIS, but you'll have to do some googling for that.. Sorry I can't be more help.

Nick

Vidya said...

Hello Nick,

For my dissertation, I am trying to move the occupants of a room to the nearest emergency exit. I am not a programmer and am learning python and java. Could you please provide me the code to move the agents as I have understood the logic but cannot translate it to code at the moment.

Thanks

Nick Malleson said...

Hi Vidya,

Have a look at RepastCity, it basically does the same thing:

http://code.google.com/p/repastcity/

Nick