32 static geom::Location Rotate(
float yaw,
const geom::Location &location) {
34 yaw *= geom::Math::Pi<float>() / 180.0f;
35 const float c = std::cos(yaw);
36 const float s = std::sin(yaw);
40 c * location.x - s * location.y,
41 s * location.x + c * location.y,
49 class LaneInvasionCallback {
60 Sensor::CallbackFunctionType &&user_callback)
61 : _parent(vehicle.GetId()),
62 _parent_bounding_box(vehicle.GetBoundingBox()),
64 _callback(
std::move(user_callback)) {
68 void Tick(
const WorldSnapshot &snapshot)
const;
75 std::array<geom::Location, 4u> corners;
78 std::shared_ptr<const Bounds> MakeBounds(
80 const geom::Transform &vehicle_transform)
const;
84 geom::BoundingBox _parent_bounding_box;
86 SharedPtr<const Map> _map;
88 Sensor::CallbackFunctionType _callback;
90 mutable AtomicSharedPtr<const Bounds> _bounds;
93 void LaneInvasionCallback::Tick(
const WorldSnapshot &snapshot)
const {
95 auto parent = snapshot.Find(_parent);
101 auto next = MakeBounds(snapshot.GetFrame(), parent->transform);
102 auto prev = _bounds.load();
105 if ((prev ==
nullptr) && _bounds.compare_exchange(&prev, next)) {
111 constexpr float distance_threshold = 10.0f * std::numeric_limits<float>::epsilon();
112 for (
auto i = 0u; i < 4u; ++i) {
113 if ((next->corners[i] - prev->corners[i]).Length() < distance_threshold) {
121 if (prev->frame >= next->frame) {
124 }
while (!_bounds.compare_exchange(&prev, next));
127 std::vector<road::element::LaneMarking> crossed_lanes;
128 for (
auto i = 0u; i < 4u; ++i) {
130 const auto lanes = _map->CalculateCrossedLanes(prev->corners[i], next->corners[i]);
131 crossed_lanes.insert(crossed_lanes.end(), lanes.begin(), lanes.end());
135 if (!crossed_lanes.empty()) {
136 if (!crossed_lanes.empty()) {
137 _callback(MakeShared<sensor::data::LaneInvasionEvent>(
138 snapshot.GetTimestamp().frame,
139 snapshot.GetTimestamp().elapsed_seconds,
142 std::move(crossed_lanes)));
146 std::shared_ptr<const LaneInvasionCallback::Bounds> LaneInvasionCallback::MakeBounds(
148 const geom::Transform &transform)
const {
149 const auto &box = _parent_bounding_box;
150 const auto location = transform.location + box.location;
151 const auto yaw = transform.rotation.yaw;
154 return std::make_shared<Bounds>(Bounds{frame, {
155 location + Rotate(yaw, geom::Location( box.extent.x, box.extent.y, 0.0f)),
156 location + Rotate(yaw, geom::Location(-box.extent.x, box.extent.y, 0.0f)),
157 location + Rotate(yaw, geom::Location( box.extent.x, -box.extent.y, 0.0f)),
158 location + Rotate(yaw, geom::Location(-box.extent.x, -box.extent.y, 0.0f))}});
174 auto vehicle = boost::dynamic_pointer_cast<Vehicle>(
GetParent());
175 if (vehicle ==
nullptr) {
182 auto cb = std::make_shared<LaneInvasionCallback>(
184 episode->GetCurrentMap(),
185 std::move(callback));
189 const size_t callback_id = episode->RegisterOnTickEvent([cb=std::move(cb)](
const auto &snapshot) {
192 }
catch (
const std::exception &e) {
193 log_error(
"LaneInvasionSensor:", e.what());
197 const size_t previous =
_callback_id.exchange(callback_id);
198 if (previous != 0u) {
200 episode->RemoveOnTickEvent(previous);
207 if ((previous != 0u) && (episode !=
nullptr)) {
208 episode->RemoveOnTickEvent(previous);
#define DEBUG_ASSERT(predicate)
包含LaneInvasionSensor类的声明,这是一个继承自ClientSideSensor的类,用于检测车辆压线。
std::atomic_size_t _callback_id
原子性的回调ID,用于标识当前设置的回调。 当_callback_id不为0时,表示正在监听。
~LaneInvasionSensor()
析构函数,用于清理LaneInvasionSensor对象。
void Stop() override
停止监听新的车辆压线测量结果。
void Listen(CallbackFunctionType callback) override
注册一个回调,每次收到新的车辆压线测量值时执行。
EpisodeProxy & GetEpisode()
SharedPtr< Actor > GetParent() const
const std::string & GetDisplayId() const
SharedPtrType TryLock() const noexcept
SharedPtrType Lock() const
与 TryLock 相同,但永远不会返回 nullptr。
static void log_error(Args &&... args)