bool shutdown_vicon() { ROS_INFO_STREAM("Disconnecting from Vicon DataStream SDK"); MyClient.Disconnect(); ROS_ASSERT(!MyClient.IsConnected().Connected); ROS_INFO_STREAM("... disconnected."); return true; }
void updateCallback(const ros::TimerEvent& e) { static bool got_first = false; latest_dt = (e.current_real - e.last_real).toSec(); latest_jitter = (e.current_real - e.current_expected).toSec(); max_abs_jitter = max(max_abs_jitter, fabs(latest_jitter)); Result::Enum the_result; bool was_new_frame = true; if ((not segment_data_enabled) // and (pose_pub.getNumSubscribers() > 0 or markers_pub.getNumSubscribers() > 0)) { the_result = MyClient.EnableSegmentData().Result; if (the_result != Result::Success) { ROS_ERROR("Enable segment data call failed"); } else { ROS_ASSERT(MyClient.IsSegmentDataEnabled().Enabled); ROS_INFO("Segment data enabled"); segment_data_enabled = true; } } if (segment_data_enabled) { while (was_new_frame and (the_result = MyClient.GetFrame().Result) == Result::Success) ; { now_time = ros::Time::now(); // try to grab as close to getting message as possible was_new_frame = process_frame(); got_first = true; } if (the_result != Result::NoFrame) { ROS_ERROR_STREAM("GetFrame() returned " << (int)the_result); } if (got_first) { max_period_between_updates = max(max_period_between_updates, latest_dt); last_callback_duration = e.profile.last_duration.toSec(); } } diag_updater.update(); }
void process_subjects(const ros::Time& frame_time) { if (pose_pub.getNumSubscribers() > 0) { // We know the subject and segment names a priori, so don't bother enumerating, just grab the data: // Flyer: Output_GetSegmentGlobalTranslation trans = MyClient.GetSegmentGlobalTranslation(SubjectName, SegmentName); Output_GetSegmentGlobalRotationQuaternion quat = MyClient.GetSegmentGlobalRotationQuaternion(SubjectName, SegmentName); if (trans.Result == Result::Success and quat.Result == Result::Success) { if ((not trans.Occluded) and (not quat.Occluded)) { flyer_transform.setOrigin( tf::Vector3(trans.Translation[0] / 1000, trans.Translation[1] / 1000, trans.Translation[2] / 1000)); flyer_transform.setRotation( tf::Quaternion(quat.Rotation[0], quat.Rotation[1], quat.Rotation[2], quat.Rotation[3])); //ros::Time thisTime = now_time - ros::Duration(latencyInMs / 1000); tf::StampedTransform transform = tf::StampedTransform(flyer_transform, frame_time, tf_ref_frame_id, tf_tracked_frame_id); if (enable_tf_broadcast) tf_broadcast.sendTransform(transform); geometry_msgs::TransformStamped pose_msg; tf::transformStampedTFToMsg(transform, pose_msg); pose_pub.publish(pose_msg); } else { ROS_WARN_STREAM("occluded, not publishing..."); } } else { ROS_WARN("GetSegmentGlobalTranslation/Rotation failed (result = %d, %d), not publishing...", (int)(trans.Result), (int)(quat.Result)); } } }
bool process_frame() { static ros::Time lastTime; Output_GetFrameNumber OutputFrameNum = MyClient.GetFrameNumber(); if ((OutputFrameNum.Result != Result::Success) and (OutputFrameNum.Result != Result::NoFrame)) { ROS_ERROR("GetFrameNumber() returned %d", int(OutputFrameNum.Result)); return false; } if (frame_datum == 0 or (fabs(latest_time_bias) > time_bias_reset)) // this is the first frame we've gotten { frame_datum = OutputFrameNum.FrameNumber; time_datum = now_time; ROS_INFO("Time bias reset (bias was %f): marking VICON frame number %d as datum time %d.%d", latest_time_bias, frame_datum, time_datum.sec, time_datum.nsec); time_bias_reset_count++; } //frameCount++; // ROS_INFO_STREAM("Grabbed a frame: " << OutputFrameNum.FrameNumber); int frameDiff = 0; if (lastFrameNumber != 0) { frameDiff = OutputFrameNum.FrameNumber - lastFrameNumber; frameCount += frameDiff; if ((frameDiff) > 1) { droppedFrameCount += frameDiff - 1; double droppedFramePct = (double)droppedFrameCount / frameCount * 100; ROS_DEBUG_STREAM( (frameDiff - 1) << " more (total " << droppedFrameCount << "/" << frameCount << ", " << droppedFramePct << "%) frame(s) dropped. Consider adjusting rates."); } } lastFrameNumber = OutputFrameNum.FrameNumber; if (frameDiff == 0) { return false; } else { freq_status.tick(); //double latencyInMs = MyClient.GetLatencyTotal().Total * 1000; ros::Time frame_time = time_datum + ros::Duration((lastFrameNumber - frame_datum) / vicon_capture_rate); latest_time_bias = (frame_time - now_time).toSec(); process_subjects(frame_time); process_markers(frame_time, lastFrameNumber); lastTime = now_time; return true; } }
bool grab_vicon_pose_callback(vicon_mocap::viconGrabPose::Request& req, vicon_mocap::viconGrabPose::Response& resp) { ROS_INFO("Got request for a VICON pose"); updateTimer.stop(); tf::StampedTransform transform; //tf::Quaternion quat; if (not segment_data_enabled) { MyClient.EnableSegmentData(); ROS_ASSERT(MyClient.IsSegmentDataEnabled().Enabled); segment_data_enabled = true; } // Gather data: int N = req.n_measurements; double accum_trans[3] = {0, 0, 0}; double accum_quat[4] = {0, 0, 0, 0}; Result::Enum the_result; int n_success = 0; for (int k = 0; k < N; k++) { ros::Duration(1 / vicon_capture_rate).sleep(); // Wait at least as long as vicon needs to capture the next frame if ((the_result = MyClient.GetFrame().Result) == Result::Success) { try { Output_GetSegmentGlobalTranslation trans = MyClient.GetSegmentGlobalTranslation(req.subject_name, req.segment_name); Output_GetSegmentGlobalRotationQuaternion quat = MyClient.GetSegmentGlobalRotationQuaternion(req.subject_name, req.segment_name); if ((!trans.Occluded) && (!quat.Occluded)) { accum_trans[0] += trans.Translation[0] / 1000; accum_trans[1] += trans.Translation[1] / 1000; accum_trans[2] += trans.Translation[2] / 1000; accum_quat[0] += quat.Rotation[3]; accum_quat[1] += quat.Rotation[0]; accum_quat[2] += quat.Rotation[1]; accum_quat[3] += quat.Rotation[2]; n_success++; } } catch (tf::TransformException ex) { ROS_ERROR("%s", ex.what()); resp.success = false; return false; // TODO: should we really bail here, or just try again? } } else { if (the_result != Result::NoFrame) { ROS_ERROR_STREAM("GetFrame() returned " << (int)the_result); } } } ROS_INFO("Averaging %d measurements", n_success); // Average the data: double normalized_quat[4]; double quat_norm = sqrt( accum_quat[0] * accum_quat[0] + accum_quat[1] * accum_quat[1] + accum_quat[2] * accum_quat[2] + accum_quat[3] * accum_quat[3]); for (int i = 0; i < 4; i++) { normalized_quat[i] = accum_quat[i] / quat_norm; } double normalized_vector[3]; // Copy to inputs: for (int i = 0; i < 3; i++) { normalized_vector[i] = accum_trans[i] / n_success; } // copy what we used to service call response: resp.success = true; resp.pose.header.stamp = ros::Time::now(); resp.pose.header.frame_id = tf_ref_frame_id; resp.pose.pose.position.x = normalized_vector[0]; resp.pose.pose.position.y = normalized_vector[1]; resp.pose.pose.position.z = normalized_vector[2]; resp.pose.pose.orientation.w = normalized_quat[0]; resp.pose.pose.orientation.x = normalized_quat[1]; resp.pose.pose.orientation.y = normalized_quat[2]; resp.pose.pose.orientation.z = normalized_quat[3]; updateTimer.start(); return true; }
void process_markers(const ros::Time& frame_time, unsigned int vicon_frame_num) { if (markers_pub.getNumSubscribers() > 0) { if (not marker_data_enabled) { MyClient.EnableMarkerData(); ROS_ASSERT(MyClient.IsMarkerDataEnabled().Enabled); marker_data_enabled = true; } if (not unlabeled_marker_data_enabled) { MyClient.EnableUnlabeledMarkerData(); ROS_ASSERT(MyClient.IsUnlabeledMarkerDataEnabled().Enabled); unlabeled_marker_data_enabled = true; } n_markers = 0; vicon_mocap::Markers markers_msg; markers_msg.header.stamp = frame_time; markers_msg.frame_number = vicon_frame_num; markers_msg.header.frame_id = tf_ref_frame_id; // Count the number of subjects unsigned int SubjectCount = MyClient.GetSubjectCount().SubjectCount; // Get labeled markers for (unsigned int SubjectIndex = 0; SubjectIndex < SubjectCount; ++SubjectIndex) { std::string this_subject_name = MyClient.GetSubjectName(SubjectIndex).SubjectName; // Count the number of markers unsigned int num_subject_markers = MyClient.GetMarkerCount(SubjectName).MarkerCount; n_markers += num_subject_markers; //std::cout << " Markers (" << MarkerCount << "):" << std::endl; for (unsigned int MarkerIndex = 0; MarkerIndex < num_subject_markers; ++MarkerIndex) { vicon_mocap::Marker this_marker; this_marker.marker_name = MyClient.GetMarkerName(this_subject_name, MarkerIndex).MarkerName; this_marker.subject_name = this_subject_name; this_marker.segment_name = MyClient.GetMarkerParentName(this_subject_name, this_marker.marker_name).SegmentName; // Get the global marker translation Output_GetMarkerGlobalTranslation _Output_GetMarkerGlobalTranslation = MyClient.GetMarkerGlobalTranslation(this_subject_name, this_marker.marker_name); this_marker.translation.x = _Output_GetMarkerGlobalTranslation.Translation[0] / 1000; this_marker.translation.y = _Output_GetMarkerGlobalTranslation.Translation[1] / 1000; this_marker.translation.z = _Output_GetMarkerGlobalTranslation.Translation[2] / 1000; this_marker.occluded = _Output_GetMarkerGlobalTranslation.Occluded; markers_msg.markers.push_back(this_marker); } } // get unlabeled markers unsigned int UnlabeledMarkerCount = MyClient.GetUnlabeledMarkerCount().MarkerCount; //ROS_INFO("# unlabeled markers: %d", UnlabeledMarkerCount); n_markers += UnlabeledMarkerCount; n_unlabeled_markers = UnlabeledMarkerCount; for (unsigned int UnlabeledMarkerIndex = 0; UnlabeledMarkerIndex < UnlabeledMarkerCount; ++UnlabeledMarkerIndex) { // Get the global marker translation Output_GetUnlabeledMarkerGlobalTranslation _Output_GetUnlabeledMarkerGlobalTranslation = MyClient.GetUnlabeledMarkerGlobalTranslation(UnlabeledMarkerIndex); if (_Output_GetUnlabeledMarkerGlobalTranslation.Result == Result::Success) { vicon_mocap::Marker this_marker; this_marker.translation.x = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[0] / 1000; this_marker.translation.y = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[1] / 1000; this_marker.translation.z = _Output_GetUnlabeledMarkerGlobalTranslation.Translation[2] / 1000; this_marker.occluded = false; // unlabeled markers can't be occluded markers_msg.unlabeled_markers.push_back(this_marker); } else { ROS_WARN("GetUnlabeledMarkerGlobalTranslation failed (result = %d)", (int)(_Output_GetUnlabeledMarkerGlobalTranslation.Result)); } } markers_pub.publish(markers_msg); } }
bool init_vicon() { ROS_INFO_STREAM("Connecting to Vicon DataStream SDK at " << HostName << " ..."); while (!MyClient.IsConnected().Connected) { MyClient.Connect(HostName); ROS_INFO("."); sleep(1); ros::spinOnce(); if (!ros::ok()) return false; } ROS_ASSERT(MyClient.IsConnected().Connected); ROS_INFO_STREAM("... connected!"); ROS_INFO_STREAM("Setting Stream Mode to " << StreamMode); { Output_SetStreamMode result; if (StreamMode == "ServerPush") { result = MyClient.SetStreamMode(StreamMode::ServerPush); } else if (StreamMode == "ClientPull") { result = MyClient.SetStreamMode(StreamMode::ClientPull); } else if (StreamMode == "ClientPullPreFetch") { result = MyClient.SetStreamMode(StreamMode::ClientPullPreFetch); } else { ROS_FATAL("Unknown stream mode -- options are ServerPush, ClientPull, ClientPullPreFetch"); ros::shutdown(); } if (result.Result != Result::Success) { ROS_FATAL("Set stream mode call failed -- shutting down"); ros::shutdown(); } } { Output_SetAxisMapping result; result = MyClient.SetAxisMapping(Direction::Forward, Direction::Left, Direction::Up); // 'Z-up' if (result.Result != Result::Success) { ROS_FATAL("Set axis mapping call failed -- shutting down"); ros::shutdown(); } Output_GetAxisMapping _Output_GetAxisMapping = MyClient.GetAxisMapping(); ROS_INFO_STREAM( "Axis Mapping: X-" << Adapt(_Output_GetAxisMapping.XAxis) << " Y-" << Adapt(_Output_GetAxisMapping.YAxis) << " Z-" << Adapt(_Output_GetAxisMapping.ZAxis)); Output_GetVersion _Output_GetVersion = MyClient.GetVersion(); ROS_INFO_STREAM( "Version: " << _Output_GetVersion.Major << "." << _Output_GetVersion.Minor << "." << _Output_GetVersion.Point); } return true; }
// mocap position thread void DataStreamClient::run(void) { while (true) //TODO: exit cleanly? { // get frame while (_vicon_client.GetFrame().Result != Result::Success) { dbg("Couldn't GetFrame()\n"); usleep(1000); } // get timecode and populate subject message // Output_GetTimecode time_code = _vicon_client.GetTimecode(); vicon::body_t msg; msg.utime = _timestamp_now(); vicon::vicon_t system; // get subject count system.nummodels = _vicon_client.GetSubjectCount().SubjectCount; // Uh oh, models disappeared - realloc the system if (system.nummodels < system.models.size()) { system.models.clear(); system.models.reserve(system.nummodels); } if (system.nummodels == 0) { std::cout << "no models detected" << std::endl; continue; } // loop through subjects for (uint subject_index = 0; subject_index < system.nummodels; subject_index++) { //////////////////////////////////////////////////////////////////////// /// Marker vicon::model_t& model = findModel(system.models, _vicon_client.GetSubjectName(subject_index).SubjectName); model.nummarkers = _vicon_client.GetMarkerCount(model.name).MarkerCount; if (model.nummarkers < model.markers.size()) { model.markers.clear(); model.markers.reserve(model.nummarkers); } for(int32_t j = 0; j < model.nummarkers; j++) { vicon::marker_t& marker = findMarker(model.markers, _vicon_client.GetMarkerName(model.name, j).MarkerName); Output_GetMarkerGlobalTranslation translation = _vicon_client.GetMarkerGlobalTranslation(model.name, marker.name); marker.o = translation.Occluded; memcpy(marker.xyz, translation.Translation, 3*sizeof(double)); } //////////////////////////////////////////////////////////////////////// /// Segments // get number of segments model.numsegments = _vicon_client.GetSegmentCount(model.name).SegmentCount; if (model.numsegments < model.segments.size()) { model.segments.clear(); model.segments.reserve(model.numsegments); } // get subject name std::string subject_name = _vicon_client.GetSubjectName(subject_index).SubjectName; // get root segment name std::string root_segment_name = _vicon_client.GetSubjectRootSegmentName(subject_name).SegmentName; // loop through segments for (uint segment_index = 0; segment_index < model.numsegments; segment_index++) { // get segment name std::string segment_name = _vicon_client.GetSegmentName(subject_name, segment_index).SegmentName; vicon::segment_t& segment = findSegment(model.segments, segment_name); Output_GetSegmentGlobalRotationEulerXYZ A = _vicon_client.GetSegmentGlobalRotationEulerXYZ(model.name, segment.name); Output_GetSegmentGlobalTranslation T = _vicon_client.GetSegmentGlobalTranslation(model.name, segment.name); Output_GetSegmentLocalRotationEulerXYZ ba = _vicon_client.GetSegmentLocalRotationEulerXYZ(model.name, segment.name); Output_GetSegmentLocalTranslation bt = _vicon_client.GetSegmentLocalTranslation(model.name, segment.name); memcpy(segment.A, A.Rotation, 3*sizeof(double)); memcpy(segment.T, T.Translation, 3*sizeof(double)); memcpy(segment.ba, ba.Rotation, 3*sizeof(double)); memcpy(segment.bt, bt.Translation, 3*sizeof(double)); // check if root segment if (segment_name == root_segment_name) { //TODO: handle articulated bodies // get segment translation // Output_GetSegmentStaticTranslation segment_translation = _vicon_client.GetSegmentStaticTranslation(subject_name, segment_name); Output_GetSegmentGlobalTranslation segment_translation = _vicon_client.GetSegmentGlobalTranslation( subject_name, segment_name); // get segment rotation //Output_GetSegmentStaticRotationQuaternion segment_rotation = _vicon_client.GetSegmentStaticRotationQuaternion(subject_name, segment_name); Output_GetSegmentGlobalRotationQuaternion segment_rotation = _vicon_client.GetSegmentGlobalRotationQuaternion(subject_name, segment_name); // Output_GetSegmentGlobalRotationEulerXYZ segment_rotation = _vicon_client.GetSegmentGlobalRotationEulerXYZ(subject_name, segment_name); // populate message with position for (int i = 0; i < 3; i++) msg.trans[i] = segment_translation.Translation[i]/1000.0; //vicon data is in mm msg.quat[0] = segment_rotation.Rotation[3]; //vicon is x,y,z,w msg.quat[1] = segment_rotation.Rotation[0]; msg.quat[2] = segment_rotation.Rotation[1]; msg.quat[3] = segment_rotation.Rotation[2]; std::string channel = "VICON_" + subject_name; _lcm.publish(channel.c_str(), &msg); // break from segment for loop break; } // root segment } // for each segment (model.numsegments) } // for each subject (system.nummodels) _lcm.publish("VICON_MARKERS", &system); } // disconnect client dbg("Subject position thread terminated properly, disconnecting client\n"); _vicon_client.Disconnect(); }