Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • sw/armarx/robot-api
  • uwkce_singer/robot-api
  • untcg_hofmann/robot-api
  • ulqba_korosakov/RobotAPI
4 results
Show changes
Commits on Source (23)
Showing
with 224 additions and 91 deletions
......@@ -47,6 +47,7 @@ namespace armarx::armem::server::robot_state
RobotStateMemory::RobotStateMemory() :
descriptionSegment(iceAdapter()),
proprioceptionSegment(iceAdapter()),
exteroceptionSegment(iceAdapter()),
localizationSegment(iceAdapter()),
commonVisu(descriptionSegment, proprioceptionSegment, localizationSegment)
{
......@@ -86,6 +87,7 @@ namespace armarx::armem::server::robot_state
setMemoryName(armem::robot_state::memoryID.memoryName);
descriptionSegment.defineProperties(defs, prefix + "desc.");
exteroceptionSegment.defineProperties(defs, prefix + "ext.");
proprioceptionSegment.defineProperties(defs, prefix + "prop.");
localizationSegment.defineProperties(defs, prefix + "loc.");
commonVisu.defineProperties(defs, prefix + "visu.");
......@@ -104,6 +106,7 @@ namespace armarx::armem::server::robot_state
{
descriptionSegment.init();
proprioceptionSegment.init();
exteroceptionSegment.init();
localizationSegment.init();
commonVisu.init();
......
......@@ -38,6 +38,7 @@
#include <RobotAPI/libraries/armem_robot_state/server/proprioception/RobotUnitData.h>
#include <RobotAPI/libraries/armem_robot_state/server/proprioception/RobotUnitReader.h>
#include <RobotAPI/libraries/armem_robot_state/server/proprioception/Segment.h>
#include <RobotAPI/libraries/armem_robot_state/server/exteroception/Segment.h>
namespace armarx::plugins
......@@ -105,6 +106,9 @@ namespace armarx::armem::server::robot_state
proprioception::Segment proprioceptionSegment;
armem::data::MemoryID robotUnitProviderID;
// - exteroception
exteroception::Segment exteroceptionSegment;
// - localization
localization::Segment localizationSegment;
......
......@@ -59,12 +59,17 @@ namespace armarx
return _id.str();
}
ObjectInfo::path ObjectInfo::objectDirectory() const
ObjectInfo::path ObjectInfo::objectDirectory(const bool fixDataPath) const
{
if(fixDataPath)
{
return _relObjectsPath / _id.dataset() / _id.className();
}
return path(_packageName) / _relObjectsPath / _id.dataset() / _id.className();
}
PackageFileLocation ObjectInfo::file(const std::string& _extension, const std::string& suffix) const
PackageFileLocation ObjectInfo::file(const std::string& _extension, const std::string& suffix, const bool fixDataPath) const
{
std::string extension = _extension;
if (extension.at(0) != '.')
......@@ -75,8 +80,8 @@ namespace armarx
PackageFileLocation loc;
loc.package = _packageName;
loc.relativePath = objectDirectory() / filename;
loc.absolutePath = _absPackageDataDir / loc.relativePath;
loc.relativePath = objectDirectory(fixDataPath) / filename;
loc.absolutePath = _absPackageDataDir / objectDirectory(false) / filename;
return loc;
}
......@@ -118,12 +123,12 @@ namespace armarx
PackageFileLocation ObjectInfo::articulatedSimoxXML() const
{
return file(".xml", "_articulated");
return file(".xml", "_articulated", true);
}
PackageFileLocation ObjectInfo::articulatedUrdf() const
{
return file(".urdf", "_articulated");
return file(".urdf", "_articulated", true);
}
PackageFileLocation ObjectInfo::articulatedSdf() const
......@@ -332,5 +337,3 @@ std::ostream& armarx::operator<<(std::ostream& os, const ObjectInfo& rhs)
{
return os << rhs.id();
}
......@@ -76,7 +76,7 @@ namespace armarx
std::string idStr() const;
PackageFileLocation file(const std::string& extension, const std::string& suffix = "") const;
PackageFileLocation file(const std::string& extension, const std::string& suffix = "", bool fixDataPath = false) const;
PackageFileLocation simoxXML() const;
......@@ -136,7 +136,7 @@ namespace armarx
private:
path objectDirectory() const;
path objectDirectory(bool fixDataPath) const;
std::optional<std::vector<std::string>> loadNames(const std::string& jsonKey) const;
......
......@@ -63,12 +63,16 @@ namespace armarx::armem::client::util
};
subscribe(subscriptionID, cb);
}
template <class CalleeT>
void subscribe(const MemoryID& subscriptionID, CalleeT* callee, MemberCallbackUpdatedOnly<CalleeT> callback)
{
auto cb = [callee, callback](const MemoryID&, const std::vector<MemoryID>& updatedSnapshotIDs)
{
(callee->*callback)(updatedSnapshotIDs);
if(callee)
{
(callee->*callback)(updatedSnapshotIDs);
}
};
subscribe(subscriptionID, cb);
}
......
......@@ -3,44 +3,53 @@
#include <Eigen/Core>
#include <Eigen/Geometry>
#include <VirtualRobot/Robot.h>
#include <ArmarXCore/core/exceptions/local/ExpressionException.h>
#include <ArmarXCore/core/logging/Logging.h>
#include <ArmarXCore/core/system/ArmarXDataPath.h>
#include <VirtualRobot/Robot.h>
#include <ArmarXCore/core/system/cmake/CMakePackageFinder.h>
namespace armarx::armem::articulated_object
{
armem::articulated_object::ArticulatedObject convert(
const VirtualRobot::Robot& obj,
const armem::Time& timestamp)
armem::articulated_object::ArticulatedObject
convert(const VirtualRobot::Robot& obj, const armem::Time& timestamp)
{
ARMARX_DEBUG << "Filename is " << obj.getFilename();
// TODO(fabian.reister): remove "PriorKnowledgeData" below
const std::vector<std::string> packages =
armarx::CMakePackageFinder::FindAllArmarXSourcePackages();
const std::string package = armarx::ArmarXDataPath::getProject(packages, obj.getFilename());
return armem::articulated_object::ArticulatedObject
// make sure that the relative path is without the 'package/' prefix
const std::string fileRelPath = [&obj, &package]() -> std::string
{
.description = {
.name = obj.getType(),
.xml = PackagePath(armarx::ArmarXDataPath::getProject(
{"PriorKnowledgeData"}, obj.getFilename()),
obj.getFilename())
},
.instance = obj.getName(),
.config = {
.timestamp = timestamp,
.globalPose = Eigen::Affine3f(obj.getRootNode()->getGlobalPose()),
.jointMap = obj.getJointValues()
},
.timestamp = timestamp};
if (simox::alg::starts_with(obj.getFilename(), package))
{
// remove "package" + "/"
const std::string fixedFilename = obj.getFilename().substr(package.size() + 1, -1);
return fixedFilename;
}
return obj.getFilename();
}();
return armem::articulated_object::ArticulatedObject{
.description = {.name = obj.getType(),
.xml = PackagePath(armarx::ArmarXDataPath::getProject(
{package}, fileRelPath),
obj.getFilename())},
.instance = obj.getName(),
.config = {.timestamp = timestamp,
.globalPose = Eigen::Affine3f(obj.getRootNode()->getGlobalPose()),
.jointMap = obj.getJointValues()},
.timestamp = timestamp};
}
bool
ArticulatedObjectWriter::storeArticulatedObject(
const VirtualRobot::RobotPtr& articulatedObject,
const armem::Time& timestamp)
ArticulatedObjectWriter::storeArticulatedObject(const VirtualRobot::RobotPtr& articulatedObject,
const armem::Time& timestamp)
{
ARMARX_CHECK_NOT_NULL(articulatedObject);
......
......@@ -222,12 +222,21 @@ namespace armarx::armem::server::obj::instance
stats.numUpdated++;
VirtualRobot::RobotPtr robot = robots.get(provided.robotName, provided.providerName);
if(not robot)
{
ARMARX_INFO << deactivateSpam(1) << "Failed to retrieve robot `" << provided.robotName << "`.";
}
// robot may be null!
// Update the robot to obtain correct local -> global transformation
if (robot and robotSyncTimestamp != timestamp)
{
ARMARX_CHECK(robots.reader->synchronizeRobot(*robot, timestamp));
ARMARX_CHECK(robots.reader->synchronizeRobot(*robot, timestamp))
<< "Failed to synchronize robot to timestamp " << timestamp
<< ". This is " << (Clock::Now() - timestamp).toSecondsDouble() << " seconds in the past.";
robotSyncTimestamp = timestamp;
......@@ -1308,7 +1317,7 @@ namespace armarx::armem::server::obj::instance
if (robot)
{
reader->synchronizeRobot(*robot, Clock::Now());
ARMARX_CHECK(reader->synchronizeRobot(*robot, Clock::Now()));
// Store robot if valid.
loaded.emplace(robotName, robot);
}
......
......@@ -194,7 +194,7 @@ namespace armarx::armem::server::obj::instance
{
viz::Robot robot(key);
robot.pose(pose);
robot.file(model->package, model->relativePath);
robot.file(model->package, model->package + "/" + model->relativePath);
robot.joints(objectPose.objectJointValues);
layer.add(robot);
......
......@@ -42,6 +42,12 @@ namespace armarx::armem::robot
using ToFArray = Eigen::MatrixXf;
struct ToF
{
ToFArray array;
std::string frame;
};
struct RobotState
{
......
......@@ -65,6 +65,7 @@ armarx_enable_aron_file_generation_for_target(
ARON_FILES
aron/JointState.xml
aron/Proprioception.xml
aron/Exteroception.xml
aron/TransformHeader.xml
aron/Transform.xml
)
......
<?xml version="1.0" encoding="UTF-8" ?>
<AronTypeDefinition>
<CodeIncludes>
<SystemInclude include="Eigen/Core" />
<SystemInclude include="Eigen/Geometry" />
</CodeIncludes>
<GenerateTypes>
<Object name="armarx::armem::exteroception::arondto::ToF">
<ObjectChild key="array">
<Matrix rows="-1" cols="-1" type="float32" />
</ObjectChild>
</Object>
<Object name="armarx::armem::arondto::Exteroception">
<ObjectChild key="iterationID">
<long />
</ObjectChild>
<ObjectChild key="tof">
<Dict>
<armarx::armem::exteroception::arondto::ToF/>
</Dict>
</ObjectChild>
</Object>
</GenerateTypes>
</AronTypeDefinition>
......@@ -234,15 +234,6 @@
</ObjectChild>
</Object>
<Object name="armarx::armem::prop::arondto::ToF">
<ObjectChild key="array">
<Matrix rows="-1" cols="-1" type="float32" />
</ObjectChild>
</Object>
<Object name="armarx::armem::arondto::Proprioception">
......@@ -264,13 +255,6 @@
</Dict>
</ObjectChild>
<!-- TODO move to separate segment -->
<ObjectChild key="tof">
<Dict>
<armarx::armem::prop::arondto::ToF/>
</Dict>
</ObjectChild>
<ObjectChild key="extraFloats">
<Dict>
<Float />
......
......@@ -6,6 +6,7 @@
#include <RobotAPI/libraries/armem_robot_state/aron/JointState.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/aron/Exteroception.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/aron/Transform.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/types.h>
#include <RobotAPI/libraries/aron/common/aron_conversions.h>
......@@ -98,11 +99,11 @@ namespace armarx::armem
}
void fromAron(const armarx::armem::prop::arondto::ToF& dto, robot::ToFArray& bo){
void fromAron(const armarx::armem::exteroception::arondto::ToF& dto, robot::ToFArray& bo){
bo = dto.array;
}
void toAron(armarx::armem::prop::arondto::ToF& dto, const robot::ToFArray& bo){
void toAron(armarx::armem::exteroception::arondto::ToF& dto, const robot::ToFArray& bo){
dto.array = bo;
}
......
......@@ -38,6 +38,10 @@ namespace armarx::armem
{
struct Platform;
struct ForceTorque;
}
namespace exteroception::arondto
{
struct ToF;
}
......@@ -66,9 +70,8 @@ namespace armarx::armem
void fromAron(const armarx::armem::prop::arondto::ForceTorque& dto, robot::ForceTorque& bo);
void toAron(armarx::armem::prop::arondto::ForceTorque& dto, const robot::ForceTorque& bo);
void fromAron(const armarx::armem::prop::arondto::ToF& dto, robot::ToFArray& bo);
void toAron(armarx::armem::prop::arondto::ToF& dto, const robot::ToFArray& bo);
void fromAron(const armarx::armem::exteroception::arondto::ToF& dto, robot::ToFArray& bo);
void toAron(armarx::armem::exteroception::arondto::ToF& dto, const robot::ToFArray& bo);
} // namespace armarx::armem
......@@ -22,6 +22,7 @@
#include <RobotAPI/libraries/armem_robot/aron_conversions.h>
#include <RobotAPI/libraries/armem_robot/robot_conversions.h>
#include <RobotAPI/libraries/armem_robot/types.h>
#include <RobotAPI/libraries/armem_robot_state/aron/Exteroception.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/aron/JointState.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/aron/Proprioception.aron.generated.h>
#include <RobotAPI/libraries/armem_robot_state/aron_conversions.h>
......@@ -135,9 +136,7 @@ namespace armarx::armem::robot_state
}
std::optional<robot::RobotDescription>
RobotReader::queryDescription(
const std::string& name,
const armem::Time& timestamp)
RobotReader::queryDescription(const std::string& name, const armem::Time& timestamp)
{
const auto sanitizedTimestamp = timestamp.isValid() ? timestamp : Clock::Now();
......@@ -158,7 +157,7 @@ namespace armarx::armem::robot_state
if (not memoryReader)
{
ARMARX_WARNING << "Memory reader is null. Did you forget to call "
"RobotReader::connect() in onConnectComponent()?";
"RobotReader::connect() in onConnectComponent()?";
return std::nullopt;
}
......@@ -344,7 +343,8 @@ namespace armarx::armem::robot_state
{
try
{
const auto result = transformReader.getGlobalPose(description.name, constants::robotRootNodeName, timestamp);
const auto result = transformReader.getGlobalPose(
description.name, constants::robotRootNodeName, timestamp);
if (not result)
{
return std::nullopt;
......@@ -429,7 +429,7 @@ namespace armarx::armem::robot_state
coreSegment.forEachEntity(
[&jointMap](const wm::Entity& entity)
{
if(not entity.getLatestSnapshot().hasInstance(0))
if (not entity.getLatestSnapshot().hasInstance(0))
{
return;
}
......@@ -564,18 +564,18 @@ namespace armarx::armem::robot_state
}
std::optional<std::map<RobotReader::Hand, robot::ToFArray>> RobotReader::queryToF(const robot::RobotDescription& description,
const armem::Time& timestamp) const
std::optional<std::map<RobotReader::Hand, robot::ToFArray>>
RobotReader::queryToF(const robot::RobotDescription& description,
const armem::Time& timestamp) const
{
// Query all entities from provider.
// Query all entities from provider.
armem::client::query::Builder qb;
ARMARX_DEBUG << "Querying ToF data for robot: " << description;
// clang-format off
qb
.coreSegments().withName(constants::proprioceptionCoreSegment)
.coreSegments().withName(constants::exteroceptionCoreSegment)
.providerSegments().withName(description.name) // agent
.entities().all() // TODO
.snapshots().beforeOrAtTime(timestamp);
......@@ -609,7 +609,7 @@ namespace armarx::armem::robot_state
coreSegment.forEachEntity(
[&platformState](const wm::Entity& entity)
{
if(not entity.getLatestSnapshot().hasInstance(0))
if (not entity.getLatestSnapshot().hasInstance(0))
{
return;
}
......@@ -657,7 +657,7 @@ namespace armarx::armem::robot_state
coreSegment.forEachEntity(
[&forceTorques](const wm::Entity& entity)
{
if(not entity.getLatestSnapshot().hasInstance(0))
if (not entity.getLatestSnapshot().hasInstance(0))
{
return;
}
......@@ -715,14 +715,13 @@ namespace armarx::armem::robot_state
}
std::map<RobotReader::Hand, robot::ToFArray>
RobotReader::getToF(const armarx::armem::wm::Memory& memory,
const std::string& name) const
RobotReader::getToF(const armarx::armem::wm::Memory& memory, const std::string& name) const
{
std::map<RobotReader::Hand, robot::ToFArray> tofs;
// clang-format off
const armem::wm::CoreSegment& coreSegment = memory
.getCoreSegment(constants::proprioceptionCoreSegment);
.getCoreSegment(constants::exteroceptionCoreSegment);
// clang-format on
coreSegment.forEachEntity(
......@@ -730,18 +729,18 @@ namespace armarx::armem::robot_state
{
ARMARX_DEBUG << "Processing ToF element";
if(not entity.getLatestSnapshot().hasInstance(0))
if (not entity.getLatestSnapshot().hasInstance(0))
{
return;
}
const auto& entityInstance = entity.getLatestSnapshot().getInstance(0);
const auto proprioception =
tryCast<::armarx::armem::arondto::Proprioception>(entityInstance);
ARMARX_CHECK(proprioception.has_value());
const auto exteroception =
tryCast<::armarx::armem::arondto::Exteroception>(entityInstance);
ARMARX_CHECK(exteroception.has_value());
for (const auto& [handName, dtoFt] : proprioception->tof)
for (const auto& [handName, dtoFt] : exteroception->tof)
{
ARMARX_DEBUG << "Processing ToF element for hand `" << handName << "`";
......@@ -779,4 +778,70 @@ namespace armarx::armem::robot_state
return robot::convertRobotDescription(*instance);
}
std::vector<robot::RobotDescription>
RobotReader::getRobotDescriptions(const armarx::armem::wm::Memory& memory) const
{
const armem::wm::CoreSegment& coreSegment =
memory.getCoreSegment(constants::descriptionCoreSegment);
std::vector<robot::RobotDescription> descriptions;
coreSegment.forEachInstance(
[&descriptions](const wm::EntityInstance& instance)
{
if (const std::optional<robot::RobotDescription> desc =
robot::convertRobotDescription(instance))
{
descriptions.push_back(desc.value());
}
});
return descriptions;
}
std::vector<robot::RobotDescription>
RobotReader::queryDescriptions(const armem::Time& timestamp)
{
const auto sanitizedTimestamp = timestamp.isValid() ? timestamp : Clock::Now();
// Query all entities from provider.
armem::client::query::Builder qb;
// clang-format off
qb
.coreSegments().withName(constants::descriptionCoreSegment)
.providerSegments().all()
.entities().all()
.snapshots().beforeOrAtTime(sanitizedTimestamp);
// clang-format on
ARMARX_DEBUG << "Lookup query in reader";
if (not memoryReader)
{
ARMARX_WARNING << "Memory reader is null. Did you forget to call "
"RobotReader::connect() in onConnectComponent()?";
return {};
}
try
{
const armem::client::QueryResult qResult = memoryReader.query(qb.buildQueryInput());
ARMARX_DEBUG << "Lookup result in reader: " << qResult;
if (not qResult.success) /* c++20 [[unlikely]] */
{
return {};
}
return getRobotDescriptions(qResult.memory);
}
catch (...)
{
ARMARX_VERBOSE << "Query description failure" << GetHandledExceptionString();
}
return {};
}
} // namespace armarx::armem::robot_state
......@@ -23,6 +23,7 @@
#include <mutex>
#include <optional>
#include <vector>
#include <RobotAPI/libraries/armem/client/MemoryNameSystem.h>
#include <RobotAPI/libraries/armem/client/Reader.h>
......@@ -60,6 +61,8 @@ namespace armarx::armem::robot_state
std::optional<robot::RobotDescription> queryDescription(const std::string& name,
const armem::Time& timestamp);
std::vector<robot::RobotDescription> queryDescriptions(const armem::Time& timestamp);
std::optional<robot::RobotState> queryState(const robot::RobotDescription& description,
const armem::Time& timestamp);
......@@ -100,8 +103,8 @@ namespace armarx::armem::robot_state
const armem::Time& end) const;
std::optional<std::map<Hand, robot::ToFArray>> queryToF(const robot::RobotDescription& description,
const armem::Time& timestamp) const;
std::optional<std::map<Hand, robot::ToFArray>>
queryToF(const robot::RobotDescription& description, const armem::Time& timestamp) const;
/**
* @brief retrieve the robot's pose in the odometry frame.
......@@ -128,6 +131,9 @@ namespace armarx::armem::robot_state
std::optional<robot::RobotDescription>
getRobotDescription(const armarx::armem::wm::Memory& memory, const std::string& name) const;
std::vector<robot::RobotDescription>
getRobotDescriptions(const armarx::armem::wm::Memory& memory) const;
std::optional<robot::RobotState::JointMap>
getRobotJointState(const armarx::armem::wm::Memory& memory, const std::string& name) const;
......@@ -145,8 +151,8 @@ namespace armarx::armem::robot_state
std::map<RobotReader::Hand, std::map<armem::Time, robot::ForceTorque>>
getForceTorques(const armarx::armem::wm::Memory& memory, const std::string& name) const;
std::map<RobotReader::Hand, robot::ToFArray>
getToF(const armarx::armem::wm::Memory& memory, const std::string& name) const;
std::map<RobotReader::Hand, robot::ToFArray> getToF(const armarx::armem::wm::Memory& memory,
const std::string& name) const;
struct Properties
{
......
......@@ -38,11 +38,11 @@ namespace armarx::armem::robot_state
bool
VirtualRobotReader::synchronizeRobot(VirtualRobot::Robot& robot, const armem::Time& timestamp)
{
const static auto packages = armarx::CMakePackageFinder::FindAllArmarXSourcePackages();
const auto package = armarx::ArmarXDataPath::getProject(packages, robot.getFilename());
// const static auto packages = armarx::CMakePackageFinder::FindAllArmarXSourcePackages();
// const auto package = armarx::ArmarXDataPath::getProject(packages, robot.getFilename());
const robot::RobotDescription robotDescription{
.name = robot.getName(), .xml = PackagePath{package, robot.getFilename()}};
.name = robot.getName(), .xml = PackagePath{"", ""}};
const auto robotState = queryState(robotDescription, timestamp);
if (not robotState)
......
......@@ -27,7 +27,6 @@
#include "RobotReader.h"
namespace armarx::armem::robot_state
{
/**
......@@ -47,7 +46,8 @@ namespace armarx::armem::robot_state
void connect();
void registerPropertyDefinitions(::armarx::PropertyDefinitionsPtr& def);
bool synchronizeRobot(VirtualRobot::Robot& robot, const armem::Time& timestamp);
[[nodiscard]] bool synchronizeRobot(VirtualRobot::Robot& robot,
const armem::Time& timestamp);
[[nodiscard]] VirtualRobot::RobotPtr
getRobot(const std::string& name,
......@@ -70,14 +70,12 @@ namespace armarx::armem::robot_state
private:
[[nodiscard]] VirtualRobot::RobotPtr
_getSynchronizedRobot(const std::string& name,
const armem::Time& timestamp = armem::Time::Invalid(),
const VirtualRobot::RobotIO::RobotDescription& loadMode =
VirtualRobot::RobotIO::RobotDescription::eStructure,
VirtualRobot::RobotIO::RobotDescription::eStructure,
bool blocking = true);
};
} // namespace armarx::armem::robot_state
......@@ -28,6 +28,7 @@ namespace armarx::armem::robot_state::constants
inline const std::string descriptionCoreSegment = "Description";
inline const std::string localizationCoreSegment = "Localization";
inline const std::string proprioceptionCoreSegment = "Proprioception";
inline const std::string exteroceptionCoreSegment = "Exteroception";
inline const std::string descriptionEntityName = "description";
......
......@@ -30,6 +30,7 @@ namespace armarx::armem
const MemoryID robot_state::descriptionSegmentID { memoryID.withCoreSegmentName("Description") };
const MemoryID robot_state::proprioceptionSegmentID { memoryID.withCoreSegmentName("Proprioception") };
const MemoryID robot_state::exteroceptionSegmentID { memoryID.withCoreSegmentName("Exteroception") };
const MemoryID robot_state::localizationSegmentID { memoryID.withCoreSegmentName("Localization") };
......