std::bad_alloc and std::length_error (basic_string::_M_create)
Hello,
I posted my issues some days ago, but while trying to solve them I encountered a problem different enough to deserve its own topic.
I'm working on Melodic (Ubuntu 18.04, x86) and I have written the following code, which will work on TIAGo in a simulated environment. Please don't question the logic behind what I'm doing: this is just a somewhat minimal test to ask if I'm getting something wrong about the basics of ROS and/or the use of OOP while dealing with ROS.
#include <string>
#include <vector>
#include <ros/ros.h>
#include <actionlib/client/simple_action_client.h>
#include <tf/transform_listener.h>
#include <tf/message_filter.h>
#include <message_filters/subscriber.h>
#include <sensor_msgs/LaserScan.h>
#include <sensor_msgs/PointCloud.h>
#include <geometry_msgs/TransformStamped.h>
#include <geometry_msgs/Point32.h>
#include <laser_geometry/laser_geometry.h> //from laserscan to pointcloud
#include <nav_msgs/OccupancyGrid.h>
#include <nav_msgs/GetMap.h>
#include <move_base_msgs/MoveBaseAction.h>
/**
* This class saves the map and returns it.
*/
class map_saver {
private:
ros::NodeHandle _n;
nav_msgs::OccupancyGrid _global_map;
ros::Subscriber _map_subscriber;
bool _map_is_saved = false;
public:
map_saver(ros::NodeHandle n)
:_n(n)
{}
/**
* Move to position (hardcoded) at the end of the corridor, then save the occupancy grid.
*/
void save_map()
{
/* STEP 1: move to a waypoint at the end of the corridor */
actionlib::SimpleActionClient<move_base_msgs::MoveBaseAction> ac("move_base", true);
//wait for the spawn of the action server
while(!ac.waitForServer(ros::Duration(5.0))){
ROS_INFO("Waiting for the move_base action server to come up");
}
move_base_msgs::MoveBaseGoal goal;
goal.target_pose.header.frame_id = "map";
goal.target_pose.header.stamp = ros::Time::now();
//use hardcoded pose
goal.target_pose.pose.position.x = 8; //test it!!
goal.target_pose.pose.orientation.w = 0.375;
ROS_INFO("save_map is trying to reach the waypoint");
ac.sendGoal(goal);
ac.waitForResult();
if(ac.getState() == actionlib::SimpleClientGoalState::SUCCEEDED)
ROS_INFO("save_map reached waypoint");
else {
ROS_ERROR("save_map could not reach the waypoint, aborting...");
ros::shutdown();
}
/* STEP 2: obtain the map from the service static_map */
ros::service::waitForService("static_map");
nav_msgs::GetMap srv;
ros::ServiceClient client = _n.serviceClient<nav_msgs::GetMap>("static_map");
if(client.call(srv))
{
_global_map = srv.response.map;
_map_is_saved = true;
ROS_INFO("map obtained from GetMap service");
}
else
{
ROS_ERROR("could not get map from GetMap service");
}
}
const nav_msgs::OccupancyGrid& get_map()
{return _global_map;}
bool map_is_available()
{return _map_is_saved;};
};
/**
* This class is responsible for listening to transforms and waiting for pointcloud data to be published.
* The callback is used to update the pointcloud member variable
*
*/
class pointcloud_subscriber
{
private:
ros::NodeHandle _n;
sensor_msgs::PointCloud _pointcloud;
laser_geometry::LaserProjection _projector;
tf::TransformListener _listener;
message_filters::Subscriber<sensor_msgs::LaserScan> _laser_sub;
tf::MessageFilter<sensor_msgs::LaserScan> _laser_notifier;
const std::string LASERSCAN_TOPIC = "scan_raw";
const std::string ABS_FRAME = "map";
const std::string LASER_FRAME = "base_laser_link";
public:
pointcloud_subscriber(ros::NodeHandle n)
:_n(n),
_laser_sub(_n, LASERSCAN_TOPIC, 5),
_laser_notifier(_laser_sub,_listener, ABS_FRAME, 5)
{
ROS_INFO("entering pointcloud_subscriber constructor...");
_laser_notifier.registerCallback(boost::bind(&pointcloud_subscriber::save_pointcloud, this, _1));
_laser_notifier.setTolerance(ros::Duration(0.01));
}
void save_pointcloud(const sensor_msgs::LaserScan::ConstPtr& msg)
{
//obtain the laserscan & turn it into a PointCloud in the map reference frame
sensor_msgs::PointCloud p;
ROS_INFO("Starting laserscan transform...");
try{
_projector.transformLaserScanToPointCloud(ABS_FRAME, *msg, p, _listener ...