Carma-platform v4.2.0
CARMA Platform is built on robot operating system (ROS) and utilizes open source software (OSS) that enables Cooperative Driving Automation (CDA) features to allow Automated Driving Systems to interact and cooperate with infrastructure and other vehicles through communication.
GeofenceSchedule.cpp
Go to the documentation of this file.
1/*
2 * Copyright (C) 2022 LEIDOS.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5 * use this file except in compliance with the License. You may obtain a copy of
6 * the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations under
14 * the License.
15 */
16
18#include <boost/date_time/posix_time/posix_time.hpp>
19
20namespace carma_wm_ctrl
21{
23{
24}
25
26GeofenceSchedule::GeofenceSchedule(rclcpp::Time schedule_start, rclcpp::Time schedule_end, rclcpp::Duration control_start,
27 rclcpp::Duration control_duration, rclcpp::Duration control_offset,
28 rclcpp::Duration control_span, rclcpp::Duration control_period, DayOfTheWeekSet week_day_set):
29 schedule_start_(schedule_start), schedule_end_(schedule_end),
30 control_start_ (control_start), control_duration_ (control_duration),
31 control_offset_ (control_offset), control_span_ (control_span), control_period_ (control_period), week_day_set_(week_day_set)
32{}
33
34bool GeofenceSchedule::scheduleExpired(const rclcpp::Time& time) const
35{
36 return schedule_end_ < time;
37}
38
39bool GeofenceSchedule::scheduleStarted(const rclcpp::Time& time) const
40{
41 return schedule_start_ <= time;
42}
43
44// returns rclcpp::Time(0) when the schedule is expired or the next interval will be on a different day of the week
45// Argument provided as absolute time (since 1970)
46std::pair<bool, rclcpp::Time> GeofenceSchedule::getNextInterval(const rclcpp::Time& time) const
47{
48 auto clock_type = time.get_clock_type();
49 if (scheduleExpired(time))
50 {
51 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm_ctrl"), "Geofence schedule expired");
52 return std::make_pair(false, rclcpp::Time(0, 0, clock_type)); // If the schedule has expired or was never started
53 }
54
55 boost::posix_time::ptime boost_time = boost::posix_time::from_time_t(time.seconds());
56 boost_time += boost::posix_time::microseconds((int)((time.seconds()-std::floor(time.seconds()))*1e6));
57 boost::gregorian::date date = boost_time.date();
58
59 if (week_day_set_.find(date.day_of_week()) == week_day_set_.end())
60 {
61 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm_ctrl"), "Geofence wrong day of the week");
62 return std::make_pair(false, rclcpp::Time(0, 0, clock_type)); // This geofence is not active on this day
63 }
64
65 auto time_of_day = boost_time.time_of_day();
66
67
68 // Convert schedule into workable components
69 boost::posix_time::ptime ptime_start_of_day(date, boost::posix_time::hours(0)); // Get absolute start time of the day
70
71 rclcpp::Time ros_time_of_day = rclcpp::Time(lanelet::time::toSec(time_of_day) * 1e9, clock_type);
72
73 rclcpp::Time abs_day_start = rclcpp::Time(lanelet::time::toSec(ptime_start_of_day) * 1e9, clock_type);
74 rclcpp::Duration cur_start = control_start_ + control_offset_; // accounting for the shift of repetition start
75
76 // Check if current time is after end of control
77 if (ros_time_of_day > rclcpp::Time((control_start_ + control_duration_).nanoseconds(), clock_type))
78 {
79 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm_ctrl"), "Geofence schedule too late in the day");
80 // The requested time is after control end so there will not be another interval
81 return std::make_pair(false, rclcpp::Time(0, 0, clock_type));
82 }
83
84 // Iterate over the day to find the next control interval
85 constexpr int num_sec_in_day = 86400;
86 const rclcpp::Duration full_day(num_sec_in_day* 1e9);
87 bool time_in_active_period = false; // Flag indicating if the requested time is within an active control span
88
89 while (cur_start < full_day && ros_time_of_day > rclcpp::Time(cur_start.nanoseconds(), clock_type))
90 {
91 // Check if the requested time is within the control period being evaluated
92 if (rclcpp::Time(cur_start.nanoseconds(), clock_type) < ros_time_of_day &&
93 ros_time_of_day < rclcpp::Time((cur_start + control_span_).nanoseconds(), clock_type))
94 {
95 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm_ctrl"), "Geofence schedule active!");
96
97 time_in_active_period = true;
98 }
99 cur_start = cur_start + control_period_;
100
101 }
102
103
104 // check if the only next interval is after the schedule end or past the end of the day
105 if (abs_day_start + cur_start > schedule_end_ || cur_start > full_day || cur_start > (control_start_ + control_duration_))
106 {
107 RCLCPP_DEBUG_STREAM(rclcpp::get_logger("carma_wm_ctrl"), "Geofence schedule beyond end time");
108 return std::make_pair(time_in_active_period, rclcpp::Time(0, 0, clock_type));
109 }
110
111 // At this point we should have the next start time which is still within the schedule and day
112 return std::make_pair(time_in_active_period, abs_day_start + cur_start);
113}
114
115} // namespace carma_wm_ctrl
bool scheduleStarted(const rclcpp::Time &time) const
Returns true if the schedule has started by the provided time.
std::pair< bool, rclcpp::Time > getNextInterval(const rclcpp::Time &time) const
Returns the start time of the next active interval defined by this schedule.
GeofenceSchedule()
Default Constructor does not initialize any members.
std::unordered_set< boost::gregorian::greg_weekday, std::hash< int > > DayOfTheWeekSet
bool scheduleExpired(const rclcpp::Time &time) const
Returns true if the schedule has expired by the provided time.