6#include <Eigen/Geometry>
8#include <range/v3/algorithm/max_element.hpp>
9#include <range/v3/range/conversion.hpp>
10#include <range/v3/view/transform.hpp>
12#include <SimoxUtility/shapes/AxisAlignedBoundingBox.h>
13#include <SimoxUtility/shapes/OrientedBox.h>
20#include <ArmarXCore/interface/core/UserException.h>
34#include <armarx/view_selection/gaze_targets/aron/AttentionType.aron.generated.h>
35#include <armarx/view_selection/gaze_targets/aron/GazeTarget.aron.generated.h>
36#include <armarx/view_selection/skills/aron/LookAt.aron.generated.h>
37#include <armarx/view_selection/skills/aron/LookAtObject.aron.generated.h>
48 LookAtObject::init(
const Base::SpecializedInitInput& in)
50 return ::armarx::skills::Skill::InitResult{
55 LookAtObject::main(
const Base::SpecializedMainInput& in)
59 fromAron(in.parameters.object, objectID);
67 ARMARX_INFO <<
"Memory query did not provide any observation for " << objectID;
72 objectID = result->objectID;
74 const simox::OrientedBoxf oobb = [&]()
76 if (result->localOOBB.has_value())
78 return result->localOOBB.value();
83 auto finder = ObjectFinder();
84 auto objectClassInfoOpt = finder.findObject(objectID);
87 const auto& objectClassInfo = objectClassInfoOpt.value();
89 const auto oobbOpt = objectClassInfo.loadOOBB();
92 const simox::OrientedBoxf& oobb = oobbOpt.value();
98 const armarx::objpose::ObjectPose& objectObservation = result.value();
101 const Eigen::Vector3f global_P_obj = [&]() -> Eigen::Vector3f
103 const Eigen::Isometry3f globalObjectPose{objectObservation.
objectPoseGlobal};
105 ARMARX_INFO <<
"Object global position " << globalObjectPose.translation();
107 using armarx::view_selection::skills::arondto::PointOnObject;
108 switch (in.parameters.pointOnObject.value)
110 case PointOnObject::Center:
112 const Eigen::Vector3f globalObjectCenter =
113 globalObjectPose * (oobb.center() + in.parameters.pointOnObjectOffset);
115 return globalObjectCenter;
118 case PointOnObject::BoundingBoxTopCenter:
121 const std::vector<Eigen::Vector3f> faceCenterMultipliers{
122 Eigen::Vector3f::UnitX(),
123 -Eigen::Vector3f::UnitX(),
124 Eigen::Vector3f::UnitY(),
125 -Eigen::Vector3f::UnitY(),
126 Eigen::Vector3f::UnitZ(),
127 -Eigen::Vector3f::UnitZ(),
130 const auto applyTransformation =
133 pointOnObjectOffset = in.parameters.pointOnObjectOffset](
134 const Eigen::Vector3f& faceMultiplier) -> Eigen::Vector3f
136 const Eigen::Vector3f shift =
137 Eigen::Vector3f(oobb.dimensions() / 2) +
138 Eigen::Vector3f{Eigen::Vector3f(oobb.dimensions() / 2).array() *
139 faceMultiplier.array()};
142 return Eigen::Vector3f{globalObjectPose * oobb.from_box_frame(shift) +
143 pointOnObjectOffset};
153 const std::vector<Eigen::Vector3f> globalObjectSurfaceCenters =
154 faceCenterMultipliers | ranges::views::transform(applyTransformation) |
157 const std::vector<float> height =
158 globalObjectSurfaceCenters |
159 ranges::views::transform([](
const Eigen::Vector3f& v) {
return v.z(); }) |
162 const auto it = ranges::max_element(height);
164 const Eigen::Vector3f& highestSurfaceCenter =
165 globalObjectSurfaceCenters.at(std::distance(height.begin(), it));
167 return highestSurfaceCenter;
172 throw armarx::InvalidArgumentException(
"should not get here");
176 ARMARX_INFO <<
"Looking at global position " << global_P_obj;
179 if (in.parameters.permissibleRegionGlobalFrame.has_value())
182 <<
"Permissible region provided. Will check whether object position is valid.";
187 const Eigen::Isometry3f global_T_root{srv_.robot->getGlobalPose()};
188 const Eigen::Vector3f root_P_obj = global_T_root.inverse() * global_P_obj;
190 ::simox::OrientedBoxf bb;
191 fromAron(in.parameters.permissibleRegionGlobalFrame.value(), bb);
197 if (bb.contains(root_P_obj))
199 ARMARX_INFO <<
"Object position is inside permissible region.";
204 ARMARX_INFO <<
"Object position is outside permissible region.";
209 else if (in.parameters.permissibleRegionRobotFrame.has_value())
212 <<
"Permissible region provided. Will check whether object position is valid.";
217 const Eigen::Isometry3f global_T_root{srv_.robot->getGlobalPose()};
218 const Eigen::Vector3f root_P_obj = global_T_root.inverse() * global_P_obj;
220 ::simox::AxisAlignedBoundingBox bb;
221 fromAron(in.parameters.permissibleRegionRobotFrame.value(), bb);
227 if (bb.is_inside(root_P_obj))
229 ARMARX_INFO <<
"Object position is inside permissible region.";
234 ARMARX_INFO <<
"Object position is outside permissible region.";
240 const armarx::view_selection::gaze_targets::arondto::GazeTarget gazeTarget = [&]()
242 armarx::view_selection::gaze_targets::arondto::GazeTarget gazeTarget;
243 gazeTarget.name =
"LookAtObject_" + objectID.
str();
245 gazeTarget.position.header.agent =
"";
248 gazeTarget.position.position = global_P_obj;
250 gazeTarget.duration =
253 gazeTarget.priority.attentionType =
254 gaze_targets::arondto::AttentionType::ImplEnum::TaskDriven;
255 gazeTarget.priority.priority = in.parameters.priority;
258 gazeTarget.keepInQueue =
false;
265 using Parameters = armarx::view_selection::skills::arondto::LookAtParams;
268 const ::armarx::skills::SkillID skillId{
270 ::armarx::skills::ProviderID{.providerName = armarx::view_selection::skills::
271 constants::ViewSelectionSkillProviderName},
277 [&gazeTarget](Parameters& subSkillParams)
278 { subSkillParams.target = gazeTarget; });
290 LookAtObject::onStopRequested()
294 ::armarx::skills::SkillDescription
298 defaults.priority = 100;
300 defaults.durationSeconds = 20;
301 defaults.pointOnObject = armarx::view_selection::skills::arondto::PointOnObject::Center;
302 defaults.pointOnObjectOffset = Eigen::Vector3f::Zero();
303 defaults.permissibleRegionGlobalFrame = std::nullopt;
304 defaults.permissibleRegionRobotFrame = std::nullopt;
308 .description =
"Look at the location where an instance of the object class has most "
309 "recently been seen.",
310 .rootProfileDefaults = defaults.toAron(),
312 .parametersType = Params::ToAronType(),
313 .resultType = Result::ToAronType(),
static DateTime Now()
Current time on the virtual clock.
static Duration Minutes(std::int64_t minutes)
Constructs a duration in minutes.
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
std::string str() const
Return "dataset/className" or "dataset/className/instanceName".
static Duration SecondsDouble(double seconds)
Constructs a duration in seconds.
std::optional< TerminatedSkillStatusUpdate > callSubskill(const SkillID &skillId)
Call a subskill with the given ID and its default parameters.
static MainResult MakeSucceededResult(aron::data::DictPtr data=nullptr)
static MainResult MakeFailedResult(aron::data::DictPtr data=nullptr)
::armarx::skills::SimpleSpecializedSkill< Params > Base
static armarx::skills::SkillDescription DefaultSkillDescription()
LookAtObject(const Services &srv)
arondto::LookAtObjectParams Params
#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_INFO
The normal logging level.
std::string const GlobalFrame
Variable of the global coordinate system.
bool update(mongocxx::collection &coll, const nlohmann::json &query, const nlohmann::json &update)
double v(double t, double v0, double a0, double j)
aron::data::DictPtr Parameters
bool skillExecutionFailed(const std::optional< armarx::skills::TerminatedSkillStatusUpdate > &update)
const armarx::skills::SkillID LookAtObject
This file is part of ArmarX.
void fromAron(const arondto::PackagePath &dto, PackageFileLocation &bo)
Eigen::Matrix4f objectPoseGlobal
The object pose in the global frame.
A result struct for skill initialization.
A result struct for th main method of a skill.
std::experimental::observer_ptr<::armarx::armem::obj::instance::Reader > objectInstanceReader