Cómo crear agentes con rangos de visión en AnyLogic
- Contexto
- Modelo
- Video
- Descarga
Con frecuencia se desea limitar el movimiento e iteración de los agentes a solo aquellos elementos que caen dentro un rango de visión limitado. Este modelo es una demostración de cómo se pueden crear rangos de visión a los agentes en un espacio determinado.
En este modelo se asumen agentes representando bulldozers esparcidos en un campo donde hay diferentes minas a las que los agentes deben trasladarse. Estos agentes solo pueden identificar las minas que se encuentran en el rango de visión establecido.
El modelo cuenta con dos tipos de agentes: MyAgents y Mine.
MyAgent representa el bulldozer cuya visión es limitada. La mina es el lugar donde el bulldozer debe desplazarse.
Los agentes estan contenidos en dos poblaciones: myAgents y mines, ambas inician vacías al comienzo del modelo mediante la función Setup. Esta crea los agentes, los ubica de manera aleatoria en el espacio y asigna parámetros. A continuación se presenta la función:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
for(int i=0; i<totAgents; i++){ MyAgent m = add_myAgents(); m.angleRange=angleRange; Point p = rectangle.randomPointInside(); m.setXY(p.getX(), p.getY()); m.polyline.setPoint(1, 50, -50*Math.tan(m.angleRange/57.2958)); m.polyline.setPoint(2, 50, +50*Math.tan(m.angleRange/57.2958)); m.setRotation(uniform(-1, 1)*Math.PI); m.rot=m.getRotation()*57.2958; } for(int i=0; i<totMines; i++){ Mine m = add_mines(); Point p = rectangle.randomPointInside(); m.setXY(p.getX(), p.getY()); m.remaining=uniform(20, 140); } |
El usuario cuenta con diferentes botones donde puede seleccionar agentes, rotarlo y obtener los agentes dentro del rango de visión frente a él. Este rango de visión es determinado por el ángulo solamente (cualquier agente con un ángulo menor a una referencia predeterminada es aceptable. El usuario puede además incluir la distancia como parte del rango de visión, es decir no solo considerar las minas que estén dentro del ángulo de visión frente a el sino también dentro de una distancia determinada).
La selección del agente se realiza utilizando el siguiente código
1 2 3 4 5 6 7 8 9 10 11 12 |
for(MyAgent m:myAgents) { m.polyline.setFillColor(new Color(238, 232, 170, 107)); m.view=false; } textResults.get(0).setText(""); textResults.get(1).setText(""); MyAgent m = myAgents.random(); m.view=true; textSelected.get(0).setText("Selected Bulldozer " + m.getIndex()); textSelected.get(1).setText("Selected Bulldozer " + m.getIndex()); m.polyline.setFillColor(new Color(255, 160, 122, 107)); agent=m; |
El cálculo del ángulo y la distancia se hace en el siguiente código
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
if(agent!=null){ textResults.get(0).setText(""); textResults.get(1).setText(""); collection.clear(); double x1 = agent.getX(); double y1 = agent.getY(); int from = agent.getIndex(); for(Mine m: mines){ double x2 = m.getX(); double y2 = m.getY(); int to = m.getIndex(); double r = getAngleTo(m, agent); collection.put(r, m); } Iterator it = collection.keySet().iterator(); while (it.hasNext()) { double val = (double)it.next(); if(val<agent.angleRange) { textResults.get(0).setText(textResults.get(0).getText() + "\nmine " + collection.get(val).getIndex() + " angle " + val + " distance " + getDistanceTo(collection.get(val), agent)); textResults.get(1).setText(textResults.get(1).getText() + "\nmine " + collection.get(val).getIndex() + " angle " + val + " distance " + getDistanceTo(collection.get(val), agent)); } } } |
Este código hace uso de dos funciones: getAngleTo y getDistanceTo. A continuación se presentan estas dos funciones:
1 2 3 4 5 6 7 |
double x1 = a.getX(); double y1 = a.getY(); double x2 = m.getX(); double y2 = m.getY(); double r = Math.atan2(y2 - y1,x2 - x1)*57.2958-a.rot; if(r<-180) r+=360.0; return abs(r); |
1 2 3 4 5 6 |
double x1 = a.getX(); double y1 = a.getY(); double x2 = m.getX(); double y2 = m.getY(); double r = getDistance(x1, y1, x2, y2); return r; |
Existen además botones para aumentar o reducir el ángulo de rotación de los bulldozers. El ángulo del campo de visión puede ser ajustado usando un slider. El código del slider se presenta a continuación:
1 2 3 4 5 |
for(MyAgent m:myAgents){ m.angleRange=angleRange; m.polyline.setPoint(1, 50, -50*Math.tan(m.angleRange/57.2958)); m.polyline.setPoint(2, 50, +50*Math.tan(m.angleRange/57.2958)); } |
El siguiente es un video del modelo en funcionamiento
El modelo en AnyLogic puede ser descargado en el siguiente Link
Comentario Final
Como se ha podido observar el modelo no pretende hacer más que reportar las minas frente al agente que están dentro de su campo de visión. El usuario puede agregar utilizar este código como base para agregar acciones más complejas como movimientos, ruteos e incluso algoritmos de decisión.
No olviden dejar su comentario!