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

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

21 Oct 2025 08:15AM UTC coverage: 75.283% (-3.0%) from 78.302%
#726

Pull #113

github

sceredi
chore: create dynamic entity actions logic for base simulation state
Pull Request #113: feat: create reinforcement learning controller

107 of 209 new or added lines in 20 files covered. (51.2%)

7 existing lines in 4 files now uncovered.

1462 of 1942 relevant lines covered (75.28%)

8.29 hits per line

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

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

3
import scala.annotation.unused
4

5
import cats.effect.unsafe.implicits.global
6
import io.github.srs.model.ModelModule
7
import io.github.srs.config.SimulationConfig
8
import io.github.srs.model.environment.ValidEnvironment
9
import io.github.srs.utils.random.RNG
10
import io.github.srs.model.entity.dynamicentity.action.Action
11
import cats.Id
12
import io.github.srs.model.Simulation.simulation
13
import io.github.srs.model.logic.RLLogicsBundle
14
import io.github.srs.model.entity.dynamicentity.sensor.SensorReadings
15
import io.github.srs.model.entity.dynamicentity.sensor.Sensor.senseAll
16
import io.github.srs.view.rendering.EnvironmentRenderer
17
import io.github.srs.model.entity.dynamicentity.agent.Agent
18
import io.github.srs.controller.message.DynamicEntityProposal
19
import cats.effect.IO
20

21
object RLControllerModule:
NEW
22

×
23
  type Observations = Map[Agent, SensorReadings]
NEW
24
  type Infos = Map[Agent, String]
×
25

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

37
  /**
38
   * Controller trait defines the interface for a Reinforcement Learning controller.
39
   */
40
  trait Controller[S <: ModelModule.BaseState]:
41

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

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

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

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

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

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

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

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

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

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

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

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

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

14✔
113
        var _state: S = initialState
114

12✔
115
        override def initialState: S = _initialState
116

3✔
117
        override def state: S = _state
118

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

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

19✔
132
        override def step(actions: Map[Agent, Action[IO]]): StepResponse =
133
          _state = context.model.update(state)(using s => bundle.tickLogic.tick(s, state.dt)).unsafeRunSync()
134
          @unused val actionsList =
16✔
135
            actions.map { (agent, action) => DynamicEntityProposal(agent, action) }.toList.sortBy(_.entity.id)
136
          StepResponse(
13✔
137
            observations = Map.empty,
1✔
138
            rewards = Map.empty,
3✔
139
            terminateds = Map.empty,
3✔
140
            truncateds = Map.empty,
3✔
141
            infos = Map.empty,
3✔
142
          )
5✔
143

144
        override def render(width: Int, height: Int): Image =
145
          EnvironmentRenderer.renderToPNG(state.environment, width, height)
146
      end ControllerImpl
2✔
147
    end Controller
148
  end Component
149

150
  trait Interface[S <: ModelModule.BaseState] extends Provider[S] with Component[S]:
151
    self: Requirements[S] =>
152
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