-
Notifications
You must be signed in to change notification settings - Fork 9
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added discrete movement and utility to build mission from an XML file #180
Open
EHAT32
wants to merge
29
commits into
trueagi-io:main
Choose a base branch
from
EHAT32:main
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
29 commits
Select commit
Hold shift + click to select a range
30fa214
added ModSettings class
EHAT32 7b17011
corrected xml method for ModSettings
EHAT32 0dc0073
added ModSettings into MissionXML
EHAT32 86fec19
excluded modSettings from MissionXML.xml()
EHAT32 f8b6952
added RewardForTouchingBlockType into AgentHandlers
EHAT32 4d5192d
added RewardForSendingCommand and included in AgentHandlers
EHAT32 5b8fc8d
renamed RewardBlock into Block, changed .xml() method
EHAT32 e5078e5
added AgentQuitFromTouchingBlockType and included into AgentHandlers
EHAT32 bcdb3ac
fixed typo
EHAT32 44c55e0
fixed typo
EHAT32 7adfa09
fixed AgentQuitFromTouchingBlockType class
EHAT32 efd8b4d
fixed .xml() in RewardForTouchingBlockType
EHAT32 ef3646d
added a convertion from an XML into a dictionary
EHAT32 fb11703
remove_namespace tweak
EHAT32 0616388
fixed default field creation for Pytthon 3.11+
EHAT32 6552322
creation of mission from an XML file
EHAT32 97adefe
fixed ModSettings
EHAT32 f370ec0
example for discrete movement on a platform
EHAT32 81c798e
added command for discrete movement
EHAT32 ea28dbf
test for discrete movement
EHAT32 96d768f
removed
EHAT32 b26d27d
removed using of dicts
EHAT32 106a360
Merge remote-tracking branch 'upstream/main'
EHAT32 07d9267
moved test_discrete_motion into test_motion_vereya
EHAT32 2459d66
reverted merging two tests
EHAT32 d9ae3a6
added test_discrete_motion into run_tests
EHAT32 a21ba74
removed excessive code
EHAT32 3f490e5
removed deprecated import
EHAT32 d208185
Merge branch 'trueagi-io:main' into main
EHAT32 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,223 @@ | ||
import xml.etree.ElementTree as ET | ||
import tagilmo.utils.mission_builder as mb | ||
from .xml_util import remove_namespaces | ||
|
||
def _createAbout(aboutRoot = None): | ||
about = mb.About() | ||
if aboutRoot is None or len(list(aboutRoot)) == 0: | ||
return about | ||
summary = aboutRoot.find("Summary") | ||
if summary is not None: | ||
about.summary = summary.text | ||
return about | ||
|
||
|
||
def _createModSettings(msRoot = None): | ||
ms = mb.ModSettings() | ||
if msRoot is None or len(list(msRoot)) == 0: | ||
return ms | ||
|
||
msTick = msRoot.find("MsPerTick") | ||
if msTick is not None: | ||
ms.ms_per_tick = msTick.text | ||
return ms | ||
|
||
|
||
def _createTime(timeRoot = None): | ||
if timeRoot is None or len(list(timeRoot)) == 0: | ||
return None, None | ||
|
||
time_start = None | ||
if timeRoot.find("StartTime") is not None: | ||
time_start = timeRoot.find("StartTime").text | ||
|
||
time_pass = None | ||
if timeRoot.find("AllowPassageOfTime") is not None: | ||
time_pass = timeRoot.find("AllowPassageOfTime").text | ||
|
||
return time_start, time_pass | ||
|
||
|
||
def _createServerInitialConditions(initConditionsRoot = None): | ||
if initConditionsRoot is None or len(list(initConditionsRoot)) == 0: | ||
return mb.ServerInitialConditions() | ||
|
||
time_start, time_pass = _createTime(initConditionsRoot.find("Time")) | ||
|
||
weather = None | ||
if initConditionsRoot.find("Weather") is not None: | ||
weather = initConditionsRoot.find("Weather").text | ||
|
||
allow_spawning = "true" | ||
if initConditionsRoot.find("AllowSpawning") is not None: | ||
allow_spawning = initConditionsRoot.find("AllowSpawning").text | ||
|
||
initial_conditions = mb.ServerInitialConditions(time_start_string=time_start, | ||
time_pass_string=time_pass, | ||
weather_string=weather, | ||
spawning_string=allow_spawning) | ||
return initial_conditions | ||
|
||
def _createDrawingDecorator(drawingDecoratorRoot = None): | ||
if drawingDecoratorRoot is None or len(list(drawingDecoratorRoot)) == 0: | ||
return mb.DrawingDecorator() | ||
decorators = [] | ||
drawing_elements = list(drawingDecoratorRoot) | ||
for el in drawing_elements: | ||
match el.tag: | ||
case "DrawCuboid": | ||
decorators.append(mb.DrawCuboid(el.attrib["x1"], el.attrib["y1"], el.attrib["z1"], | ||
el.attrib["x2"], el.attrib["y2"], el.attrib["z2"], | ||
el.attrib["type"])) | ||
case "DrawBlock": | ||
decorators.append(mb.DrawBlock(el.attrib["x"], el.attrib["y"], el.attrib["z"], | ||
el.attrib["type"])) | ||
case "DrawLine": | ||
decorators.append(mb.DrawLine(el.attrib["x1"], el.attrib["y1"], el.attrib["z1"], | ||
el.attrib["x2"], el.attrib["y2"], el.attrib["z2"], | ||
el.attrib["type"])) | ||
case "DrawItem": | ||
decorators.append(mb.DrawItem(el.attrib["x"], el.attrib["y"], el.attrib["z"], | ||
el.attrib["type"])) | ||
case _: | ||
continue | ||
return mb.DrawingDecorator(decorators) | ||
|
||
|
||
def _createServerHandlers(handlersRoot = None): | ||
serverHandlers = mb.ServerHandlers() | ||
if handlersRoot is None or len(list(handlersRoot)) == 0: | ||
return serverHandlers | ||
|
||
world_generator = mb.defaultworld() | ||
flat_gen = handlersRoot.find("FlatWorldGenerator") | ||
if flat_gen is not None: | ||
world_generator = mb.flatworld(flat_gen.attrib["generatorString"]) | ||
serverHandlers.worldgenerator = world_generator | ||
|
||
serverHandlers.drawingdecorator = _createDrawingDecorator(handlersRoot.find("DrawingDecorator")) | ||
|
||
time_limit = None | ||
if handlersRoot.find("ServerQuitFromTimep") is not None: | ||
time_limit = handlersRoot.find("ServerQuitFromTimep").attrib["timeLimitMs"] | ||
serverHandlers.timeLimitsMs = time_limit | ||
|
||
return serverHandlers | ||
|
||
|
||
def _createServerSection(serverSectionRoot = None): | ||
init_conditions = _createServerInitialConditions(serverSectionRoot.find("ServerInitialConditions")) | ||
handlers = _createServerHandlers(serverSectionRoot.find('ServerHandlers')) | ||
return mb.ServerSection(handlers=handlers, initial_conditions=init_conditions) | ||
|
||
|
||
def _createCommands(commandsRoot= None): | ||
if commandsRoot is None: | ||
return mb.Commands() | ||
# TODO: parsing non-empty root | ||
return mb.Commands() | ||
|
||
|
||
def _createRewardForTouchingBlockType(rewardForTouchingBlockTypeRoot = None): | ||
if rewardForTouchingBlockTypeRoot is None or len(list(rewardForTouchingBlockTypeRoot)) == 0: | ||
return mb.RewardForTouchingBlockType() | ||
rewards = [] | ||
reward_blocks = rewardForTouchingBlockTypeRoot.findall("Block") | ||
for block in reward_blocks: | ||
rewards.append(mb.Block(reward=block.attrib['reward'], | ||
blockType=block.attrib['type'], | ||
behaviour=block.attrib['behaviour'])) | ||
return mb.RewardForTouchingBlockType(rewards) | ||
|
||
|
||
def _createAgentQuitFromTouchingBlockType(agentQuitFromTouchingBlockType = None): | ||
if agentQuitFromTouchingBlockType is None or len(list(agentQuitFromTouchingBlockType)) == 0: | ||
return mb.AgentQuitFromTouchingBlockType() | ||
quit_blocks = [] | ||
blocks = agentQuitFromTouchingBlockType.findall("Block") | ||
for block in blocks: | ||
quit_blocks.append(mb.Block(blockType=block.attrib['type'])) | ||
return mb.AgentQuitFromTouchingBlockType(quit_blocks) | ||
|
||
|
||
def _createAgentHandlers(agentHandlersRoot = None): | ||
if agentHandlersRoot is None: | ||
return mb.AgentHandlers() | ||
obsFullStats = None | ||
if agentHandlersRoot.find("ObservationFromFullStats") is not None: | ||
obsFullStats = True | ||
obs = mb.Observations(bFullStats=obsFullStats) | ||
video_producer = mb.VideoProducer() | ||
if agentHandlersRoot.find("VideoProducer") is not None: | ||
producer = agentHandlersRoot.find("VideoProducer") | ||
video_producer = mb.VideoProducer(height=int(producer.find("Height").text), | ||
width=int(producer.find("Width").text), | ||
want_depth=producer.attrib["want_depth"] == "true") | ||
commands = _createCommands() | ||
|
||
rewards_for_touching = None | ||
if agentHandlersRoot.find("RewardForTouchingBlockType") is not None: | ||
rewards_for_touching = _createRewardForTouchingBlockType(agentHandlersRoot.find("RewardForTouchingBlockType")) | ||
|
||
reward_for_sending_command = None | ||
if agentHandlersRoot.find("RewardForSendingCommand") is not None: | ||
reward = agentHandlersRoot.find("RewardForSendingCommand").attrib['reward'] | ||
reward_for_sending_command = mb.RewardForSendingCommand(reward=reward) | ||
|
||
agent_quit = None | ||
if agentHandlersRoot.find('AgentQuitFromTouchingBlockType') is not None: | ||
agent_quit = _createAgentQuitFromTouchingBlockType(agentHandlersRoot.find('AgentQuitFromTouchingBlockType')) | ||
|
||
return mb.AgentHandlers(commands=commands, observations=obs, video_producer=video_producer, | ||
rewardForTouchingBlockType=rewards_for_touching, | ||
rewardForSendingCommand=reward_for_sending_command, agentQuitFromTouchingBlockType=agent_quit) | ||
|
||
|
||
def _createAgentSection(agentSectionRoot = None): | ||
|
||
if agentSectionRoot is None or len(agentSectionRoot) == 0: | ||
return [mb.AgentSection()] | ||
|
||
sections = [] | ||
for agent in agentSectionRoot: | ||
agent_section = mb.AgentSection() | ||
if agent.find("mode") is not None: | ||
agent_section.mode = agent.attrib["mode"] | ||
|
||
if agent.find("Name") is not None: | ||
agent_section.name = agent.find("Name").text | ||
|
||
if agent.find("AgentStart") is not None: | ||
xyzp = None | ||
if agent.find("AgentStart").find("Placement") is not None: | ||
placement = agent.find("AgentStart").find("Placement") | ||
xyzp = [float(v) for _,v in placement.items()][:4] #yaw is not in constructor | ||
agent_start = mb.AgentStart(place_xyzp=xyzp) | ||
agent_section.agentstart = agent_start | ||
|
||
agent_section.agenthandlers = _createAgentHandlers(agent.find("AgentHandlers")) | ||
|
||
sections.append(agent_section) | ||
|
||
return sections | ||
|
||
|
||
def _createMissionXML(missionRoot): | ||
mission = mb.MissionXML() | ||
if missionRoot is None or len(list(missionRoot)) == 0: | ||
return mission | ||
|
||
mission.about = _createAbout(missionRoot.find("About")) | ||
mission.modSettings = _createModSettings(missionRoot.find("ModSettings")) | ||
mission.serverSection = _createServerSection(missionRoot.find("ServerSection")) | ||
mission.agentSections = _createAgentSection(missionRoot.findall("AgentSection")) | ||
|
||
return mission | ||
|
||
|
||
def load_mission(path): | ||
tree = ET.parse(path) | ||
root = tree.getroot() | ||
remove_namespaces(root) | ||
miss = _createMissionXML(root) | ||
return miss |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can move these helper functions into corresponding classes, e.g. createAbout into About.from_xml, _createAgentSection into AgentSection.from_xml etc..
@CICS-Oleg what do you think?