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

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

04 Aug 2025 07:18PM UTC coverage: 87.129% (+1.6%) from 85.542%
#177

push

github

srs-mate
chore: remove comments

616 of 707 relevant lines covered (87.13%)

13.02 hits per line

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

92.0
/src/main/scala/io/github/srs/model/entity/dynamicentity/sensor/Sensor.scala
1
package io.github.srs.model.entity.dynamicentity.sensor
2

3
import cats.Monad
4
import cats.syntax.all.*
5
import io.github.srs.model.PositiveDouble
6
import io.github.srs.model.entity.dynamicentity.{ DynamicEntity, Robot }
7
import io.github.srs.model.entity.{ Orientation, Point2D }
8
import io.github.srs.model.environment.Environment
9
import io.github.srs.model.validation.Validation
10
import io.github.srs.utils.Ray.intersectRay
11

12
/**
13
 * Represents the range of a sensor.
14
 */
15
type Range = Double
16

×
17
/**
18
 * Represents the distance from the center of a dynamic entity to a sensor.
19
 */
20
type Distance = Double
21

22
/**
23
 * Represents a sensor that can sense the environment for a dynamic entity.
24
 * @tparam Entity
25
 *   the type of dynamic entity that the sensor can act upon.
26
 * @tparam Env
27
 *   the type of environment in which the sensor operates.
28
 */
29
trait Sensor[-Entity <: DynamicEntity, -Env <: Environment]:
30
  /**
31
   * The type of data that the sensor returns. This type can vary based on the specific sensor implementation.
32
   */
33
  type Data
34

35
  /**
36
   * The offset orientation of the sensor relative to the entity's orientation.
37
   * @return
38
   *   the orientation offset of the sensor.
39
   */
40
  def offset: Orientation
41

42
  /**
43
   * The distance from the center of the entity to the sensor.
44
   * @return
45
   *   the distance of the sensor from the entity's center.
46
   */
47
  def distance: Distance
48

49
  /**
50
   * The range of the sensor, which defines how far it can sense.
51
   * @note
52
   *   The range is typically a positive value that indicates the maximum distance the sensor can detect.
53
   * @return
54
   *   the range of the sensor.
55
   */
56
  def range: Range
57

58
  /**
59
   * Senses the environment for the given entity and returns the data collected by the sensor.
60
   * @param entity
61
   *   the dynamic entity that the sensor is attached to.
62
   * @param env
63
   *   the environment in which the sensor operates.
64
   * @param x$3
65
   *   the implicit Monad instance for the effect type `F`.
66
   * @tparam F
67
   *   the effect type in which the sensing operation is performed.
68
   * @return
69
   *   a monadic effect containing the data sensed by the sensor.
70
   */
71
  def sense[F[_]](entity: Entity, env: Env)(using Monad[F]): F[Data]
72
end Sensor
73

74
/**
75
 * Represents a reading from a sensor. This case class encapsulates the sensor and the value it has sensed.
76
 * @param sensor
77
 *   the sensor that has taken the reading.
78
 * @param value
79
 *   the value sensed by the sensor.
80
 * @tparam S
81
 *   the type of sensor, which is a subtype of [[Sensor]].
82
 * @tparam A
83
 *   the type of data sensed by the sensor.
84
 */
85
final case class SensorReading[S <: Sensor[?, ?], A](sensor: S, value: A)
86

60✔
87
/**
88
 * A collection of sensor readings. This type is used to represent multiple sensor readings from a dynamic entity. It is
89
 * a vector of [[SensorReading]] instances, allowing for efficient access and manipulation of sensor data.
90
 */
91
type SensorReadings = Vector[SensorReading[? <: Sensor[?, ?], ?]]
92

93
/**
94
 * A proximity sensor that can sense the distance to other entities in the environment. It calculates the distance to
95
 * the nearest entity within its range and returns a normalized value. The value is normalized to a range between 0.0
96
 * (closest) and 1.0 (farthest).
97
 * @param offset
98
 *   the offset orientation of the sensor relative to the entity's orientation.
99
 * @param distance
100
 *   the distance from the center of the entity to the sensor.
101
 * @param range
102
 *   the range of the sensor, which defines how far it can sense.
103
 * @tparam Entity
104
 *   the type of dynamic entity that the sensor can act upon.
105
 * @tparam Env
106
 *   the type of environment in which the sensor operates.
107
 */
108
final case class ProximitySensor[Entity <: DynamicEntity, Env <: Environment](
109
    offset: Orientation,
80✔
110
    distance: Distance,
3✔
111
    range: Range,
3✔
112
) extends Sensor[Entity, Env]:
3✔
113

114
  override type Data = Double
115

116
  override def sense[F[_]](entity: Entity, env: Env)(using Monad[F]): F[Data] =
117
    import Point2D.*
4✔
118
    val globalOrientation = entity.orientation.toRadians + offset.toRadians
119
    val direction = Point2D(math.cos(globalOrientation), -math.sin(globalOrientation))
20✔
120
    val origin = entity.position + direction * distance
26✔
121
    val end = origin + direction * range
26✔
122

19✔
123
    val distances = env.entities
124
      .filter(!_.equals(entity))
5✔
125
      .flatMap(intersectRay(_, origin, end))
7✔
126
      .filter(_ <= range)
8✔
127

8✔
128
    summon[Monad[F]].pure(distances.minOption.map(_ / range).getOrElse(1.0))
129

35✔
130
end ProximitySensor
131

132
object Sensor:
133

×
134
  extension [E <: DynamicEntity, Env <: Environment](s: Sensor[E, Env])
135

5✔
136
    /**
137
     * Validates the properties of a sensor.
138
     */
139
    def validate: Validation[Sensor[E, Env]] =
140
      for
4✔
141
        _ <- PositiveDouble(s.distance).validate
1✔
142
        _ <- PositiveDouble(s.range).validate
26✔
143
      yield s
144

3✔
145
  extension (r: Robot)
146

147
    /**
148
     * Senses all sensors of the robot in the given environment.
149
     * @param env
150
     *   the environment in which to sense.
151
     * @return
152
     *   a vector of sensor readings.
153
     */
154
    def senseAll[F[_]: Monad](env: Environment): F[SensorReadings] =
155
      r.sensors.traverse: sensor =>
4✔
156
        sensor.sense(r, env).map(reading => SensorReading(sensor, reading))
17✔
157
end Sensor
6✔
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