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

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

21 Oct 2025 07:59AM UTC coverage: 75.387% (-2.9%) from 78.302%
#725

Pull #113

github

sceredi
chore: generalize action proposals to dynamic entity
Pull Request #113: feat: create reinforcement learning controller

84 of 179 new or added lines in 20 files covered. (46.93%)

7 existing lines in 4 files now uncovered.

1461 of 1938 relevant lines covered (75.39%)

8.29 hits per line

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

75.76
/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.action.Action
9
import cats.Id
10
import io.github.srs.model.Simulation.simulation
11
import io.github.srs.model.logic.RLLogicsBundle
12
import io.github.srs.model.entity.dynamicentity.sensor.SensorReadings
13
import io.github.srs.model.entity.dynamicentity.sensor.Sensor.senseAll
14
import io.github.srs.view.rendering.EnvironmentRenderer
15
import io.github.srs.model.entity.dynamicentity.agent.Agent
16

17
object RLControllerModule:
NEW
18

×
19
  type Observations = Map[Agent, SensorReadings]
NEW
20
  type Infos = Map[Agent, String]
×
21

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

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

38
    /**
39
     * The type of the image used for rendering the simulation on the RL client.
40
     */
41
    type Image = Array[Byte]
42

43
    /**
44
     * The initial state of the controller.
45
     */
46
    def initialState: S
47

48
    /**
49
     * The current state of the controller.
50
     */
51
    def state: S
52

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

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

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

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

93
  trait Provider[S <: ModelModule.BaseState]:
94
    val controller: Controller[S]
95

96
  type Requirements[S <: ModelModule.BaseState] = ModelModule.Provider[S]
97

98
  trait Component[S <: ModelModule.BaseState]:
NEW
99
    context: Requirements[S] =>
×
100

101
    object Controller:
102
      def apply()(using bundle: RLLogicsBundle[S]): Controller[S] = new ControllerImpl
5✔
103

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

8✔
106
        var _initialState: S =
107
          bundle.stateLogic.createState(SimulationConfig(simulation, ValidEnvironment.empty))
4✔
108

14✔
109
        var _state: S = initialState
110

12✔
111
        override def initialState: S = _initialState
112

3✔
113
        override def state: S = _state
114

3✔
115
        override def init(config: SimulationConfig[ValidEnvironment]): Unit =
116
          _initialState = bundle.stateLogic.createState(config)
117
          _state = _initialState
7✔
118

5✔
119
        override def reset(rng: RNG): (Observations, Infos) =
120
          _state = context.model.update(state)(using _ => bundle.stateLogic.updateState(initialState, rng))
121
          state.environment.entities.collect { case a: Agent =>
13✔
122
            (a, a.senseAll[Id](state.environment), "")
17✔
123
          }.map { case (agent, readings, info) =>
9✔
124
            (agent -> readings, agent -> info)
2✔
125
          }.unzip match
126
            case (obsList, infosList) => (obsList.toMap, infosList.toMap)
4✔
127

19✔
128
        override def step(actions: Map[Agent, Action[Id]]): StepResponse =
129
          _state = context.model.update(state)(using s => bundle.tickLogic.tick(s, state.dt)).unsafeRunSync()
130
          StepResponse(
16✔
131
            observations = Map.empty,
1✔
132
            rewards = Map.empty,
3✔
133
            terminateds = Map.empty,
3✔
134
            truncateds = Map.empty,
3✔
135
            infos = Map.empty,
3✔
136
          )
5✔
137

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