29 #include <std_msgs/String.h> 30 #include <robot_calibration_msgs/CalibrationData.h> 31 #include <robot_calibration_msgs/CaptureConfig.h> 41 #include <boost/foreach.hpp> 73 int main(
int argc,
char** argv)
75 ros::init(argc, argv,
"robot_calibration");
80 nh.
param<
bool>(
"verbose", verbose,
false);
83 std_msgs::String description_msg;
84 std::vector<robot_calibration_msgs::CalibrationData> data;
87 std::string pose_bag_name(
"calibration_poses.bag");
89 pose_bag_name = argv[1];
91 if (pose_bag_name.compare(
"--from-bag") != 0)
97 if (!feature_finder_loader.
load(nh, finders_))
99 ROS_FATAL(
"Unable to load feature finders!");
107 if (!nh.
getParam(
"/robot_description", description_msg.data))
112 urdf_pub.publish(description_msg);
115 std::vector<robot_calibration_msgs::CaptureConfig> poses;
116 if (pose_bag_name.compare(
"--manual") != 0)
133 robot_calibration_msgs::CaptureConfig::ConstPtr msg = m.
instantiate<robot_calibration_msgs::CaptureConfig>();
137 sensor_msgs::JointState::ConstPtr js_msg = m.
instantiate<sensor_msgs::JointState>();
140 robot_calibration_msgs::CaptureConfig config;
141 config.joint_states = *js_msg;
143 for (robot_calibration::FeatureFinderMap::iterator it = finders_.begin();
144 it != finders_.end();
147 config.features.push_back(it->first);
149 poses.push_back(config);
154 poses.push_back(*msg);
160 ROS_INFO(
"Using manual calibration mode...");
164 for (
unsigned pose_idx = 0;
165 (pose_idx < poses.size() || poses.size() == 0) &&
ros::ok();
168 robot_calibration_msgs::CalibrationData msg;
170 if (poses.size() == 0)
173 ROS_INFO(
"Press key when arm is ready... (type 'done' to finish capture)");
174 std::string throwaway;
175 std::getline(std::cin, throwaway);
176 if (throwaway.compare(
"done") == 0)
184 if (!chain_manager_.
moveToState(poses[pose_idx].joint_states))
186 ROS_WARN(
"Unable to move to desired state for sample %u.", pose_idx);
198 bool found_all_features =
true;
199 if (poses.size() == 0 || poses[pose_idx].features.empty())
202 for (robot_calibration::FeatureFinderMap::iterator it = finders_.begin();
203 it != finders_.end();
206 if (!it->second->find(&msg))
208 ROS_WARN(
"%s failed to capture features.", it->first.c_str());
209 found_all_features =
false;
217 for (
size_t i = 0; i < poses[pose_idx].features.size(); i++)
219 std::string feature = poses[pose_idx].features[i];
220 if (!finders_[feature]->find(&msg))
222 ROS_WARN(
"%s failed to capture features.", feature.c_str());
223 found_all_features =
false;
230 if (found_all_features)
232 ROS_INFO(
"Captured pose %u", pose_idx);
236 ROS_WARN(
"Failed to capture sample %u.", pose_idx);
241 chain_manager_.
getState(&msg.joint_states);
255 std::string data_bag_name(
"/tmp/calibration_data.bag");
257 data_bag_name = argv[2];
273 if (nh.
getParam(
"cal_steps", cal_steps))
278 ROS_FATAL(
"Parameter 'cal_steps' should be a struct.");
284 size_t max_step = (cal_steps.
size()>0)?cal_steps.
size():1;
285 std::vector<std::string> prev_frame_names;
286 std::string prev_params_yaml;
287 for (step = 0, it = cal_steps.
begin(); step < max_step; step++, it++)
289 std::string name =
static_cast<std::string
>(it->first);
292 opt.
optimize(params, data, verbose);
295 std::cout <<
"Parameter Offsets:" << std::endl;
296 std::cout << opt.
getOffsets()->getOffsetYAML() << std::endl;
304 opt.
optimize(params, data, verbose);
307 std::cout <<
"Parameter Offsets:" << std::endl;
308 std::cout << opt.
getOffsets()->getOffsetYAML() << std::endl;
315 std::time_t
t = std::time(NULL);
316 std::strftime(datecode, 80,
"%Y_%m_%d_%H_%M_%S", std::localtime(&t));
321 std::string
s = opt.
getOffsets()->updateURDF(description_msg.data);
322 std::stringstream urdf_name;
323 urdf_name <<
"/tmp/calibrated_" << datecode <<
".urdf";
325 file.open(urdf_name.str().c_str());
332 std::stringstream depth_name;
333 depth_name <<
"/tmp/depth_" << datecode <<
".yaml";
340 data[0].observations[0].ext_camera_info.camera_info));
342 std::stringstream rgb_name;
343 rgb_name <<
"/tmp/rgb_" << datecode <<
".yaml";
350 data[0].observations[0].ext_camera_info.camera_info));
355 std::stringstream yaml_name;
356 yaml_name <<
"/tmp/calibration_" << datecode <<
".yaml";
358 file.open(yaml_name.str().c_str());
360 file <<
"depth_info: depth_" << datecode <<
".yaml" << std::endl;
361 file <<
"rgb_info: rgb_" << datecode <<
".yaml" << std::endl;
362 file <<
"urdf: calibrated_" << datecode <<
".urdf" << std::endl;
sensor_msgs::CameraInfo updateCameraInfo(double camera_fx, double camera_fy, double camera_cx, double camera_cy, const sensor_msgs::CameraInfo &info)
Update the camera calibration with the new offsets.
void publish(const boost::shared_ptr< M > &message) const
std::map< std::string, FeatureFinderPtr > FeatureFinderMap
ValueStruct::iterator iterator
void open(std::string const &filename, uint32_t mode=bagmode::Read)
int optimize(OptimizationParams ¶ms, std::vector< robot_calibration_msgs::CalibrationData > data, bool progress_to_stdout=false)
Run optimization.
Class to hold parameters for optimization.
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
Load feature finders, based on param server config.
Manages moving joints to a new pose, determining when they are settled, and returning current joint_s...
Type const & getType() const
geometry_msgs::TransformStamped t
boost::shared_ptr< CalibrationOffsetParser > getOffsets()
bool LoadFromROS(ros::NodeHandle &nh)
#define ROS_FATAL_STREAM(args)
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
int main(int argc, char **argv)
boost::shared_ptr< T > instantiate() const
bool load(ros::NodeHandle &nh, FeatureFinderMap &features)
bool writeCalibration(const std::string &file_name, const std::string &camera_name, const sensor_msgs::CameraInfo &cam_info)
bool waitToSettle()
Wait for joints to settle.
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
bool load_bag(const std::string &file_name, std_msgs::String &description_msg, std::vector< robot_calibration_msgs::CalibrationData > &data)
Load a bagfile of calibration data.
#define ROS_INFO_STREAM(args)
bool moveToState(const sensor_msgs::JointState &state)
Send commands to all managed joints. The ChainManager automatically figures out which controller to s...
Class to do optimization.
bool getParam(const std::string &key, std::string &s) const
bool getState(sensor_msgs::JointState *state)
Get the current JointState message.