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

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

28 Aug 2025 02:16PM UTC coverage: 47.411% (+0.5%) from 46.919%
#424

Pull #67

github

sceredi
chore: update default robot size and sensor range
Pull Request #67: feat(obstacleAvoidance): implement obstacle avoidance behavior in policy

67 of 93 new or added lines in 10 files covered. (72.04%)

2 existing lines in 1 file now uncovered.

1282 of 2704 relevant lines covered (47.41%)

6.71 hits per line

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

57.32
/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.unsafe.implicits.global
9
import io.github.srs.model.entity.*
10
import io.github.srs.model.entity.dynamicentity.Robot
11
import io.github.srs.model.entity.dynamicentity.actuator.{ Actuator, Wheel as ActWheel }
12
import io.github.srs.model.entity.dynamicentity.behavior.Policy
13
import io.github.srs.model.entity.dynamicentity.sensor.*
14
import io.github.srs.model.environment.Environment
15
import cats.effect.IO
16
import io.github.srs.model.illumination.LightMap
17
import io.github.srs.model.illumination.engine.SquidLibFovEngine
18
import io.github.srs.model.illumination.model.ScaleFactor
19

20
object SimulationDefaults:
21

×
22
  object Illumination:
23

3✔
24
    val GridThreshold = 10_000
25
    val LightThreshold = 2
8✔
26

5✔
27
    object Occlusion:
28
      val FullRotation: Double = 90.0
3✔
29
      val AlmostZero: Double = 1e-6
8✔
30

5✔
31
  object Behaviors:
NEW
32

×
33
    object ObstacleAvoidance:
34
      val CruiseSpeed: Double = 0.35
3✔
35
      val WarnSpeed: Double = 0.15
8✔
36
      val WarnTurnSpeed: Double = 0.55
2✔
37
      val BackBoost: Double = 0.20
2✔
38
      val SafeDist: Double = 0.5
4✔
39
      val CriticalDist: Double = 0.35
4✔
40

5✔
41
    object RandomWalk:
42
      val MinForwardFactor: Double = 0.35
3✔
43
      val MaxForwardExtra: Double = 0.35
8✔
44
      val MinTurnOfBase: Double = 0.35
4✔
45
      val MaxTurnOfBase: Double = 1.15
4✔
46
      val TurnExponent: Double = 1.2
4✔
47
      val PivotBoostProb: Double = 0.20
4✔
48
      val PivotBoostAbs: Double = 0.15
4✔
49

5✔
50
  object UI:
51

×
52
    object SimulationViewConstants:
53
      val IdDisplayLength = 8
×
54
      val PositionDecimals = 2
×
55
      val OrientationDecimals = 1
×
56
      val DefaultRobotInfo = "Select a robot to view details"
×
57
      val StopConfirmMessage = "Are you sure you want to stop the simulation?\n\nClick Yes to stop, No to continue."
×
58
      val StopConfirmTitle = "Stop Simulation"
×
59

×
60
    object Colors:
61
      @inline private def rgb(r: Int, g: Int, b: Int) = new java.awt.Color(r, g, b)
×
62
      @inline private def rgba(r: Int, g: Int, b: Int, a: Int) = new java.awt.Color(r, g, b, a)
×
63
      def backgroundLight: Color = rgb(250, 250, 250)
×
64
      def backgroundMedium: Color = rgb(245, 245, 245)
×
65
      def border: Color = rgb(200, 200, 200)
×
66
      def text: Color = rgb(60, 60, 60)
×
67
      def obstacleGradientStart: Color = rgb(120, 120, 120)
×
68
      def obstacleGradientEnd: Color = rgb(80, 80, 80)
×
69
      def obstacleBorder: Color = rgb(60, 60, 60)
×
70
      def robotDefault: Color = rgb(100, 150, 255)
×
71
      def robotDefaultDark: Color = rgb(50, 100, 200)
×
72
      def robotDefaultBorder: Color = rgb(0, 50, 150)
×
73
      def robotSelected: Color = rgb(255, 100, 100)
×
74
      def robotSelectedDark: Color = rgb(200, 50, 50)
×
75
      def robotSelectedBorder: Color = rgb(150, 0, 0)
×
76
      def robotShadow: Color = rgba(0, 0, 0, 50)
×
77
      def lightCenter: Color = rgba(255, 255, 200, 200)
×
78
      def lightEdge: Color = rgba(255, 140, 0, 80)
×
79
      def buttonHover: Color = rgb(230, 230, 230)
×
80
      def buttonPressed: Color = rgb(220, 235, 250)
×
81
      def timeDisplay: Color = rgb(50, 50, 50)
×
82

×
83
    end Colors
84

85
    object Fonts:
86
      val fontSize = 12
×
87
      val titleSize = 12
×
88

×
89
    object Spacing:
90
      val standardPadding = 10
×
91
      val innerPadding = 5
×
92
      val componentGap = 10
×
93

×
94
    object Dimensions:
95
      val buttonWidth = 150
×
96
      val buttonHeight = 30
×
97
      val robotListWidth = 250
×
98
      val robotListHeight = 300
×
99
      val infoAreaRows = 6
×
100
      val infoAreaColumns = 25
×
101

×
102
    object Strokes:
103
      val obstacleStroke = 1.5f
×
104
      val robotShadowStroke = 3f
×
105

×
106
    object Icons:
107
      val play = "\u25B6"
×
108
      val stop = "\u23F9"
×
109
      val pause = "\u23F8"
×
110
  end UI
×
111

112
  val duration: Option[Long] = None
113
  val seed: Option[Long] = None
8✔
114
  val debugMode = true
4✔
115
  val binarySearchDurationThreshold: FiniteDuration = 1.microseconds
2✔
116

13✔
117
  /**
118
   * Alternative light map configurations for different use cases
119
   */
120
  object LightMapConfigs:
121

3✔
122
    /**
123
     * Default light map with caching enabled Uses scale factor 10 for a good balance of performance and precision
124
     */
125
    lazy val baseLightMap: LightMap[IO] =
126
      LightMap
11✔
127
        .create[IO](ScaleFactor.default, SquidLibFovEngine)
30✔
128
        .unsafeRunSync()
19✔
129

68✔
130
    /**
131
     * High-precision light map for detailed rendering Uses scale factor 100 for maximum precision.
132
     *
133
     * @return
134
     *   A [[LightMap]] configured for high precision, or the default light map if the scale factor is invalid.
135
     */
136
    def HPLightMap: LightMap[IO] =
137
      ScaleFactor
×
138
        .validate(80)
×
139
        .map { scale =>
×
140
          LightMap
×
141
            .create[IO](scale, SquidLibFovEngine)
142
            .unsafeRunSync()
143
        }
144
        .getOrElse(baseLightMap)
×
145

×
146
    /**
147
     * Fast light map for real-time simulation Uses scale factor 5 for maximum performance.
148
     *
149
     * @return
150
     *   A [[LightMap]] configured for fast computation, or the default light map if the scale factor is invalid.
151
     */
152
    def fastLightMap: LightMap[IO] =
153
      ScaleFactor
×
154
        .validate(10)
×
155
        .map { scale =>
×
156
          LightMap
×
157
            .create[IO](scale, SquidLibFovEngine)
158
            .unsafeRunSync()
159
        }
160
        .getOrElse(baseLightMap)
×
161

×
162
    /**
163
     * Custom light map with specific scale factor Curried for better composition.
164
     *
165
     * @param scaleFactor
166
     *   The desired scale factor (cells per meter).
167
     * @return
168
     *   A [[LightMap]] configured with the specified scale factor, or the default light map if the scale factor is
169
     *   invalid.
170
     */
171
    def withScale(scaleFactor: Int): LightMap[IO] =
172
      ScaleFactor
×
173
        .validate(scaleFactor)
×
174
        .map { scale =>
×
175
          LightMap
×
176
            .create[IO](scale, SquidLibFovEngine)
177
            .unsafeRunSync()
178
        }
179
        .getOrElse(baseLightMap)
×
180

×
181
  end LightMapConfigs
182

183
  object SimulationConfig:
184
    val maxCount = 10_000
×
185

×
186
  object Environment:
187
    val defaultWidth: Int = 10
3✔
188
    val minWidth: Int = 1
8✔
189
    val maxWidth: Int = 500
4✔
190

4✔
191
    val defaultHeight: Int = 10
192
    val minHeight: Int = 1
4✔
193
    val maxHeight: Int = 500
4✔
194

4✔
195
    val defaultEntities: Set[Entity] = Set.empty
196
    val maxEntities: Int = 200
10✔
197

5✔
198
  object StaticEntity:
199

×
200
    object Obstacle:
201
      val defaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000000")
3✔
202
      val defaultPosition: Point2D = (0.0, 0.0)
13✔
203
      val defaultOrientation: Orientation = Orientation(0.0)
8✔
204
      val defaultWidth: Double = 1.0
10✔
205
      val defaultHeight: Double = 1.0
4✔
206

5✔
207
    object Light:
208
      val defaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000001")
3✔
209
      val defaultPosition: Point2D = (0.0, 0.0)
13✔
210
      val defaultOrientation: Orientation = Orientation(0.0)
8✔
211
      val defaultRadius: Double = 0.05
10✔
212
      val defaultIlluminationRadius: Double = 1.0
4✔
213
      val defaultIntensity: Double = 1.0
4✔
214
      val defaultAttenuation: Double = 1.0
4✔
215

5✔
216
    object Boundary:
217
      val defaultPosition: Point2D = (0.0, 0.0)
3✔
218
      val defaultOrientation: Orientation = Orientation(0.0)
12✔
219
      val defaultWidth: Double = 1.0
10✔
220
      val defaultHeight: Double = 1.0
4✔
221

5✔
222
  end StaticEntity
223

224
  object DynamicEntity:
225
    val zeroSpeed: Double = 0.0
3✔
226
    val MinSpeed: Double = -1.0
8✔
227
    val MaxSpeed: Double = 1.0
4✔
228
    val halfSpeed: Double = 0.5
4✔
229

5✔
230
    object Actuator:
231

×
232
      object DifferentialWheelMotor:
233
        val defaultWheel: ActWheel = ActWheel()
3✔
234

22✔
235
        object Wheel:
236
          val defaultSpeed: Double = 1.0
3✔
237
          val defaultShape: ShapeType.Circle = ShapeType.Circle(0.1)
8✔
238
          val MinSpeed: Double = -1.0
6✔
239
          val MaxSpeed: Double = 1.0
4✔
240

5✔
241
    object Sensor:
242

×
243
      object ProximitySensor:
244
        val DefaultOffset: Double = 0.0
3✔
245
        val DefaultRange: Double = 1.0
8✔
246

5✔
247
    object Robot:
248

3✔
249
      val defaultMaxRetries = 10
250

6✔
251
      val defaultId: UUID = UUID.fromString("00000000-0000-0000-0000-000000000002")
252
      val defaultPosition: Point2D = (0.0, 0.0)
9✔
253
      val defaultShape: ShapeType.Circle = ShapeType.Circle(0.25)
8✔
254
      val defaultOrientation: Orientation = Orientation(0.0)
6✔
255
      val defaultActuators: Seq[Actuator[Robot]] = Seq.empty
10✔
256
      val defaultSensors: Vector[Sensor[Robot, Environment]] = Vector.empty
11✔
257
      val MinRadius: Double = 0.01
10✔
258
      val MaxRadius: Double = 0.5
4✔
259

4✔
260
      val selectionStroke: Float = 3f
261
      val normalStroke: Float = 1f
2✔
262
      val arrowLengthFactor: Double = 0.6
2✔
263
      val arrowWidthFactor: Double = 0.3
2✔
264
      val minArrowWidth: Float = 2f
2✔
265

2✔
266
      val stdProximitySensors: Vector[Sensor[Robot, Environment]] = Vector(
267
        ProximitySensor(Orientation(0.0)),
6✔
268
        ProximitySensor(Orientation(45.0)),
26✔
269
        ProximitySensor(Orientation(90.0)),
18✔
270
        ProximitySensor(Orientation(135.0)),
18✔
271
        ProximitySensor(Orientation(180.0)),
18✔
272
        ProximitySensor(Orientation(225.0)),
18✔
273
        ProximitySensor(Orientation(270.0)),
18✔
274
        ProximitySensor(Orientation(315.0)),
18✔
275
      )
18✔
276

3✔
277
      val stdLightSensors: Vector[Sensor[Robot, Environment]] = Vector(
278
        LightSensor(Orientation(0.0)),
6✔
279
        LightSensor(Orientation(45.0)),
20✔
280
        LightSensor(Orientation(90.0)),
12✔
281
        LightSensor(Orientation(135.0)),
12✔
282
        LightSensor(Orientation(180.0)),
12✔
283
        LightSensor(Orientation(225.0)),
12✔
284
        LightSensor(Orientation(270.0)),
12✔
285
        LightSensor(Orientation(315.0)),
12✔
286
      )
12✔
287
      val defaultPolicy: Policy = Policy.AlwaysForward
3✔
288
    end Robot
5✔
289
  end DynamicEntity
290

291
  object Fields:
292

×
293
    object Simulation:
294
      val self: String = "simulation"
3✔
295
      val duration: String = "duration"
8✔
296
      val seed: String = "seed"
4✔
297

5✔
298
    object Environment:
299
      val self: String = "environment"
3✔
300
      val width: String = "width"
8✔
301
      val height: String = "height"
4✔
302
      val entities: String = "entities"
4✔
303

5✔
304
    object Entity:
305
      val id: String = "id"
3✔
306
      val position: String = "position"
8✔
307
      val x: String = "x"
4✔
308
      val y: String = "y"
2✔
309
      val orientation: String = "orientation"
2✔
310

5✔
311
      object StaticEntity:
312

×
313
        object Obstacle:
314
          val self: String = "obstacle"
3✔
315
          val width: String = "width"
8✔
316
          val height: String = "height"
4✔
317

5✔
318
        object Light:
319
          val self: String = "light"
3✔
320
          val radius: String = "radius"
8✔
321
          val illuminationRadius: String = "illuminationRadius"
4✔
322
          val intensity: String = "intensity"
4✔
323
          val attenuation: String = "attenuation"
4✔
324

5✔
325
      object DynamicEntity:
326

×
327
        object Robot:
328
          val self: String = "robot"
3✔
329
          val radius: String = "radius"
8✔
330
          val speed: String = "speed"
4✔
331
          val withProximitySensors: String = "withProximitySensors"
4✔
332
          val withLightSensors: String = "withLightSensors"
4✔
333
          val behavior: String = "behavior"
4✔
334
    end Entity
5✔
335
  end Fields
336

337
  object Layout:
338
    val splitPaneWeight: Double = 0.8
×
339
    val splitPaneLocation: Double = 0.8
×
340

×
341
  object Frame:
342
    val minWidth = 800
×
343
    val minHeight = 600
×
344
    val prefWidth = 1200
×
345
    val prefHeight = 720
×
346
    val splitWeight = 0.8
×
347
    val canvasBorder: Int = 2
×
348

×
349
  object Canvas:
350
    val borderSize = 2
×
351
    val minZoom = 0.2
×
352
    val maxZoom = 5.0
×
353
    val zoomInFactor = 1.2
×
354
    val zoomOutFactor = 0.8
×
355
    val desiredLabelPixels = 40.0
×
356
    val gridStrokeWidth = 1f
×
357
    val labelDesiredPx: Double = 40.0
×
358
    val minLightSize: Int = 12
×
359
    val lightStroke: Float = 2f
×
360
    val labelBottomOffset: Int = 4
×
361
    val labelYOffset: Int = 12
×
362
    val labelXOffset: Int = 2
×
363

×
364
  object ControlsPanel:
365
    val startStopButtonText: String = "Start/Stop"
×
366

×
367
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