• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Scala-Robotics-Simulator / PPS-22-srs / #802

27 Oct 2025 11:25AM UTC coverage: 73.259% (-3.3%) from 76.593%
#802

Pull #131

github

sceredi
chore: format python
Pull Request #131: feat: q-learning implementation of obstacle avoidance

40 of 114 new or added lines in 10 files covered. (35.09%)

4 existing lines in 4 files now uncovered.

1578 of 2154 relevant lines covered (73.26%)

8.26 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

58.13
/src/main/scala/io/github/srs/utils/SimulationDefaults.scala
1
package io.github.srs.utils
2

3
import java.awt.Color
4
import java.util.UUID
5

6
import scala.concurrent.duration.{ DurationInt, FiniteDuration }
7

8
import cats.effect.IO
9
import cats.effect.unsafe.implicits.global
10
import io.github.srs.model.entity.*
11
import io.github.srs.model.entity.dynamicentity.actuator.{ Actuator, Wheel as ActWheel }
12
import io.github.srs.model.entity.dynamicentity.agent.Agent
13
import io.github.srs.model.entity.dynamicentity.agent.reward.Reward
14
import io.github.srs.model.entity.dynamicentity.robot.Robot
15
import io.github.srs.model.entity.dynamicentity.robot.behavior.Policy
16
import io.github.srs.model.entity.dynamicentity.sensor.*
17
import io.github.srs.model.environment.Environment
18
import io.github.srs.model.illumination.LightMap
19
import io.github.srs.model.illumination.engine.SquidLibFovEngine
20
import io.github.srs.model.illumination.model.ScaleFactor
21
import io.github.srs.model.entity.dynamicentity.agent.termination.Termination
22
import io.github.srs.model.entity.dynamicentity.agent.truncation.Truncation
23

24
object SimulationDefaults:
25

×
26
  object Illumination:
27

3✔
28
    val GridThreshold = 10_000
29
    val LightThreshold = 2
8✔
30

5✔
31
    object Occlusion:
32
      val FullRotation: Double = 90.0
3✔
33
      val AlmostZero: Double = 1e-6
8✔
34

5✔
35
  object Behaviors:
36

×
37
    object Prioritized:
38
      val DangerDist: Double = 0.40
3✔
39
      val LightThreshold: Double = 0.05
8✔
40

5✔
41
    object Phototaxis:
42
      val Epsilon: Double = 1e-9
3✔
43
      val MinForwardBias: Double = 0.4
8✔
44
      val TurnGain: Double = 1.0
4✔
45

5✔
46
    object ObstacleAvoidance:
47
      val CruiseSpeed: Double = 0.35
3✔
48
      val WarnSpeed: Double = 0.15
8✔
49
      val WarnTurnSpeed: Double = 0.55
4✔
50
      val BackBoost: Double = 0.20
4✔
51
      val SafeDist: Double = 0.5
4✔
52
      val CriticalDist: Double = 0.35
4✔
53

5✔
54
    object RandomWalk:
55
      val MinForwardFactor: Double = 0.35
3✔
56
      val MaxForwardExtra: Double = 0.35
8✔
57
      val MinTurnOfBase: Double = 0.35
4✔
58
      val MaxTurnOfBase: Double = 1.15
4✔
59
      val TurnExponent: Double = 1.2
4✔
60
      val PivotBoostProb: Double = 0.20
4✔
61
      val PivotBoostAbs: Double = 0.15
4✔
62

5✔
63
  end Behaviors
64

65
  object UI:
66

×
67
    object SimulationViewConstants:
68
      val IdDisplayLength = 8
×
69
      val PositionDecimals = 2
×
70
      val OrientationDecimals = 1
×
71
      val DefaultRobotInfo = "Select a robot to view details"
×
72
      val StopConfirmMessage = "Are you sure you want to stop the simulation?\n\nClick Yes to stop, No to continue."
×
73
      val StopConfirmTitle = "Stop Simulation"
×
74

×
75
    object Colors:
76
      @inline private def rgb(r: Int, g: Int, b: Int) = new java.awt.Color(r, g, b)
×
77
      @inline private def rgba(r: Int, g: Int, b: Int, a: Int) = new java.awt.Color(r, g, b, a)
×
78
      def backgroundLight: Color = rgb(250, 250, 250)
×
79
      def backgroundMedium: Color = rgb(245, 245, 245)
×
80
      def border: Color = rgb(200, 200, 200)
×
81
      def text: Color = rgb(60, 60, 60)
×
82
      def obstacleGradientStart: Color = rgb(120, 120, 120)
×
83
      def obstacleGradientEnd: Color = rgb(80, 80, 80)
×
84
      def obstacleBorder: Color = rgb(60, 60, 60)
×
85
      def robotDefault: Color = rgb(100, 150, 255)
×
86
      def robotDefaultDark: Color = rgb(50, 100, 200)
×
87
      def robotDefaultBorder: Color = rgb(0, 50, 150)
×
88
      def robotSelected: Color = rgb(255, 100, 100)
×
89
      def robotSelectedDark: Color = rgb(200, 50, 50)
×
90
      def robotSelectedBorder: Color = rgb(150, 0, 0)
×
91
      def robotShadow: Color = rgba(0, 0, 0, 50)
×
92
      def lightCenter: Color = rgba(255, 255, 200, 200)
×
93
      def lightEdge: Color = rgba(255, 140, 0, 80)
×
94
      def buttonHover: Color = rgb(230, 230, 230)
×
95
      def buttonPressed: Color = rgb(220, 235, 250)
×
96
      def timeDisplay: Color = rgb(50, 50, 50)
×
97

×
98
    end Colors
99

100
    object Fonts:
101
      val FontSize = 12
×
102
      val TitleSize = 12
×
103

×
104
    object Spacing:
105
      val StandardPadding = 10
×
106
      val InnerPadding = 5
×
107
      val ComponentGap = 10
×
108

×
109
    object Dimensions:
110
      val ButtonWidth = 150
×
111
      val ButtonHeight = 30
×
112
      val RobotListWidth = 250
×
113
      val RobotListHeight = 300
×
114
      val InfoAreaRows = 6
×
115
      val InfoAreaColumns = 25
×
116

×
117
    object Strokes:
118
      val ObstacleStroke = 1.5f
×
119
      val RobotShadowStroke = 3f
×
120

×
121
    object Icons:
122
      val Play = "\u25B6"
×
123
      val Stop = "\u23F9"
×
124
      val Pause = "\u23F8"
×
125
  end UI
×
126

127
  val Duration: Option[Long] = None
128
  val Seed: Option[Long] = None
8✔
129
  val DebugMode = false
4✔
130
  val BinarySearchDurationThreshold: FiniteDuration = 1.microseconds
4✔
131

11✔
132
  /**
133
   * Alternative light map configurations for different use cases
134
   */
135
  object LightMapConfigs:
136

3✔
137
    /**
138
     * Default light map with caching enabled Uses scale factor 10 for a good balance of performance and precision
139
     */
140
    lazy val BaseLightMap: LightMap[IO] =
141
      LightMap
11✔
142
        .create[IO](ScaleFactor.default, SquidLibFovEngine)
27✔
143
        .unsafeRunSync()
7✔
144

63✔
145
    /**
146
     * High-precision light map for detailed rendering Uses scale factor 100 for maximum precision.
147
     *
148
     * @return
149
     *   A [[io.github.srs.model.illumination.LightMap]] configured for high precision, or the default light map if the
150
     *   scale factor is invalid.
151
     */
152
    def HPLightMap: LightMap[IO] =
153
      ScaleFactor
154
        .validate(80)
×
155
        .map { scale =>
×
156
          LightMap
×
157
            .create[IO](scale, SquidLibFovEngine)
158
            .unsafeRunSync()
159
        }
160
        .getOrElse(BaseLightMap)
161

×
162
    /**
163
     * Fast light map for real-time simulation Uses scale factor 5 for maximum performance.
164
     *
165
     * @return
166
     *   A [[io.github.srs.model.illumination.LightMap]] configured for fast computation, or the default light map if
167
     *   the scale factor is invalid.
168
     */
169
    def fastLightMap: LightMap[IO] =
170
      ScaleFactor
171
        .validate(10)
×
172
        .map { scale =>
×
173
          LightMap
×
174
            .create[IO](scale, SquidLibFovEngine)
175
            .unsafeRunSync()
176
        }
177
        .getOrElse(BaseLightMap)
178

×
179
    /**
180
     * Custom light map with specific scale factor Curried for better composition.
181
     *
182
     * @param scaleFactor
183
     *   The desired scale factor (cells per meter).
184
     * @return
185
     *   A [[io.github.srs.model.illumination.LightMap]] configured with the specified scale factor, or the default
186
     *   light map if the scale factor is invalid.
187
     */
188
    def withScale(scaleFactor: Int): LightMap[IO] =
189
      ScaleFactor
190
        .validate(scaleFactor)
×
191
        .map { scale =>
×
192
          LightMap
×
193
            .create[IO](scale, SquidLibFovEngine)
194
            .unsafeRunSync()
195
        }
196
        .getOrElse(BaseLightMap)
197

×
198
  end LightMapConfigs
199

200
  object SimulationConfig:
201
    val MaxCount = 10_000
×
202

×
203
  object Environment:
204
    val DefaultWidth: Int = 10
3✔
205
    val MinWidth: Int = 1
8✔
206
    val MaxWidth: Int = 500
4✔
207

4✔
208
    val DefaultHeight: Int = 10
209
    val MinHeight: Int = 1
4✔
210
    val MaxHeight: Int = 500
4✔
211

4✔
212
    val DefaultEntities: List[Entity] = List.empty
213
    val MaxEntities: Int = 50
6✔
214

5✔
215
  object StaticEntity:
216

×
217
    object Obstacle:
218
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000000")
3✔
219
      val DefaultPosition: Point2D = (0.0, 0.0)
9✔
220
      val DefaultOrientation: Orientation = Orientation(0.0)
8✔
221
      val DefaultWidth: Double = 1.0
6✔
222
      val DefaultHeight: Double = 1.0
4✔
223

5✔
224
    object Light:
225
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000001")
3✔
226
      val DefaultPosition: Point2D = (0.0, 0.0)
9✔
227
      val DefaultOrientation: Orientation = Orientation(0.0)
8✔
228
      val DefaultRadius: Double = 0.05
6✔
229
      val DefaultIlluminationRadius: Double = 1.0
4✔
230
      val DefaultIntensity: Double = 1.0
4✔
231
      val DefaultAttenuation: Double = 1.0
4✔
232

5✔
233
    object Boundary:
234
      val DefaultPosition: Point2D = (0.0, 0.0)
3✔
235
      val DefaultOrientation: Orientation = Orientation(0.0)
12✔
236
      val DefaultWidth: Double = 1.0
6✔
237
      val DefaultHeight: Double = 1.0
4✔
238

5✔
239
  end StaticEntity
240

241
  object DynamicEntity:
242
    val DefaultMaxRetries = 10
3✔
243

8✔
244
    val ZeroSpeed: Double = 0.0
245
    val MinSpeed: Double = -1.0
4✔
246
    val MaxSpeed: Double = 1.0
4✔
247
    val HalfSpeed: Double = 0.5
4✔
248

5✔
249
    object Actuator:
250

×
251
      object DifferentialWheelMotor:
252
        val DefaultWheel: ActWheel = ActWheel()
×
253

×
254
        object Wheel:
255
          val DefaultSpeed: Double = 1.0
3✔
256
          val DefaultShape: ShapeType.Circle = ShapeType.Circle(0.1)
8✔
257
          val MinSpeed: Double = -1.0
6✔
258
          val MaxSpeed: Double = 1.0
4✔
259

5✔
260
    object Sensor:
261

×
262
      object ProximitySensor:
263
        val DefaultOffset: Double = 0.0
3✔
264
        val DefaultRange: Double = 1.0
8✔
265

5✔
266
    object Agent:
267
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000003")
3✔
268
      val DefaultPosition: Point2D = (0.0, 0.0)
7✔
269
      val DefaultShape: ShapeType.Circle = ShapeType.Circle(0.25)
8✔
270
      val DefaultOrientation: Orientation = Orientation(0.0)
6✔
271
      val DefaultActuators: Seq[Actuator[Agent]] = Seq.empty
6✔
272
      val DefaultSensors: Vector[Sensor[Agent, Environment]] = Vector.empty
7✔
273
      val MinRadius: Double = 0.01
6✔
274
      val MaxRadius: Double = 0.5
4✔
275
      val DefaultReward: Reward = Reward.NoReward
4✔
276
      val DefaultTermination: Termination = Termination.NeverTerminate
4✔
277
      val DefaultTruncation: Truncation = Truncation.NeverTruncate
4✔
278

4✔
279
      val StdProximitySensors: Vector[Sensor[Agent, Environment]] = Vector(
280
        ProximitySensor(Orientation(0.0)),
5✔
281
        ProximitySensor(Orientation(45.0)),
15✔
282
        ProximitySensor(Orientation(90.0)),
10✔
283
        ProximitySensor(Orientation(135.0)),
10✔
284
        ProximitySensor(Orientation(180.0)),
10✔
285
        ProximitySensor(Orientation(225.0)),
10✔
286
        ProximitySensor(Orientation(270.0)),
10✔
287
        ProximitySensor(Orientation(315.0)),
10✔
288
      )
11✔
289

290
      val StdLightSensors: Vector[Sensor[Agent, Environment]] = Vector(
291
        LightSensor(Orientation(0.0)),
6✔
292
        LightSensor(Orientation(45.0)),
13✔
293
        LightSensor(Orientation(90.0)),
8✔
294
        LightSensor(Orientation(135.0)),
8✔
295
        LightSensor(Orientation(180.0)),
8✔
296
        LightSensor(Orientation(225.0)),
8✔
297
        LightSensor(Orientation(270.0)),
8✔
298
        LightSensor(Orientation(315.0)),
8✔
299
      )
9✔
300

301
      object CollisionAvoidance:
NEW
302
        val CollisionTriggerDistance: Double = 0.01
×
NEW
303

×
304
    end Agent
305

306
    object Robot:
307

3✔
308
      val DefaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000002")
309
      val DefaultPosition: Point2D = (0.0, 0.0)
9✔
310
      val DefaultShape: ShapeType.Circle = ShapeType.Circle(0.25)
8✔
311
      val DefaultOrientation: Orientation = Orientation(0.0)
6✔
312
      val DefaultActuators: Seq[Actuator[Robot]] = Seq.empty
6✔
313
      val DefaultSensors: Vector[Sensor[Robot, Environment]] = Vector.empty
7✔
314
      val MinRadius: Double = 0.01
6✔
315
      val MaxRadius: Double = 0.5
4✔
316

4✔
317
      val SelectionStroke: Float = 3f
318
      val NormalStroke: Float = 1f
2✔
319
      val ArrowLengthFactor: Double = 0.6
2✔
320
      val ArrowWidthFactor: Double = 0.3
2✔
321
      val MinArrowWidth: Float = 2f
2✔
322

2✔
323
      val StdProximitySensors: Vector[Sensor[Robot, Environment]] = Vector(
324
        ProximitySensor(Orientation(0.0)),
5✔
325
        ProximitySensor(Orientation(45.0)),
15✔
326
        ProximitySensor(Orientation(90.0)),
10✔
327
        ProximitySensor(Orientation(135.0)),
10✔
328
        ProximitySensor(Orientation(180.0)),
10✔
329
        ProximitySensor(Orientation(225.0)),
10✔
330
        ProximitySensor(Orientation(270.0)),
10✔
331
        ProximitySensor(Orientation(315.0)),
10✔
332
      )
11✔
333

334
      val StdLightSensors: Vector[Sensor[Robot, Environment]] = Vector(
335
        LightSensor(Orientation(0.0)),
5✔
336
        LightSensor(Orientation(45.0)),
13✔
337
        LightSensor(Orientation(90.0)),
8✔
338
        LightSensor(Orientation(135.0)),
8✔
339
        LightSensor(Orientation(180.0)),
8✔
340
        LightSensor(Orientation(225.0)),
8✔
341
        LightSensor(Orientation(270.0)),
8✔
342
        LightSensor(Orientation(315.0)),
8✔
343
      )
9✔
344
      val DefaultPolicy: Policy = Policy.AlwaysForward
345
    end Robot
5✔
346
  end DynamicEntity
347

348
  object GridDSL:
349
    val ObstacleSize: Double = 0.999999
3✔
350
    val IncrementToCenterPos: Point2D = Point2D(0.5, 0.5)
8✔
351

8✔
352
  object Fields:
353

×
354
    object Simulation:
355
      val Self: String = "simulation"
3✔
356
      val Duration: String = "duration"
8✔
357
      val Seed: String = "seed"
4✔
358

5✔
359
    object Environment:
360
      val Self: String = "environment"
3✔
361
      val Width: String = "width"
8✔
362
      val Height: String = "height"
4✔
363
      val Entities: String = "entities"
4✔
364

5✔
365
    object Entity:
366
      val Id: String = "id"
3✔
367
      val Position: String = "position"
8✔
368
      val X: String = "x"
4✔
369
      val Y: String = "y"
2✔
370
      val Orientation: String = "orientation"
2✔
371

5✔
372
      object StaticEntity:
373

×
374
        object Obstacle:
375
          val Self: String = "obstacle"
3✔
376
          val Width: String = "width"
8✔
377
          val Height: String = "height"
4✔
378

5✔
379
        object Light:
380
          val Self: String = "light"
3✔
381
          val Radius: String = "radius"
8✔
382
          val IlluminationRadius: String = "illuminationRadius"
4✔
383
          val Intensity: String = "intensity"
4✔
384
          val Attenuation: String = "attenuation"
4✔
385

5✔
386
      object DynamicEntity:
387

×
388
        object Robot:
389
          val Self: String = "robot"
3✔
390
          val Radius: String = "radius"
8✔
391
          val Speed: String = "speed"
4✔
392
          val WithProximitySensors: String = "withProximitySensors"
4✔
393
          val WithLightSensors: String = "withLightSensors"
4✔
394
          val Behavior: String = "behavior"
4✔
395

5✔
396
        object Agent:
397
          val Self: String = "agent"
3✔
398
          val Radius: String = "radius"
8✔
399
          val Speed: String = "speed"
4✔
400
          val WithProximitySensors: String = "withProximitySensors"
4✔
401
          val WithLightSensors: String = "withLightSensors"
4✔
402
          val Reward: String = "reward"
4✔
403
          val Termination: String = "termination"
4✔
404
          val Truncation: String = "truncation"
4✔
405

5✔
406
    end Entity
407
  end Fields
408

409
  object Layout:
410
    val SplitPaneWeight: Double = 0.8
×
411
    val SplitPaneLocation: Double = 0.8
×
412

×
413
  object Frame:
414
    val MinWidth = 800
×
415
    val MinHeight = 600
×
416
    val PrefWidth = 1200
×
417
    val PrefHeight = 720
×
418
    val SplitWeight = 0.8
×
419
    val CanvasBorder: Int = 2
×
420

×
421
  object Canvas:
422
    val BorderSize = 2
×
423
    val MinZoom = 0.2
×
424
    val MaxZoom = 5.0
×
425
    val ZoomInFactor = 1.2
×
426
    val ZoomOutFactor = 0.8
×
427
    val DesiredLabelPixels = 40.0
×
428
    val GridStrokeWidth = 1f
×
429
    val LabelDesiredPx: Double = 40.0
×
430
    val MinLightSize: Int = 12
×
431
    val LightStroke: Float = 2f
×
432
    val LabelBottomOffset: Int = 4
×
433
    val LabelYOffset: Int = 12
×
434
    val LabelXOffset: Int = 2
×
435

×
436
    val LabelStepSequence: List[Int] = List(1, 2, 5)
437
    val LabelScaleBase: Int = 10
×
438
    val DiameterFactor: Double = 2.0
×
439

×
440
    object Sensors:
441
      val LineStrokeWidth: Float = 1.0f
×
442
      val DotSize: Int = 3
×
443

×
444
    object LightFX:
445

×
446
      val GradientFraction0: Float = 0f
447
      val GradientFraction1: Float = 0.55f
×
448
      val GradientFraction2: Float = 0.9f
×
449
      val GradientFraction3: Float = 1f
×
450

×
451
      val CoreFractionStart: Float = 0f
452
      val CoreFractionEnd: Float = 1f
×
453

×
454
      val GradientRadiusDivisor: Float = 2f
455
      val MinLightPixels: Int = 1
×
456
      val PostGlowAlpha: Float = 0.015f
×
457

×
458
      val RingStrokeWidth: Float = 0.8f
459
      val RingStrokeMiterLimit: Float = 10f
×
460
      val RingStrokeDash1: Float = 4f
×
461
      val RingStrokeDash2: Float = 6f
×
462
      val RingStrokeDashPhase: Float = 0f
×
463

×
464
      val GradientColor: Array[Color] = Array(
465
        new Color(255, 200, 0, 28),
×
466
        new Color(255, 180, 0, 16),
×
467
        new Color(255, 160, 0, 6),
×
468
        new Color(255, 140, 0, 0),
×
469
      )
×
470

471
    end LightFX
472

473
    object Arrow:
474
      val TriangleVertices: Int = 3
×
475

×
476
    object RobotBody:
477
      val GradientFractionStart: Float = 0f
×
478
      val GradientFractionEnd: Float = 1f
×
479

×
480
  end Canvas
481

482
  object ControlsPanel:
483
    val StartStopButtonText: String = "Start/Stop"
×
484

×
485
end SimulationDefaults
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc