Newer
Older
waypoint_navigation / waypoint_saver / src / waypoint_saver.cpp
@koki koki on 15 Aug 2022 6 KB update
#include <ros/ros.h>
#include <tf/transform_listener.h>

#include <sensor_msgs/Joy.h>
#include <geometry_msgs/PointStamped.h>
#include <geometry_msgs/PoseStamped.h>

#include <vector>
#include <fstream>
#include <string>


class Waypoint : public geometry_msgs::PointStamped {
public:
    float vel;
    float rad;

    Waypoint() : vel(1.0), rad(0.8) {}

    double get_x() { return point.x; }
    double get_y() { return point.y; }
    double get_z() { return point.z; }
    float get_vel() { return vel; }
    float get_rad() { return rad; }

    void set_x(double x) { point.x = x; }
    void set_y(double y) { point.x = y; }
    void set_z(double z) { point.x = z; }
    void set_vel(float v) { vel = v; }
    void set_rad(float r) { rad = r; }
};



class WaypointsSaver{
public:
    WaypointsSaver() : 
        filename_("waypoints.yaml"), 
        default_rad_(0.8)
    {
        waypoints_viz_sub_ = nh_.subscribe("waypoints_viz", 1, &WaypointsSaver::waypointsVizCallback, this);
        waypoints_joy_sub_ = nh_.subscribe("waypoints_joy", 1, &WaypointsSaver::waypointsJoyCallback, this);
        finish_pose_sub_ = nh_.subscribe("finish_pose", 1, &WaypointsSaver::finishPoseCallback, this);

        ros::NodeHandle private_nh("~");
        private_nh.param("filename", filename_, filename_);
        private_nh.param("save_joy_button", save_joy_button_, 0);
        private_nh.param("robot_frame", robot_frame_, std::string("base_link"));
        private_nh.param("world_frame", world_frame_, std::string("map"));
        private_nh.param("default_rad", default_rad_, default_rad_);
    }
    
    
    void waypointsJoyCallback(const sensor_msgs::Joy &msg)
    {
        static ros::Time saved_time(0.0);
        if(msg.buttons[save_joy_button_] == 1 && (ros::Time::now() - saved_time).toSec() > 3.0) {
            tf::StampedTransform robot_gl;
            try {
                tf_listener_.lookupTransform(world_frame_, robot_frame_, ros::Time(0.0), robot_gl);
                Waypoint point;
                point.set_x(robot_gl.getOrigin().x());
                point.set_y(robot_gl.getOrigin().y());
                point.set_z(robot_gl.getOrigin().z());
                point.set_rad(default_rad_);
                waypoints_.push_back(point);
                saved_time = ros::Time::now();
            }
            catch(tf::TransformException &e) {
                ROS_WARN_STREAM("tf::TransformException: " << e.what());
            }
        }
    }
    
    
    void waypointsVizCallback(const geometry_msgs::PointStamped &msg)
    {
        Waypoint point;
        point.set_x(msg.point.x);
        point.set_y(msg.point.y);
        point.set_z(msg.point.z);
        point.set_rad(default_rad_);
        ROS_INFO_STREAM("point = " << point);
        waypoints_.push_back(point);
    }
    
    
    void finishPoseCallback(const geometry_msgs::PoseStamped &msg)
    {
        finish_pose_ = msg;
        save2();
        waypoints_.clear();
    }
    
    
    void save()
    {
        std::ofstream ofs(filename_.c_str(), std::ios::out);
        
        ofs << "waypoints:" << std::endl;
        for(int i=0; i < waypoints_.size(); i++) {
            ofs << "    " << "- point:" << std::endl;
            ofs << "        x: " << waypoints_[i].point.x << std::endl;
            ofs << "        y: " << waypoints_[i].point.y << std::endl;
            ofs << "        z: " << waypoints_[i].point.z << std::endl;
        }
        
        ofs << "finish_pose:"           << std::endl;
        ofs << "    header:"            << std::endl;
        ofs << "        seq: "          << finish_pose_.header.seq << std::endl;
        ofs << "        stamp: "        << finish_pose_.header.stamp << std::endl;
        ofs << "        frame_id: "     << finish_pose_.header.frame_id << std::endl;;
        ofs << "    pose:"              << std::endl;
        ofs << "        position:"      << std::endl;
        ofs << "            x: "        << finish_pose_.pose.position.x << std::endl;
        ofs << "            y: "        << finish_pose_.pose.position.y << std::endl;
        ofs << "            z: "        << finish_pose_.pose.position.z << std::endl;
        ofs << "        orientation:"   << std::endl;
        ofs << "            x: "        << finish_pose_.pose.orientation.x << std::endl;
        ofs << "            y: "        << finish_pose_.pose.orientation.y << std::endl;
        ofs << "            z: "        << finish_pose_.pose.orientation.z << std::endl;
        ofs << "            w: "        << finish_pose_.pose.orientation.w << std::endl;

        ofs.close();

        ROS_INFO_STREAM("write success");
    }


    void save2()
    {
        std::ofstream ofs(filename_.c_str(), std::ios::out);
        /*
        waypoints:
        - point: {x: *, y: *, z: *, vel: *, rad: *}
        */
        ofs << "waypoints:" << std::endl;
        for(int i=0; i < waypoints_.size(); i++) {
            ofs << "- point: {" ;
            ofs << "x: "   << waypoints_[i].get_x()   << ", " ;
            ofs << "y: "   << waypoints_[i].get_y()   << ", " ;
            ofs << "z: "   << waypoints_[i].get_z()   << ", " ;
            ofs << "vel: " << waypoints_[i].get_vel() << ", " ;
            ofs << "rad: " << waypoints_[i].get_rad() << "}"  << std::endl;
        }
        /*
        finish_pose:
          header: {seq: *, stamp: *, frame_id: *}
          pose:
            positioin: {x: *, y: *, z: *}
            orientation: {x: *, y: *, z: *, w: *}
        */
        ofs << "finish_pose:" << std::endl;
        ofs << "  header: {" ;
        ofs << "seq: "      << finish_pose_.header.seq        << ", " ;
        ofs << "stamp: "    << finish_pose_.header.stamp      << ", " ;
        ofs << "frame_id: " << finish_pose_.header.frame_id   << "}"  << std::endl;
        ofs << "  pose: " << std::endl;
        ofs << "    position: {" ;
        ofs << "x: " << finish_pose_.pose.position.x << ", " ;
        ofs << "y: " << finish_pose_.pose.position.y << ", " ;
        ofs << "z: " << finish_pose_.pose.position.z << "}"  << std::endl;
        ofs << "    orientation: {" ;
        ofs << "x: " << finish_pose_.pose.orientation.x << ", " ;
        ofs << "y: " << finish_pose_.pose.orientation.y << ", " ;
        ofs << "z: " << finish_pose_.pose.orientation.z << ", " ;
        ofs << "w: " << finish_pose_.pose.orientation.w << "}"  << std::endl;

        ofs.close();
        ROS_INFO_STREAM("write success");
    }
    

    void run()
    {
        ros::spin();
    }


private:
    ros::Subscriber waypoints_viz_sub_;
    ros::Subscriber waypoints_joy_sub_;
    ros::Subscriber finish_pose_sub_;
    std::vector<Waypoint> waypoints_;
    geometry_msgs::PoseStamped finish_pose_;
    tf::TransformListener tf_listener_;
    int save_joy_button_;
    ros::NodeHandle nh_;
    std::string filename_;
    std::string world_frame_;
    std::string robot_frame_;
    float default_rad_;
};



int main(int argc, char *argv[])
{
    ros::init(argc, argv, "waypoints_saver");
    WaypointsSaver saver;
    saver.save2();
    saver.run();

    return 0;
}