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

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

20 Oct 2025 10:09AM UTC coverage: 75.196% (-2.7%) from 77.925%
#699

Pull #113

github

sceredi
chore: fix metal only compiling protobuf project
Pull Request #113: feat: create reinforcement learning controller

49 of 129 new or added lines in 14 files covered. (37.98%)

6 existing lines in 3 files now uncovered.

1340 of 1782 relevant lines covered (75.2%)

8.42 hits per line

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

71.43
/src/main/scala/io/github/srs/controller/RLControllerModule.scala
1
package io.github.srs.controller
2

3
import cats.effect.unsafe.implicits.global
4
import io.github.srs.model.ModelModule
5
import io.github.srs.config.SimulationConfig
6
import io.github.srs.model.environment.ValidEnvironment
7
import io.github.srs.utils.random.RNG
8
import io.github.srs.model.entity.dynamicentity.DynamicEntity
9
import io.github.srs.model.entity.dynamicentity.action.Action
10
import cats.Id
11
import io.github.srs.model.Simulation.simulation
12
import io.github.srs.model.logic.RLLogicsBundle
13
import io.github.srs.model.entity.dynamicentity.sensor.SensorReadings
14
import io.github.srs.model.entity.dynamicentity.Robot
15
import io.github.srs.model.entity.dynamicentity.sensor.Sensor.senseAll
16
import io.github.srs.view.rendering.EnvironmentRenderer
17

18
object RLControllerModule:
NEW
19

×
20
  type Observations = Map[DynamicEntity, SensorReadings]
21
  type Infos = Map[DynamicEntity, String]
5✔
22

23
  /**
24
   * The resonse after each simulation step.
25
   */
26
  case class StepResponse private (
NEW
27
      observations: Observations,
×
NEW
28
      rewards: Map[DynamicEntity, Double],
×
NEW
29
      terminateds: Map[DynamicEntity, Boolean],
×
NEW
30
      truncateds: Map[DynamicEntity, Boolean],
×
NEW
31
      infos: Infos,
×
NEW
32
  )
×
33

34
  /**
35
   * Controller trait defines the interface for a Reinforcement Learning controller.
36
   */
37
  trait Controller[S <: ModelModule.BaseState]:
38

39
    type StepResponse
40

41
    /**
42
     * The type of the image used for rendering the simulation on the RL client.
43
     */
44
    type Image = Array[Byte]
45

46
    /**
47
     * The initial state of the controller.
48
     */
49
    def initialState: S
50

51
    /**
52
     * The current state of the controller.
53
     */
54
    def state: S
55

56
    /**
57
     * Initializes the controller with the given simulation configuration.
58
     *
59
     * @param config
60
     *   the simulation configuration to initialize the controller.
61
     */
62
    def init(config: SimulationConfig[ValidEnvironment]): Unit
63

64
    /**
65
     * Resets the controller to its initial state using the provided random number generator.
66
     *
67
     * @param rng
68
     *   the random number generator to use for reproducibility in the next run.
69
     */
70
    def reset(rng: RNG): (Observations, Infos)
71

72
    /**
73
     * Performs a simulation step using the provided actions for each agent.
74
     *
75
     * @param actions
76
     *   a map of agents to their corresponding actions to be performed in this step.
77
     * @return
78
     *   a response containing the results of the simulation step.
79
     */
80
    def step(actions: Map[DynamicEntity, Action[Id]]): StepResponse
81

82
    /**
83
     * Renders the current state of the simulation to an image for the RL client.
84
     *
85
     * @param width
86
     *   the width of the rendered image.
87
     * @param height
88
     *   the height of the rendered image.
89
     *
90
     * @return
91
     *   an image representing the current state of the simulation.
92
     */
93
    def render(width: Int, height: Int): Image
94
  end Controller
95

96
  trait Provider[S <: ModelModule.BaseState]:
97
    val controller: Controller[S]
98

99
  type Requirements[S <: ModelModule.BaseState] = ModelModule.Provider[S]
100

101
  trait Component[S <: ModelModule.BaseState]:
NEW
102
    context: Requirements[S] =>
×
103

104
    object Controller:
105
      def apply()(using bundle: RLLogicsBundle[S]): Controller[S] = new ControllerImpl
5✔
106

9✔
107
      private class ControllerImpl(using bundle: RLLogicsBundle[S]) extends Controller[S]:
108

8✔
109
        type StepResponse = String
110

111
        var _initialState: S =
112
          bundle.stateLogic.createState(SimulationConfig(simulation, ValidEnvironment.empty))
4✔
113

14✔
114
        var _state: S = initialState
115

12✔
116
        override def initialState: S = _initialState
117

3✔
118
        override def state: S = _state
119

3✔
120
        override def init(config: SimulationConfig[ValidEnvironment]): Unit =
121
          _initialState = bundle.stateLogic.createState(config)
122
          _state = _initialState
7✔
123

5✔
124
        override def reset(rng: RNG): (Observations, Infos) =
125
          _state = context.model.update(state)(using _ => bundle.stateLogic.updateState(initialState, rng))
126
          state.environment.entities.collect {
13✔
127
            // TODO: will be agent
12✔
128
            case r: Robot => (r, r.senseAll[Id](state.environment), "")
129
          }.map { case (robot, readings, info) =>
37✔
130
            (robot -> readings, robot -> info)
2✔
131
          }.unzip match
132
            case (obsList, infosList) => (obsList.toMap, infosList.toMap)
4✔
133

19✔
134
        override def step(actions: Map[DynamicEntity, Action[Id]]): StepResponse =
135
          _state = context.model.update(state)(using s => bundle.tickLogic.tick(s, state.dt)).unsafeRunSync()
136
          "Called step"
16✔
137

2✔
138
        override def render(width: Int, height: Int): Image =
139
          EnvironmentRenderer.renderToPNG(state.environment, width, height)
140
      end ControllerImpl
2✔
141
    end Controller
142
  end Component
143

144
  trait Interface[S <: ModelModule.BaseState] extends Provider[S] with Component[S]:
145
    self: Requirements[S] =>
146
end RLControllerModule
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