Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <ros/ros.h>
00021 #include <cortex_stream/cortex.h>
00022 #include <map>
00023 #include <visualization_msgs/Marker.h>
00024 #include <visualization_msgs/MarkerArray.h>
00025 #include <std_msgs/ColorRGBA.h>
00026 #include <geometry_msgs/Pose.h>
00027 #include <geometry_msgs/Vector3.h>
00028 #include <boost/thread.hpp>
00029 #include <boost/lexical_cast.hpp>
00030 #include <limits>
00031 using namespace std;
00032
00033
00034
00035 ros::Publisher marker_pub;
00036
00037
00038 class MocapInterface
00039 {
00040 public:
00041 MocapInterface();
00042 void init_colors();
00043 void processOnce();
00044 int cortexRequestPort;
00045 int cortexMulticastPort;
00046 std::string cortexAddress;
00047 void handleCortexFrame(void *frame);
00048 protected:
00049 double conversionFactor;
00050 double requestCortexTimeout;
00051 double frameRate;
00052 struct BodyDefinition {
00053 std::vector<std::string> markerNames;
00054 };
00055 boost::recursive_mutex marker_array_msg_lock_;
00056 visualization_msgs::MarkerArray markerArrayMsg;
00057 std::map<std::string, BodyDefinition> body;
00058 std::string marker_frame_id_;
00059 std::vector<std_msgs::ColorRGBA> colors_;
00060 };
00061
00062
00063 MocapInterface::MocapInterface()
00064 {
00065 ros::NodeHandle nh;
00066 ros::NodeHandle private_nh("~");
00067 private_nh.param("cortexRequestPort", cortexRequestPort, 1510);
00068 private_nh.param("cortexMulticastPort", cortexMulticastPort, 1509);
00069 private_nh.param("cortexAddress", cortexAddress, std::string("132.230.167.153"));
00070 private_nh.param("markerFrameId", marker_frame_id_, std::string("/map"));
00071 conversionFactor = 0.001;
00072 requestCortexTimeout = 0.5;
00073 init_colors();
00074 }
00075 void MocapInterface::init_colors()
00076 {
00077 double alpha = 0.8;
00078 std_msgs::ColorRGBA color;
00079 color.r = 1.0;
00080 color.g = 0.0;
00081 color.b = 0.0;
00082 color.a = alpha;
00083 colors_.push_back(color);
00084 color.r = 0.0;
00085 color.g = 1.0;
00086 color.b = 0.0;
00087 colors_.push_back(color);
00088 color.r = 0.0;
00089 color.g = 0.0;
00090 color.b = 1.0;
00091 colors_.push_back(color);
00092 color.r = 0.0;
00093 color.g = 1.0;
00094 color.b = 1.0;
00095 colors_.push_back(color);
00096 color.r = 1.0;
00097 color.g = 1.0;
00098 color.b = 0.0;
00099 colors_.push_back(color);
00100 color.r = 1.0;
00101 color.g = 0.0;
00102 color.b = 1.0;
00103 colors_.push_back(color);
00104
00105 }
00106
00107
00108
00109 void CortexDataHandler(sFrameOfData* frame, void *params)
00110 {
00111 ((MocapInterface*)params)->handleCortexFrame(frame);
00112 }
00113
00114
00115
00116 void MocapInterface::handleCortexFrame(void *frame)
00117 {
00118 static unsigned int frame_count = 0;
00119 if (frame_count % 200 == 0)
00120 {
00121 ROS_INFO("Got frame (this message shows only every 2 secs)");
00122 frame_count = 0;
00123 }
00124 frame_count++;
00125 sFrameOfData *f = (sFrameOfData*)frame;
00126 ros::Time timestamp = ros::Time::now() - ros::Duration(f->fDelay);
00127
00128 double scale_fac = 0.05;
00129 sBodyData *b = f->BodyData;
00130 markerArrayMsg.markers.clear();
00131 boost::recursive_mutex::scoped_lock marker_array_msglock(marker_array_msg_lock_);
00132
00133 for (int i=0; i<f->nBodies; i++, b++) {
00134 visualization_msgs::Marker markerMsg;
00135 markerMsg.type = visualization_msgs::Marker::CUBE_LIST;
00136 markerMsg.header.frame_id = marker_frame_id_;
00137 markerMsg.header.stamp = timestamp;
00138 markerMsg.header.seq = f->iFrame;
00139 markerMsg.action = visualization_msgs::Marker::ADD;
00140 markerMsg.id = 0;
00141 markerMsg.ns = b->szName;
00142 markerMsg.points.clear();
00143 markerMsg.colors.clear();
00144
00145 markerMsg.color.r = 1.0;
00146 markerMsg.color.g = 1.0;
00147 markerMsg.color.b = 1.0;
00148 markerMsg.color.a = 1.0;
00149 markerMsg.scale.x = scale_fac;
00150 markerMsg.scale.y = scale_fac;
00151 markerMsg.scale.z = scale_fac;
00152 geometry_msgs::Pose pose;
00153
00154
00155 pose.position.x = 0;
00156 pose.position.y = 0;
00157 pose.position.z = 0;
00158 for (int j=0; j<b->nMarkers; j++) {
00159 geometry_msgs::Point p;
00160 std_msgs::ColorRGBA color;
00161
00162 if (b->Markers[j][0] == XEMPTY &&
00163 b->Markers[j][1] == XEMPTY &&
00164 b->Markers[j][2] == XEMPTY)
00165 {
00166 float quietNan = std::numeric_limits<float>::quiet_NaN();
00167 p.x = quietNan;
00168 p.y = quietNan;
00169 p.z = quietNan;
00170 }
00171 else
00172 {
00173 p.x = b->Markers[j][0]*conversionFactor;
00174 p.y = b->Markers[j][1]*conversionFactor;
00175 p.z = b->Markers[j][2]*conversionFactor;
00176 }
00177 color = colors_[ j % colors_.size() ];
00178 markerMsg.colors.push_back(color);
00179 markerMsg.points.push_back(p);
00180
00181
00182
00183 }
00184 markerArrayMsg.markers.push_back(markerMsg);
00185 }
00186 marker_pub.publish(markerArrayMsg);
00187 }
00188
00189
00190 void CortexErrorMsgHandler(int iLevel, const char *szMsg, void*)
00191 {
00192 if (iLevel == VL_Debug) {
00193 ROS_DEBUG("Cortex: %s", szMsg);
00194 } else if (iLevel == VL_Info) {
00195 ROS_INFO("Cortex: %s", szMsg);
00196 } else if (iLevel == VL_Warning) {
00197 ROS_WARN("Cortex: %s", szMsg);
00198 } else if (iLevel == VL_Error) {
00199 ROS_ERROR("Cortex: %s", szMsg);
00200 } else {
00201 ROS_ERROR("Received unknown Cortex Error Msg");
00202 }
00203 }
00204
00205
00206 void MocapInterface::processOnce()
00207 {
00208 Cortex_SetVerbosityLevel(VL_Info);
00209 Cortex_SetErrorMsgHandlerFunc(CortexErrorMsgHandler, this);
00210 if (Cortex_SetRequestPort(cortexRequestPort) != RC_Okay)
00211 return;
00212 if (Cortex_SetMulticastPort(cortexMulticastPort) != RC_Okay)
00213 return;
00214 if (Cortex_Initialize(cortexAddress.c_str()) != RC_Okay) {
00215 std::cerr << "Unable to initialize Cortex client\n";
00216 return;
00217 }
00218
00219
00220 void *response = NULL;
00221 int numBytes = 0;
00222 int retval;
00223 retval = Cortex_Request("GetConversionToMillimeters", &response, &numBytes, requestCortexTimeout);
00224 if (retval != RC_Okay || numBytes != 4) {
00225 std::cerr << "Error: Failed to get conversion factor to millimeters\n";
00226 Cortex_Exit();
00227 return;
00228 }
00229 float factor;
00230 memcpy(&factor, response, 4);
00231 conversionFactor = factor/1000.0;
00232 std::cerr << "Got conversion factor " << conversionFactor << " meters per MoCap unit\n";
00233
00234
00235 numBytes = 0;
00236 retval = Cortex_Request("GetContextFrameRate", &response, &numBytes, requestCortexTimeout);
00237 if (retval != RC_Okay || numBytes != 4) {
00238 std::cerr << "Error: Failed to get frame rate\n";
00239 Cortex_Exit();
00240 return;
00241 }
00242 float rate;
00243 memcpy(&rate, response, 4);
00244 frameRate = rate;
00245
00246 ROS_INFO("Got frame rate %4.2f Hz",frameRate);
00247
00248
00249 sBodyDefs *bodies = Cortex_GetBodyDefs(requestCortexTimeout);
00250 if (bodies == NULL) {
00251 std::cerr << "Error: Failed to get body definitions\n";
00252 Cortex_Exit();
00253 return;
00254 }
00255
00256
00257
00258 std::cerr << "Got body definitions:";
00259 sBodyDef *b = bodies->BodyDefs;
00260 for (int i=0; i<bodies->nBodyDefs; i++, b++) {
00261 BodyDefinition bd;
00262 bd.markerNames.reserve(b->nMarkers);
00263 for (int j=0; j<b->nMarkers; j++)
00264 bd.markerNames.push_back(b->szMarkerNames[j]);
00265 body[b->szName] = bd;
00266 std::cerr << " " << b->szName;
00267 }
00268 std::cerr << "\n";
00269
00270
00271 Cortex_SetDataHandlerFunc(CortexDataHandler, this);
00272 }
00273
00274
00275 int main(int argc, char ** argv)
00276 {
00277 ros::init(argc,argv,"cortex_stream");
00278 ros::NodeHandle nh;
00279 marker_pub = nh.advertise<visualization_msgs::MarkerArray>( "cortex_marker_array", 0 );
00280 MocapInterface mocap;
00281 mocap.processOnce();
00282 ros::Rate r(100.0);
00283 while(ros::ok())
00284 {
00285 r.sleep();
00286 ros::spinOnce();
00287 }
00288 Cortex_Exit();
00289 ROS_INFO("Exit peacefully");
00290 return 0;
00291 }