Commit 0d776ef2 authored by k20066's avatar k20066
Browse files

initialize

parents
File added
#
# https://help.github.com/articles/dealing-with-line-endings/
#
# These are explicitly windows files and should use crlf
*.bat text eol=crlf
# Java
*.class
# Log files
*.log
hs_err_pid*
# Gradle
.gradle
build
bin
# IntelliJ
*.iml
*.ipr
*.iws
.idea
# Eclipse project
.settings
.project
.classpath
# Visual Studio Code
.vscode
# Theia IDE
.theia
# Project
precomp_data
test-results
BSD 3-Clause License
Copyright (c) 2018-2021, RoboCupRescue
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the copyright holder nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# `adf-sample-agent-java` Agent Development Framework Sample Agent Java
(Linux) Instructions to download, build and run the sample implementation using the Agent Development Framework (ADF)
## 1. Software Pre-Requisites
* Git
* OpenJDK Java 17
* Gradle
## 2. Download
```bash
$ git clone https://github.com/roborescue/adf-sample-agent-java.git
```
## 3. Compile
```bash
$ cd adf-sample-agent-java
$ ./gradlew clean
$ ./gradlew build
```
## 4. Execute
The `adf-sample-agent-java` is a sample team implementation for the RCRS (`rcrs-server`) using the ADF core (`adf-core-java`).
To run the `adf-sample-agent-java`, first the `rcrs-server` must be running (Instructions of how to download, compile and run the `rcrs-server` are available at <https://github.com/roborescue/rcrs-server>).
After start the `rcrs-server`, open a new terminal window and execute
```bash
$ cd adf-sample-agent-java
$ ./launch.sh -all
```
## 5. Support
To report a bug, suggest improvements or request support, please open an issue at GitHub <https://github.com/roborescue/rcrs-adf-sample/issues>.
\ No newline at end of file
plugins {
id 'java'
}
defaultTasks 'build'
group = 'com.github.roborescue'
sourceCompatibility = '17'
targetCompatibility = '17'
version = '4.0'
dependencies {
implementation fileTree(dir: 'lib', include: '*.jar')
implementation 'com.github.roborescue:rcrs-server:master-SNAPSHOT'
implementation 'com.github.roborescue:adf-core-java:master-SNAPSHOT'
implementation 'log4j:log4j:1.2.17'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
}
repositories {
mavenCentral()
maven {
url = 'https://sourceforge.net/projects/jsi/files/m2_repo'
}
maven {
url = 'https://repo.enonic.com/public/'
}
maven {
url 'https://jitpack.io'
}
}
test {
useJUnitPlatform()
}
javadoc {
options {
encoding = 'UTF-8'
addStringOption('Xdoclint:none', '-quiet')
}
}
clean {
doFirst {
delete file( new File( rootDir, 'bin' ) )
delete file( new File( rootDir, 'build' ) )
delete file( new File( rootDir, 'precomp_data' ) )
delete file( new File( rootDir, 'test-results' ) )
}
}
[compileJava, compileTestJava].each {
it.options.encoding = 'UTF-8'
it.options.compilerArgs += [ '-Xlint:unchecked', '-Xlint:deprecation' ]
}
task launch(type: JavaExec) {
classpath = files('lib')
classpath += files('.')
classpath += sourceSets.main.runtimeClasspath
mainClass = 'adf.core.Main'
maxHeapSize = '2048m'
}
\ No newline at end of file
{
"ActionFireFighting.refill.completed": 10,
"ActionFireFighting.refill.request": 1,
"ActionFireFighting.rest": 100,
"ActionFireRescue.rest": 100,
"ActionExtClear.forcedMove": 3,
"ActionExtClear.rest": 100,
"ActionTransport.rest": 100,
"ActionExtMove.rest": 100,
"SampleBuildingDetector.sendingAvoidTimeClearRequest": 5,
"SampleBuildingDetector.sendingAvoidTimeReceived": 3,
"SampleBuildingDetector.sendingAvoidTimeSent": 5,
"SampleBuildingDetector.moveDistance": 40000,
"SampleHumanDetector.sendingAvoidTimeClearRequest": 5,
"SampleHumanDetector.sendingAvoidTimeReceived": 3,
"SampleHumanDetector.sendingAvoidTimeSent": 5,
"SampleHumanDetector.moveDistance": 40000,
"CommandPickerAmbulance.scoutDistance": 40000,
"CommandPickerFire.scoutDistance": 40000
}
\ No newline at end of file
kernel.host: localhost
kernel.port: 27931
team.name: sample_team
adf.launcher.precompute: 0
adf.debug.flag: 0
adf.develop.flag: 0
adf.develop.filename: config/develop.json
#adf.develop.data:
adf.agent.moduleconfig.filename: config/module.cfg
#adf.agent.moduleconfig.data:
adf.team.platoon.ambulance.count: -1
adf.team.platoon.fire.count: -1
adf.team.platoon.police.count: -1
adf.team.office.ambulance.count: -1
adf.team.office.fire.count: -1
adf.team.office.police.count: -1
\ No newline at end of file
## DefaultTacticsAmbulanceTeam
DefaultTacticsAmbulanceTeam.HumanDetector : sample_team.module.complex.SampleHumanDetector
DefaultTacticsAmbulanceTeam.Search : sample_team.module.complex.SampleSearch
DefaultTacticsAmbulanceTeam.ExtActionTransport : adf.impl.extaction.DefaultExtActionTransport
DefaultTacticsAmbulanceTeam.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
DefaultTacticsAmbulanceTeam.CommandExecutorAmbulance : adf.impl.centralized.DefaultCommandExecutorAmbulance
DefaultTacticsAmbulanceTeam.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScout
## DefaultTacticsFireBrigade
DefaultTacticsFireBrigade.HumanDetector : sample_team.module.complex.SampleHumanDetector
DefaultTacticsFireBrigade.Search : sample_team.module.complex.SampleSearch
DefaultTacticsFireBrigade.ExtActionFireRescue : adf.impl.extaction.DefaultExtActionFireRescue
DefaultTacticsFireBrigade.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
DefaultTacticsFireBrigade.CommandExecutorFire : adf.impl.centralized.DefaultCommandExecutorFire
DefaultTacticsFireBrigade.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScout
## DefaultTacticsPoliceForce
DefaultTacticsPoliceForce.RoadDetector : sample_team.module.complex.SampleRoadDetector
DefaultTacticsPoliceForce.Search : sample_team.module.complex.SampleSearch
DefaultTacticsPoliceForce.ExtActionClear : adf.impl.extaction.DefaultExtActionClear
DefaultTacticsPoliceForce.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
DefaultTacticsPoliceForce.CommandExecutorPolice : adf.impl.centralized.DefaultCommandExecutorPolice
DefaultTacticsPoliceForce.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScoutPolice
## DefaultTacticsAmbulanceCentre
DefaultTacticsAmbulanceCentre.TargetAllocator : sample_team.module.complex.SampleAmbulanceTargetAllocator
DefaultTacticsAmbulanceCentre.CommandPicker : adf.impl.centralized.DefaultCommandPickerAmbulance
## DefaultTacticsFireStation
DefaultTacticsFireStation.TargetAllocator : sample_team.module.complex.SampleFireTargetAllocator
DefaultTacticsFireStation.CommandPicker : adf.impl.centralized.DefaultCommandPickerFire
## DefaultTacticsPoliceOffice
DefaultTacticsPoliceOffice.TargetAllocator : sample_team.module.complex.SamplePoliceTargetAllocator
DefaultTacticsPoliceOffice.CommandPicker : adf.impl.centralized.DefaultCommandPickerPolice
## SampleSearch
SampleSearch.PathPlanning.Ambulance : adf.impl.module.algorithm.DijkstraPathPlanning
SampleSearch.Clustering.Ambulance : adf.impl.module.algorithm.KMeansClustering
SampleSearch.PathPlanning.Fire : adf.impl.module.algorithm.DijkstraPathPlanning
SampleSearch.Clustering.Fire : adf.impl.module.algorithm.KMeansClustering
SampleSearch.PathPlanning.Police : adf.impl.module.algorithm.DijkstraPathPlanning
SampleSearch.Clustering.Police : adf.impl.module.algorithm.KMeansClustering
## SampleBuildDetector
SampleBuildingDetector.Clustering : adf.impl.module.algorithm.KMeansClustering
## SampleRoadDetector
SampleRoadDetector.Clustering : adf.impl.module.algorithm.KMeansClustering
SampleRoadDetector.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## SampleHumanDetector
SampleHumanDetector.Clustering : adf.impl.module.algorithm.KMeansClustering
## DefaultExtActionClear
DefaultExtActionClear.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## DefaultExtActionFireFighting
DefaultExtActionFireFighting.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## DefaultExtActionFireRescue
DefaultExtActionFireRescue.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## DefaultExtActionMove
DefaultExtActionMove.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## DefaultExtActionTransport
DefaultExtActionTransport.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## DefaultCommandExecutorAmbulance
DefaultCommandExecutorAmbulance.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
DefaultCommandExecutorAmbulance.ExtActionTransport : adf.impl.extaction.DefaultExtActionTransport
DefaultCommandExecutorAmbulance.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
## DefaultCommandExecutorFire
DefaultCommandExecutorFire.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
DefaultCommandExecutorFire.EtxActionFireRescue : adf.impl.extaction.DefaultExtActionFireRescue
DefaultCommandExecutorFire.EtxActionFireFighting : adf.impl.extaction.DefaultExtActionFireFighting
DefaultCommandExecutorFire.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
## DefaultCommandExecutorPolice
DefaultCommandExecutorPolice.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
DefaultCommandExecutorPolice.ExtActionClear : adf.impl.extaction.DefaultExtActionClear
DefaultCommandExecutorPolice.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
## DefaultCommandExecutorScout
DefaultCommandExecutorScout.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
## DefaultCommandExecutorScoutPolice
DefaultCommandExecutorScoutPolice.PathPlanning : adf.impl.module.algorithm.DijkstraPathPlanning
DefaultCommandExecutorScoutPolice.ExtActionClear : adf.impl.extaction.DefaultExtActionClear
## MessageManager
MessageManager.PlatoonChannelSubscriber : adf.impl.module.comm.DefaultChannelSubscriber
MessageManager.CenterChannelSubscriber : adf.impl.module.comm.DefaultChannelSubscriber
MessageManager.PlatoonMessageCoordinator : adf.impl.module.comm.DefaultMessageCoordinator
MessageManager.CenterMessageCoordinator : adf.impl.module.comm.DefaultMessageCoordinator
## VisualDebug
VisualDebug : true
\ No newline at end of file
File added
= Agent Development Framework (ADF) Manual
:author: RoboCup Rescue Simulation Team
:revnumber: 4.1
:revdate: February 03, 2023
:size: A4
:reproducible: true
:encode: UTF-8
:lang: en
:sectids!:
:sectnums:
:sectnumlevels: 3
:toclevels: 3
:outlinelevels: 3
:xrefstyle: short
:imagesoutdir: images
:imagesdir: images
:math:
:stem: latexmath
:source-highlighter: rouge
:bibtex-file: references.bib
:bibtex-style: apa
:bibtex-order: alphabetical
:bibtex-format: asciidoc
:title-page:
:toc: left
<<<
[#purpose]
== Purpose
The manual instructs how to install and execute the RoboCup Rescue Simulation Agent Development Framework (ADF) Sample Agents, and how to implement a new team of agents using the ADF Sample Agents.
[#installation]
== Installation
This manual assumes the agents will run in a Linux machine even though it is possible to run them in Microsoft Windows or Apple macOS. We recommend to use Linux because it is open-source and most of the distributions have a good support from the users' community. If you have never used Linux before and intend to, we recommend starting with a user-friendly distribution, such as https://www.ubuntu.com/[Ubuntu] or https://getfedora.org[Fedora].
[#requirements]
=== Software Requirements
* Git
* OpenJDK Java 17
* Gradle
* Utilities like `wget`, `bash`, `xterm`, `tar`, `gzip`, etc. +
**NOTE:** If you are using Ubuntu, all of these utilities are present in the default software repositories.
[#download]
=== Download
You can download the sample agents with ADF by cloning the `https://github.com/roborescue/adf-sample-agent-java` repository. Clone this repository using the command
[source,shell]
----
git clone https://github.com/roborescue/adf-sample-agent-java.git
----
[#directories]
=== Directories
The `adf-sample-agent-java` contains multiple directories. The important directories are:
* `config/`: ADF and Agent Modules' configuration files
* `src/`: Sample agents' source codes
* `precomp_data`: results of a precomputation for each type of agents
[#compiling]
=== Compiling
Execute the steps below to compile the ADF Sample Agent.
[source,shell]
----
$ cd adf-sample-agent-java
$ ./gradlew clean build
----
[#running]
== Running
There are two modes of execution of the simulation server and ADF Sample Agent: *Precomputation* and *Normal*.
[#precomputation_mode]
=== Precomputation Mode
In the precomputation mode, the simulator connects one agent of each type and allows them to write the computation results persistently.
The sequence of commands to run the simulation server in precomputation mode are:
[source,shell]
----
$ cd rcrs-server
$ cd scripts
$ ./start-precompute.sh -m ../maps/test/maps -c ../maps/test/config
----
See https://roborescue.github.io/rcrs-server/rcrs-server/index.html[RoboCup Rescue Simulator Manual] for further information on how to compile and run the RoboCup Rescue Simulator server.
After running the simulation server for the precomputation, move to the ADF Sample Agent directory on another terminal window and run the agents executing the commands:
[source,shell]
----
$ bash launch.sh -t 1,0,1,0,1,0 -h localhost -pre 1 & APID=$! ; sleep 120 ; kill $APID
[START] Connect to server (host:localhost, port:27931)
[INFO] Connected - adf.agent.platoon.PlatoonFire@756ec19c (PRECOMPUTATION)
[INFO] Connected - adf.agent.platoon.PlatoonPolice@366bbbe (PRECOMPUTATION)
[INFO] Connected - adf.agent.platoon.PlatoonAmbulance@2a453513 (PRECOMPUTATION)
********************
[FINISH] Connect PoliceForce (success:1)
[FINISH] Connect AmbulanceTeam (success:1)
[FINISH] Connect FireBrigade (success:1)
[FINISH] Done connecting to server (3 agents)
----
Once the precomputation is completed, press _Control-C_ and type `bash kill.sh` to stop the simulation server of running.
[source,shell]
----
Control-C
$ bash kill.sh
----
[#normal_mode]
=== Normal Mode
In the normal mode, the simulator connects all agents defined in the scenario and allows them to use the precomputation output (see <<precomputation_mode>>).
The sequence of commands to run the simulation server in normal mode are:
[source,shell]
----
$ cd rcrs-server
$ cd scripts
$ bash start-comprun.sh
----
See https://roborescue.github.io/rcrs-server/rcrs-server/index.html[RoboCup Rescue Simulator Manual] for further information on how to compile and run the RoboCup Rescue Simulator server.
After running the simulation server, move to the ADF Sample Agent directory on another terminal window and run the agents using the commands:
[source,shell]
----
$ bash launch.sh -all
[FINISH] Done connecting to server (3 agents)
----
[#develop_agent]
== Develop your own agents using ADF
This section explain how to implement your agents using the ADF Sample Agent as the starting point.
[#workflow]
=== Workflow for coding your agents
The steps necessary to code your own agents are:
* Implement the customized modules
* Change the `config/module.cfg` to point to the customized modules
[#files]
=== Customize modules
ADF is a modular framework whose modules were define in the `adf-core-java` (https://github.com/roborescue/adf-core-java) repository together with a set of default implementations. To implement your own team of agents, you have to implement the modules' Java interfaces correspondent to the behavior you want to customize.
The default implementations of the modules' Java interfaces is available under the package `impl` in the `adf-core-java` repository. There you find default implementations for:
* `adf.impl.centralized`: source code of the _central agents_. This is the type of agents whose only interaction with the world is through radio communication. There are three types of central agents: *Ambulance Centers*, *Fire Stations* and *Police Office*, and they are represented as buildings in the simulation server.
* `adf.impl.extraction`: source code of the possible actions available to agents.
* `adf.impl.module`: source code of the algorithms, e.g., path planning, clustering, target detection, etc. representing the agents' behavior. The modules are split into
+
--
* `adf.impl.module.algorithm`
* `adf.impl.module.comm`
* `adf.impl.module.complex`
--
To customize any of these modules, you can copy modules' file you want to customize to you team agents' repository and make changes to the implementation. Then you need to change the references to your modules by modifying `config/module.cfg` file (see below).
[#module_configuration]
=== Modules' configuration file
The modules configuration file `config/module.cfg` indicates which class will be used as agents' module. <<lst:module_configuration,Listing 1>> shows part of the modules configuration file. The left-hand side of the colon indicates the module name, the right-hand side is the class name. In most cases, modules of which targets' problems are the same should refer to an identical class for all agent types. The example in <<lst:module_configuration,Listing 1>> is in `DefaultTacticsAmbulanceTeam.Search` and `DefaultTacticsFireBrigade.Search` indicates that both modules refer to `sample_team.module.complex.SampleSearch`. An usage example is shown in <<edit_module_configuration>>.
[#lst:module_configuration]
[source,text]
.*Listing 1*. Part of a module configuration file
----
## DefaultTacticsAmbulanceTeam
DefaultTacticsAmbulanceTeam.HumanDetector : sample_team.module.complex.SampleHumanDetector
DefaultTacticsAmbulanceTeam.Search : sample_team.module.complex.SampleSearch
DefaultTacticsAmbulanceTeam.ExtActionTransport : adf.impl.extaction.DefaultExtActionTransport
DefaultTacticsAmbulanceTeam.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
DefaultTacticsAmbulanceTeam.CommandExecutorAmbulance : adf.impl.centralized.DefaultCommandExecutorAmbulance
DefaultTacticsAmbulanceTeam.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScout
## DefaultTacticsFireBrigade
DefaultTacticsFireBrigade.HumanDetector : sample_team.module.complex.SampleHumanDetector
DefaultTacticsFireBrigade.Search : sample_team.module.complex.SampleSearch
DefaultTacticsFireBrigade.ExtActionFireRescue : adf.impl.extaction.DefaultExtActionFireRescue
DefaultTacticsFireBrigade.ExtActionMove : adf.impl.extaction.DefaultExtActionMove
DefaultTacticsFireBrigade.CommandExecutorFire : adf.impl.centralized.DefaultCommandExecutorFire
DefaultTacticsFireBrigade.CommandExecutorScout : adf.impl.centralized.DefaultCommandExecutorScout
----
[#astar_example]
=== Example of implementing A* algorithm for Path Planning algorithm
In this example, you will learn how to implement the A* Path Planning algorithm in a module and how to setup the ADF Sample Agent to use it instead of the Dijkstra Path Planning. Here we assume that you will apply the changes to the `adf-sample-agent-java` repository.
[#copy_sample]
==== Copy the Dijkstra Path Planning file
First, you should copy the Dijkstra path planning (`src/main/java/adf/impl/module/algorithm/DijkstraPathPlanning.java`) from the `adf-core-java` repository to the `adf-sample-agent-java` repository (`src/main/java/sample_team/module/algorithm`).
[source,shell]
----
$ cd adf-sample-agent-java
$ mkdir -p src/main/java/sample_team/module/algorithm
$ cp ../adf-core-java/src/main/java/adf/impl/module/algorithm/DijkstraPathPlanning.java src/main/java/sample_team/module/algorithm/AStarPathPlanning.java
----
[#edit_sample]
==== Edit the Dijkstra code
<<lst:sample_path_planning,Listing 2>> is the code of `DijkstraPathPlanning.java`, which implements the Dijkstra's algorithm. You should edit line 1 and 23th as well as replace the code in the method `calc()` starting on line 96. Remove the method `isGoal()` that is only used by the Dijkstra `calc()`. <<lst:astar_planning,Listing 3>> shows the results of editing these lines.
You must implement the method `calc()` to get its calculation result
by the method `getResult()`. The type of `getResult()` returning is `List<EntityID>`.
<<lst:astar_planning_calc,Listing 4>> indicates the contents of the method `calc()`. In addition, you should write the new private class `Node` which is used by the method `calc()`. The code is shown in <<lst:astar_node_class,Listing 5>>.
[#lst:sample_path_planning]
[source,java,linenums]
.*Listing 2*. `DijkstraPathPlanning.java` file
----
package adf.impl.module.algorithm; // Edit this line
import adf.core.agent.communication.MessageManager;
import adf.core.agent.develop.DevelopData;
import adf.core.agent.info.AgentInfo;
import adf.core.agent.info.ScenarioInfo;
import adf.core.agent.info.WorldInfo;
import adf.core.agent.module.ModuleManager;
import adf.core.agent.precompute.PrecomputeData;
import adf.core.component.module.algorithm.PathPlanning;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import rescuecore2.misc.collections.LazyMap;
import rescuecore2.standard.entities.Area;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
public class DijkstraPathPlanning extends PathPlanning { // Edit this line
private Map<EntityID, Set<EntityID>> graph;
private EntityID from;
private Collection<EntityID> targets;
private List<EntityID> result;
public DijkstraPathPlanning(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) {
super(ai, wi, si, moduleManager, developData);
this.init();
}
private void init() {
Map<EntityID,
Set<EntityID>> neighbours = new LazyMap<EntityID, Set<EntityID>>() {
@Override
public Set<EntityID> createValue() {
return new HashSet<>();
}
};
for (Entity next : this.worldInfo) {
if (next instanceof Area) {
Collection<EntityID> areaNeighbours = ((Area) next).getNeighbours();
neighbours.get(next.getID()).addAll(areaNeighbours);
}
}
this.graph = neighbours;
}
@Override
public List<EntityID> getResult() {
return this.result;
}
@Override
public PathPlanning setFrom(EntityID id) {
this.from = id;
return this;
}
@Override
public PathPlanning setDestination(Collection<EntityID> targets) {
this.targets = targets;
return this;
}
@Override
public PathPlanning updateInfo(MessageManager messageManager) {
super.updateInfo(messageManager);
return this;
}
@Override
public PathPlanning precompute(PrecomputeData precomputeData) {
super.precompute(precomputeData);
return this;
}
@Override
public PathPlanning resume(PrecomputeData precomputeData) {
super.resume(precomputeData);
return this;
}
@Override
public PathPlanning preparate() {
super.preparate();
return this;
}
@Override
public PathPlanning calc() { // Replace the code in this method by the A* Path Planning algorithm
List<EntityID> open = new LinkedList<>();
Map<EntityID, EntityID> ancestors = new HashMap<>();
open.add(this.from);
EntityID next;
boolean found = false;
ancestors.put(this.from, this.from);
do {
next = open.remove(0);
if (isGoal(next, targets)) {
found = true;
break;
}
Collection<EntityID> neighbours = graph.get(next);
if (neighbours.isEmpty()) {
continue;
}
for (EntityID neighbour : neighbours) {
if (isGoal(neighbour, targets)) {
ancestors.put(neighbour, next);
next = neighbour;
found = true;
break;
} else {
if (!ancestors.containsKey(neighbour)) {
open.add(neighbour);
ancestors.put(neighbour, next);
}
}
}
} while (!found && !open.isEmpty());
if (!found) {
// No path
this.result = null;
}
// Walk back from goal to this.from
EntityID current = next;
LinkedList<EntityID> path = new LinkedList<>();
do {
path.add(0, current);
current = ancestors.get(current);
if (current == null) {
throw new RuntimeException(
"Found a node with no ancestor! Something is broken.");
}
} while (current != this.from);
this.result = path;
return this;
}
private boolean isGoal(EntityID e, Collection<EntityID> test) {
return test.contains(e);
}
}
----
[#lst:astar_planning]
[source,java,linenums]
.*Listing 3*. `AStartPlanning.java` file
----
package sample_team.module.algorithm; // Position of the file
import adf.core.agent.develop.DevelopData;
import adf.core.agent.info.AgentInfo;
import adf.core.agent.info.ScenarioInfo;
import adf.core.agent.info.WorldInfo;
import adf.core.agent.module.ModuleManager;
import adf.core.agent.precompute.PrecomputeData;
import adf.core.component.module.algorithm.PathPlanning;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import rescuecore2.misc.collections.LazyMap;
import rescuecore2.standard.entities.Area;
import rescuecore2.worldmodel.Entity;
import rescuecore2.worldmodel.EntityID;
public class AStarPathPlanning extends PathPlanning {
private Map<EntityID, Set<EntityID>> graph;
private EntityID from;
private Collection<EntityID> targets;
private List<EntityID> result;
public AStarPathPlanning(AgentInfo ai, WorldInfo wi, ScenarioInfo si, ModuleManager moduleManager, DevelopData developData) {
super(ai, wi, si, moduleManager, developData);
this.init();
}
...
----
[#lst:astar_planning_calc]
[source,java,linenums]
.*Listing 4*. `calc()` method
----
@Override
public PathPlanning calc() {
List<EntityID> open = new LinkedList<>();
List<EntityID> close = new LinkedList<>();
Map<EntityID, Node> nodeMap = new HashMap<>();
open.add(this.from);
nodeMap.put(this.from, new Node(null, this.from));
close.clear();
while (true) {
if (open.size() < 0) {
this.result = null;
return this;
}
Node n = null;
for (EntityID id : open) {
Node node = nodeMap.get(id);
if (n == null) {
n = node;
} else if (node.estimate() < n.estimate()) {
n = node;
}
}
if (targets.contains(n.getID())) {
List<EntityID> path = new LinkedList<>();
while (n != null) {
path.add(0, n.getID());
n = nodeMap.get(n.getParent());
}
this.result = path;
return this;
}
open.remove(n.getID());
close.add(n.getID());
Collection<EntityID> neighbours = this.graph.get(n.getID());
for (EntityID neighbour : neighbours) {
Node m = new Node(n, neighbour);
if (!open.contains(neighbour) && !close.contains(neighbour)) {
open.add(m.getID());
nodeMap.put(neighbour, m);
} else if (open.contains(neighbour)
&& m.estimate() < nodeMap.get(neighbour).estimate()) {
nodeMap.put(neighbour, m);
} else if (!close.contains(neighbour)
&& m.estimate() < nodeMap.get(neighbour).estimate()) {
nodeMap.put(neighbour, m);
}
}
}
}
----
[#lst:astar_node_class]
[source,java,linenums]
.*Listing 5*. `Node` class
----
private class Node {
EntityID id;
EntityID parent;
double cost;
double heuristic;
public Node(Node from, EntityID id) {
this.id = id;
if (from == null) {
this.cost = 0;
} else {
this.parent = from.getID();
this.cost = from.getCost() + worldInfo.getDistance(from.getID(), id);
}
this.heuristic = worldInfo.getDistance(id,
targets.toArray(new EntityID[targets.size()])[0]);
}
public EntityID getID() {
return id;
}
public double getCost() {
return cost;
}
public double estimate() {
return cost + heuristic;
}
public EntityID getParent() {
return this.parent;
}
}
}
----
[#edit_module_configuration]
==== Edit the Modules' configuration file
After created the module code, you must edit the module configuration file `config/module.cfg` and replace the modules you would like to use your implementation. <<lst:default_module_cfg,Listing 6>> and <<lst:edited_module_cfg,Listing 7>> show the part of the default `module.cfg` and the part of the edited `config/module.cfg` where the lines related to a path planning are changed. In this case, all `adf.impl.module.algorithm.DijkstraPathPlanning` are replaced with `sample_team.module.algorithm.AStarPathPlanning`.
[#lst:default_module_cfg]
[source,text]
.*Listing 6*. Default `module.cfg`
----
## SampleSearch
SampleSearch.PathPlanning.Ambulance : adf.impl.module.algorithm.DijkstraPathPlanning
SampleSearch.Clustering.Ambulance : adf.impl.module.algorithm.KMeansClustering
SampleSearch.PathPlanning.Fire : adf.impl.module.algorithm.DijkstraPathPlanning
SampleSearch.Clustering.Fire : adf.impl.module.algorithm.KMeansClustering
SampleSearch.PathPlanning.Police : adf.impl.module.algorithm.DijkstraPathPlanning
SampleSearch.Clustering.Police : adf.impl.module.algorithm.KMeansClustering
----
[#lst:edited_module_cfg]
[source,text]
.*Listing 7*. Edited `module.cfg`
----
## SampleSearch
SampleSearch.PathPlanning.Ambulance : sample_team.module.algorithm.AStarPathPlanning
SampleSearch.Clustering.Ambulance : adf.impl.module.algorithm.KMeansClustering
SampleSearch.PathPlanning.Fire : adf.impl.module.algorithm.AStarPathPlanning
SampleSearch.Clustering.Fire : adf.impl.module.algorithm.KMeansClustering
SampleSearch.PathPlanning.Police : adf.impl.module.algorithm.AStarPathPlanning
SampleSearch.Clustering.Police : adf.impl.module.algorithm.KMeansClustering
----
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment