GuideHumanToRoom.cpp
Go to the documentation of this file.
1#include "GuideHumanToRoom.h"
2
3#include <math.h>
4
5#include <cmath>
6#include <string>
7
8#include <Eigen/Core>
9#include <Eigen/Geometry>
10
11#include <VirtualRobot/VirtualRobot.h>
12
17
20
32
34{
36 const NavigatingSkillHelper::Services& helperSrv,
37 const Services& srv) :
38 Base(DefaultSkillDescription()), helper(helperProperties, helperSrv)
39 {
40 srv_.emplace(srv);
41 }
42
44 GuideHumanToRoom::init(const Base::SpecializedInitInput& in)
45 {
46 ARMARX_CHECK(srv_.has_value());
47
48 helper.init(in.parameters.navigatingSkillParams,
49 DefaultSkillDescription().skillId.skillName);
50
51 return ::armarx::skills::Skill::InitResult{
53 }
54
56 GuideHumanToRoom::main(const Base::SpecializedMainInput& in)
57 {
58 const core::Pose globalTarget = getTargetInFrontOfRoom(in.parameters.room);
59
60 ARMARX_INFO << "moving to target " << VAROUT(globalTarget.matrix());
61
62 // execute and wait until goal is reached, re-planning while the retry budget lasts.
63 ARMARX_INFO << "Sending navigation request";
64 // TODO: this skill never checks `shouldSkillTerminate()` (and its SkillDescription
65 // timeout is `Duration()`, i.e. already expired), so the predicate stays `false` here
66 // to keep the existing behaviour.
67 client::StopEvent se = helper.moveAndWaitForStop(
68 [&] { helper.getNavigator()->moveTo(globalTarget, core::NavigationFrame::Absolute); },
69 [] { return false; });
70 if (se)
71 {
72 ARMARX_INFO << "Goal " << QUOTED(globalTarget.translation()) << "reached.";
73 }
74 else
75 {
76 if (se.isSafetyStopTriggeredEvent())
77 {
78 ARMARX_ERROR << "Safety stop was triggered!";
79
80 return ::armarx::skills::Skill::MainResult{
82 }
83 if (se.isUserAbortTriggeredEvent())
84 {
85 ARMARX_ERROR << "Aborted by user!";
86
87 return ::armarx::skills::Skill::MainResult{
89 }
90 if (se.isInternalErrorEvent())
91 {
92 ARMARX_ERROR << "Unknown internal error occured! "
93 << se.toInternalErrorEvent().message;
94
95 return ::armarx::skills::Skill::MainResult{
97 }
98 if (se.isGlobalPlanningFailedEvent())
99 {
100 ARMARX_ERROR << "Global planning failed! "
101 << se.toGlobalPlanningFailedEvent().message;
102
103 return ::armarx::skills::Skill::MainResult{
105 }
106
107 ARMARX_ERROR << "Unknown event!";
108 return ::armarx::skills::Skill::MainResult{
110 }
111
112
113 return ::armarx::skills::Skill::MainResult{
115 }
116
117 void
118 GuideHumanToRoom::onStopRequested()
119 {
120 if (helper.getNavigator().has_value())
121 {
122 ARMARX_CHECK(helper.getNavigator().has_value());
123 helper.getNavigator()->stop();
124 }
125 }
126
128 GuideHumanToRoom::getTargetInFrontOfRoom(const std::string& roomName) const
129 {
130 const algorithms::Costmap costmap = [&]
131 {
132 const memory::client::costmap::Reader::Query costmapQuery{
133 .providerName = properties.distanceToObstacleCostmapProvider,
134 .name = "distance_to_obstacles",
135 .timestamp = Clock::Now()};
136
137 const auto result = srv_->costmapReader.query(costmapQuery);
138 ARMARX_CHECK(result) << result.errorMessage;
139 ARMARX_CHECK(result.costmap.has_value());
140 return result.costmap.value();
141 }();
142
143 const armarx::navigation::algorithms::Room room = [&]
144 {
145 const memory::client::rooms::Reader::Query roomQuery{.providerName =
146 properties.roomsProvider,
147 .name = roomName,
148 .timestamp = Clock::Now()};
149
150 const auto result = srv_->roomsReader.query(roomQuery);
151 ARMARX_CHECK(result) << "Failed to query room " << QUOTED(roomName) << " from provider `"
152 << properties.roomsProvider
153 << "`. Reason: " << result.errorMessage;
154 ARMARX_CHECK_NOT_EMPTY(result.rooms);
155 ARMARX_CHECK_EQUAL(result.rooms.size(), 1);
156
157 return result.rooms.front();
158 }();
159
160 const VirtualRobot::RobotPtr robot =
161 srv_->virtualRobotReader.getRobotWaiting(properties.robotName);
163 ARMARX_CHECK(srv_->virtualRobotReader.synchronizeRobotPose(*robot, Clock::Now()));
164
165 const core::Pose global_T_robot(robot->getGlobalPose());
166
167 rooms::RoomNavigationTargetCreator::Params algoParams;
168 rooms::RoomNavigationTargetCreator algo(algoParams);
169 auto result = algo.getClosestPositionOutsideOfRoom(
170 costmap, room, global_T_robot.translation(), &srv_->arviz);
171
172 const core::Direction dirToRoom = result.global_P_roomEntry - result.global_P_robot;
173
174 // the robot should point to the room entry
175 const float yaw = std::atan2(dirToRoom.y(), dirToRoom.x()) - M_PI_2f32;
176
177 // TODO maybe rotate robot a bit towards the human?
178
179 core::Pose global_T_robot_target = core::Pose::Identity();
180 global_T_robot_target.translation() = result.global_P_robot;
181 global_T_robot_target.linear() =
182 Eigen::AngleAxisf(yaw, Eigen::Vector3f::UnitZ()).toRotationMatrix();
183
184 return global_T_robot_target;
185 }
186
187
188} // namespace armarx::navigation::skills
#define ARMARX_CHECK_NOT_EMPTY(c)
#define VAROUT(x)
#define QUOTED(x)
static DateTime Now()
Current time on the virtual clock.
Definition Clock.cpp:93
::armarx::skills::SimpleSpecializedSkill< Params > Base
GuideHumanToRoom(const NavigatingSkillHelper::Properties &helperProperties, const NavigatingSkillHelper::Services &helperSrv, const Services &srv)
static armarx::skills::SkillDescription DefaultSkillDescription()
std::optional< client::Navigator > & getNavigator()
void init(const arondto::NavigatingSkillParams &params, const std::string &id)
client::StopEvent moveAndWaitForStop(IssueNavigationCommandT &&issueNavigationCommand, ShouldTerminateT &&shouldTerminate)
Issues the navigation command and waits for the navigator to stop, polling shouldTerminate meanwhile.
#define ARMARX_CHECK(expression)
Shortcut for ARMARX_CHECK_EXPRESSION.
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:179
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:194
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
Eigen::Vector3f Direction
Definition basic_types.h:39
Eigen::Isometry3f Pose
Definition basic_types.h:31
A result struct for skill initialization.
Definition Skill.h:50
A result struct for th main method of a skill.
Definition Skill.h:62