Skip to content
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

Randomisation settings #260

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions ev3sim/assets/default_theme.json
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,16 @@
"size": "24"
}
},
"settings-title": {
"colours": {
"normal_text": "#f7ede2",
"dark_bg": "#00000000"
},
"font": {
"name": "Roboto",
"size": "24"
}
},
"checkbox-button": {
"colours": {
"normal_bg": "#ffffff00",
Expand Down
26 changes: 26 additions & 0 deletions ev3sim/simulation/loader.py
Original file line number Diff line number Diff line change
Expand Up @@ -328,11 +328,37 @@ def __init__(self):
"FPS": ObjectSetting(ScriptLoader, "VISUAL_TICK_RATE"),
"tick_rate": ObjectSetting(ScriptLoader, "GAME_TICK_RATE"),
"timescale": ObjectSetting(ScriptLoader, "TIME_SCALE"),
"randomise_sensors": ObjectSetting(ScriptLoader, "RANDOMISE_SENSORS"),
"console_log": ObjectSetting(Logger, "LOG_CONSOLE"),
"workspace_folder": ObjectSetting(StateHandler, "WORKSPACE_FOLDER"),
}
from ev3sim.devices.colour.base import ColourSensorMixin
from ev3sim.devices.colour.ev3 import ColorSensor
from ev3sim.devices.compass.ev3 import CompassSensor
from ev3sim.devices.infrared.base import InfraredSensorMixin
from ev3sim.devices.motor.base import MotorMixin
from ev3sim.devices.ultrasonic.base import UltrasonicSensorMixin

randomisation_settings = {
"COLOUR_SENSOR_RADIUS": ObjectSetting(ColourSensorMixin, "SENSOR_RADIUS"),
"COLOUR_SENSOR_SAMPLING_POINTS": ObjectSetting(ColourSensorMixin, "SENSOR_POINTS"),
"COLOUR_MAX_RGB_BIAS": ObjectSetting(ColorSensor, "MAX_RGB_BIAS"),
"COLOUR_MIN_RGB_BIAS": ObjectSetting(ColorSensor, "MIN_RGB_BIAS"),
"COMPASS_N_POINTS": ObjectSetting(CompassSensor, "NEAREST_POINTS_NUMBER"),
"COMPASS_POINT_VARIANCE": ObjectSetting(CompassSensor, "NEAREST_POINTS_VARIANCE"),
"COMPASS_NOISE_RATE": ObjectSetting(CompassSensor, "NOISE_WIDTH_PER_TICK"),
"COMPASS_NOISE_AMP": ObjectSetting(CompassSensor, "NOISE_AMPLIFIER"),
"COMPASS_MAXIMUM_NOISE_EFFECT": ObjectSetting(CompassSensor, "NOISE_EFFECT_MAX"),
"INFRARED_BIAS_AMP": ObjectSetting(InfraredSensorMixin, "SUBSENSOR_BIAS_MAGNITUDE"),
"MOTOR_MIN_MULT": ObjectSetting(MotorMixin, "MIN_FORCE_PCT"),
"MOTOR_MAX_MULT": ObjectSetting(MotorMixin, "MAX_FORCE_PCT"),
"MOTOR_N_SPEEDS": ObjectSetting(MotorMixin, "FIXED_SPEED_POINTS"),
"ULTRASONIC_NOISE_ANGLE_AMPLITUDE": ObjectSetting(UltrasonicSensorMixin, "ANGLE_RANDOM_AMPLITUDE"),
"ULTRASONIC_OFFSET_AMP": ObjectSetting(UltrasonicSensorMixin, "OFFSET_MAX"),
}
settings.addSettingGroup("app", loader_settings)
settings.addSettingGroup("screen", screen_settings)
settings.addSettingGroup("randomisation", randomisation_settings)
self.shared_info = {}

def closeProcesses(self):
Expand Down
2 changes: 2 additions & 0 deletions ev3sim/visual/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ class ScreenObjectManager:
SCREEN_SIM = "SIMULATOR"
SCREEN_BOTS = "BOT_SELECT"
SCREEN_SETTINGS = "SETTINGS"
SCREEN_RANDOM_SETTINGS = "RANDOM_SETTINGS"
SCREEN_WORKSPACE = "WORKSPACE"
SCREEN_UPDATE = "UPDATE"
SCREEN_BOT_EDIT = "BOT_EDIT"
Expand Down Expand Up @@ -106,6 +107,7 @@ def initScreens(self):
from ev3sim.visual.settings.menu import SettingsMenu

self.screens[self.SCREEN_SETTINGS] = SettingsMenu((self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
self.screens[self.SCREEN_RANDOM_SETTINGS] = SettingsMenu((self.SCREEN_WIDTH, self.SCREEN_HEIGHT))
# Rescue edit screen
from ev3sim.visual.menus.rescue_edit import RescueMapEditMenu

Expand Down
31 changes: 31 additions & 0 deletions ev3sim/visual/settings/elements.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,37 @@ def generateVisual(self, size, container, manager, idx):
raise NotImplementedError()


class Title(SettingsVisualElement):

num_objs = 1

def __init__(self, title, offset):
self.title = title
self.offset = offset
self.menu = None
self.json_keys = "__filename__"

def getFromJson(self, json_obj):
pass

def setToJson(self, json_obj):
pass

def generateVisual(self, size, container, manager, idx):
self.container = container
off = self.offset(size)
label_size = ((size[0] - 40), 40)
label_pos = (off[0] + 20, off[1])
self.button = pygame_gui.elements.UILabel(
relative_rect=pygame.Rect(*label_pos, *label_size),
manager=manager,
object_id=pygame_gui.core.ObjectID(f"{idx}-title-label", "settings-title"),
container=container,
text=self.title,
)
return [self.button]


class Button(SettingsVisualElement):

num_objs = 1
Expand Down
24 changes: 23 additions & 1 deletion ev3sim/visual/settings/main_settings.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
from ev3sim.visual.settings.elements import NumberEntry, FileEntry, Checkbox
from ev3sim.file_helper import find_abs
from ev3sim.search_locations import config_locations
from ev3sim.visual.settings.elements import NumberEntry, FileEntry, Checkbox, Button
from ev3sim.visual.settings.randomisation_settings import randomisation_settings


def onClickConfigEditor(filename):
from ev3sim.visual.manager import ScreenObjectManager

ScreenObjectManager.instance.pushScreen(
ScreenObjectManager.SCREEN_RANDOM_SETTINGS,
file=find_abs("user_config.yaml", config_locations()),
settings=randomisation_settings,
)
ScreenObjectManager.instance.screens[ScreenObjectManager.SCREEN_RANDOM_SETTINGS].clearEvents()


main_settings = [
{
Expand All @@ -16,6 +31,13 @@
Checkbox(["app", "console_log"], True, "Console", (lambda s: (0, 170) if s[0] < 540 else (s[0] / 2, 70))),
],
},
{
"height": (lambda s: 90),
"objects": [
Checkbox(["app", "randomise_sensors"], False, "Random Noise", (lambda s: (0, 20))),
Button("Randomisation Config", (lambda s: (0, 70) if s[0] < 540 else (s[0] / 2, 20)), onClickConfigEditor),
],
},
{
"height": (lambda s: 90),
"objects": [
Expand Down
31 changes: 28 additions & 3 deletions ev3sim/visual/settings/menu.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from ev3sim.visual.menus.utils import CustomScroll
from ev3sim.settings import SettingsManager
from ev3sim.visual.settings.elements import TextEntry
import os
Expand All @@ -21,6 +22,25 @@ def clearEvents(self):
self.onCancel = None

def generateObjects(self):
# Scrolling container
old_y = 0
self.scrolling_container = CustomScroll(
relative_rect=pygame.Rect(0, 0, *self._size),
manager=self,
object_id=pygame_gui.core.ObjectID("scroll_container"),
)
self.scrolling_container.num_elems = 1
self.scrolling_container.elems_size = 1
self.scrolling_container.span_elems = 1
scroll_height = self._size[1] - 90
scrolling_size = (self._size[0], scroll_height)
# Setting dimensions and positions on a UIScrollingContainer seems buggy. This works.
self.scrolling_container.set_dimensions(scrolling_size)
self.scrolling_container.set_position(scrolling_size)
self.scrolling_container.cur_y = old_y
self.scrolling_container.set_scroll(old_y)
self._all_objs.append(self.scrolling_container)

yPadding = 20
yOffset = 0
index = 0
Expand All @@ -30,6 +50,7 @@ def generateObjects(self):
relative_rect=pygame.Rect(0, 0, *self._size),
starting_layer_height=-1,
manager=self,
container=self.scrolling_container,
object_id=pygame_gui.core.ObjectID(f"{index}-bg", "settings-background"),
)
self._all_objs.append(container)
Expand All @@ -49,6 +70,10 @@ def generateObjects(self):
yOffset += group["height"](self._size)
yOffset += yPadding

self.scrolling_container.elems_size = yOffset
self.scrolling_container.span_elems = min(1, scroll_height / yOffset)
self.scrolling_container.set_scrollable_area_dimensions((self._size[0], yOffset))

self.bg = pygame_gui.elements.UIPanel(
relative_rect=pygame.Rect(0, 0, *self._size),
starting_layer_height=-2,
Expand All @@ -58,15 +83,15 @@ def generateObjects(self):
self._all_objs.append(self.bg)

container = pygame_gui.elements.UIPanel(
relative_rect=pygame.Rect(20, yOffset, self._size[0] - 40, 80),
relative_rect=pygame.Rect(20, min(yOffset, self._size[1] - 80), self._size[0] - 40, 80),
starting_layer_height=-1,
manager=self,
object_id=pygame_gui.core.ObjectID(f"{index}-bg", "settings-background"),
)
self._all_objs.append(container)

self.save = pygame_gui.elements.UIButton(
relative_rect=pygame.Rect(self._size[0] - 300, yOffset + 10, 120, 60),
relative_rect=pygame.Rect(self._size[0] - 300, min(yOffset + 10, self._size[1] - 70), 120, 60),
manager=self,
object_id=pygame_gui.core.ObjectID("save-changes", "action_button"),
text="Create" if self.creating else "Save",
Expand All @@ -75,7 +100,7 @@ def generateObjects(self):
self._all_objs.append(self.save)

self.cancel = pygame_gui.elements.UIButton(
relative_rect=pygame.Rect(self._size[0] - 160, yOffset + 10, 120, 60),
relative_rect=pygame.Rect(self._size[0] - 160, min(yOffset + 10, self._size[1] - 70), 120, 60),
manager=self,
object_id=pygame_gui.core.ObjectID("cancel-changes", "action_button"),
text="Cancel",
Expand Down
115 changes: 115 additions & 0 deletions ev3sim/visual/settings/randomisation_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
from ev3sim.visual.settings.elements import NumberEntry, Title

randomisation_settings = [
{
"height": (lambda s: 290 if s[0] < 580 else 190),
"objects": [
Title("Colour Sensor", (lambda s: (0, 20))),
NumberEntry(["randomisation", "COLOUR_SENSOR_RADIUS"], 1, "Sampling Radius", (lambda s: (0, 70)), float),
NumberEntry(
["randomisation", "COLOUR_SENSOR_SAMPLING_POINTS"],
100,
"Sampling Points",
(lambda s: (0, 120) if s[0] < 540 else (s[0] / 2, 70)),
int,
),
NumberEntry(
["randomisation", "COLOUR_MAX_RGB_BIAS"],
400,
"Max RGB Bias",
(lambda s: (0, 170) if s[0] < 540 else (0, 120)),
float,
),
NumberEntry(
["randomisation", "COLOUR_MIN_RGB_BIAS"],
230,
"Min RGB Bias",
(lambda s: (0, 220) if s[0] < 540 else (s[0] / 2, 120)),
float,
),
],
},
{
"height": (lambda s: 340 if s[0] < 580 else 240),
"objects": [
Title("Compass Sensor", (lambda s: (0, 20))),
NumberEntry(["randomisation", "COMPASS_N_POINTS"], 51, "Static Points", (lambda s: (0, 70)), int),
NumberEntry(
["randomisation", "COMPASS_POINT_VARIANCE"],
16,
"Static Variance",
(lambda s: (0, 120) if s[0] < 540 else (s[0] / 2, 70)),
float,
),
NumberEntry(
["randomisation", "COMPASS_NOISE_RATE"],
0.03,
"Noise rate of change",
(lambda s: (0, 170) if s[0] < 540 else (0, 120)),
float,
),
NumberEntry(
["randomisation", "COMPASS_NOISE_AMP"],
0.2,
"Noise amplitude",
(lambda s: (0, 220) if s[0] < 540 else (s[0] / 2, 120)),
float,
),
NumberEntry(
["randomisation", "COMPASS_MAXIMUM_NOISE_EFFECT"],
15,
"Max Noise effect",
(lambda s: (0, 270) if s[0] < 540 else (0, 170)),
float,
),
],
},
{
"height": (lambda s: 140),
"objects": [
Title("Infrared Sensor", (lambda s: (0, 20))),
NumberEntry(["randomisation", "INFRARED_BIAS_AMP"], 5, "Bias Amplitude", (lambda s: (0, 70)), float),
],
},
{
"height": (lambda s: 190 if s[0] < 580 else 140),
"objects": [
Title("Ultrasonic Sensor", (lambda s: (0, 20))),
NumberEntry(
["randomisation", "ULTRASONIC_NOISE_ANGLE_AMPLITUDE"],
40,
"Angle change effect",
(lambda s: (0, 70)),
float,
),
NumberEntry(
["randomisation", "ULTRASONIC_OFFSET_AMP"],
5,
"Static noise",
(lambda s: (0, 120) if s[0] < 540 else (s[0] / 2, 70)),
float,
),
],
},
{
"height": (lambda s: 240 if s[0] < 580 else 190),
"objects": [
Title("Motors", (lambda s: (0, 20))),
NumberEntry(["randomisation", "MOTOR_MIN_MULT"], 0.9, "Min speed mult", (lambda s: (0, 70)), float),
NumberEntry(
["randomisation", "MOTOR_MAX_MULT"],
1.05,
"Max speed mult",
(lambda s: (0, 120) if s[0] < 540 else (s[0] / 2, 70)),
float,
),
NumberEntry(
["randomisation", "MOTOR_N_SPEEDS"],
71,
"Static Points",
(lambda s: (0, 170) if s[0] < 540 else (0, 120)),
int,
),
],
},
]