Skip to content

Commit 77ddc88

Browse files
authored
Merge pull request #6 from sourcebots/bugfixes
Bugfixes
2 parents f964e64 + 3419c85 commit 77ddc88

File tree

224 files changed

+765
-273
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

224 files changed

+765
-273
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,9 +160,10 @@ cython_debug/
160160
#.idea/
161161

162162
# Webots
163-
.arena.wbproj
163+
.*.wbproj
164164
.arena.jpg
165165

166166
/simulator/controllers/usercode_runner/runtime.ini
167+
/simulator/controllers/competition_supervisor/runtime.ini
167168
/zone_*
168169
/dist

README.md

Lines changed: 1 addition & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
11
# sbot_simulator
22
A simulator built around Webots to use the sbot library virtually.
33

4-
![sbot_simulator](assets/arena_overview.jpg)
5-
6-
### This is a work in progress
4+
![sbot_simulator](assets/arena_overview.png)
75

86
## Installation
97

@@ -101,54 +99,3 @@ In order to keep the released simulator tidy and easy to use, the project is spl
10199
Alongside these folders that are placed in the releases, the `assets` folder contains images and other resources that are used in the documentation. These are used to render an HTML page user facing readme that is included in the release archive.
102100

103101
Of the the folders that are not included in the release, the `tests` folder contains the unit and integration tests for the simulator that don't require running webots and the `test_simulator` folder contains a separate webots world that is used to test the simulator.
104-
105-
## Project Status
106-
107-
1. ~~device spinup~~
108-
2. ~~debug logs~~
109-
3. ~~test devices~~
110-
4. ~~webots devices~~
111-
5. ~~usercode runner~~
112-
6. ~~vision~~
113-
7. ~~arena~~
114-
- ~~box~~
115-
- ~~deck~~
116-
- ~~triangle deck~~
117-
- ~~floor texture~~
118-
- ~~line~~
119-
- ~~scoring lines~~
120-
- ~~starting zones~~
121-
8. ~~robot~~
122-
9. ~~device jitter~~
123-
- ~~in Webots~~
124-
- ~~Ultrasound noise~~
125-
- ~~Reflectance sensor noise~~
126-
- ~~in python~~
127-
- ~~motor noise~~
128-
- ~~servo noise~~
129-
10. sbot updates
130-
1. ~~simulator discovery~~
131-
2. ~~vision~~
132-
3. ~~leds~~
133-
4. ~~sleep & time~~
134-
5. Windows startup performance
135-
11. ~~keyboard robot~~
136-
12. ~~setup script~~
137-
13. ~~releases~~
138-
14. documentation
139-
1. ~~dev setup~~
140-
2. user usage
141-
3. ~~how it works~~
142-
15. simulator tests
143-
- vision position
144-
- vision orientation
145-
- distance sensor
146-
- reflectance sensor
147-
- bump sensor
148-
- motor
149-
- servo
150-
16. ~~linting~~
151-
17. ~~CI~~
152-
18. report currents
153-
19. supervisor
154-
20. comp match running

assets/arena_overview.jpg

-70.8 KB
Binary file not shown.

assets/arena_overview.png

97.7 KB
Loading

assets/user_readme.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ The API for the simulator is the same as the API for the physical robot, so you
139139

140140

141141
As well as the logs being displayed in the console, they are also saved to a file.
142-
This file is saved in the `zone_0` folder and has a name in the format `log-<date>.log`.
142+
This file is saved in the `zone_0` folder and has a name in the format `log-zone-<zone>-<date>.log`.
143143
The date is when that simulation was run.
144144

145145
### Simulation of Time
@@ -252,6 +252,15 @@ If you see a message saying that Python cannot be found that looks similar to th
252252
As well as the guidance above, there are a few other points to note when using the simulator.
253253
These can help you to understand what is happening and how to get the most out of the simulator.
254254

255+
### Using Other Zones
256+
257+
If the arena has multiple starting zones, you can run multiple robots in the simulator.
258+
To test how your robot behaves in each starting zone of the arena, you can copy your robot's code to run in each corner.
259+
260+
In the folder where you extracted the simulator, alongside the `zone_0` folder, you may have other `zone_<number>` folders.
261+
Such as `zone_1`, `zone_2`, etc.
262+
Each of these folders can contain a `robot.py` file that will be run in the corresponding starting zone of the arena.
263+
255264
### Performance Optimisations
256265

257266
The default settings work for most users however if you are using a less powerful computer or one without a dedicated graphics card (as is the case on many laptops), you may wish to adjust the graphics settings to enable the simulation to run faster.

example_robots/basic_robot.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,26 @@
1-
from sbot import Robot
1+
from sbot import arduino, motors, utils
22

3-
robot = Robot()
3+
# robot = Robot()
44

5-
robot.motor_board.motors[0].power = 1
6-
robot.motor_board.motors[1].power = 1
5+
motors.set_power(0, 1)
6+
motors.set_power(1, 1)
77

88
# measure the distance of the right ultrasound sensor
99
# pin 6 is the trigger pin, pin 7 is the echo pin
10-
distance = robot.arduino.ultrasound_measure(6, 7)
10+
distance = arduino.measure_ultrasound_distance(6, 7)
1111
print(f"Right ultrasound distance: {distance / 1000} meters")
1212

1313
# motor board, channel 0 to half power forward
14-
robot.motor_board.motors[0].power = 0.5
14+
motors.set_power(0, 0.5)
1515

1616
# motor board, channel 1 to half power forward,
17-
robot.motor_board.motors[1].power = 0.5
17+
motors.set_power(1, 0.5)
1818
# minimal time has passed at this point,
1919
# so the robot will appear to move forward instead of turning
2020

2121
# sleep for 2 second
22-
robot.sleep(2)
22+
utils.sleep(2)
2323

2424
# stop both motors
25-
robot.motor_board.motors[0].power = 0
26-
robot.motor_board.motors[1].power = 0
25+
motors.set_power(0, 0)
26+
motors.set_power(1, 0)

example_robots/keyboard_robot.py

Lines changed: 45 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
1+
# mypy: ignore-errors
12
import math
23

34
from controller import Keyboard
4-
from sbot import AnalogPins, Robot
5+
from sbot import AnalogPin, Colour, arduino, comp, leds, motors, utils, vision
56

67
# Any keys still pressed in the following period will be handled again
78
# leading to rprinting sensors multiple times
@@ -62,17 +63,17 @@ def angle_str(angle: float) -> str:
6263
return f"{angle:.4f} rad"
6364

6465

65-
def print_sensors(robot: Robot) -> None:
66+
def print_sensors() -> None:
6667
ultrasonic_sensor_names = {
6768
(2, 3): "Front",
6869
(4, 5): "Left",
6970
(6, 7): "Right",
7071
(8, 9): "Back",
7172
}
7273
reflectance_sensor_names = {
73-
AnalogPins.A0: "Left",
74-
AnalogPins.A1: "Center",
75-
AnalogPins.A2: "Right",
74+
AnalogPin.A0: "Left",
75+
AnalogPin.A1: "Center",
76+
AnalogPin.A2: "Right",
7677
}
7778
touch_sensor_names = {
7879
10: "Front Left",
@@ -83,29 +84,30 @@ def print_sensors(robot: Robot) -> None:
8384

8485
print("Distance sensor readings:")
8586
for (trigger_pin, echo_pin), name in ultrasonic_sensor_names.items():
86-
dist = robot.arduino.ultrasound_measure(trigger_pin, echo_pin)
87+
dist = arduino.measure_ultrasound_distance(trigger_pin, echo_pin)
8788
print(f"({trigger_pin}, {echo_pin}) {name: <12}: {dist:.0f} mm")
8889

8990
print("Touch sensor readings:")
9091
for pin, name in touch_sensor_names.items():
91-
touching = robot.arduino.pins[pin].digital_value
92+
touching = arduino.digital_read(pin)
9293
print(f"{pin} {name: <6}: {touching}")
9394

9495
print("Reflectance sensor readings:")
9596
for Apin, name in reflectance_sensor_names.items():
96-
reflectance = robot.arduino.pins[Apin].analog_value
97+
reflectance = arduino.analog_read(Apin)
9798
print(f"{Apin} {name: <12}: {reflectance:.2f} V")
9899

99100

100-
def print_camera_detection(robot: Robot) -> None:
101-
markers = robot.camera.see()
101+
def print_camera_detection() -> None:
102+
markers = vision.detect_markers()
102103
if markers:
103104
print(f"Found {len(markers)} makers:")
104105
for marker in markers:
105106
print(f" #{marker.id}")
106107
print(
107-
f" Position: {marker.distance:.0f} mm, azi: {angle_str(marker.azimuth)}, "
108-
f"elev: {angle_str(marker.elevation)}",
108+
f" Position: {marker.position.distance:.0f} mm, "
109+
f"{angle_str(marker.position.horizontal_angle)} right, "
110+
f"{angle_str(marker.position.vertical_angle)} up",
109111
)
110112
yaw, pitch, roll = marker.orientation
111113
print(
@@ -119,11 +121,15 @@ def print_camera_detection(robot: Robot) -> None:
119121
print()
120122

121123

122-
robot = Robot()
123-
124124
keyboard = KeyboardInterface()
125125

126-
key_sense = CONTROLS["sense"][robot.zone]
126+
# Automatically set the zone controls based on the robot's zone
127+
# Alternatively, you can set this manually
128+
# ZONE_CONTROLS = 0
129+
ZONE_CONTROLS = comp.zone
130+
131+
assert ZONE_CONTROLS < len(CONTROLS["forward"]), \
132+
"No controls defined for this zone, alter the ZONE_CONTROLS variable to use in this zone."
127133

128134
print(
129135
"Note: you need to click on 3D viewport for keyboard events to be picked "
@@ -138,36 +144,42 @@ def print_camera_detection(robot: Robot) -> None:
138144
keys = keyboard.process_keys()
139145

140146
# Actions that are run continuously while the key is held
141-
if CONTROLS["forward"][robot.zone] in keys["held"]:
147+
if CONTROLS["forward"][ZONE_CONTROLS] in keys["held"]:
142148
left_power += 0.5
143149
right_power += 0.5
144150

145-
if CONTROLS["reverse"][robot.zone] in keys["held"]:
151+
if CONTROLS["reverse"][ZONE_CONTROLS] in keys["held"]:
146152
left_power += -0.5
147153
right_power += -0.5
148154

149-
if CONTROLS["left"][robot.zone] in keys["held"]:
155+
if CONTROLS["left"][ZONE_CONTROLS] in keys["held"]:
150156
left_power -= 0.25
151157
right_power += 0.25
152158

153-
if CONTROLS["right"][robot.zone] in keys["held"]:
159+
if CONTROLS["right"][ZONE_CONTROLS] in keys["held"]:
154160
left_power += 0.25
155161
right_power -= 0.25
156162

157-
if CONTROLS["boost"][robot.zone] in keys["held"]:
163+
if CONTROLS["boost"][ZONE_CONTROLS] in keys["held"]:
158164
boost = True
159165

160166
# Actions that are run once when the key is pressed
161-
if CONTROLS["sense"][robot.zone] in keys["pressed"]:
162-
print_sensors(robot)
163-
164-
if CONTROLS["see"][robot.zone] in keys["pressed"]:
165-
print_camera_detection(robot)
166-
167-
if CONTROLS["led"][robot.zone] in keys["pressed"]:
168-
pass
169-
170-
if CONTROLS["angle_unit"][robot.zone] in keys["pressed"]:
167+
if CONTROLS["sense"][ZONE_CONTROLS] in keys["pressed"]:
168+
print_sensors()
169+
170+
if CONTROLS["see"][ZONE_CONTROLS] in keys["pressed"]:
171+
print_camera_detection()
172+
173+
if CONTROLS["led"][ZONE_CONTROLS] in keys["pressed"]:
174+
leds.set_colour(0, Colour.MAGENTA)
175+
leds.set_colour(1, Colour.MAGENTA)
176+
leds.set_colour(2, Colour.MAGENTA)
177+
elif CONTROLS["led"][ZONE_CONTROLS] in keys["released"]:
178+
leds.set_colour(0, Colour.OFF)
179+
leds.set_colour(1, Colour.OFF)
180+
leds.set_colour(2, Colour.OFF)
181+
182+
if CONTROLS["angle_unit"][ZONE_CONTROLS] in keys["pressed"]:
171183
USE_DEGREES = not USE_DEGREES
172184
print(f"Angle unit set to {'degrees' if USE_DEGREES else 'radians'}")
173185

@@ -176,7 +188,7 @@ def print_camera_detection(robot: Robot) -> None:
176188
left_power = max(min(left_power * 2, 1), -1)
177189
right_power = max(min(right_power * 2, 1), -1)
178190

179-
robot.motor_board.motors[0].power = left_power
180-
robot.motor_board.motors[1].power = right_power
191+
motors.set_power(0, left_power)
192+
motors.set_power(1, right_power)
181193

182-
robot.sleep(KEYBOARD_SAMPLING_PERIOD / 1000)
194+
utils.sleep(KEYBOARD_SAMPLING_PERIOD / 1000)

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
sbot==2024.0.1
1+
sbot==2025.1.0
22
april_vision==2.2.0
3-
opencv-python-headless >=4,<5
3+
opencv-python-headless >=4.8.0.76,<5

scripts/generate_release.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@
7878
logger.info("Copying helper scripts to temp directory")
7979
shutil.copy(project_root / "scripts/setup.py", temp_dir / "setup.py")
8080
for script in project_root.glob("scripts/run_*.py"):
81+
if "run_comp_" in str(script):
82+
continue
8183
shutil.copy(script, temp_dir)
8284

85+
script_dir = temp_dir / "scripts"
86+
script_dir.mkdir()
8387
logger.info("Copying example code to temp directory")
8488
shutil.copytree(project_root / "example_robots", temp_dir / "example_robots")
8589

0 commit comments

Comments
 (0)