From ce4c96c488bd948e3509d21fa72683a6f5238ff4 Mon Sep 17 00:00:00 2001 From: hosokawa Date: Wed, 2 Aug 2017 17:08:31 +0900 Subject: [PATCH 1/2] inverse_tf feature has been added. --- .gitignore | 7 +++++- ar_track_alvar/launch/pr2_bundle.launch | 3 ++- .../launch/pr2_bundle_no_kinect.launch | 3 ++- ar_track_alvar/launch/pr2_indiv.launch | 2 ++ .../launch/pr2_indiv_no_kinect.launch | 2 ++ .../launch/pr2_indiv_no_kinect_r200.launch | 21 ++++++++++++++++ .../pr2_indiv_no_kinect_r200_inv_0.launch | 21 ++++++++++++++++ ar_track_alvar/launch/pr2_indiv_r200.launch | 23 ++++++++++++++++++ ar_track_alvar/nodes/FindMarkerBundles.cpp | 22 +++++++++++++---- .../nodes/FindMarkerBundlesNoKinect.cpp | 23 ++++++++++++++---- ar_track_alvar/nodes/IndividualMarkers.cpp | 24 ++++++++++++++++--- .../nodes/IndividualMarkersNoKinect.cpp | 24 ++++++++++++++++--- 12 files changed, 156 insertions(+), 19 deletions(-) create mode 100755 ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch create mode 100755 ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch create mode 100755 ar_track_alvar/launch/pr2_indiv_r200.launch diff --git a/.gitignore b/.gitignore index 070bb21..38951e6 100644 --- a/.gitignore +++ b/.gitignore @@ -8,4 +8,9 @@ *bin *~ src/ar_track_alvar -*.user \ No newline at end of file +*.user +*.swp +GPATH +GRTAGS +GTAGS + diff --git a/ar_track_alvar/launch/pr2_bundle.launch b/ar_track_alvar/launch/pr2_bundle.launch index 69d49da..e02ac2e 100755 --- a/ar_track_alvar/launch/pr2_bundle.launch +++ b/ar_track_alvar/launch/pr2_bundle.launch @@ -1,4 +1,5 @@ + @@ -10,5 +11,5 @@ - + diff --git a/ar_track_alvar/launch/pr2_bundle_no_kinect.launch b/ar_track_alvar/launch/pr2_bundle_no_kinect.launch index c7892dd..f2b4ac4 100755 --- a/ar_track_alvar/launch/pr2_bundle_no_kinect.launch +++ b/ar_track_alvar/launch/pr2_bundle_no_kinect.launch @@ -1,4 +1,5 @@ + @@ -9,5 +10,5 @@ - + diff --git a/ar_track_alvar/launch/pr2_indiv.launch b/ar_track_alvar/launch/pr2_indiv.launch index 27e4689..768ec21 100755 --- a/ar_track_alvar/launch/pr2_indiv.launch +++ b/ar_track_alvar/launch/pr2_indiv.launch @@ -1,4 +1,5 @@ + @@ -12,6 +13,7 @@ + diff --git a/ar_track_alvar/launch/pr2_indiv_no_kinect.launch b/ar_track_alvar/launch/pr2_indiv_no_kinect.launch index 4428714..867ead7 100755 --- a/ar_track_alvar/launch/pr2_indiv_no_kinect.launch +++ b/ar_track_alvar/launch/pr2_indiv_no_kinect.launch @@ -1,4 +1,5 @@ + @@ -11,6 +12,7 @@ + diff --git a/ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch b/ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch new file mode 100755 index 0000000..1d49484 --- /dev/null +++ b/ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch b/ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch new file mode 100755 index 0000000..388d1e2 --- /dev/null +++ b/ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/ar_track_alvar/launch/pr2_indiv_r200.launch b/ar_track_alvar/launch/pr2_indiv_r200.launch new file mode 100755 index 0000000..568f2a1 --- /dev/null +++ b/ar_track_alvar/launch/pr2_indiv_r200.launch @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/ar_track_alvar/nodes/FindMarkerBundles.cpp b/ar_track_alvar/nodes/FindMarkerBundles.cpp index e7f83e0..23c1f35 100644 --- a/ar_track_alvar/nodes/FindMarkerBundles.cpp +++ b/ar_track_alvar/nodes/FindMarkerBundles.cpp @@ -112,6 +112,8 @@ std::string cam_info_topic; std::string output_frame; int n_bundles = 0; +bool inverse_tf = false; + //Debugging utility function void draw3dPoints(ARCloud::Ptr cloud, string frame, int color, int id, double rad) { @@ -527,8 +529,13 @@ void makeMarkerMsgs(int type, int id, Pose &p, sensor_msgs::ImageConstPtr image_ out << id; std::string id_string = out.str(); markerFrame += id_string; - tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); - tf_broadcaster->sendTransform(camToMarker); + if (inverse_tf) { + tf::StampedTransform markerToCam (t.inverse(), image_msg->header.stamp, markerFrame.c_str(), output_frame); + tf_broadcaster->sendTransform(markerToCam); + } else { + tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); + tf_broadcaster->sendTransform(camToMarker); + } //Create the rviz visualization message tf::poseTFToMsg (markerPose, rvizMarker->pose); @@ -771,10 +778,10 @@ int main(int argc, char *argv[]) ros::init (argc, argv, "marker_detect"); ros::NodeHandle n; - if(argc < 9){ + if(argc < 10){ std::cout << std::endl; cout << "Not enough arguments provided." << endl; - cout << "Usage: ./findMarkerBundles " << endl; + cout << "Usage: ./findMarkerBundles " << endl; std::cout << std::endl; return 0; } @@ -787,7 +794,12 @@ int main(int argc, char *argv[]) cam_info_topic = argv[5]; output_frame = argv[6]; med_filt_size = atoi(argv[7]); - int n_args_before_list = 8; + std::stringstream tmpss(argv[8]); + if(!(tmpss >> std::boolalpha >> inverse_tf)) { + // parse failed + inverse_tf = false; + } + int n_args_before_list = 9; n_bundles = argc - n_args_before_list; marker_detector.SetMarkerSize(marker_size); diff --git a/ar_track_alvar/nodes/FindMarkerBundlesNoKinect.cpp b/ar_track_alvar/nodes/FindMarkerBundlesNoKinect.cpp index 013588b..6a96846 100644 --- a/ar_track_alvar/nodes/FindMarkerBundlesNoKinect.cpp +++ b/ar_track_alvar/nodes/FindMarkerBundlesNoKinect.cpp @@ -82,6 +82,8 @@ void GetMultiMarkerPoses(IplImage *image); void getCapCallback (const sensor_msgs::ImageConstPtr & image_msg); void makeMarkerMsgs(int type, int id, Pose &p, sensor_msgs::ImageConstPtr image_msg, tf::StampedTransform &CamToOutput, visualization_msgs::Marker *rvizMarker, ar_track_alvar_msgs::AlvarMarker *ar_pose_marker); +bool inverse_tf = false; + // Updates the bundlePoses of the multi_marker_bundles by detecting markers and using all markers in a bundle to infer the master tag's position void GetMultiMarkerPoses(IplImage *image) { @@ -128,8 +130,14 @@ void makeMarkerMsgs(int type, int id, Pose &p, sensor_msgs::ImageConstPtr image_ out << id; std::string id_string = out.str(); markerFrame += id_string; - tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); - tf_broadcaster->sendTransform(camToMarker); + if (inverse_tf) { + tf::StampedTransform markerToCam (t.inverse(), image_msg->header.stamp, markerFrame.c_str(), output_frame); + tf_broadcaster->sendTransform(markerToCam); + } else { + tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); + tf_broadcaster->sendTransform(camToMarker); + } + } //Create the rviz visualization message @@ -281,10 +289,10 @@ int main(int argc, char *argv[]) ros::init (argc, argv, "marker_detect"); ros::NodeHandle n; - if(argc < 8){ + if(argc < 9){ std::cout << std::endl; cout << "Not enough arguments provided." << endl; - cout << "Usage: ./findMarkerBundles " << endl; + cout << "Usage: ./findMarkerBundles " << endl; std::cout << std::endl; return 0; } @@ -296,7 +304,12 @@ int main(int argc, char *argv[]) cam_image_topic = argv[4]; cam_info_topic = argv[5]; output_frame = argv[6]; - int n_args_before_list = 7; + std::stringstream tmpss(argv[7]); + if(!(tmpss >> std::boolalpha >> inverse_tf)) { + // parse failed + inverse_tf = false; + } + int n_args_before_list = 8; n_bundles = argc - n_args_before_list; marker_detector.SetMarkerSize(marker_size); diff --git a/ar_track_alvar/nodes/IndividualMarkers.cpp b/ar_track_alvar/nodes/IndividualMarkers.cpp index a44a23f..89f6e18 100644 --- a/ar_track_alvar/nodes/IndividualMarkers.cpp +++ b/ar_track_alvar/nodes/IndividualMarkers.cpp @@ -86,6 +86,8 @@ std::string output_frame; int marker_resolution = 5; // default marker resolution int marker_margin = 2; // default marker margin +bool inverse_tf = false; + //Debugging utility function void draw3dPoints(ARCloud::Ptr cloud, string frame, int color, int id, double rad) @@ -397,8 +399,13 @@ void getPointCloudCallback (const sensor_msgs::PointCloud2ConstPtr &msg) out << id; std::string id_string = out.str(); markerFrame += id_string; - tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); - tf_broadcaster->sendTransform(camToMarker); + if (inverse_tf) { + tf::StampedTransform markerToCam (t.inverse(), image_msg->header.stamp, markerFrame.c_str(), output_frame); + tf_broadcaster->sendTransform(markerToCam); + } else { + tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); + tf_broadcaster->sendTransform(camToMarker); + } //Create the rviz visualization messages tf::poseTFToMsg (markerPose, rvizMarker_.pose); @@ -500,7 +507,7 @@ int main(int argc, char *argv[]) std::cout << std::endl; cout << "Not enough arguments provided." << endl; cout << "Usage: ./individualMarkers " - << " [ ]"; + << " [ ]"; std::cout << std::endl; return 0; } @@ -522,6 +529,16 @@ int main(int argc, char *argv[]) if (argc > 9) marker_margin = atoi(argv[9]); + if (argc > 10) { + std::stringstream tmpss(argv[10]); + if(!(tmpss >> std::boolalpha >> inverse_tf)) { + // parse failed + inverse_tf = false; + } + } else { + inverse_tf = false; + } + } else { // Get params from ros param server. pn.param("marker_size", marker_size, 10.0); @@ -532,6 +549,7 @@ int main(int argc, char *argv[]) pn.param("marker_resolution", marker_resolution, 5); pn.param("marker_margin", marker_margin, 2); pn.param("output_frame_from_msg", output_frame_from_msg, false); + pn.param("inverse_tf", inverse_tf, false); if (!output_frame_from_msg && !pn.getParam("output_frame", output_frame)) { ROS_ERROR("Param 'output_frame' has to be set if the output frame is not " diff --git a/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp b/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp index d5a439e..07d77d3 100644 --- a/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp +++ b/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp @@ -75,6 +75,8 @@ std::string output_frame; int marker_resolution = 5; // default marker resolution int marker_margin = 2; // default marker margin +bool inverse_tf = false; + void getCapCallback (const sensor_msgs::ImageConstPtr & image_msg); @@ -139,8 +141,14 @@ void getCapCallback (const sensor_msgs::ImageConstPtr & image_msg) out << id; std::string id_string = out.str(); markerFrame += id_string; - tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); - tf_broadcaster->sendTransform(camToMarker); + if (inverse_tf) { + tf::StampedTransform markerToCam (t.inverse(), image_msg->header.stamp, markerFrame.c_str(), output_frame); + tf_broadcaster->sendTransform(markerToCam); + } else { + tf::StampedTransform camToMarker (t, image_msg->header.stamp, image_msg->header.frame_id, markerFrame.c_str()); + tf_broadcaster->sendTransform(camToMarker); + } + //Create the rviz visualization messages tf::poseTFToMsg (markerPose, rvizMarker_.pose); @@ -247,7 +255,7 @@ int main(int argc, char *argv[]) std::cout << std::endl; cout << "Not enough arguments provided." << endl; cout << "Usage: ./individualMarkersNoKinect " - << " [ ]"; + << " [ ]"; std::cout << std::endl; return 0; } @@ -268,6 +276,15 @@ int main(int argc, char *argv[]) marker_resolution = atoi(argv[8]); if (argc > 9) marker_margin = atoi(argv[9]); + if (argc > 10) { + std::stringstream tmpss(argv[10]); + if(!(tmpss >> std::boolalpha >> inverse_tf)) { + // parse failed + inverse_tf = false; + } + } else { + inverse_tf = false; + } } else { // Get params from ros param server. @@ -278,6 +295,7 @@ int main(int argc, char *argv[]) pn.setParam("max_frequency", max_frequency); // in case it was not set. pn.param("marker_resolution", marker_resolution, 5); pn.param("marker_margin", marker_margin, 2); + pn.param("inverse_tf", inverse_tf, false); if (!pn.getParam("output_frame", output_frame)) { ROS_ERROR("Param 'output_frame' has to be set."); exit(EXIT_FAILURE); From e81205b14b30cd0b48b034843f9cc871410f30ed Mon Sep 17 00:00:00 2001 From: HOSOKAWA Ikuto Date: Tue, 31 Oct 2017 19:47:36 +0900 Subject: [PATCH 2/2] Text decode feature of function MarkerData::Read6bitStr has been debugged. New field(string str) has been added into AlvarMarker.msg (for ar_pose_marker topic). Text extraction from markers feature for individual markers has been added (into ar_pose_marker topic). Max character limit of the file name of the marker file has been increased. (+200) Filename format of the marker file has been changed. (adding resolution of the marker) Filename character checking of the marker file has been changed. --- .gitignore | 1 + .../include/ar_track_alvar/Marker.h | 2 + .../launch/pr2_indiv_no_kinect_r200.launch | 21 -------- .../pr2_indiv_no_kinect_r200_inv_0.launch | 21 -------- ar_track_alvar/launch/pr2_indiv_r200.launch | 23 -------- ar_track_alvar/nodes/IndividualMarkers.cpp | 2 + .../nodes/IndividualMarkersNoKinect.cpp | 2 + ar_track_alvar/src/Marker.cpp | 6 ++- ar_track_alvar/src/SampleMarkerCreator.cpp | 53 ++++++++++++++----- ar_track_alvar_msgs/msg/AlvarMarker.msg | 1 + 10 files changed, 54 insertions(+), 78 deletions(-) delete mode 100755 ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch delete mode 100755 ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch delete mode 100755 ar_track_alvar/launch/pr2_indiv_r200.launch diff --git a/.gitignore b/.gitignore index 38951e6..6d7d10c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,5 @@ src/ar_track_alvar GPATH GRTAGS GTAGS +GSYMS diff --git a/ar_track_alvar/include/ar_track_alvar/Marker.h b/ar_track_alvar/include/ar_track_alvar/Marker.h index 0313833..880cef2 100644 --- a/ar_track_alvar/include/ar_track_alvar/Marker.h +++ b/ar_track_alvar/include/ar_track_alvar/Marker.h @@ -100,6 +100,8 @@ namespace alvar { void SetMarkerSize(double _edge_length = 0, int _res = 0, double _margin = 0); /** \brief Get edge length (to support different size markers */ double GetMarkerEdgeLength() const { return edge_length; } + /** \brief Method for Get the marker resolution */ + int GetMarkerRes(void); /** \brief Destructor */ ~Marker(); /** \brief Default constructor diff --git a/ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch b/ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch deleted file mode 100755 index 1d49484..0000000 --- a/ar_track_alvar/launch/pr2_indiv_no_kinect_r200.launch +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch b/ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch deleted file mode 100755 index 388d1e2..0000000 --- a/ar_track_alvar/launch/pr2_indiv_no_kinect_r200_inv_0.launch +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/ar_track_alvar/launch/pr2_indiv_r200.launch b/ar_track_alvar/launch/pr2_indiv_r200.launch deleted file mode 100755 index 568f2a1..0000000 --- a/ar_track_alvar/launch/pr2_indiv_r200.launch +++ /dev/null @@ -1,23 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - diff --git a/ar_track_alvar/nodes/IndividualMarkers.cpp b/ar_track_alvar/nodes/IndividualMarkers.cpp index 89f6e18..8ec769a 100644 --- a/ar_track_alvar/nodes/IndividualMarkers.cpp +++ b/ar_track_alvar/nodes/IndividualMarkers.cpp @@ -376,6 +376,7 @@ void getPointCloudCallback (const sensor_msgs::PointCloud2ConstPtr &msg) { //Get the pose relative to the camera int id = (*(marker_detector.markers))[i].GetId(); + std::string content_str = (*(marker_detector.markers))[i].data.str; Pose p = (*(marker_detector.markers))[i].pose; double px = p.translation[0]/100.0; @@ -470,6 +471,7 @@ void getPointCloudCallback (const sensor_msgs::PointCloud2ConstPtr &msg) ar_pose_marker.header.frame_id = output_frame; ar_pose_marker.header.stamp = image_msg->header.stamp; ar_pose_marker.id = id; + ar_pose_marker.str = content_str; arPoseMarkers_.markers.push_back (ar_pose_marker); } arPoseMarkers_.header.stamp = image_msg->header.stamp; diff --git a/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp b/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp index 07d77d3..31c60cc 100644 --- a/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp +++ b/ar_track_alvar/nodes/IndividualMarkersNoKinect.cpp @@ -111,6 +111,7 @@ void getCapCallback (const sensor_msgs::ImageConstPtr & image_msg) { //Get the pose relative to the camera int id = (*(marker_detector.markers))[i].GetId(); + std::string content_str = (*(marker_detector.markers))[i].data.str; Pose p = (*(marker_detector.markers))[i].pose; double px = p.translation[0]/100.0; double py = p.translation[1]/100.0; @@ -213,6 +214,7 @@ void getCapCallback (const sensor_msgs::ImageConstPtr & image_msg) ar_pose_marker.header.frame_id = output_frame; ar_pose_marker.header.stamp = image_msg->header.stamp; ar_pose_marker.id = id; + ar_pose_marker.str = content_str; arPoseMarkers_.markers.push_back (ar_pose_marker); } arMarkerPub_.publish (arPoseMarkers_); diff --git a/ar_track_alvar/src/Marker.cpp b/ar_track_alvar/src/Marker.cpp index fdaf503..6d07804 100644 --- a/ar_track_alvar/src/Marker.cpp +++ b/ar_track_alvar/src/Marker.cpp @@ -512,6 +512,10 @@ void Marker::SetMarkerSize(double _edge_length, int _res, double _margin) { marker_content = cvCreateMat(res, res, CV_8U); cvSet(marker_content, cvScalar(255)); } +int Marker::GetMarkerRes(void){ + return res; +} + Marker::~Marker() { if (marker_content) cvReleaseMat(&marker_content); } @@ -838,7 +842,7 @@ void MarkerData::Read6bitStr(BitsetExt *bs, char *s, size_t s_max_len) { if (bitpos < 0) { if (c == 000) s[len] = ':'; else if ((c >= 001) && (c <= 032)) s[len] = 'a' + (char)c - 1; - else if ((c >= 033) && (c <= 044)) s[len] = '0' + (char)c - 1; + else if ((c >= 033) && (c <= 044)) s[len] = '0' + (char)c - 033; else if (c == 045) s[len] = '+'; else if (c == 046) s[len] = '-'; else if (c == 047) s[len] = '*'; diff --git a/ar_track_alvar/src/SampleMarkerCreator.cpp b/ar_track_alvar/src/SampleMarkerCreator.cpp index c0a8f04..97bd46b 100644 --- a/ar_track_alvar/src/SampleMarkerCreator.cpp +++ b/ar_track_alvar/src/SampleMarkerCreator.cpp @@ -1,5 +1,6 @@ #include "ar_track_alvar/MultiMarker.h" #include "highgui.h" +#include using namespace std; using namespace alvar; @@ -75,8 +76,9 @@ struct State { maxx = new_maxx; maxy = new_maxy; } if (marker_data_content_type == MarkerData::MARKER_CONTENT_TYPE_NUMBER) { - int idi = atoi(id); + long idi = atol(id); md.SetContent(marker_data_content_type, idi, 0); + filename<<"_res"< unusable_char = { + { '#', true }, + { '<', true }, + { '$', true }, + { '+', true }, + { '%', true }, + { '>', true }, + { '!', true }, + { '`', true }, + { '&', true }, + { '*', true }, + { '"', true }, + { '|', true }, + { '{', true }, + { '?', true }, + { '=', true }, + { '}', true }, + { '/', true }, + { ':', true }, + { '\\', true }, + { '\'', true }, + { '@', true } + }; while(*p) { - if (!isalnum(*p)) filename<<"_"; + //if (!isalnum(*p)) filename<<"-"; + if (!isalnum(*p) && unusable_char.find((char)*p) != unusable_char.end()) filename<<"-"; else filename<<(char)tolower(*p); p++; counter++; - if (counter > 8) break; + //if (counter > 8) break; + if (counter > 200) break; } } md.ScaleMarkerToImage(img); @@ -106,8 +134,9 @@ struct State { img = cvCreateImage(cvSize(side_len, side_len), IPL_DEPTH_8U, 1); filename.str(""); filename<<"MarkerArtoolkit"; - md.SetContent(atoi(id)); - filename<<"_"< 0) marker_id=atoi(s.c_str()); - if (marker_id < 0) break; + std::getline(std::cin, s); if (s.length() > 0) marker_id=atol(s.c_str()); + if (marker_id < 0 || marker_id > INT_MAX ) break; std::cout<<" x position (in current units) ["< 0) posx=atof(s.c_str()); std::cout<<" y position (in current units) ["< 0) column_major=atoi(s.c_str()); std::cout<<"First marker ID : "; std::flush(std::cout); - std::getline(std::cin, s); if (s.length() > 0) first_id=atoi(s.c_str()); + std::getline(std::cin, s); if (s.length() > 0) first_id=atol(s.c_str()); if(!column_major) { for(int row = 0; row