26 #include <visualization_msgs/Marker.h> 27 #include <visualization_msgs/MarkerArray.h> 29 #include <asr_ism_visualizations/VizHelperRVIZ.hpp> 31 #include <ISM/utility/TableHelper.hpp> 32 #include <ISM/common_type/Pose.hpp> 33 #include <ISM/common_type/Track.hpp> 34 #include <ISM/common_type/Tracks.hpp> 36 #include <ISM/utility/GeometryHelper.hpp> 37 #include <ISM/utility/Util.hpp> 45 #include <rapidxml.hpp> 46 #include <rapidxml_utils.hpp> 48 #include <boost/lexical_cast.hpp> 49 #include <boost/algorithm/string.hpp> 50 #include <boost/filesystem/path.hpp> 57 #define KEY_NEXT_OBJECT 0x77 //w 58 #define KEY_PREV_OBJECT 0x73 //s 59 #define KEY_NEXT_POSE 0x64 //d 60 #define KEY_PREV_POSE 0x61 //a 61 #define KEY_SWITCH_EDIT 0x65 //e 62 #define KEY_MARK 0x6D //m 63 #define KEY_SAVE 0x6F //o 64 #define KEY_SHOW 0x70 //p 73 std::vector<std::string> patternNames;
74 std::string configFilePath;
77 if (boost::filesystem::exists(configFilePath))
79 ISM::printGreen(
"Load objects from config-file.\n");
84 ISM::printGreen(
"Load objects from database.\n");
85 if (patternNames.empty())
88 ss <<
"Parameter object_configuration_pattern_names must be specified, if database is used!";
90 throw std::runtime_error(ss.str());
94 if(!tableHandler->recordDataExists())
97 ss <<
"The database \"" <<
mDbFilename <<
"\" doesn't contain any recordings!\n";
99 throw std::runtime_error(ss.str());
106 std::stringstream ss;
107 ss <<
"Couldn't load any data! Check path to config-file or to database in the launch-file." << std::endl;
109 throw std::runtime_error(ss.str());
114 ISM::printGreen(
"WAITING FOR SUBSCRIBER\n");
115 while (visualization_pub.getNumSubscribers() == 0) {
120 ISM::printGreen(
"Started Object Configuration Generator!\n\n");
125 #include <boost/filesystem/path.hpp> 146 nh.
getParam(
"object_configuration_pattern_names", patternNames);
148 for (
unsigned int i = 0; i < patternNames.size(); ++i)
167 std::stringstream ss;
168 ss <<
"Parameter output_file_path must be specified!";
170 throw std::runtime_error(ss.str());
174 if (!
nh.
getParam(
"config_file_path", configFilePath))
178 ROS_INFO_STREAM(
"config_file_path: " << configFilePath);
187 for (
unsigned int i = 0; i <
markerArray.markers.size(); ++i)
189 markerArray.markers[i].action = visualization_msgs::Marker::DELETE;
194 unsigned int markerCount = 0;
198 std::pair<ISM::ObjectPtr, std::vector<ISM::PosePtr>> pair =
objectAndPoses[i];
199 std::string path = pair.first->ressourcePath.string();
210 ISM::PosePtr pose = pair.second[idx];
212 Eigen::Quaternion<double> rot = ISM::GeometryHelper::quatToEigenQuat(pose->quat);
213 Eigen::Matrix3d rotation = rot.toRotationMatrix();
215 Eigen::Vector3d xAxis = rotation * Eigen::Vector3d::UnitX() * 0.5;
216 Eigen::Vector3d yAxis = rotation * Eigen::Vector3d::UnitY() * 0.5;
217 Eigen::Vector3d zAxis = rotation * Eigen::Vector3d::UnitZ() * 0.5;
219 ISM::PointPtr xEnd = ISM::PointPtr(
new ISM::Point(pose->point->eigen.x() + xAxis[0],
220 pose->point->eigen.y() + xAxis[1],
221 pose->point->eigen.z() + xAxis[2]));
222 ISM::PointPtr yEnd = ISM::PointPtr(
new ISM::Point(pose->point->eigen.x() + yAxis[0],
223 pose->point->eigen.y() + yAxis[1],
224 pose->point->eigen.z() + yAxis[2]));
225 ISM::PointPtr zEnd = ISM::PointPtr(
new ISM::Point(pose->point->eigen.x() + zAxis[0],
226 pose->point->eigen.y() + zAxis[1],
227 pose->point->eigen.z() + zAxis[2]));
236 for (
unsigned int j = 0; j < pair.second.size(); ++j)
258 std_msgs::ColorRGBA color = VIZ::VizHelperRVIZ::getColorOfObject(pair.first);
276 ISM::printBlue(
"\tUNMARKED OBJECT\n");
281 ISM::printBlue(
"\tMARKED OBJECT\n");
292 bool gotAnyObjects =
false;
293 std::vector<ISM::ObjectSetPtr> objectsInPattern;
294 for(
unsigned int i = 0; i < patternNames.size(); ++i)
296 std::string patternName = patternNames.at(i);
297 if (
tableHandler->getRecordedPatternId(patternName) == 0)
299 std::stringstream ss;
300 ss <<
"Could not find pattern " + patternName +
" in database " +
mDbFilename +
"!";
306 ISM::printGreen(
"Load pattern \"" + patternName +
"\" from database.\n");
309 std::vector<ISM::ObjectSetPtr> objects =
tableHandler->getRecordedPattern(patternName)->objectSets;
310 objectsInPattern.insert(objectsInPattern.end(), objects.begin(), objects.end());
312 gotAnyObjects = gotAnyObjects || !objects.empty();
316 std::stringstream ss;
317 ss <<
"Couldn't load any data! Check your database or selected pattern." << std::endl;
319 throw std::runtime_error(ss.str());
321 ISM::TracksPtr tracksInPattern = ISM::TracksPtr(
new ISM::Tracks(objectsInPattern));
323 for (
size_t it = 0; it < tracksInPattern->tracks.size(); ++it)
325 if (it < tracksInPattern->tracks.size() - 1 && !tracksInPattern->tracks[it]->objects.size() == tracksInPattern->tracks[it + 1]->objects.size())
327 std::cerr<<
"Corrupt database\n";
332 for (
unsigned int i = 0; i < tracksInPattern->tracks.size(); ++i)
334 std::vector<ISM::ObjectPtr> objects = tracksInPattern->tracks[i]->objects;
335 std::vector<ISM::PosePtr> poses;
338 for (ISM::ObjectPtr
object : objects)
342 poses.push_back(object->pose);
346 obj = ISM::ObjectPtr(
new ISM::Object(*
object));
351 std::stringstream ss;
352 ss <<
"Loaded " << obj->type <<
" " << obj->observedId <<
" from database with " << poses.size() <<
" poses." << std::endl;
353 ISM::printGreen(ss.str());
373 std::string pose_str =
" at ";
376 pose_str +=
"edited pose";
395 ISM::printBlue(
"\tSWITCHED TO EDITED POSE\n" );
411 tcgetattr( STDIN_FILENO, &originalSettings);
428 std::stringstream commands;
429 commands <<
"Possible commands:\n" 430 <<
"\tpress \"w\"\tchoose next object for pose configuration\n" 431 <<
"\tpress \"s\"\tchoose previous object for pose configuration\n" 432 <<
"\tpress \"a\"\tchoose previous object pose for pose configuration\n" 433 <<
"\tpress \"d\"\tchoose next object pose for pose configuration\n" 434 <<
"\tpress \"m\"\tmark selected pose\n" 435 <<
"\tpress \"p\"\tshow marked objects\n" 436 <<
"\tpress \"o\"\tsave marked (red) object poses to file\n" 437 <<
"\tpress \"e\"\tchange into edit mode\n";
439 ISM::printYellow(commands.str() +
"\n");
451 ISM::printRed(
"X-Axis is red\n");
452 ISM::printGreen(
"Y-Axis is green\n");
453 ISM::printBlue(
"Z-Axis is blue\n");
455 std::stringstream commands;
456 commands <<
"\nPossible commands:\n" 457 <<
"\ttype \"s\" and enter\tsave pose changes\n" 458 <<
"\ttype \"d\" and enter\tdiscard pose changes\n";
460 ISM::printYellow(commands.str() +
"\n");
469 ISM::printBlue(
"MARKED OBJECTS:\n");
474 std::string pose_str =
" at ";
477 pose_str +=
"edited pose";
498 int tempKeyValue = getchar();
499 tcflush(STDIN_FILENO, TCIFLUSH);
502 if (tempKeyValue < 0)
532 ISM::printBlue(
"\tSWITCHED INTO EDITING MODE\n");
534 tcsetattr( STDIN_FILENO, TCSANOW, &originalSettings);
542 ISM::printBlue(
"\tSAVED OBJECT CONFIGURATION TO " +
output_file_path +
"\n");
558 std::vector<double> editParameters;
559 editParameters.reserve(6);
560 unsigned int editCounter = 0;
571 ISM::printGreen(
"\tEnter offset along ");
575 ISM::printGreen(
"\tEnter rotation around ");
578 if (editCounter % 3 == 0) ISM::printRed(
"x-axis ");
579 if (editCounter % 3 == 1) ISM::printGreen(
"y-axis ");
580 if (editCounter % 3 == 2) ISM::printBlue(
"z-axis ");
584 ISM::printGreen(
"(in meters): \n\t");
588 ISM::printGreen(
"(in degree): \n\t");
592 std::getline(std::cin, value);
594 if (value.compare(
"s") == 0)
596 ISM::printBlue(
"\tSAVED CHANGES\n\tEXITED EDITING MODE\n");
611 ISM::printBlue(
"\tOBJECT MARKED\n");
616 else if (value.compare(
"d") == 0)
618 ISM::printRed(
"\tDISCARDED CHANGES\n");
619 ISM::printBlue(
"\tEXITED EDITING MODE\n");
630 double offset = value.empty() ? 0.0 : boost::lexical_cast<
double>(value);
643 rotate(offset, 0, 0, pose);
646 rotate(0, offset, 0, pose);
649 rotate(0, 0, offset, pose);
653 editCounter = (editCounter + 1) % 6;
656 catch(boost::bad_lexical_cast& e)
679 std::ofstream myfile;
680 std::ostringstream
s;
682 myfile <<
"<Objects>";
690 Eigen::Quaterniond poseQuat(pose->quat->eigen.w(),
691 pose->quat->eigen.x(),
692 pose->quat->eigen.y(),
693 pose->quat->eigen.z());
694 Eigen::Matrix3d poseMat = poseQuat.toRotationMatrix();
695 Eigen::Vector3d poseAngles = poseMat.eulerAngles(0,1,2);
698 <<
"type=\"" << obj->type
699 <<
"\" id=\"" << obj->observedId
700 <<
"\" mesh=\"" << obj->ressourcePath.string()
701 <<
"\" angles=\"euler\">" << pose->point->eigen.x()
702 <<
"," << pose->point->eigen.y()
703 <<
"," << pose->point->eigen.z()
704 <<
"," << poseAngles[0]*180/M_PI
705 <<
"," << poseAngles[1]*180/M_PI
706 <<
"," << poseAngles[2]*180/M_PI
710 myfile <<
"</Objects>";
722 void rotate(
double alpha,
double beta,
double gamma, ISM::PosePtr pose)
724 Eigen::Matrix3d rotateBy;
725 rotateBy = Eigen::AngleAxisd(alpha * (M_PI / 180), Eigen::Vector3d::UnitX())
726 * Eigen::AngleAxisd(beta * (M_PI / 180), Eigen::Vector3d::UnitY())
727 * Eigen::AngleAxisd(gamma * (M_PI / 180), Eigen::Vector3d::UnitZ());
729 Eigen::Quaternion<double> rot = ISM::GeometryHelper::quatToEigenQuat(pose->quat);
730 Eigen::Matrix3d original = rot.toRotationMatrix();
731 original = original * rotateBy;
732 Eigen::Quaternion<double> result(original);
733 pose->quat = ISM::GeometryHelper::eigenQuatToQuat(result);
743 void translate(
double x,
double y,
double z, ISM::PosePtr pose)
745 Eigen::Quaternion<double> rot = ISM::GeometryHelper::quatToEigenQuat(pose->quat);
746 Eigen::Matrix3d rotationMat = rot.toRotationMatrix();
748 Eigen::Vector3d xAxis = rotationMat * Eigen::Vector3d::UnitX() * x;
749 Eigen::Vector3d yAxis = rotationMat * Eigen::Vector3d::UnitY() * y;
750 Eigen::Vector3d zAxis = rotationMat * Eigen::Vector3d::UnitZ() * z;
752 Eigen::Vector3d
add = xAxis + yAxis + zAxis;
754 pose->point->eigen.x() = pose->point->eigen.x() + add[0];
755 pose->point->eigen.y() = pose->point->eigen.y() + add[1];
756 pose->point->eigen.z() = pose->point->eigen.z() + add[2];
766 std::string xml_path = configFilePath;
770 rapidxml::file<> xmlFile(xml_path.c_str());
771 rapidxml::xml_document<> doc;
772 doc.parse<0>(xmlFile.data());
774 rapidxml::xml_node<> *root_node = doc.first_node();
776 rapidxml::xml_node<> *child_node = root_node->first_node();
778 rapidxml::xml_attribute<> *type_attribute = child_node->first_attribute(
"type");
779 rapidxml::xml_attribute<> *id_attribute = child_node->first_attribute(
"id");
780 rapidxml::xml_attribute<> *mesh_attribute = child_node->first_attribute(
"mesh");
781 rapidxml::xml_attribute<> *angles_attribute = child_node->first_attribute(
"angles");
783 if (type_attribute && id_attribute && mesh_attribute && angles_attribute)
785 std::string
angle = angles_attribute->value();
786 std::string pose_string = child_node->value();
791 ISM::ObjectPtr obj = ISM::ObjectPtr(
new ISM::Object(type_attribute->value(), id_attribute->value(), mesh_attribute->value()));
792 std::vector<ISM::PosePtr> poses;
793 poses.push_back(pose);
799 std::stringstream ss;
800 ss <<
"Loaded " << obj->type <<
" " << obj->observedId <<
" from config-file." << std::endl;
801 ISM::printGreen(ss.str());
805 std::stringstream ss;
806 ss <<
"Couldn't parse pose for " << type_attribute->value() <<
" " << id_attribute->value() <<
" from config-file!" << std::endl;
807 ISM::printRed(ss.str());
812 ISM::printRed(
"Couldn't load object from config-file! Check format of the file.\n");
814 child_node = child_node->next_sibling();
817 }
catch(std::runtime_error err) {
819 }
catch (rapidxml::parse_error err) {
833 std::vector<std::string> strvec;
835 boost::algorithm::trim_if(pose_string, boost::algorithm::is_any_of(delim));
836 boost::algorithm::split(strvec, pose_string, boost::algorithm::is_any_of(delim), boost::algorithm::token_compress_on);
837 if (strvec.size() == 6 || strvec.size() == 7 ) {
839 double x = boost::lexical_cast<
double>(strvec[0]);
840 double y = boost::lexical_cast<
double>(strvec[1]);
841 double z = boost::lexical_cast<
double>(strvec[2]);
842 ISM::PointPtr pointPtr = ISM::PointPtr(
new ISM::Point(x, y, z));
844 if(angles ==
"quaternion" && strvec.size() == 7)
846 double qW = boost::lexical_cast<
double>(strvec[3]);
847 double qX = boost::lexical_cast<
double>(strvec[4]);
848 double qY = boost::lexical_cast<
double>(strvec[5]);
849 double qZ = boost::lexical_cast<
double>(strvec[6]);
850 ISM::QuaternionPtr quatPtr = ISM::QuaternionPtr(
new ISM::Quaternion(qW, qX, qY, qZ));
851 pose = ISM::PosePtr(
new ISM::Pose(pointPtr, quatPtr));
855 else if(angles ==
"euler" && strvec.size() == 6)
857 double qX = boost::lexical_cast<
double>(strvec[3]) * (M_PI / 180);
858 double qY = boost::lexical_cast<
double>(strvec[4]) * (M_PI / 180);
859 double qZ = boost::lexical_cast<
double>(strvec[5]) * (M_PI / 180);
860 Eigen::Matrix3d rotMat;
861 rotMat = Eigen::AngleAxisd(qX, Eigen::Vector3d::UnitX())
862 * Eigen::AngleAxisd(qY, Eigen::Vector3d::UnitY())
863 * Eigen::AngleAxisd(qZ, Eigen::Vector3d::UnitZ());
865 Eigen::Quaterniond quat(rotMat);
866 ISM::QuaternionPtr quatPtr = ISM::QuaternionPtr(
new ISM::Quaternion(quat.w(), quat.x(), quat.y(), quat.z()));
867 pose = ISM::PosePtr(
new ISM::Pose(pointPtr, quatPtr));
871 }
catch (boost::bad_lexical_cast err) {
885 std::vector<std::pair<ISM::ObjectPtr, std::vector<ISM::PosePtr>>>
objectAndPoses;
908 const std_msgs::ColorRGBA
SELECTED = VIZ::VizHelperRVIZ::createColorRGBA(1.0, 0.0, 1.0, 1.0);
909 const std_msgs::ColorRGBA
MARKED = VIZ::VizHelperRVIZ::createColorRGBA(1.0, 0.0, 0.0, 1.0);
910 const std_msgs::ColorRGBA
IN_CURRENT_TRACK = VIZ::VizHelperRVIZ::createColorRGBA(0, 1.0, 0, 1);
912 const std_msgs::ColorRGBA
X_AXIS = VIZ::VizHelperRVIZ::createColorRGBA(1.0, 0.0, 0.0, 0.5);
913 const std_msgs::ColorRGBA
Y_AXIS = VIZ::VizHelperRVIZ::createColorRGBA(0.0, 1.0, 0.0, 0.5);
914 const std_msgs::ColorRGBA
Z_AXIS = VIZ::VizHelperRVIZ::createColorRGBA(0.0, 0.0, 1.0, 0.5);
925 int main(
int argc,
char **argv) {
928 ros::init(argc, argv,
"object_configuration_generator");
935 tcsetattr( STDIN_FILENO, TCSANOW, &originalSettings);
void markOrUnmark()
If the currently selected pose is marked, it gets unmarked, else it gets marked.
void printMarkedObjects()
const std_msgs::ColorRGBA X_AXIS
const std_msgs::ColorRGBA MARKED
void publish(const boost::shared_ptr< M > &message) const
struct termios originalSettings modifiedSettings
std::string visualizationTopic
void switchObject(SelectEntity neighbor)
Switch to the neighbor object.
void visualize()
Visulize the currently selected pose, all poses that are in the same trajectory and one pose of each ...
std::string markerNamespace
visualization_msgs::MarkerArray markerArray
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
void rotate(double alpha, double beta, double gamma, ISM::PosePtr pose)
Rotates the given pose by the values specified by the arguments.
std::set< std::string > markedObjects
bool parsePoseString(std::string pose_string, ISM::PosePtr &pose, std::string delim, std::string angles)
Creates a ISM::PosePtr from a pose_string.
std::vector< unsigned int > poseCounters
const std_msgs::ColorRGBA IN_CURRENT_TRACK
bool add(const actionlib::TwoIntsGoal &req, actionlib::TwoIntsResult &res)
TFSIMD_FORCE_INLINE const tfScalar & y() const
unsigned int objectCounter
void initInteractiveControl()
Sets up keyboard control.
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
ROSCPP_DECL void spin(Spinner &spinner)
const std_msgs::ColorRGBA Y_AXIS
std::string output_file_path
void initFromDatabase(std::vector< std::string > &patternNames)
Read tracks from the scenes specified by patternNames from database and store them in the appropriate...
void switchPose(SelectEntity neighbor)
Switch to the neighbor pose in the trajectory.
void printEditModeHelpText()
void loadConstellationFromConfigFile(const std::string &configFilePath)
Loads a configuration from an xml file located at configFilePath;mDbFilename.
ObjectConfigurationGenerator()
ISM::TableHelperPtr tableHandler
Timer createTimer(Rate r, Handler h, Obj o, bool oneshot=false, bool autostart=true) const
TFSIMD_FORCE_INLINE const tfScalar & x() const
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
void getNodeParameters(std::vector< std::string > &patternNames, std::string &configFilePath)
Read node parameters.
void keyboardInputCallback(const ros::TimerEvent &e)
Function that handles user keyboard input and calls the appropriate functions.
bool isMarked(const ISM::ObjectPtr &obj)
Checks if object is marked.
#define ROS_DEBUG_STREAM(args)
void writeMarkedPosesToFile()
Writes the type, observedId, path to the mesh and its pose to an xml file.
TFSIMD_FORCE_INLINE const tfScalar & z() const
const std_msgs::ColorRGBA SELECTED
~ObjectConfigurationGenerator()
#define ROS_INFO_STREAM(args)
std::vector< bool > editFlags
bool getParam(const std::string &key, std::string &s) const
void translate(double x, double y, double z, ISM::PosePtr pose)
Translates the given pose by the values specified by the arguments.
int main(int argc, char **argv)
void runEditMode()
Start and run edit mode in which the pose of the selected object can be manipulated.
const std_msgs::ColorRGBA Z_AXIS
#define ROS_ERROR_STREAM(args)
std::vector< std::pair< ISM::ObjectPtr, std::vector< ISM::PosePtr > > > objectAndPoses
ros::Publisher visualization_pub
const double markerLifetime
void printNormalHelpText()