39 #include <std_msgs/ColorRGBA.h> 40 #include <std_msgs/String.h> 42 #include <geometry_msgs/Point.h> 43 #include <geometry_msgs/PoseWithCovarianceStamped.h> 44 #include <geometry_msgs/TransformStamped.h> 45 #include <visualization_msgs/Marker.h> 47 #include <boost/filesystem.hpp> 73 this->visible =
false;
91 nh.
advertise<geometry_msgs::PoseWithCovarianceStamped>(
"/fiducial_slam/camera_pose", 1));
112 if (overridePublishedCovariance) {
115 overridePublishedCovariance =
false;
120 ROS_WARN(
"ignoring covariance_diagonal because it has 0 values");
121 std::fill(covarianceDiagonal.begin(), covarianceDiagonal.end(), 0);
132 std::string(getenv(
"HOME")) +
"/.ros/slam/map.txt");
134 boost::filesystem::path mapPath(mapFilename);
135 boost::filesystem::path
dir = mapPath.parent_path();
136 boost::filesystem::create_directories(dir);
138 std::string initialMap;
139 nh.
param<std::string>(
"initial_map_file", initialMap,
"");
141 if (!initialMap.empty()) {
153 ROS_INFO(
"Updating map with %d observations. Map has %d fiducials", (
int)obs.size(),
158 if (obs.size() > 0 &&
fiducials.size() == 0) {
195 tf2::Vector3 trans = T_mapFid.transform.getOrigin();
197 ROS_INFO(
"Estimate of %d %lf %lf %lf var %lf %lf", o.fid, trans.x(), trans.y(),
198 trans.z(), o.T_camFid.variance, T_mapFid.variance);
200 if (std::isnan(trans.x()) || std::isnan(trans.y()) || std::isnan(trans.z())) {
201 ROS_WARN(
"Skipping NAN estimate\n");
206 if (fiducials.find(o.fid) == fiducials.end()) {
208 fiducials[o.fid] =
Fiducial(o.fid, T_mapFid);
212 if (f.
pose.variance != 0) {
218 int fid = observation.fid;
231 geometry_msgs::TransformStamped transform;
254 if (obs.size() == 0) {
259 tf2::Vector3 c = T_camBase.transform.getOrigin();
260 ROS_INFO(
"camera->base %lf %lf %lf", c.x(), c.y(), c.z());
261 T_camBase.variance = 1.0;
263 ROS_ERROR(
"Cannot determine tf from camera to robot\n");
267 tf2::Vector3 c = T_baseCam.transform.getOrigin();
268 ROS_INFO(
"base->camera %lf %lf %lf", c.x(), c.y(), c.z());
269 T_baseCam.variance = 1.0;
271 ROS_ERROR(
"Cannot determine tf from robot to camera\n");
282 p.
stamp_ = o.T_fidCam.stamp_;
285 auto position = p.transform.getOrigin();
287 p.transform.getBasis().getRPY(roll, pitch, yaw);
292 auto cam_f = o.T_camFid.transform.getOrigin();
293 double s1 = std::pow(position.z() / cam_f.z(), 2) *
294 (std::pow(cam_f.x(), 2) + std::pow(cam_f.y(), 2));
295 double s2 = position.length2() * std::pow(std::sin(roll), 2);
296 double s3 = position.length2() * std::pow(std::sin(pitch), 2);
298 o.T_camFid.variance = p.variance;
300 ROS_INFO(
"Pose %d %lf %lf %lf %lf %lf %lf %lf", o.fid, position.x(), position.y(),
301 position.z(),
roll,
pitch, yaw, p.variance);
305 if (std::isnan(position.x()) || std::isnan(position.y()) || std::isnan(position.z())) {
306 ROS_WARN(
"Skipping NAN estimate\n");
323 ROS_INFO(
"Finished frame - no estimates\n");
329 tf2::Vector3 trans = T_mapBase.transform.getOrigin();
331 T_mapBase.transform.getBasis().getRPY(r, p, y);
333 ROS_INFO(
"Pose ALL %lf %lf %lf %lf %lf %lf %f", trans.x(), trans.y(), trans.z(), r, p, y,
339 auto robotPose =
toPose(basePose);
342 for (
int i = 0; i <= 5; i++) {
347 T_mapCam = T_mapBase * T_baseCam;
361 tf2::Vector3 c = odomTransform.
getOrigin();
362 ROS_INFO(
"odom %lf %lf %lf", c.x(), c.y(), c.z());
373 tf2::Vector3 translation = outPose.transform.getOrigin();
375 outPose.transform.setOrigin(translation);
377 outPose.transform.getBasis().getRPY(roll, pitch, yaw);
378 outPose.transform.getBasis().setRPY(0, 0, yaw);
382 poseTf.child_frame_id = outFrame;
389 ROS_INFO(
"Finished frame. Estimates %d\n", numEsts);
416 double smallestDist = -1;
419 for (
size_t i = 0; i < obs.size(); i++) {
421 double d = o.
T_camFid.transform.getOrigin().length2();
422 if (smallestDist < 0 || d < smallestDist) {
445 ROS_WARN(
"Could not find a fiducial to initialize map from");
451 ROS_INFO(
"Initializing map from fiducial %d", o.
fid);
465 tf2::Vector3 trans = T.transform.getOrigin();
466 ROS_INFO(
"Estimate of %d from base %lf %lf %lf err %lf", o.fid, trans.x(),
467 trans.y(), trans.z(), o.T_camFid.variance);
496 ROS_INFO(
"Fiducial %d is already in map - ignoring add request",
512 o.T_camFid.stamp_, T_baseCam)) {
522 ROS_INFO(
"Placing robot at the origin");
542 ROS_INFO(
"Saving map with %d fiducials to file %s\n", (
int)
fiducials.size(), filename.c_str());
544 FILE *fp = fopen(filename.c_str(),
"w");
546 ROS_WARN(
"Could not open %s for write\n", filename.c_str());
552 tf2::Vector3 trans = f.
pose.transform.getOrigin();
554 f.
pose.transform.getBasis().getRPY(rx, ry, rz);
556 fprintf(fp,
"%d %lf %lf %lf %lf %lf %lf %lf %d", f.
id, trans.x(), trans.y(), trans.z(),
559 for (
const auto linked_fid : f.
links) {
560 fprintf(fp,
" %d", linked_fid);
575 ROS_INFO(
"Load map %s", filename.c_str());
577 FILE *fp = fopen(filename.c_str(),
"r");
579 ROS_WARN(
"Could not open %s for read\n", filename.c_str());
583 const int BUFSIZE = 2048;
584 char linebuf[BUFSIZE];
585 char linkbuf[BUFSIZE];
588 if (fgets(linebuf, BUFSIZE - 1, fp) == NULL)
break;
591 double tx, ty, tz, rx, ry, rz, var;
595 int nElems = sscanf(linebuf,
"%d %lf %lf %lf %lf %lf %lf %lf %d%[^\t\n]*s", &
id, &tx, &ty,
596 &tz, &rx, &ry, &rz, &var, &numObs, linkbuf);
597 if (nElems == 9 || nElems == 10) {
598 tf2::Vector3 tvec(tx, ty, tz);
608 std::istringstream ss(linkbuf);
610 while (getline(ss, s,
' ')) {
612 f.
links.insert(stoi(s));
618 ROS_WARN(
"Invalid line: %s", linebuf);
623 ROS_INFO(
"Load map %s read %d entries", filename.c_str(), numRead);
630 fiducial_msgs::FiducialMapEntryArray fmea;
631 std::map<int, Fiducial>::iterator it;
636 fiducial_msgs::FiducialMapEntry fme;
637 fme.fiducial_id = f.
id;
639 tf2::Vector3
t = f.
pose.transform.getOrigin();
645 f.
pose.transform.getBasis().getRPY(rx, ry, rz);
650 fmea.fiducials.push_back(fme);
661 std::map<int, Fiducial>::iterator it;
677 visualization_msgs::Marker marker;
678 marker.type = visualization_msgs::Marker::CUBE;
679 marker.action = visualization_msgs::Marker::ADD;
682 marker.scale.x = 0.15;
683 marker.scale.y = 0.15;
684 marker.scale.z = 0.01;
686 marker.color.r = 1.0f;
687 marker.color.g = 0.0f;
688 marker.color.b = 0.0f;
689 marker.color.a = 1.0f;
691 marker.color.r = 0.0f;
692 marker.color.g = 1.0f;
693 marker.color.b = 0.0f;
694 marker.color.a = 1.0f;
697 marker.ns =
"fiducial";
702 visualization_msgs::Marker cylinder;
703 cylinder.type = visualization_msgs::Marker::CYLINDER;
704 cylinder.action = visualization_msgs::Marker::ADD;
705 cylinder.header.frame_id =
mapFrame;
706 cylinder.color.r = 0.0f;
707 cylinder.color.g = 0.0f;
708 cylinder.color.b = 1.0f;
709 cylinder.color.a = 0.5f;
710 cylinder.id = fid.
id + 10000;
711 cylinder.ns =
"sigma";
712 cylinder.scale.x = cylinder.scale.y = std::max(std::sqrt(fid.
pose.variance), 0.1);
713 cylinder.scale.z = 0.01;
714 cylinder.pose.position.x = marker.pose.position.x;
715 cylinder.pose.position.y = marker.pose.position.y;
716 cylinder.pose.position.z = marker.pose.position.z;
717 cylinder.pose.position.z += (marker.scale.z / 2.0) + 0.05;
721 visualization_msgs::Marker text;
722 text.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
723 text.action = visualization_msgs::Marker::ADD;
725 text.color.r = text.color.g = text.color.b = text.color.a = 1.0f;
727 text.scale.x = text.scale.y = text.scale.z = 0.1;
728 text.pose.position.x = marker.pose.position.x;
729 text.pose.position.y = marker.pose.position.y;
730 text.pose.position.z = marker.pose.position.z;
731 text.pose.position.z += (marker.scale.z / 2.0) + 0.1;
732 text.id = fid.
id + 30000;
734 text.text = std::to_string(fid.
id);
738 visualization_msgs::Marker links;
739 links.type = visualization_msgs::Marker::LINE_LIST;
740 links.action = visualization_msgs::Marker::ADD;
742 links.color.r = 0.0f;
743 links.color.g = 0.0f;
744 links.color.b = 1.0f;
745 links.color.a = 1.0f;
746 links.id = fid.
id + 40000;
748 links.scale.x = links.scale.y = links.scale.z = 0.02;
749 links.pose.position.x = 0;
750 links.pose.position.y = 0;
751 links.pose.position.z = 0;
753 geometry_msgs::Point gp0, gp1;
754 tf2::Vector3 p0 = fid.
pose.transform.getOrigin();
759 std::map<int, int>::iterator lit;
760 for (
const auto linked_fid : fid.
links) {
762 if (fid.
id < linked_fid) {
764 tf2::Vector3 p1 =
fiducials[linked_fid].pose.transform.getOrigin();
768 links.points.push_back(gp0);
769 links.points.push_back(gp1);
780 static int lid = 60000;
781 visualization_msgs::Marker line;
782 line.type = visualization_msgs::Marker::LINE_LIST;
783 line.action = visualization_msgs::Marker::ADD;
791 line.scale.x = line.scale.y = line.scale.z = 0.01;
792 line.pose.position.x = 0;
793 line.pose.position.y = 0;
794 geometry_msgs::Point gp0, gp1;
801 line.points.push_back(gp0);
802 line.points.push_back(gp1);
810 ROS_INFO(
"Clearing fiducial map from service call");
822 fiducial_slam::AddFiducial::Response &res)
824 ROS_INFO(
"Request to add fiducial %d to map", req.fiducial_id);
ros::Publisher cameraPosePub
void setRPY(const tf2Scalar &roll, const tf2Scalar &pitch, const tf2Scalar &yaw)
constexpr double deg2rad(double deg)
double future_date_transforms
tf2::Stamped< TransformWithVariance > T_fidCam
bool clearCallback(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res)
void autoInit(const std::vector< Observation > &obs, const ros::Time &time)
void publish(const boost::shared_ptr< M > &message) const
constexpr double rad2deg(double rad)
ros::ServiceServer clearSrv
virtual geometry_msgs::TransformStamped lookupTransform(const std::string &target_frame, const std::string &source_frame, const ros::Time &time, const ros::Duration timeout) const
static int findClosestObs(const std::vector< Observation > &obs)
ServiceServer advertiseService(const std::string &service, bool(T::*srv_func)(MReq &, MRes &), T *obj)
TFSIMD_FORCE_INLINE const tfScalar & y() const
geometry_msgs::TransformStamped t
std::vector< double > covarianceDiagonal
void handleAddFiducial(const std::vector< Observation > &obs)
std::unique_ptr< tf2_ros::TransformListener > listener
geometry_msgs::TransformStamped poseTf
void updateMap(const std::vector< Observation > &obs, const ros::Time &time, const tf2::Stamped< TransformWithVariance > &cameraPose)
ros::ServiceServer addSrv
std::map< int, Fiducial > fiducials
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
void fromMsg(const A &, B &b)
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
static double systematic_error
void update(const tf2::Stamped< TransformWithVariance > &newPose)
ros::Publisher robotPosePub
bool overridePublishedCovariance
void publishMarker(Fiducial &fid)
bool getParam(const std::string &key, std::string &s) const
void drawLine(const tf2::Vector3 &p0, const tf2::Vector3 &p1)
int updatePose(std::vector< Observation > &obs, const ros::Time &time, tf2::Stamped< TransformWithVariance > &cameraPose)
tf2_ros::TransformBroadcaster broadcaster
tf2::Stamped< TransformWithVariance > pose
bool addFiducialCallback(fiducial_slam::AddFiducial::Request &req, fiducial_slam::AddFiducial::Response &res)
double multiErrorThreshold
tf2::Stamped< TransformWithVariance > T_camFid
void setData(const T &input)
bool lookupTransform(const std::string &from, const std::string &to, const ros::Time &time, tf2::Transform &T) const