viz.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2018-2020 Michael Ferguson
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 // Author: Michael Ferguson
18 
19 //#include <fstream>
20 
21 #include <ros/ros.h>
23 #include <sensor_msgs/JointState.h>
24 #include <sensor_msgs/PointCloud2.h>
25 #include <visualization_msgs/MarkerArray.h>
26 
27 #include <urdf/model.h>
29 
34 
35 int main(int argc, char** argv)
36 {
37  // What bag to visualize
38  if (argc == 1)
39  {
40  std::cerr << std::endl;
41  std::cerr << "usage:" << std::endl;
42  std::cerr << " viz calibration_data.bag [offsets.yaml]" << std::endl;
43  std::cerr << std::endl;
44  return -1;
45  }
46  std::string bag_name = argv[1];
47 
48  // Start up ROS
49  ros::init(argc, argv, "robot_calibration_viz");
50  ros::NodeHandle nh("~");
51 
52  // The calibration data
53  std_msgs::String description_msg;
54  std::vector<robot_calibration_msgs::CalibrationData> data;
55  if (!robot_calibration::load_bag(bag_name, description_msg, data))
56  {
57  // Error will be printed in function
58  return -1;
59  }
60 
61  // Load KDL from URDF
62  urdf::Model model;
63  KDL::Tree tree;
64  if (!model.initString(description_msg.data))
65  {
66  ROS_FATAL("Failed to parse URDF.");
67  return -1;
68  }
69  if (!kdl_parser::treeFromUrdfModel(model, tree))
70  {
71  ROS_FATAL("Failed to construct KDL tree");
72  return -1;
73  }
74 
75  // Get parameters
78  params.LoadFromROS(nh);
79  ROS_INFO_STREAM("Publishing markers in " << params.base_link << " frame.");
80 
81  // Create models for reprojection
82  std::map<std::string, robot_calibration::ChainModel*> models;
83  std::map<std::string, ros::Publisher> camera_pubs;
84  std::vector<std::string> model_names;
85  for (size_t i = 0; i < params.models.size(); ++i)
86  {
87  if (params.models[i].type == "chain")
88  {
89  ROS_INFO_STREAM("Creating chain '" << params.models[i].name << "' from " <<
90  params.base_link << " to " <<
91  params.models[i].params["frame"]);
92  robot_calibration::ChainModel* model = new robot_calibration::ChainModel(params.models[i].name, tree, params.base_link, params.models[i].params["frame"]);
93  models[params.models[i].name] = model;
94  model_names.push_back(params.models[i].name);
95  }
96  else if (params.models[i].type == "camera3d")
97  {
98  ROS_INFO_STREAM("Creating camera3d '" << params.models[i].name << "' in frame " <<
99  params.models[i].params["frame"]);
100  robot_calibration::Camera3dModel* model = new robot_calibration::Camera3dModel(params.models[i].name, tree, params.base_link, params.models[i].params["frame"]);
101  models[params.models[i].name] = model;
102  model_names.push_back(params.models[i].name);
103  camera_pubs[params.models[i].name] = nh.advertise<sensor_msgs::PointCloud2>(params.models[i].name, 1);
104  }
105  else
106  {
107  // ERROR unknown
108  }
109  }
110 
111  // Setup our colors
112  std::vector<std_msgs::ColorRGBA> model_colors;
113  {
114  // Index 0 is white -- used for first points
115  std_msgs::ColorRGBA color;
116  color.r = 1.0;
117  color.b = 1.0;
118  color.g = 1.0;
119  color.a = 1.0;
120  model_colors.push_back(color);
121  while (model_colors.size() < model_names.size() + 1)
122  {
123  // Red
124  std_msgs::ColorRGBA color;
125  color.r = 1;
126  color.g = 0;
127  color.b = 0;
128  color.a = 1;
129  model_colors.push_back(color);
130  // Green
131  color.r = 0;
132  color.g = 1;
133  color.b = 0;
134  color.a = 1;
135  model_colors.push_back(color);
136  // Green
137  color.r = 0;
138  color.g = 0;
139  color.b = 1;
140  color.a = 1;
141  model_colors.push_back(color);
142  }
143  }
144 
145  // Load initial values for offsets (if any)
146  for (size_t i = 0; i < params.free_params.size(); ++i)
147  {
148  offsets.add(params.free_params[i]);
149  }
150  for (size_t i = 0; i < params.free_frames.size(); ++i)
151  {
152  offsets.addFrame(params.free_frames[i].name,
153  params.free_frames[i].x,
154  params.free_frames[i].y,
155  params.free_frames[i].z,
156  params.free_frames[i].roll,
157  params.free_frames[i].pitch,
158  params.free_frames[i].yaw);
159  }
160  for (size_t i = 0; i < params.free_frames_initial_values.size(); ++i)
161  {
162  if (!offsets.setFrame(params.free_frames_initial_values[i].name,
163  params.free_frames_initial_values[i].x,
164  params.free_frames_initial_values[i].y,
165  params.free_frames_initial_values[i].z,
166  params.free_frames_initial_values[i].roll,
167  params.free_frames_initial_values[i].pitch,
168  params.free_frames_initial_values[i].yaw))
169  {
170  ROS_ERROR_STREAM("Error setting initial value for " <<
171  params.free_frames_initial_values[i].name);
172  }
173  }
174 
175  // Load final values for offsets (if requested)
176  if (argc == 3)
177  {
178  std::string offsets_yaml = argv[2];
179  if (!offsets.loadOffsetYAML(offsets_yaml))
180  {
181  ROS_FATAL("Unable to load offsets from YAML");
182  return -1;
183  }
184  }
185 
186  // Publisher of fake joint states
187  ros::Publisher state = nh.advertise<sensor_msgs::JointState>("/fake_controller_joint_states", 1);
188 
189  // Publisher of visualization
190  ros::Publisher pub = nh.advertise<visualization_msgs::MarkerArray>("data", 10);
191  for (size_t i = 0; i < data.size(); ++i)
192  {
193  // Break out if ROS is dead
194  if (!ros::ok())
195  break;
196 
197  // Publish a marker array
198  visualization_msgs::MarkerArray markers;
199  for (size_t m = 0; m < model_names.size(); ++m)
200  {
201  // Project through model
202  std::vector<geometry_msgs::PointStamped> points;
203  points = models[model_names[m]]->project(data[i], offsets);
204 
205  // Convert into marker
206  visualization_msgs::Marker msg;
207  msg.header.frame_id = params.base_link;
208  msg.header.stamp = ros::Time::now();
209  msg.ns = model_names[m];
210  msg.id = m;
211  msg.type = msg.SPHERE_LIST;
212  msg.pose.orientation.w = 1.0;
213  msg.scale.x = 0.005;
214  msg.scale.y = 0.005;
215  msg.scale.z = 0.005;
216  msg.points.push_back(points[0].point);
217  msg.colors.push_back(model_colors[0]);
218  for (size_t p = 1; p < points.size(); ++p)
219  {
220  msg.points.push_back(points[p].point);
221  msg.colors.push_back(model_colors[m+1]);
222  }
223  markers.markers.push_back(msg);
224  }
225  pub.publish(markers);
226 
227  // Publish the joint states
228  sensor_msgs::JointState state_msg = data[i].joint_states;
229  for (size_t j = 0; j < state_msg.name.size(); ++j)
230  {
231  double offset = offsets.get(state_msg.name[j]);
232  state_msg.position[j] += offset;
233  }
234  state.publish(state_msg);
235 
236  // Publish sensor data (if present)
237  for (size_t obs = 0; obs < data[i].observations.size(); ++obs)
238  {
239  if (data[i].observations[obs].cloud.height != 0)
240  {
241  auto pub = camera_pubs.find(data[i].observations[obs].sensor_name);
242  if (pub != camera_pubs.end())
243  {
244  pub->second.publish(data[i].observations[obs].cloud);
245  }
246  }
247  }
248 
249  // Wait to proceed
250  std::cout << "Press enter to continue...";
251  std::string throwaway;
252  std::getline(std::cin, throwaway);
253  }
254 
255  return 0;
256 }
#define ROS_FATAL(...)
void publish(const boost::shared_ptr< M > &message) const
URDF_EXPORT bool initString(const std::string &xmlstring)
KDL_PARSER_PUBLIC bool treeFromUrdfModel(const urdf::ModelInterface &robot_model, KDL::Tree &tree)
Class to hold parameters for optimization.
ROSCPP_DECL void init(int &argc, char **argv, const std::string &name, uint32_t options=0)
std::vector< FreeFrameInitialValue > free_frames_initial_values
Combined parser and configuration for calibration offsets. Holds the configuration of what is to be c...
std::vector< std::string > free_params
bool add(const std::string name)
Tell the parser we wish to calibrate an active joint or other single parameter.
bool setFrame(const std::string name, double x, double y, double z, double roll, double pitch, double yaw)
Set the values for a frame.
ROSCPP_DECL bool ok()
Publisher advertise(const std::string &topic, uint32_t queue_size, bool latch=false)
double get(const std::string name) const
Get the offset.
bool addFrame(const std::string name, bool calibrate_x, bool calibrate_y, bool calibrate_z, bool calibrate_roll, bool calibrate_pitch, bool calibrate_yaw)
Tell the parser we wish to calibrate a fixed joint.
std::vector< FreeFrameParams > free_frames
Model of a camera on a kinematic chain.
Definition: camera3d.h:31
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.
Definition: load_bag.h:42
int main(int argc, char **argv)
Definition: viz.cpp:35
#define ROS_INFO_STREAM(args)
static Time now()
#define ROS_ERROR_STREAM(args)
bool loadOffsetYAML(const std::string &filename)
Load all the current offsets from a YAML.
Model of a kinematic chain. This is the basic instance where we transform the world observations into...
Definition: chain.h:107


robot_calibration
Author(s): Michael Ferguson
autogenerated on Tue Nov 3 2020 17:30:30