Skip to content

Commit 6dd43f5

Browse files
committed
Implement synced-ish bot support
1 parent 422254e commit 6dd43f5

9 files changed

+339
-177
lines changed

README.md

+15-5
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,16 @@ Path creation/visualization tool for Road Runner
55

66
![MeepMeep Sample Recording](/images/readme/screen-recording.gif?raw=true)
77

8-
# 🔨 Installing
8+
# 🔨 Installing
99

1010
## Gradle Snippet:
1111
```groovy
1212
repositories {
13-
maven { url 'https://jitpack.io' }
13+
maven { url 'https://jitpack.io' }
1414
}
1515
1616
dependencies {
17-
implementation 'com.github.NoahBres:MeepMeep:1.0.6'
17+
implementation 'com.github.NoahBres:MeepMeep:1.0.6'
1818
}
1919
```
2020

@@ -67,5 +67,15 @@ public class MeepMeepTesting {
6767
On some systems hardware acceleration may not be enabled by default where it could be used. To enable hardware acceleration use the cli flag: `-Dsun.java2d.opengl=true` or enable it _before_ initializing your `MeepMeep` instance with `System.setProperty("sun.java2d.opengl", "true");`.
6868

6969
## Notes:
70-
Default Bot Constraints
71-
-
70+
Default Bot Settings:
71+
- Constraints
72+
- Max Vel: 30in/s
73+
- Max Accel: 30in/s/s
74+
- Max Ang Vel: 60deg/s
75+
- Max Ang Accel: 60deg/s/s
76+
- Track Width: 15in
77+
- Bot Width: 18in
78+
- Bot Width: 18in
79+
- Start Pose: (x: 0in, y: 0in, heading: 0rad)
80+
- Color Scheme: Inherited from MeepMeep.colorManager unless overriden
81+
- Drive Train Type: Mecanum

src/main/kotlin/com/noahbres/meepmeep/MeepMeep.kt

+32-12
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import com.noahbres.meepmeep.core.entity.*
77
import com.noahbres.meepmeep.core.ui.WindowFrame
88
import com.noahbres.meepmeep.core.util.FieldUtil
99
import com.noahbres.meepmeep.core.util.LoopManager
10+
import com.noahbres.meepmeep.roadrunner.entity.RoadRunnerBotEntity
11+
import com.noahbres.meepmeep.roadrunner.ui.TrajectoryProgressSliderMaster
1012
import java.awt.*
1113
import java.awt.datatransfer.StringSelection
1214
import java.awt.event.*
@@ -43,7 +45,7 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
4345

4446
private val entityList = mutableListOf<Entity>()
4547
private val requestedAddEntityList = mutableListOf<Entity>()
46-
private val requestedClearEntityList = mutableListOf<Entity>()
48+
private val requestedRemoveEntityList = mutableListOf<Entity>()
4749

4850
private val zIndexManager = ZIndexManager();
4951

@@ -103,10 +105,10 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
103105

104106
private val update: (deltaTime: Long) -> Unit = { deltaTime ->
105107
if (entityListDirty) {
106-
requestedClearEntityList.forEach {
108+
requestedRemoveEntityList.forEach {
107109
removeEntity(it)
108110
}
109-
requestedClearEntityList.clear();
111+
requestedRemoveEntityList.clear();
110112

111113
requestedAddEntityList.forEach {
112114
addEntity(it)
@@ -126,7 +128,16 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
126128
private val loopManager = LoopManager(fps, update, render)
127129

128130
// Road Runner UI Elements
129-
val sliderPanel = JPanel()
131+
132+
// Handles progress slider elements
133+
private val progressSliderMasterPanel: TrajectoryProgressSliderMaster by lazy {
134+
TrajectoryProgressSliderMaster(
135+
this,
136+
FieldUtil.CANVAS_WIDTH.toInt(),
137+
20
138+
)
139+
}
140+
130141
var middleButtonPanel = JPanel()
131142

132143
private val standardCursorButton = JButton("test")
@@ -160,9 +171,7 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
160171
this, colorManager.theme, 30.0, 30.0, Vector2d(-54.0, 54.0)
161172
)
162173

163-
// Road Runner Init
164174
// Handle UI
165-
sliderPanel.layout = BoxLayout(sliderPanel, BoxLayout.Y_AXIS)
166175

167176
middleButtonList.forEach {
168177
it.alignmentX = 0.5f
@@ -178,7 +187,7 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
178187
middleButtonPanel.add(pathSelectionButton)
179188
middleButtonPanel.add(Box.createVerticalGlue())
180189

181-
windowFrame.canvasPanel.add(sliderPanel)
190+
windowFrame.canvasPanel.add(progressSliderMasterPanel)
182191
// windowFrame.contentPane.add(middleButtonPanel)
183192

184193
windowFrame.pack()
@@ -233,15 +242,15 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
233242
addEntity(DEFAULT_COMPASS_ENTITY)
234243
}
235244

236-
open fun start(): MeepMeep {
237-
// Core Start
245+
fun start(): MeepMeep {
238246
if (bg == null) setBackground(Background.GRID_BLUE)
239247
windowFrame.isVisible = true
240248

241249
// Default added entities are initialized before color schemes are set
242250
// Thus make sure to reset them
243251
entityList.forEach {
244252
if (it is ThemedEntity) it.switchScheme(colorManager.theme)
253+
if (it is RoadRunnerBotEntity) it.start()
245254
}
246255

247256
onCanvasResize()
@@ -373,6 +382,12 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
373382

374383
if (entity is MouseMotionListener) canvas.addMouseMotionListener(entity)
375384

385+
if (entity is RoadRunnerBotEntity)
386+
progressSliderMasterPanel.addRoadRunnerBot(entity)
387+
388+
if (entity is EntityEventListener)
389+
entity.onAddToEntityList()
390+
376391
return this
377392
}
378393

@@ -381,11 +396,16 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
381396
requestedAddEntityList.remove(entity)
382397
entityListDirty = true
383398

384-
385399
if (entity is MouseListener) canvas.removeMouseListener(entity)
386400

387401
if (entity is MouseMotionListener) canvas.removeMouseMotionListener(entity)
388402

403+
if (entity is RoadRunnerBotEntity)
404+
progressSliderMasterPanel.removeRoadRunnerBot(entity)
405+
406+
if (entity is EntityEventListener)
407+
entity.onRemoveFromEntityList()
408+
389409
return this
390410
}
391411

@@ -397,8 +417,8 @@ class MeepMeep @JvmOverloads constructor(private val windowSize: Int, fps: Int =
397417
}
398418

399419

400-
fun requestToClearEntity(entity: Entity): MeepMeep {
401-
requestedClearEntityList.add(entity)
420+
fun requestToRemoveEntity(entity: Entity): MeepMeep {
421+
requestedRemoveEntityList.add(entity)
402422
entityListDirty = true
403423

404424
return this
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package com.noahbres.meepmeep.core.entity
2+
3+
interface EntityEventListener {
4+
fun onAddToEntityList()
5+
fun onRemoveFromEntityList()
6+
}

src/main/kotlin/com/noahbres/meepmeep/roadrunner/DefaultBotBuilder.kt

+8-2
Original file line numberDiff line numberDiff line change
@@ -58,19 +58,25 @@ class DefaultBotBuilder(private val meepMeep: MeepMeep) {
5858
return this
5959
}
6060

61+
fun setColorScheme(scheme: ColorScheme): DefaultBotBuilder {
62+
this.colorScheme = scheme
63+
64+
return this
65+
}
66+
6167
fun build(): RoadRunnerBotEntity {
6268
return RoadRunnerBotEntity(
6369
meepMeep,
6470
constraints,
6571
width, height,
66-
startPose, colorScheme ?: meepMeep.colorManager.theme, opacity
72+
startPose, colorScheme ?: meepMeep.colorManager.theme, opacity,
73+
driveTrainType, false
6774
)
6875
}
6976

7077
fun followTrajectorySequence(trajectorySequence: TrajectorySequence): RoadRunnerBotEntity {
7178
val bot = this.build()
7279
bot.followTrajectorySequence(trajectorySequence)
73-
bot.start()
7480

7581
return bot
7682
}

src/main/kotlin/com/noahbres/meepmeep/roadrunner/entity/RoadRunnerBotEntity.kt

+43-38
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,14 @@ import com.acmerobotics.roadrunner.geometry.Pose2d
44
import com.noahbres.meepmeep.MeepMeep
55
import com.noahbres.meepmeep.core.colorscheme.ColorScheme
66
import com.noahbres.meepmeep.core.entity.BotEntity
7+
import com.noahbres.meepmeep.core.entity.EntityEventListener
78
import com.noahbres.meepmeep.core.exhaustive
8-
import com.noahbres.meepmeep.core.util.FieldUtil
99
import com.noahbres.meepmeep.roadrunner.Constraints
1010
import com.noahbres.meepmeep.roadrunner.DriveShim
1111
import com.noahbres.meepmeep.roadrunner.DriveTrainType
1212
import com.noahbres.meepmeep.roadrunner.trajectorysequence.*
13-
import com.noahbres.meepmeep.roadrunner.ui.TrajectoryProgressSlider
13+
import com.noahbres.meepmeep.roadrunner.ui.TrajectoryProgressSliderMaster
14+
import kotlin.math.min
1415

1516
class RoadRunnerBotEntity(
1617
meepMeep: MeepMeep,
@@ -19,14 +20,15 @@ class RoadRunnerBotEntity(
1920
width: Double, height: Double,
2021
pose: Pose2d,
2122

22-
private val colorScheme: ColorScheme,
23+
val colorScheme: ColorScheme,
2324
opacity: Double,
2425

25-
private var driveTrainType: DriveTrainType = DriveTrainType.MECANUM
26-
) : BotEntity(meepMeep, width, height, pose, colorScheme, opacity) {
26+
private var driveTrainType: DriveTrainType = DriveTrainType.MECANUM,
27+
28+
var listenToSwitchThemeRequest: Boolean = false
29+
) : BotEntity(meepMeep, width, height, pose, colorScheme, opacity), EntityEventListener {
2730
companion object {
2831
const val SKIP_LOOPS = 2
29-
const val PROGRESS_SLIDER_HEIGHT = 20
3032
}
3133

3234
override val tag = "RR_BOT_ENTITY"
@@ -39,7 +41,7 @@ class RoadRunnerBotEntity(
3941

4042
private var trajectorySequenceEntity: TrajectorySequenceEntity? = null
4143

42-
private var looping = true
44+
var looping = true
4345
private var running = false
4446

4547
private var trajectorySequenceElapsedTime = 0.0
@@ -52,23 +54,8 @@ class RoadRunnerBotEntity(
5254

5355
private var skippedLoops = 0
5456

55-
private val progressSlider = TrajectoryProgressSlider(
56-
this,
57-
FieldUtil.CANVAS_WIDTH.toInt(),
58-
PROGRESS_SLIDER_HEIGHT,
59-
colorScheme.TRAJECTORY_SLIDER_FG,
60-
colorScheme.TRAJECTORY_SLIDER_BG,
61-
colorScheme.TRAJECTORY_TEXT_COLOR,
62-
MeepMeep.FONT_CMU_BOLD
63-
)
64-
65-
init {
66-
progressSlider.progress = 0.0
67-
meepMeep.sliderPanel.add(progressSlider)
68-
meepMeep.windowFrame.pack()
69-
70-
meepMeep.windowFrame
71-
}
57+
private var sliderMaster: TrajectoryProgressSliderMaster? = null
58+
private var sliderMasterIndex: Int? = null
7259

7360
override fun update(deltaTime: Long) {
7461
if (!running) return
@@ -106,19 +93,26 @@ class RoadRunnerBotEntity(
10693

10794
trajectorySequenceEntity!!.markerEntityList.forEach { if (trajectorySequenceElapsedTime >= it.time) it.passed() }
10895

109-
progressSlider.progress = (trajectorySequenceElapsedTime / currentTrajectorySequence!!.duration)
96+
sliderMaster?.reportProgress(sliderMasterIndex ?: -1, trajectorySequenceElapsedTime)
97+
98+
Unit
11099
}
111100

112101
looping -> {
113102
trajectorySequenceEntity!!.markerEntityList.forEach {
114103
it.reset()
115104
}
116105
trajectorySequenceElapsedTime = 0.0
106+
107+
sliderMaster?.reportDone(sliderMasterIndex ?: -1)
117108
}
118109

119110
else -> {
120111
trajectorySequenceElapsedTime = 0.0
121-
currentTrajectorySequence = null
112+
running = false
113+
// currentTrajectorySequence = null
114+
115+
sliderMaster?.reportDone(sliderMasterIndex ?: -1)
122116
}
123117
}.exhaustive
124118
}
@@ -128,28 +122,27 @@ class RoadRunnerBotEntity(
128122
trajectorySequenceElapsedTime = 0.0
129123
}
130124

125+
fun resume() {
126+
running = true
127+
}
128+
131129
fun pause() {
132130
trajectoryPaused = true
133131
}
134132

135-
fun unPause() {
133+
fun unpause() {
136134
trajectoryPaused = false
137135
}
138136

139-
fun togglePause() {
140-
trajectoryPaused = !trajectoryPaused
141-
}
142-
143-
fun setTrajectoryProgress(progress: Double) {
137+
fun setTrajectoryProgressSeconds(seconds: Double) {
144138
if (currentTrajectorySequence != null)
145-
trajectorySequenceElapsedTime = progress * currentTrajectorySequence!!.duration
139+
trajectorySequenceElapsedTime = min(seconds, currentTrajectorySequence!!.duration)
146140
}
147141

148142
fun followTrajectorySequence(sequence: TrajectorySequence) {
149143
currentTrajectorySequence = sequence
150144

151145
trajectorySequenceEntity = TrajectorySequenceEntity(meepMeep, sequence, colorScheme)
152-
meepMeep.addEntity(trajectorySequenceEntity!!)
153146
}
154147

155148
fun setConstraints(constraints: Constraints) {
@@ -165,10 +158,22 @@ class RoadRunnerBotEntity(
165158
}
166159

167160
override fun switchScheme(scheme: ColorScheme) {
168-
super.switchScheme(scheme)
161+
if (listenToSwitchThemeRequest)
162+
super.switchScheme(scheme)
163+
}
164+
165+
fun setTrajectoryProgressSliderMaster(master: TrajectoryProgressSliderMaster, index: Int) {
166+
sliderMaster = master
167+
sliderMasterIndex = index
168+
}
169+
170+
override fun onAddToEntityList() {
171+
if (trajectorySequenceEntity != null)
172+
meepMeep.requestToAddEntity(trajectorySequenceEntity!!)
173+
}
169174

170-
this.progressSlider.fg = scheme.TRAJECTORY_SLIDER_FG
171-
this.progressSlider.bg = scheme.TRAJECTORY_SLIDER_BG
172-
this.progressSlider.textColor = scheme.TRAJECTORY_TEXT_COLOR
175+
override fun onRemoveFromEntityList() {
176+
if (trajectorySequenceEntity != null)
177+
meepMeep.requestToRemoveEntity(trajectorySequenceEntity!!)
173178
}
174179
}

src/main/kotlin/com/noahbres/meepmeep/roadrunner/entity/TrajectorySequenceEntity.kt

+2-4
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
package com.noahbres.meepmeep.roadrunner.entity
22

33
import com.acmerobotics.roadrunner.geometry.Pose2d
4-
import com.acmerobotics.roadrunner.geometry.Vector2d
54
import com.noahbres.meepmeep.MeepMeep
65
import com.noahbres.meepmeep.core.colorscheme.ColorScheme
76
import com.noahbres.meepmeep.core.entity.ThemedEntity
8-
import com.noahbres.meepmeep.core.exhaustive
97
import com.noahbres.meepmeep.core.toScreenCoord
108
import com.noahbres.meepmeep.core.util.FieldUtil
119
import com.noahbres.meepmeep.roadrunner.trajectorysequence.*
@@ -56,13 +54,13 @@ class TrajectorySequenceEntity(
5654
private fun redrawPath() {
5755
// Request to clear previous turn indicator entities
5856
turnEntityList.forEach {
59-
meepMeep.requestToClearEntity(it)
57+
meepMeep.requestToRemoveEntity(it)
6058
}
6159
turnEntityList.clear()
6260

6361
// Request to clear previous marker indicator entities
6462
markerEntityList.forEach {
65-
meepMeep.requestToClearEntity(it)
63+
meepMeep.requestToRemoveEntity(it)
6664
}
6765
markerEntityList.clear()
6866

0 commit comments

Comments
 (0)