28#include <opencv2/opencv.hpp>
36 const std::string SimpleEpisodicMemory::NO_EPISODE =
"NO_EPISODE";
39 {EpisodeStatus::EPISODE_STARTED,
"started"},
40 {EpisodeStatus::EPISODE_COMPLETED_SUCCESS,
"success"},
41 {EpisodeStatus::EPISODE_COMPLETED_FAILURE,
"failure"},
42 {EpisodeStatus::EPISODE_COMPLETED_ABORT,
"abort"},
46 {ActionStatus::ACTION_STARTED,
"started"},
47 {ActionStatus::ACTION_RUNNING,
"running"},
48 {ActionStatus::ACTION_REPEATED,
"repeated"},
49 {ActionStatus::ACTION_COMPLETED_SUCCESS,
"success"},
50 {ActionStatus::ACTION_COMPLETED_FAILURE,
"failure"},
55 {ObjectPoseEventType::NEW_OBJECT_RECOGNIZED,
"newly detected"},
56 {ObjectPoseEventType::OBJECT_POSE_UPDATE,
"updated"},
62 return "SimpleEpisodicMemory";
68 return "SimpleEpisodicMemory";
74 m_enable_export =
true;
75 m_export_folder =
"/tmp/EMExport";
95 SimpleEpisodicMemory::export_episode()
const
98 if (m_current_episode.episodeName == NO_EPISODE)
102 if (m_current_episode.imageEvents.size() + m_current_episode.actionEvents.size() +
103 m_current_episode.humanPoseEvents.size() + m_current_episode.speechEvents.size() +
104 m_current_episode.objectPoseEvents.size() +
105 m_current_episode.kinematicUnitEvents.size() +
106 m_current_episode.platformUnitEvents.size() +
107 m_current_episode.platformUnitTargetEvents.size() ==
114 if (std::filesystem::exists(m_export_folder))
116 const std::string episode_output =
117 m_export_folder +
"/episode_" + std::to_string(m_current_episode.startedInMs) +
"/";
118 if (!std::filesystem::create_directory(episode_output))
120 ARMARX_ERROR <<
"Couldn't create episode folder: " << episode_output;
124 const std::string camera_output = episode_output +
"camera/";
125 if (!std::filesystem::create_directory(camera_output))
131 const std::string object_output = episode_output +
"objects/";
132 if (!std::filesystem::create_directory(object_output))
138 const std::string action_output = episode_output +
"actions/";
139 if (!std::filesystem::create_directory(action_output))
145 const std::string human_poses_output = episode_output +
"poses/";
146 if (!std::filesystem::create_directory(human_poses_output))
152 const std::string speech_output = episode_output +
"speech/";
153 if (!std::filesystem::create_directory(speech_output))
159 const std::string platformUnit_output = episode_output +
"platformUnit/";
160 if (!std::filesystem::create_directory(platformUnit_output))
166 const std::string platformUnitTarget_output = episode_output +
"platformUnitTarget/";
167 if (!std::filesystem::create_directory(platformUnitTarget_output))
169 ARMARX_ERROR <<
"Couldn't create platformUnitTarget folder";
173 const std::string kinematicUnit_output = episode_output +
"kinematicUnit/";
174 if (!std::filesystem::create_directory(kinematicUnit_output))
186 std::filesystem::path path{episode_output +
"episode.json"};
188 std::ofstream e_ofs(path);
190 e_ofs <<
"\t\"name\": \"" + m_current_episode.episodeName +
"\",\n";
191 e_ofs <<
"\t\"status\": \"" +
193 m_current_episode.status) +
195 e_ofs <<
"\t\"started\": \"" + std::to_string(m_current_episode.startedInMs) +
197 e_ofs <<
"\t\"ended\": \"" + std::to_string(m_current_episode.endedInMs) +
"\"\n";
205 for (
const auto& objectEvent : m_current_episode.objectPoseEvents)
207 const double timestamp = objectEvent.receivedInMs;
209 std::ofstream o_ofs(object_output +
"obj_" + std::to_string(
timestamp) +
212 o_ofs <<
"\t\"name\": \"" + objectEvent.objectName +
"\",\n";
213 o_ofs <<
"\t\"position\": [" + std::to_string(objectEvent.x) +
", " +
214 std::to_string(objectEvent.y) +
", " +
215 std::to_string(objectEvent.z) +
"],\n";
216 o_ofs <<
"\t\"started\": \"" + std::to_string(
timestamp) +
"\",\n";
217 o_ofs <<
"\t\"frame\": \"" + objectEvent.frame +
"\",\n";
218 o_ofs <<
"\t\"type\": \"" +
229 for (
const auto& actionEvent : m_current_episode.actionEvents)
231 const double timestamp = actionEvent.receivedInMs;
233 std::ofstream a_ofs(action_output +
"act_" + std::to_string(
timestamp) +
236 a_ofs <<
"\t\"name\": \"" + actionEvent.actionName +
"\",\n";
237 a_ofs <<
"\t\"status\": \"" +
239 actionEvent.status) +
241 a_ofs <<
"\t\"started\": \"" + std::to_string(
timestamp) +
"\"\n";
250 for (
const auto& humanPose : m_current_episode.humanPoseEvents)
252 const double timestamp = humanPose.receivedInMs;
254 std::ofstream p_ofs(human_poses_output +
"pose_" + std::to_string(
timestamp) +
258 for (
const auto& [label, keypoint] : humanPose.keypoints)
260 p_ofs <<
"\t\"" + label +
"\":\n";
262 p_ofs <<
"\t\t \"confidence\": " + std::to_string(keypoint.confidence) +
264 p_ofs <<
"\t\t \"local\": [" + std::to_string(keypoint.x) +
", " +
265 std::to_string(keypoint.y) +
", " +
266 std::to_string(keypoint.z) +
" ],\n";
267 p_ofs <<
"\t\t \"global\": [" + std::to_string(keypoint.globalX) +
", " +
268 std::to_string(keypoint.globalY) +
", " +
269 std::to_string(keypoint.globalZ) +
" ]\n";
280 for (
const auto& speech : m_current_episode.speechEvents)
282 const double timestamp = speech.receivedInMs;
284 std::ofstream s_ofs(speech_output +
"speech_" + std::to_string(
timestamp) +
287 s_ofs <<
"\t \"text\": " << speech.text <<
"\n";
296 for (
const auto& kinematicUnit : m_current_episode.kinematicUnitEvents)
298 const double timestamp = kinematicUnit.receivedInMs;
300 std::ofstream k_ofs(kinematicUnit_output +
"kinematicUnit_" +
303 for (
const auto& [key, value] : kinematicUnit.data)
305 k_ofs <<
"\t \"" + key +
"\": {\n";
306 k_ofs <<
"\t\t \"jointAngle\": \"" <<
value.jointAngle <<
"\",\n";
307 k_ofs <<
"\t\t \"jointVelocity\": \"" <<
value.jointVelocity <<
"\",\n";
308 k_ofs <<
"\t\t \"jointTorque\": \"" <<
value.jointTorque <<
"\",\n";
309 k_ofs <<
"\t\t \"jointAcceleration\": \"" <<
value.jointAcceleration
311 k_ofs <<
"\t\t \"current\": \"" <<
value.current <<
"\",\n";
312 k_ofs <<
"\t\t \"temperature\": \"" <<
value.temperature <<
"\",\n";
313 k_ofs <<
"\t\t \"enabled\": \"" <<
value.enabled <<
"\"\n";
324 for (
const auto& platformUnit : m_current_episode.platformUnitEvents)
326 const double timestamp = platformUnit.receivedInMs;
328 std::ofstream p_ofs(platformUnit_output +
"platformUnit_" +
331 p_ofs <<
"\t \"x\": \"" << platformUnit.x <<
"\",\n";
332 p_ofs <<
"\t \"y\": \"" << platformUnit.y <<
"\",\n";
333 p_ofs <<
"\t \"rot\": \"" << platformUnit.rot <<
"\",\n";
334 p_ofs <<
"\t \"acc_x\": \"" << platformUnit.acc_x <<
"\",\n";
335 p_ofs <<
"\t \"acc_y\": \"" << platformUnit.acc_y <<
"\",\n";
336 p_ofs <<
"\t \"acc_rot\": \"" << platformUnit.acc_rot <<
"\"\n";
345 for (
const auto& platformUnitTarget : m_current_episode.platformUnitTargetEvents)
347 const double timestamp = platformUnitTarget.receivedInMs;
349 std::ofstream t_ofs(platformUnitTarget_output +
"platformUnitTarget_" +
352 t_ofs <<
"\t \"x\": \"" << platformUnitTarget.target_x <<
"\",\n";
353 t_ofs <<
"\t \"y\": \"" << platformUnitTarget.target_y <<
"\",\n";
354 t_ofs <<
"\t \"rot\": \"" << platformUnitTarget.target_rot <<
"\"\n";
364 for (
const auto& [imageProvider, imageEventList] : m_current_episode.imageEvents)
366 if (imageEventList.size() == 0)
370 const std::string image_provider_output = camera_output + imageProvider +
"/";
371 if (!std::filesystem::create_directory(image_provider_output))
373 ARMARX_ERROR <<
"Couldn't create image provider folder: " + imageProvider;
377 for (
const auto& imageEvent : imageEventList)
379 const double timestamp = imageEvent.receivedInMs;
382 if (imageEvent.colourType == memoryx::ColourSpace::GRAYSCALE)
386 std::vector<uchar>
data(imageEvent.data);
387 ARMARX_DEBUG <<
"Image size is " << imageEvent.width <<
", "
388 << imageEvent.height <<
", " << imageEvent.colourType <<
" => "
389 << imageEvent.data.size();
391 cv::Mat(imageEvent.height, imageEvent.width, mode,
data.data());
393 cv::cvtColor(cv_image, cv_image, cv::COLOR_RGB2BGR);
394 cv::imwrite(image_provider_output +
"img_" + std::to_string(
timestamp) +
398 <<
"Exporting image to: img_" + std::to_string(
timestamp) +
".jpg";
405 ARMARX_ERROR <<
"Cannot export files because folder does not exist: "
411 SimpleEpisodicMemory::clearAll()
414 m_current_episode.episodeName = NO_EPISODE;
415 m_current_episode.startedInMs = IceUtil::Time::now().toMilliSecondsDouble();
416 m_current_episode.status = EpisodeStatus::EPISODE_STARTED;
422 std::lock_guard<std::mutex> l(episodeEventMutex);
423 if (m_current_episode.episodeName != e.episodeName && e.status != EPISODE_STARTED)
425 ARMARX_ERROR <<
"Received an episode unequal to current one with non-starting status: "
428 if (m_current_episode.episodeName != e.episodeName && m_current_episode.endedInMs != 0 &&
429 e.status == EPISODE_STARTED)
431 ARMARX_WARNING <<
"Received a new starting episode without ending the last one. Last "
433 << m_current_episode.episodeName <<
". Finishing it now.";
435 abort.episodeName = m_current_episode.episodeName;
436 abort.status = EpisodeStatus::EPISODE_COMPLETED_ABORT;
437 abort.receivedInMs = IceUtil::Time::now().toMilliSecondsDouble();
441 if (e.status == EPISODE_COMPLETED_SUCCESS || e.status == EPISODE_COMPLETED_FAILURE ||
442 e.status == EPISODE_COMPLETED_ABORT)
444 ARMARX_DEBUG <<
"Received a terminating episode (" << e.episodeName <<
")";
445 m_current_episode.status = e.status;
446 m_current_episode.endedInMs = e.receivedInMs;
450 ARMARX_DEBUG <<
"Received a starting episode (" << e.episodeName <<
")";
451 m_current_episode.episodeName = e.episodeName;
452 m_current_episode.status = e.status;
453 m_current_episode.startedInMs = e.receivedInMs;
456 std::lock_guard<std::mutex> l2(imageEventMutex);
457 std::lock_guard<std::mutex> l3(humanPoseEventMutex);
458 std::lock_guard<std::mutex> l4(speechEventMutex);
459 std::lock_guard<std::mutex> l5(objectPoseEventMutex);
460 std::lock_guard<std::mutex> l6(kinematicUnitEventMutex);
461 std::lock_guard<std::mutex> l7(platformUnitEventMutex);
462 std::lock_guard<std::mutex> l8(platformUnitTargetEventMutex);
463 std::lock_guard<std::mutex> l9(actionEventMutex);
464 if (m_enable_export && m_current_episode.endedInMs != 0)
475 std::lock_guard<std::mutex> l(imageEventMutex);
476 ARMARX_DEBUG <<
"Received an image. Current number of images of provider " << i.providerName
478 << this->m_current_episode.imageEvents[i.providerName].size();
479 this->m_current_episode.imageEvents[i.providerName].push_back(i);
485 std::lock_guard<std::mutex> l(objectPoseEventMutex);
486 ARMARX_DEBUG <<
"Received an objectPose (" << o.objectName
487 <<
"). Current number of objectPoses in episode: "
488 << this->m_current_episode.objectPoseEvents.size();
489 this->m_current_episode.objectPoseEvents.push_back(o);
495 std::lock_guard<std::mutex> l(actionEventMutex);
496 ARMARX_DEBUG <<
"Received an action (" << a.actionName <<
" with status "
498 <<
")Current number of actions in episode: "
499 << this->m_current_episode.actionEvents.size();
500 this->m_current_episode.actionEvents.push_back(a);
506 std::lock_guard<std::mutex> l(humanPoseEventMutex);
507 ARMARX_DEBUG <<
"Received a human pose. Current number of poses in episode: "
508 << this->m_current_episode.humanPoseEvents.size();
509 this->m_current_episode.humanPoseEvents.push_back(p);
515 if (s.text.find(
"export now") != std::string::npos)
517 ARMARX_IMPORTANT <<
"Received export token!. Terminating current episode and create an "
520 terminate.episodeName = m_current_episode.episodeName;
521 terminate.status = EpisodeStatus::EPISODE_COMPLETED_ABORT;
522 terminate.receivedInMs = IceUtil::Time::now().toMilliSecondsDouble();
527 std::lock_guard<std::mutex> l(speechEventMutex);
529 <<
"). Current number of speeches in episode: "
530 << this->m_current_episode.speechEvents.size();
531 this->m_current_episode.speechEvents.push_back(s);
538 std::lock_guard<std::mutex> l(kinematicUnitEventMutex);
539 ARMARX_DEBUG <<
"Received a kinematicUnitEvent. Current number of events in episode: "
540 << this->m_current_episode.kinematicUnitEvents.size();
541 this->m_current_episode.kinematicUnitEvents.push_back(k);
547 std::lock_guard<std::mutex> l(platformUnitEventMutex);
548 ARMARX_DEBUG <<
"Received a platformUnitEvent. Current number of events in episode: "
549 << this->m_current_episode.platformUnitEvents.size();
550 this->m_current_episode.platformUnitEvents.push_back(p);
557 std::lock_guard<std::mutex> l(platformUnitTargetEventMutex);
558 ARMARX_DEBUG <<
"Received a platformUnitTarget. Current number of events in episode: "
559 << this->m_current_episode.platformUnitTargetEvents.size();
560 this->m_current_episode.platformUnitTargetEvents.push_back(t);
#define ARMARX_REGISTER_COMPONENT_EXECUTABLE(ComponentT, applicationName)
Default component property definition container.
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
void terminate()
Initiates termination of this IceManagedObject.
void onInitComponent() override
Pure virtual hook for the subclass.
void onDisconnectComponent() override
Hook for subclass.
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
void registerHumanPoseEvent(const Body25HumanPoseEvent &, const Ice::Current &=Ice::emptyCurrent) override
static const std::map< ActionStatus, std::string > action_status_descriptor
void registerObjectPoseEvent(const ObjectPoseEvent &, const Ice::Current &=Ice::emptyCurrent) override
void registerKinematicUnitEvent(const KinematicUnitEvent &, const Ice::Current &=Ice::emptyCurrent) override
void registerActionEvent(const ActionEvent &, const Ice::Current &=Ice::emptyCurrent) override
void registerSpeechEvent(const SpeechEvent &, const Ice::Current &=Ice::emptyCurrent) override
void onConnectComponent() override
Pure virtual hook for the subclass.
void registerImageEvent(const ImageEvent &, const Ice::Current &=Ice::emptyCurrent) override
static std::string GetDefaultName()
void notifyKeyframe(const Ice::Current &=Ice::emptyCurrent) override
void onExitComponent() override
Hook for subclass.
void registerPlatformUnitEvent(const PlatformUnitEvent &, const Ice::Current &=Ice::emptyCurrent) override
void registerPlatformUnitTargetEvent(const PlatformUnitTargetEvent &, const Ice::Current &=Ice::emptyCurrent) override
std::string getDefaultName() const override
Retrieve default name of component.
static const std::map< EpisodeStatus, std::string > episode_status_descriptor
void registerEpisodeEvent(const EpisodeEvent &, const Ice::Current &=Ice::emptyCurrent) override
static const std::map< ObjectPoseEventType, std::string > object_type_descriptor
#define ARMARX_IMPORTANT
The logging level for always important information, but expected behaviour (in contrast to ARMARX_WAR...
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
std::shared_ptr< Value > value()