@@ -78,9 +78,15 @@ class TrafficLight::UpdateHandle::Implementation::Data
78
78
std::vector<rmf_traffic::Route> plan_itinerary;
79
79
std::vector<rmf_traffic::agv::Plan::Waypoint> pending_waypoints;
80
80
81
+ struct Location
82
+ {
83
+ std::string map;
84
+ Eigen::Vector3d position;
85
+ };
86
+
81
87
// Remember which checkpoint we need to depart from next
82
88
std::optional<std::size_t > last_departed_waypoint;
83
- std::optional<Eigen::Vector3d> latest_location ;
89
+ std::optional<Location> last_known_location ;
84
90
bool awaiting_confirmation = false ;
85
91
bool rejected = false ;
86
92
bool approved = false ;
@@ -244,21 +250,21 @@ void TrafficLight::UpdateHandle::Implementation::Data::update_path(
244
250
ready_check_timer = nullptr ;
245
251
waiting_timer = nullptr ;
246
252
last_departed_waypoint.reset ();
247
- latest_location.reset ();
248
253
249
254
if (new_path.empty ())
250
255
{
251
256
// Clear out this robot's itinerary because it is done moving
252
257
RCLCPP_INFO (
253
258
node->get_logger (),
254
259
" Traffic light controlled robot [%s] owned by [%s] is being taken off "
255
- " the schedule after being given a null path ." ,
260
+ " the schedule because it is idle ." ,
256
261
itinerary.description ().name ().c_str (),
257
262
itinerary.description ().owner ().c_str ());
258
263
259
264
planner = nullptr ;
260
265
path.clear ();
261
266
departure_timing.clear ();
267
+ blockade.cancel ();
262
268
return ;
263
269
}
264
270
else if (new_path.size () == 1 )
@@ -330,7 +336,11 @@ void TrafficLight::UpdateHandle::Implementation::Data::update_path(
330
336
rmf_traffic::agv::Plan::Configuration (graph, traits),
331
337
rmf_traffic::agv::Plan::Options (nullptr ));
332
338
333
- latest_location = new_path.front ().position ();
339
+ last_known_location = Location{
340
+ new_planner->get_configuration ().graph ().get_waypoint (0 ).get_map_name (),
341
+ new_path.front ().position ()
342
+ };
343
+
334
344
rmf_traffic::agv::Plan::Start start{now, 0 , new_path.front ().position ()[2 ]};
335
345
336
346
auto approval_cb =
@@ -757,15 +767,15 @@ rmf_traffic::schedule::Negotiation::Alternatives make_reservation_alts(
757
767
758
768
alts.emplace_back (std::move (preferred_itinerary));
759
769
760
- if (data->latest_location .has_value ())
770
+ if (data->last_known_location .has_value ())
761
771
{
762
772
// TODO(MXG): Should we do something about the situation where we don't know
763
773
// the latest location? Maybe just add a stop_and_sit on the first waypoint?
764
774
rmf_traffic::Trajectory stop_and_sit;
765
775
stop_and_sit.insert (
766
- now, data->latest_location . value () , Eigen::Vector3d::Zero ());
776
+ now, data->last_known_location -> position , Eigen::Vector3d::Zero ());
767
777
stop_and_sit.insert (
768
- now + 10s, data->latest_location . value () , Eigen::Vector3d::Zero ());
778
+ now + 10s, data->last_known_location -> position , Eigen::Vector3d::Zero ());
769
779
770
780
const auto & graph = data->planner ->get_configuration ().graph ();
771
781
const auto & wp = graph.get_waypoint (data->blockade .last_reached ());
@@ -1124,7 +1134,11 @@ void TrafficLight::UpdateHandle::Implementation::Data::update_location(
1124
1134
data->last_departed_waypoint = checkpoint_index;
1125
1135
}
1126
1136
1127
- data->latest_location = location;
1137
+ data->last_known_location = Location{
1138
+ data->planner ->get_configuration ().graph ()
1139
+ .get_waypoint (checkpoint_index).get_map_name (),
1140
+ location
1141
+ };
1128
1142
data->blockade .reached (checkpoint_index);
1129
1143
1130
1144
if (plan_version != data->current_plan_version )
@@ -1651,7 +1665,11 @@ void TrafficLight::UpdateHandle::Implementation::Data::reject(
1651
1665
// Even if the plan version is wrong, it may still be useful to update this
1652
1666
// information.
1653
1667
data->last_departed_waypoint = actual_last_departed;
1654
- data->latest_location = stopped_location;
1668
+ data->last_known_location = Location{
1669
+ data->planner ->get_configuration ().graph ()
1670
+ .get_waypoint (actual_last_departed).get_map_name (),
1671
+ stopped_location
1672
+ };
1655
1673
1656
1674
if (plan_version != data->current_plan_version )
1657
1675
return ;
@@ -1674,13 +1692,13 @@ TrafficLight::UpdateHandle::Implementation::Data::current_location() const
1674
1692
{
1675
1693
const auto now = rmf_traffic_ros2::convert (node->now ());
1676
1694
1677
- if (last_departed_waypoint.has_value () && latest_location .has_value ())
1695
+ if (last_departed_waypoint.has_value () && last_known_location .has_value ())
1678
1696
{
1679
1697
const auto * lane = planner->get_configuration ().graph ().lane_from (
1680
1698
*last_departed_waypoint, *last_departed_waypoint+1 );
1681
1699
assert (lane);
1682
1700
1683
- const Eigen::Vector3d p = *latest_location ;
1701
+ const Eigen::Vector3d p = last_known_location-> position ;
1684
1702
1685
1703
return rmf_traffic::agv::Plan::Start (
1686
1704
now,
@@ -1700,6 +1718,9 @@ TrafficLight::UpdateHandle::Implementation::Data::current_location() const
1700
1718
void TrafficLight::UpdateHandle::Implementation::Data
1701
1719
::publish_fleet_state () const
1702
1720
{
1721
+ if (!last_known_location.has_value ())
1722
+ return ;
1723
+
1703
1724
auto robot_mode = [&]()
1704
1725
{
1705
1726
if (current_range.begin == current_range.end )
@@ -1718,23 +1739,15 @@ ::publish_fleet_state() const
1718
1739
.mode_request_id (0 );
1719
1740
}();
1720
1741
1721
- auto location = [&]() -> rmf_fleet_msgs::msg::Location
1722
- {
1723
- const auto & graph = planner->get_configuration ().graph ();
1724
- const auto & l = current_location ();
1725
- const auto & wp = graph.get_waypoint (l.waypoint ());
1726
- const Eigen::Vector2d p = l.location ().value_or (wp.get_location ());
1727
-
1728
- return rmf_fleet_msgs::build<rmf_fleet_msgs::msg::Location>()
1729
- .t (rmf_traffic_ros2::convert (l.time ()))
1742
+ const auto & map = last_known_location->map ;
1743
+ const auto p = last_known_location->position ;
1744
+ auto location = rmf_fleet_msgs::build<rmf_fleet_msgs::msg::Location>()
1745
+ .t (node->now ())
1730
1746
.x (p.x ())
1731
1747
.y (p.y ())
1732
- .yaw (l.orientation ())
1733
- .level_name (wp.get_map_name ())
1734
- // NOTE(MXG): This field is only used by the fleet drivers. For now, we
1735
- // will just fill it with a zero.
1748
+ .yaw (p[2 ])
1749
+ .level_name (map)
1736
1750
.index (0 );
1737
- }();
1738
1751
1739
1752
const auto & fleet_name = itinerary.description ().owner ();
1740
1753
auto robot_state = rmf_fleet_msgs::build<rmf_fleet_msgs::msg::RobotState>()
@@ -2005,6 +2018,13 @@ TrafficLight::UpdateHandle::Implementation::make(
2005
2018
std::size_t TrafficLight::UpdateHandle::follow_new_path (
2006
2019
const std::vector<Waypoint>& new_path)
2007
2020
{
2021
+ if (new_path.size () < 2 )
2022
+ {
2023
+ throw std::runtime_error (
2024
+ " [TrafficLight::follow_new_path] Invalid number of waypoints given ["
2025
+ + std::to_string (new_path.size ()) + " ]. Must be at least 2." );
2026
+ }
2027
+
2008
2028
const std::size_t version = ++_pimpl->received_version ;
2009
2029
_pimpl->data ->worker .schedule (
2010
2030
[version, new_path, data = _pimpl->data ](const auto &)
@@ -2015,6 +2035,31 @@ std::size_t TrafficLight::UpdateHandle::follow_new_path(
2015
2035
return version;
2016
2036
}
2017
2037
2038
+ // ==============================================================================
2039
+ auto TrafficLight::UpdateHandle::update_idle_location (
2040
+ std::string map,
2041
+ Eigen::Vector3d position) -> UpdateHandle&
2042
+ {
2043
+ const std::size_t version = ++_pimpl->received_version ;
2044
+ _pimpl->data ->worker .schedule (
2045
+ [version, map = std::move (map), position, data = _pimpl->data ](const auto &)
2046
+ {
2047
+ if (rmf_utils::modular (version).less_than (data->processing_version ))
2048
+ return ;
2049
+
2050
+ data->last_known_location =
2051
+ Implementation::Data::Location{
2052
+ map,
2053
+ position
2054
+ };
2055
+
2056
+ if (!data->path .empty ())
2057
+ data->update_path (version, {});
2058
+ });
2059
+
2060
+ return *this ;
2061
+ }
2062
+
2018
2063
// ==============================================================================
2019
2064
auto TrafficLight::UpdateHandle::update_battery_soc (double battery_soc)
2020
2065
-> UpdateHandle&
0 commit comments