Skip to content

Commit 7a3e019

Browse files
authored
Merge pull request #76 from adf-python/feature/cli
コマンドでテンプレの開発環境を作成する
2 parents 1581d1b + b80f8ce commit 7a3e019

File tree

15 files changed

+648
-10
lines changed

15 files changed

+648
-10
lines changed

adf_core_python/cli/__init__.py

Whitespace-only changes.

adf_core_python/cli/cli.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
import os
2+
3+
import click
4+
5+
NAME_PLACEHOLDER = "team_name"
6+
7+
8+
@click.command()
9+
@click.option(
10+
"--name", prompt="Your agent team name", help="The name of your agent team"
11+
)
12+
def cli(name: str) -> None:
13+
# load template dir and create a new agent team
14+
click.echo(f"Creating a new agent team with name: {name}")
15+
# 自身がいるディレクトリを取得
16+
template_dir = os.path.join(os.path.abspath(os.path.dirname(__file__)), "template")
17+
# コマンドラインのカレントディレクトリを取得
18+
current_dir = os.getcwd()
19+
20+
_copy_template(
21+
template_dir,
22+
current_dir,
23+
name,
24+
)
25+
26+
27+
def _copy_template(
28+
src: str,
29+
dest: str,
30+
name: str,
31+
) -> None:
32+
if os.path.isdir(src):
33+
if not os.path.exists(dest):
34+
os.makedirs(dest)
35+
for item in os.listdir(src):
36+
s = os.path.join(src, item)
37+
d = os.path.join(
38+
dest,
39+
item.replace(NAME_PLACEHOLDER, name),
40+
)
41+
_copy_template(s, d, name)
42+
else:
43+
with open(src, "r") as f:
44+
content = f.read()
45+
with open(dest, "w") as f:
46+
f.write(content.replace(NAME_PLACEHOLDER, name))
47+
new_dest = dest.replace(NAME_PLACEHOLDER, name)
48+
if new_dest != dest:
49+
os.rename(dest, new_dest)
50+
51+
52+
if __name__ == "__main__":
53+
cli()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"test": "test"
3+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
kernel:
2+
host: localhost
3+
port: 27931
4+
5+
team:
6+
name: team_name
7+
8+
adf:
9+
launcher:
10+
precompute: 0
11+
debug:
12+
flag: 0
13+
agent:
14+
moduleconfig:
15+
filename: config/module.yaml
16+
17+
develop:
18+
flag: 1
19+
filename: config/development.json
20+
21+
team:
22+
platoon:
23+
ambulance:
24+
count: 100
25+
fire:
26+
count: 100
27+
police:
28+
count: 100
29+
office:
30+
ambulance:
31+
count: -1
32+
fire:
33+
count: -1
34+
police:
35+
count: -1
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
## DefaultTacticsAmbulanceTeam
2+
DefaultTacticsAmbulanceTeam:
3+
HumanDetector: src.team_name.module.complex.sample_human_detector.SampleHumanDetector
4+
Search: src.team_name.module.complex.sample_search.SampleSearch
5+
ExtendActionTransport: adf_core_python.implement.action.default_extend_action_transport.DefaultExtendActionTransport
6+
ExtendActionMove: adf_core_python.implement.action.default_extend_action_move.DefaultExtendActionMove
7+
CommandExecutorAmbulance: adf_core_python.implement.centralized.DefaultCommandExecutorAmbulance
8+
CommandExecutorScout: adf_core_python.implement.centralized.DefaultCommandExecutorScout
9+
10+
# ## DefaultTacticsFireBrigade
11+
DefaultTacticsFireBrigade:
12+
HumanDetector: src.team_name.module.complex.sample_human_detector.SampleHumanDetector
13+
Search: src.team_name.module.complex.sample_search.SampleSearch
14+
ExtendActionRescue: adf_core_python.implement.action.default_extend_action_rescue.DefaultExtendActionRescue
15+
ExtendActionMove: adf_core_python.implement.action.default_extend_action_move.DefaultExtendActionMove
16+
CommandExecutorFire: adf_core_python.implement.centralized.DefaultCommandExecutorFire
17+
CommandExecutorScout: adf_core_python.implement.centralized.DefaultCommandExecutorScout
18+
19+
# ## DefaultTacticsPoliceForce
20+
DefaultTacticsPoliceForce:
21+
RoadDetector: src.team_name.module.complex.sample_road_detector.SampleRoadDetector
22+
Search: src.team_name.module.complex.sample_search.SampleSearch
23+
ExtendActionClear: adf_core_python.implement.action.default_extend_action_clear.DefaultExtendActionClear
24+
ExtendActionMove: adf_core_python.implement.action.default_extend_action_move.DefaultExtendActionMove
25+
CommandExecutorPolice: adf_core_python.implement.centralized.DefaultCommandExecutorPolice
26+
CommandExecutorScout: adf_core_python.implement.centralized.DefaultCommandExecutorScoutPolice
27+
28+
# ## DefaultTacticsAmbulanceCentre
29+
# DefaultTacticsAmbulanceCentre:
30+
# TargetAllocator: sample_team.module.complex.SampleAmbulanceTargetAllocator
31+
# CommandPicker: adf_core_python.implement.centralized.DefaultCommandPickerAmbulance
32+
33+
# ## DefaultTacticsFireStation
34+
# DefaultTacticsFireStation:
35+
# TargetAllocator: sample_team.module.complex.SampleFireTargetAllocator
36+
# CommandPicker: adf_core_python.implement.centralized.DefaultCommandPickerFire
37+
38+
# ## DefaultTacticsPoliceOffice
39+
# DefaultTacticsPoliceOffice:
40+
# TargetAllocator: sample_team.module.complex.SamplePoliceTargetAllocator
41+
# CommandPicker: adf_core_python.implement.centralized.DefaultCommandPickerPolice
42+
43+
## SampleSearch
44+
SampleSearch:
45+
PathPlanning: adf_core_python.implement.module.algorithm.a_star_path_planning.AStarPathPlanning
46+
Clustering: adf_core_python.implement.module.algorithm.k_means_clustering.KMeansClustering
47+
48+
# ## SampleBuildDetector
49+
# SampleBuildingDetector:
50+
# Clustering: adf_core_python.implement.module.algorithm.KMeansClustering
51+
52+
# ## SampleRoadDetector
53+
# SampleRoadDetector:
54+
# Clustering: adf_core_python.implement.module.algorithm.KMeansClustering
55+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
56+
57+
# ## SampleHumanDetector
58+
# SampleHumanDetector:
59+
# Clustering: adf_core_python.implement.module.algorithm.KMeansClustering
60+
61+
# ## DefaultExtendActionClear
62+
# DefaultExtendActionClear:
63+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
64+
65+
# ## DefaultExtendActionFireFighting
66+
# DefaultExtendActionFireFighting:
67+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
68+
69+
# ## DefaultExtendActionRescue
70+
# DefaultExtendActionRescue:
71+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
72+
73+
# ## DefaultExtendActionMove
74+
# DefaultExtendActionMove:
75+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
76+
77+
# ## DefaultExtendActionTransport
78+
# DefaultExtendActionTransport:
79+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
80+
# ## DefaultCommandExecutorAmbulance
81+
# DefaultCommandExecutorAmbulance:
82+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
83+
# ExtendActionTransport: adf_core_python.implement.action.DefaultExtendActionTransport
84+
# ExtendActionMove: adf_core_python.implement.action.DefaultExtendActionMove
85+
86+
# ## DefaultCommandExecutorFire
87+
# DefaultCommandExecutorFire:
88+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
89+
# EtxActionFireRescue: adf_core_python.implement.action.DefaultExtendActionRescue
90+
# EtxActionFireFighting: adf_core_python.implement.action.DefaultExtendActionFireFighting
91+
# ExtendActionMove: adf_core_python.implement.action.DefaultExtendActionMove
92+
93+
# ## DefaultCommandExecutorPolice
94+
# DefaultCommandExecutorPolice:
95+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
96+
# ExtendActionClear: adf_core_python.implement.action.DefaultExtendActionClear
97+
# ExtendActionMove: adf_core_python.implement.action.DefaultExtendActionMove
98+
99+
# ## DefaultCommandExecutorScout
100+
# DefaultCommandExecutorScout:
101+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
102+
103+
# ## DefaultCommandExecutorScoutPolice
104+
# DefaultCommandExecutorScoutPolice:
105+
# PathPlanning: adf_core_python.implement.module.algorithm.DijkstraPathPlanning
106+
# ExtendActionClear: adf_core_python.implement.action.DefaultExtendActionClear
107+
108+
# ## MessageManager
109+
MessageManager:
110+
PlatoonChannelSubscriber: adf_core_python.implement.module.communication.default_channel_subscriber.DefaultChannelSubscriber
111+
CenterChannelSubscriber: adf_core_python.implement.module.communication.default_channel_subscriber.DefaultChannelSubscriber
112+
PlatoonMessageCoordinator: adf_core_python.implement.module.communication.default_message_coordinator.DefaultMessageCoordinator
113+
CenterMessageCoordinator: adf_core_python.implement.module.communication.default_message_coordinator.DefaultMessageCoordinator
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from adf_core_python.launcher import Launcher
2+
3+
if __name__ == "__main__":
4+
launcher = Launcher("./config/launcher.yaml")
5+
launcher.launch()

adf_core_python/cli/template/src/team_name/__init__.py

Whitespace-only changes.

adf_core_python/cli/template/src/team_name/module/__init__.py

Whitespace-only changes.

adf_core_python/cli/template/src/team_name/module/complex/__init__.py

Whitespace-only changes.
Lines changed: 149 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,149 @@
1+
from typing import Optional, cast
2+
3+
from rcrs_core.connection.URN import Entity as EntityURN
4+
from rcrs_core.entities.civilian import Civilian
5+
from rcrs_core.entities.entity import Entity
6+
from rcrs_core.entities.human import Human
7+
from rcrs_core.worldmodel.entityID import EntityID
8+
9+
from adf_core_python.core.agent.develop.develop_data import DevelopData
10+
from adf_core_python.core.agent.info.agent_info import AgentInfo
11+
from adf_core_python.core.agent.info.scenario_info import ScenarioInfo
12+
from adf_core_python.core.agent.info.world_info import WorldInfo
13+
from adf_core_python.core.agent.module.module_manager import ModuleManager
14+
from adf_core_python.core.component.module.algorithm.clustering import Clustering
15+
from adf_core_python.core.component.module.complex.human_detector import HumanDetector
16+
from adf_core_python.core.logger.logger import get_agent_logger
17+
18+
19+
class SampleHumanDetector(HumanDetector):
20+
def __init__(
21+
self,
22+
agent_info: AgentInfo,
23+
world_info: WorldInfo,
24+
scenario_info: ScenarioInfo,
25+
module_manager: ModuleManager,
26+
develop_data: DevelopData,
27+
) -> None:
28+
super().__init__(
29+
agent_info, world_info, scenario_info, module_manager, develop_data
30+
)
31+
self._clustering: Clustering = cast(
32+
Clustering,
33+
module_manager.get_module(
34+
"DefaultHumanDetector.Clustering",
35+
"adf_core_python.implement.module.algorithm.k_means_clustering.KMeansClustering",
36+
),
37+
)
38+
self.register_sub_module(self._clustering)
39+
40+
self._result: Optional[EntityID] = None
41+
self._logger = get_agent_logger(
42+
f"{self.__class__.__module__}.{self.__class__.__qualname__}",
43+
self._agent_info,
44+
)
45+
46+
def calculate(self) -> HumanDetector:
47+
transport_human: Optional[Human] = self._agent_info.some_one_on_board()
48+
if transport_human is not None:
49+
self._result = transport_human.get_id()
50+
return self
51+
52+
if self._result is not None:
53+
if not self._is_valid_human(self._result):
54+
self._result = None
55+
56+
if self._result is None:
57+
self._result = self._select_target()
58+
59+
return self
60+
61+
def _select_target(self) -> Optional[EntityID]:
62+
if self._result is not None and self._is_valid_human(self._result):
63+
return self._result
64+
65+
cluster_index: int = self._clustering.get_cluster_index(
66+
self._agent_info.get_entity_id()
67+
)
68+
cluster_entities: list[Entity] = self._clustering.get_cluster_entities(
69+
cluster_index
70+
)
71+
72+
cluster_valid_human_entities: list[Entity] = [
73+
entity
74+
for entity in cluster_entities
75+
if self._is_valid_human(entity.get_id()) and isinstance(entity, Civilian)
76+
]
77+
if len(cluster_valid_human_entities) != 0:
78+
nearest_human_entity = cluster_valid_human_entities[0]
79+
nearest_distance = self._world_info.get_distance(
80+
self._agent_info.get_entity_id(),
81+
nearest_human_entity.get_id(),
82+
)
83+
for entity in cluster_valid_human_entities:
84+
distance = self._world_info.get_distance(
85+
self._agent_info.get_entity_id(),
86+
entity.get_id(),
87+
)
88+
if distance < nearest_distance:
89+
nearest_distance = distance
90+
nearest_human_entity = entity
91+
return nearest_human_entity.get_id()
92+
93+
world_valid_human_entities: list[Entity] = [
94+
entity
95+
for entity in self._world_info.get_entities_of_types([Civilian])
96+
if self._is_valid_human(entity.get_id())
97+
]
98+
if len(world_valid_human_entities) != 0:
99+
nearest_human_entity = world_valid_human_entities[0]
100+
nearest_distance = self._world_info.get_distance(
101+
self._agent_info.get_entity_id(),
102+
nearest_human_entity.get_id(),
103+
)
104+
for entity in world_valid_human_entities:
105+
distance = self._world_info.get_distance(
106+
self._agent_info.get_entity_id(),
107+
entity.get_id(),
108+
)
109+
if distance < nearest_distance:
110+
nearest_distance = distance
111+
nearest_human_entity = entity
112+
return nearest_human_entity.get_id()
113+
114+
return None
115+
116+
def _is_valid_human(self, target_entity_id: EntityID) -> bool:
117+
target: Optional[Entity] = self._world_info.get_entity(target_entity_id)
118+
if target is None:
119+
return False
120+
if not isinstance(target, Human):
121+
return False
122+
hp: Optional[int] = target.get_hp()
123+
if hp is None or hp <= 0:
124+
return False
125+
buriedness: Optional[int] = target.get_buriedness()
126+
if buriedness is None:
127+
return False
128+
myself = self._agent_info.get_myself()
129+
if myself.get_urn() == EntityURN.FIRE_BRIGADE and buriedness == 0:
130+
return False
131+
if myself.get_urn() == EntityURN.AMBULANCE_TEAM and buriedness > 0:
132+
return False
133+
damage: Optional[int] = target.get_damage()
134+
if damage is None or damage == 0:
135+
return False
136+
position_entity_id: Optional[EntityID] = target.get_position()
137+
if position_entity_id is None:
138+
return False
139+
position: Optional[Entity] = self._world_info.get_entity(position_entity_id)
140+
if position is None:
141+
return False
142+
urn: EntityURN = position.get_urn()
143+
if urn == EntityURN.REFUGE or urn == EntityURN.AMBULANCE_TEAM:
144+
return False
145+
146+
return True
147+
148+
def get_target_entity_id(self) -> Optional[EntityID]:
149+
return self._result

0 commit comments

Comments
 (0)