ros_Time and Duration

这篇文章回顾了2016年JavaScript框架如Vue、React和Angular的发展趋势,探讨了它们在Web开发中的重要角色和应用案例。
#include "oryxbot_cruise_ex/oryxbot_task.h" bool ORYXTask::CheckServiceIsExist(std::string serviceName, ros::Duration timeout){ ROS_INFO("waiting for service: %s ...", serviceName.c_str()); if(ros::service::waitForService(serviceName, timeout)){ ROS_INFO("service: %s is ready!!!", serviceName.c_str()); return true; }else ROS_ERROR("!!!Did not find service: %s", serviceName.c_str()); return false; } bool ORYXTask::Init(ros::NodeHandle &nh){ ROS_INFO("***ORYXTask::Init()***"); relativServiceName_ = "relative_move"; //相对移动服务 arTarckServiceName_ = "ar_track"; //ar码对齐服务 // chargeServiceName_ = "goto_charge"; //自主充电服务 pickServiceName_ = "pick_ar"; //手臂ar码抓取服务 gotoPositionServiceName_ = "goto_position"; //手臂控制服务 pumpOffServiceName_ = "swiftpro/off"; //仿真气泵关闭服务 pumpOnServiceName_ = "swiftpro/on"; //仿真气泵开启服务 if(!CheckServiceIsExist(relativServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::Init() relative failed"); return false; } if(!CheckServiceIsExist(arTarckServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::Init() arTrack failed"); return false; } // if(!CheckServiceIsExist(chargeServiceName_, ros::Duration(60))){ // ROS_ERROR("!!!ORYXTask::Init() charge failed"); // return false; // } if(!CheckServiceIsExist(pickServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::Init() pick failed"); return false; } if(!CheckServiceIsExist(gotoPositionServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::Init() gotoPosition failed"); return false; } if(!CheckServiceIsExist(pumpOffServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::Init() pumpOff failed"); return false; } if(!CheckServiceIsExist(pumpOnServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::Init() pumpOn failed"); return false; } pickClient_ = nh.serviceClient<arm_controller::PickPlace>(pickServiceName_); gotoPositionClient_ = nh.serviceClient<arm_controller::move>(gotoPositionServiceName_.c_str()); pumpOffClient_ = nh.serviceClient<std_srvs::Empty>(pumpOffServiceName_); pumpOnClient_ = nh.serviceClient<std_srvs::Empty>(pumpOnServiceName_); relativeClient_ = nh.serviceClient<relative_move::SetRelativeMove>(relativServiceName_); trackClient_ = nh.serviceClient<ar_pose::Track>(arTarckServiceName_); // chargeClient_ = nh.serviceClient<auto_charging::SetCharge>(chargeServiceName_); ROS_INFO("ORYXTask init successed!!!"); return true; } /** * @brief 对齐ar码 * * @param arId 需要对齐的ar码id * @return true 对齐成功 * @return false 对齐失败,可能原因为ar码丢失 */ bool ORYXTask::ArAdjust(int arId=0){ ROS_INFO("***ORYXTask::ArAdjust()***"); if(!CheckServiceIsExist(arTarckServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::ArAdjust() failed"); return false; } ar_pose::Track srv; srv.request.ar_id = arId; srv.request.goal_dist = 0.3; trackClient_.call(srv); if(srv.response.success){ ROS_INFO("track ar id: %d successed!!!", arId); return true; } else{ ROS_ERROR("!!!track ar id: %d failed, err info is: %s", arId, srv.response.message.c_str()); return false; } } /** * @brief 相对移动 * * @return true * @return false */ bool ORYXTask::RelativeMove(float x_,float y_,float theta_,std::string frame_id_){ ROS_INFO("***ORYXTask::RelativeMove()***"); if(!CheckServiceIsExist(relativServiceName_, ros::Duration(60))){ ROS_ERROR("!!!ORYXTask::RelativeMove() failed"); return false; } relative_move::SetRelativeMove srv; srv.request.goal.x = x_; srv.request.goal.y = y_; srv.request.goal.theta = theta_; srv.request.global_frame = frame_id_; relativeClient_.call(srv); if(srv.response.success){ ROS_INFO("relative move successed!!!"); return true; } else{ ROS_ERROR("!!!relative move failed, err info is: %s", srv.response.message.c_str()); return false; } } // bool ORYXTask::Charge(int arId){ // ROS_INFO("***ORYXTask::Charge()***"); // if(!CheckServiceIsExist(chargeServiceName_, ros::Duration(60))){ // ROS_ERROR("!!!ORYXTask::Charge() failed"); // return false; // } // auto_charging::SetCharge srv; // srv.request.ar_id = arId; // srv.request.ar_track = true; // chargeClient_.call(srv); // if(srv.response.success){ // ROS_INFO("goto charge successed!!!"); // return true; // } // else{ // ROS_ERROR("!!!go to charge failed, err info is: %s", srv.response.message.c_str()); // return false; // } // } bool ORYXTask::PickPlace(int arId, float x, float y, float z, float r ){ ROS_INFO("***ORYXTask::PickPlace(%d, %f, %f, %f, %f)***",arId,x,y,z,r); if(!CheckServiceIsExist(pickServiceName_, ros::Duration(5))){ ROS_ERROR("!!!ORYXTask::PickPlace() failed"); return false; } arm_controller::PickPlace srv; srv.request.mode = 1; srv.request.pose.position.x = x; srv.request.pose.position.y = y; srv.request.pose.position.z = z; srv.request.pose.yaw = r; srv.request.number = arId; pickClient_.call(srv); if(srv.response.success){ ROS_INFO("pick ar id: %d successed!!!", arId); return true; } ROS_ERROR("!!!pick ar id: %d failed, err info is: %s", arId, srv.response.message.c_str()); return false; } bool ORYXTask::GotoPosition(float x, float y, float z, float r ){ ROS_INFO("***ORYXTask::GotoPosition(%f, %f, %f, %f)***",x,y,z,r); if(!CheckServiceIsExist(gotoPositionServiceName_, ros::Duration(10))){ ROS_ERROR("!!!ORYXTask::GotoPosition() failed"); return false; } arm_controller::move srv; srv.request.pose.position.x = x; srv.request.pose.position.y = y; srv.request.pose.position.z = z; srv.request.pose.yaw = r; gotoPositionClient_.call(srv); if(srv.response.success){ ROS_INFO("arm go to position successed!!!"); return true; } ROS_ERROR("!!!arm go to position failed, err info is: %s", srv.response.message.c_str()); return false; } bool ORYXTask::GetArIDs(std::vector<int> &arIdOutArray){ ROS_INFO("***ORYXTask::GetArIDs()***"); for(int i=0; i<5; i++){ ar_track_alvar_msgs::AlvarMarkers::ConstPtr arTopic = ros::topic::waitForMessage<ar_track_alvar_msgs::AlvarMarkers>("/hand_cam/ar_pose_marker", ros::Duration(1.0)); if(arTopic!=NULL){ if(arTopic->markers.empty()) continue; arIdOutArray.clear(); std::string ids=""; for (auto arInfo : arTopic->markers) { ids = ids+" "; arIdOutArray.push_back(arInfo.id); ids = ids+std::to_string(arInfo.id); } ROS_INFO("find ar ids: [%s]", ids.c_str()); return true; } } ROS_ERROR("!!!Topic <ar_pose_marker> not be published"); return false; } bool ORYXTask::ResetArm(float x, float y, float z, float r ){ ROS_INFO("***ORYXTask::ResetArm(%f, %f, %f, %f)***",x,y,z,r); if(!CheckServiceIsExist(pumpOffServiceName_, ros::Duration(10))){ ROS_ERROR("!!!ORYXTask::ResetArm() failed"); return false; } if(GotoPosition(x, y, z, r)){ ROS_INFO("arm go to position successed!!!"); std_srvs::Empty pumpSrv; pumpOffClient_.call(pumpSrv); ROS_INFO("turn off pump successed!!!"); ROS_INFO("reset arm successed!!!"); return true; } return false; }帮我修改给我一个完整的
06-29
void MainThread(const ros::TimerEvent &event) { static int fsm_num = 0; fsm_num++; if (fsm_num == 100) { fsm_num = 0; printStateMachine(); } if (!have_geometry_ || !have_goal_ || !allow_plan_traj_) return; // collision check if (have_geometry_) { if (state_machine_ != EMERGENCY_STOP && sdfmap_->getDistanceReal(Eigen::Vector2d(current_state_XYTheta_.x(), current_state_XYTheta_.y())) <= 0.15) { std_msgs::Bool emergency_stop; emergency_stop.data = true; emergency_stop_pub_.publish(emergency_stop); state_machine_ = EMERGENCY_STOP; ROS_INFO_STREAM("current_state_XYTheta_: " << current_state_XYTheta_.transpose()); ROS_INFO_STREAM("Dis: " << sdfmap_->getDistanceReal(Eigen::Vector2d(current_state_XYTheta_.x(), current_state_XYTheta_.y()))); ROS_ERROR("EMERGENCY_STOP!!! too close to obstacle!!!"); return; } else if (state_machine_ == EMERGENCY_STOP && sdfmap_->getDistanceReal(Eigen::Vector2d(current_state_XYTheta_.x(), current_state_XYTheta_.y())) > (road_map_safe_dis / 2.0)) { std_msgs::Bool emergency_stop; emergency_stop.data = false; emergency_stop_pub_.publish(emergency_stop); state_machine_ = IDLE; ROS_INFO("EMERGENCY_STOP released, back to IDLE state."); } } if (state_machine_ == StateMachine::IDLE || ((state_machine_ == StateMachine::PLANNING || state_machine_ == StateMachine::REPLAN) && (ros::Time::now() - loop_start_time_).toSec() > replan_time_)) { loop_start_time_ = ros::Time::now(); double current = loop_start_time_.toSec(); // start new plan if (state_machine_ == StateMachine::IDLE) { // 发布路图 if (if_road_map) { nav_msgs::Path road_map_msg; road_map_msg.header.frame_id = "world"; geometry_msgs::PoseStamped pose; for (int i = 0; i < road_map.size() - 1; i++) { pose.pose.position.x = road_map[i](0); pose.pose.position.y = road_map[i](1); pose.pose.orientation = tf::createQuaternionMsgFromYaw(atan2(road_map[i](1) - road_map[i - 1](1), road_map[i](0) - road_map[i - 1](0))); road_map_msg.poses.push_back(pose); } pose.pose.position.x = road_map_goal.x(); pose.pose.position.y = road_map_goal.y(); pose.pose.orientation = tf::createQuaternionMsgFromYaw(road_map_goal.z()); road_map_msg.poses.push_back(pose); road_map_pub_.publish(road_map_msg); } state_machine_ = StateMachine::PLANNING; plan_start_time_ = -1; predicted_traj_start_time_ = -1; plan_start_state_XYTheta = current_state_XYTheta_; plan_start_state_VAJ = current_state_VAJ_; plan_start_state_OAJ = current_state_OAJ_; goal_state_ = findRoadMapPoint(); std::cout << "start IDIE to PLANNING: " << goal_state_.transpose() << std::endl; } // Use predicted distance for replanning in planning state else if (state_machine_ == StateMachine::PLANNING || state_machine_ == StateMachine::REPLAN) { if (((current_state_XYTheta_ - road_map_goal).head(2).squaredNorm() + fmod(fabs((plan_start_state_XYTheta - road_map_goal)[2]), 2.0 * M_PI) * 0.02 < 1.0) || msplanner_->final_traj_.getTotalDuration() < max_replan_time_) { state_machine_ = StateMachine::GOINGTOGOAL; return; } state_machine_ = StateMachine::REPLAN; predicted_traj_start_time_ = current + max_replan_time_ - plan_start_time_; msplanner_->get_the_predicted_state(predicted_traj_start_time_, plan_start_state_XYTheta, plan_start_state_VAJ, plan_start_state_OAJ); goal_state_ = findRoadMapPoint(); // std::cout << "start REPLAN: " << goal_state_.transpose() << std::endl; } ROS_INFO("\033[32;40mstart new plan\033[0m"); visualizer_->finalnodePub(plan_start_state_XYTheta, goal_state_); // ROS_INFO("init_state_: %.10f %.10f %.10f", plan_start_state_XYTheta(0), plan_start_state_XYTheta(1), plan_start_state_XYTheta(2)); // ROS_INFO("goal_state_: %.10f %.10f %.10f", goal_state_(0), goal_state_(1), goal_state_(2)); // std::cout << "<arg name=\"start_x_\" value=\"" << plan_start_state_XYTheta(0) << "\"/>" << std::endl; // std::cout << "<arg name=\"start_y_\" value=\"" << plan_start_state_XYTheta(1) << "\"/>" << std::endl; // std::cout << "<arg name=\"start_yaw_\" value=\"" << plan_start_state_XYTheta(2) << "\"/>" << std::endl; // std::cout << "<arg name=\"final_x_\" value=\"" << goal_state_(0) << "\"/>" << std::endl; // std::cout << "<arg name=\"final_y_\" value=\"" << goal_state_(1) << "\"/>" << std::endl; // std::cout << "<arg name=\"final_yaw_\" value=\"" << goal_state_(2) << "\"/>" << std::endl; // std::cout << "plan_start_state_VAJ: " << plan_start_state_VAJ.transpose() << std::endl; // std::cout << "plan_start_state_OAJ: " << plan_start_state_OAJ.transpose() << std::endl; // ROS_INFO("<arg name=\"start_x_\" value=\"%f\"/>", plan_start_state_XYTheta(0)); // ROS_INFO("<arg name=\"start_y_\" value=\"%f\"/>", plan_start_state_XYTheta(1)); // ROS_INFO("<arg name=\"start_yaw_\" value=\"%f\"/>", plan_start_state_XYTheta(2)); // ROS_INFO("<arg name=\"final_x_\" value=\"%f\"/>", goal_state_(0)); // ROS_INFO("<arg name=\"final_y_\" value=\"%f\"/>", goal_state_(1)); // ROS_INFO("<arg name=\"final_yaw_\" value=\"%f\"/>", goal_state_(2)); // ROS_INFO_STREAM("plan_start_state_VAJ: " << plan_start_state_VAJ.transpose()); // ROS_INFO_STREAM("plan_start_state_OAJ: " << plan_start_state_OAJ.transpose()); // front end ros::Time astar_start_time = ros::Time::now(); if (!findJPSRoad()) { // state_machine_ = EMERGENCY_STOP; // ROS_ERROR("EMERGENCY_STOP!!! can not find astar road !!!"); ROS_ERROR("Can't find JPS road!"); if (state_machine_ == PLANNING) state_machine_ = IDLE; return; } ROS_INFO("\033[41;37m all of front end time:%f \033[0m", (ros::Time::now() - astar_start_time).toSec()); // optimizer bool result = msplanner_->minco_plan(jps_planner_->flat_traj_); if (!result) { ROS_ERROR("Optimization failed!"); if (state_machine_ == PLANNING) state_machine_ = IDLE; return; } ROS_INFO("\033[43;32m all of plan time:%f \033[0m", (ros::Time::now().toSec() - current)); // visualization msplanner_->mincoPathPub(msplanner_->final_traj_, plan_start_state_XYTheta, visualizer_->mincoPathPath); msplanner_->mincoPointPub(msplanner_->final_traj_, plan_start_state_XYTheta, visualizer_->mincoPointMarker, Eigen::Vector3d(239, 41, 41)); // for replan if (plan_start_time_ < 0) { Traj_start_time_ = ros::Time::now(); plan_start_time_ = Traj_start_time_.toSec(); } else { plan_start_time_ = current + max_replan_time_; Traj_start_time_ = ros::Time(plan_start_time_); } MPCPathPub(plan_start_time_, traj_id_); traj_id_++; Eigen::Vector3d start_state = msplanner_->get_current_iniStateXYTheta(); Eigen::MatrixXd initstate = msplanner_->get_current_iniState(); Eigen::MatrixXd finalstate = msplanner_->get_current_finState(); Eigen::MatrixXd InnerPoints = msplanner_->get_current_Innerpoints(); Eigen::VectorXd t_pts = msplanner_->get_current_finalpieceTime(); traj_anal_.setTraj(start_state, initstate, finalstate, InnerPoints, t_pts, Eigen::Vector3d(msplanner_->ICR_.x(), msplanner_->ICR_.y(), msplanner_->ICR_.z())); traj_anal_.if_get_traj_ = true; Traj_total_time_ = msplanner_->final_traj_.getTotalDuration(); } if ((ros::Time::now() - Traj_start_time_).toSec() >= Traj_total_time_ && state_machine_ != StateMachine::EMERGENCY_STOP && state_machine_ != StateMachine::IDLE) { state_machine_ = StateMachine::IDLE; have_goal_ = false; allow_plan_traj_ = false; if ((goal_state_ - road_map_goal).head(2).norm() > 0.01) { if (sdfmap_->getDistanceReal(road_map_goal.head(2)) <= road_map_safe_dis) { // publish if_change_goal true std_msgs::Bool if_change_goal; if_change_goal.data = true; if_change_goal_pub_.publish(if_change_goal); ROS_WARN("The goal is occupied! So the planning will be stopped and the next goal can be published!"); } else { traj_id_ = 0; have_goal_ = true; allow_plan_traj_ = true; ROS_WARN("Planning haven't reached the goal yet, and the goal is able to be reached! So the planning won't be stopped!"); } } } } 详细注释上述代码并保留原有注释掉的内容
09-29
#include <ros/ros.h> #include <rosbag/bag.h> #include <sensor_msgs/PointCloud2.h> #include <deque> #include <thread> #include <mutex> #include <chrono> #include <cstdlib> #include <fstream> #include <sstream> #include <sys/time.h> #include <memory> #include <atomic> extern "C" { #include <libavformat/avformat.h> #include <libavcodec/avcodec.h> #include <libavutil/opt.h> #include <libavutil/time.h> } class FFmpegRTSPStreamer { public: FFmpegRTSPStreamer(int port = 8554, const std::string& stream_name = "mystream") : port_(port), stream_name_(stream_name), context_(nullptr), running_(false) { av_register_all(); avformat_network_init(); } ~FFmpegRTSPStreamer() { stop(); } bool start() { if (running_) return true; // 创建输出格式上下文 - 指定为RTSP服务器 avformat_alloc_output_context2(&context_, nullptr, "rtsp", nullptr); if (!context_) { ROS_ERROR("Could not create RTSP server context"); return false; } // 设置服务器选项 AVDictionary* options = nullptr; char port_str[16]; snprintf(port_str, sizeof(port_str), "%d", port_); av_dict_set(&options, "rtsp_port", port_str, 0); av_dict_set(&options, "listen", "1", 0); // 设置为监听模式 // 创建输出流 AVStream* stream = avformat_new_stream(context_, nullptr); if (!stream) { ROS_ERROR("Could not create output stream"); return false; } // 设置输出URL std::stringstream url_ss; url_ss << "rtsp://0.0.0.0:" << port_ << "/" << stream_name_; std::string url = url_ss.str(); // 打开输出 if (avio_open2(&context_->pb, url.c_str(), AVIO_FLAG_WRITE, nullptr, &options) < 0) { ROS_ERROR("Could not open RTSP URL: %s", url.c_str()); av_dict_free(&options); return false; } av_dict_free(&options); // 写入头部信息 if (avformat_write_header(context_, nullptr) < 0) { ROS_ERROR("Error writing RTSP header"); return false; } running_ = true; ROS_INFO("FFmpeg RTSP server started at: %s", url.c_str()); return true; } void stream_frame(AVPacket* packet) { if (!running_) return; // 发送数据包到RTSP客户端 if (av_interleaved_write_frame(context_, packet) < 0) { ROS_ERROR("Error writing frame to RTSP stream"); } } void stop() { if (!running_) return; // 写入尾部信息 av_write_trailer(context_); // 关闭输出 if (context_->pb) { avio_close(context_->pb); } // 释放资源 avformat_free_context(context_); context_ = nullptr; running_ = false; ROS_INFO("FFmpeg RTSP server stopped"); } bool is_running() const { return running_; } private: int port_; std::string stream_name_; AVFormatContext* context_; bool running_; }; class AVPointCloudSyncer { public: AVPointCloudSyncer(const std::string& bag_file, const std::string& topic_name, const std::string& video_path, int rtsp_port = 8554, const std::string& rtsp_stream_name = "mystream") : bag_file_(bag_file), topic_name_(topic_name), video_path_(video_path), rtsp_port_(rtsp_port), rtsp_stream_name_(rtsp_stream_name), sync_ratio_(1.0), running_(false) { // 初始化FFmpeg库 av_register_all(); avformat_network_init(); } ~AVPointCloudSyncer() { cleanup(); } // 设置RTSP服务器参数的方法 void set_rtsp_params(int port, const std::string& stream_name) { rtsp_port_ = port; rtsp_stream_name_ = stream_name; } bool initialize() { // 创建ROS发布器 pub_ = nh_.advertise<sensor_msgs::PointCloud2>(topic_name_, 1000); // 确保发布器已连接 ros::WallDuration(2.0).sleep(); // 设置AV流 if (!setup_av_streaming()) { ROS_ERROR("Failed to setup AV streaming"); return false; } // 设置RTSP服务器 if (!setup_rtsp_server()) { ROS_ERROR("Failed to setup RTSP server"); return false; } // 提取时间戳 if (!extract_video_timestamps()) { ROS_ERROR("Failed to extract video timestamps"); return false; } if (!extract_pointcloud_timestamps()) { ROS_ERROR("Failed to extract pointcloud timestamps"); return false; } return true; } void run() { if (!initialize()) { ROS_ERROR("Initialization failed. Exiting."); return; } running_ = true; // 启动视频流线程 std::thread video_thread(&AVPointCloudSyncer::stream_video_with_av, this); // 在主线程中同步播放点云 replay_pointcloud_synced(); // 等待视频线程结束 if (video_thread.joinable()) { video_thread.join(); } running_ = false; ROS_INFO("AVPointCloudSyncer finished"); } void cleanup() { running_ = false; // 关闭FFmpeg资源 if (input_context_) { avformat_close_input(&input_context_); input_context_ = nullptr; } // 停止RTSP服务器 if (rtsp_streamer_) { rtsp_streamer_->stop(); } } private: // 设置RTSP服务器 bool setup_rtsp_server() { ROS_INFO("Setting up RTSP server on port %d with stream name '%s'", rtsp_port_, rtsp_stream_name_.c_str()); rtsp_streamer_ = std::make_unique<FFmpegRTSPStreamer>(rtsp_port_, rtsp_stream_name_); return rtsp_streamer_->start(); } // FFmpeg设置 bool setup_av_streaming() { ROS_INFO("Setting up AV streaming..."); input_context_ = avformat_alloc_context(); if (!input_context_) { ROS_ERROR("Failed to allocate AVFormatContext"); return false; } // 设置输入选项(针对文件的优化) AVDictionary* options = nullptr; av_dict_set(&options, "analyzeduration", "1000000", 0); // 1秒分析时长 av_dict_set(&options, "probesize", "500000", 0); // 500KB探测大小 // 打开输入视频 if (avformat_open_input(&input_context_, video_path_.c_str(), nullptr, &options) != 0) { ROS_ERROR("Could not open input file: %s", video_path_.c_str()); av_dict_free(&options); return false; } av_dict_free(&options); // 查找流信息 if (avformat_find_stream_info(input_context_, nullptr) < 0) { ROS_ERROR("Failed to find stream information"); return false; } // 查找视频流 video_stream_index_ = -1; for (unsigned int i = 0; i < input_context_->nb_streams; i++) { if (input_context_->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index_ = i; break; } } if (video_stream_index_ == -1) { ROS_ERROR("Could not find video stream"); return false; } // 获取视频流参数 AVStream* video_stream = input_context_->streams[video_stream_index_]; ROS_INFO("Video stream initialized: index %d, codec: %s, resolution: %dx%d", video_stream_index_, avcodec_get_name(video_stream->codecpar->codec_id), video_stream->codecpar->width, video_stream->codecpar->height); return true; } // 视频流处理(集成RTSP输出) void stream_video_with_av() { ROS_INFO("Starting video streaming with FFmpeg RTSP server..."); if (!input_context_) { ROS_ERROR("AVFormatContext not initialized"); return; } AVPacket packet; av_init_packet(&packet); packet.data = nullptr; packet.size = 0; int frame_count = 0; auto start_time = std::chrono::steady_clock::now(); while (running_ && av_read_frame(input_context_, &packet) >= 0) { if (packet.stream_index == video_stream_index_) { // 如果RTSP服务器正在运行,转发视频帧 if (rtsp_streamer_ && rtsp_streamer_->is_running()) { // 创建输出包副本 AVPacket output_packet; if (av_packet_ref(&output_packet, &packet) < 0) { ROS_ERROR("Failed to create packet reference"); } else { // 发送到RTSP服务器 rtsp_streamer_->stream_frame(&output_packet); av_packet_unref(&output_packet); } } frame_count++; if (frame_count % 30 == 0) { auto elapsed = std::chrono::steady_clock::now() - start_time; double fps = 30.0 / (std::chrono::duration<double>(elapsed).count()); ROS_INFO("Processed %d video frames (%.1f FPS)", frame_count, fps); start_time = std::chrono::steady_clock::now(); } } av_packet_unref(&packet); } ROS_INFO("Video streaming completed: %d frames", frame_count); } // 提取视频时间戳 bool extract_video_timestamps() { ROS_INFO("Extracting video timestamps..."); AVFormatContext* temp_context = avformat_alloc_context(); if (!temp_context) { ROS_ERROR("Failed to allocate temporary AVFormatContext"); return false; } if (avformat_open_input(&temp_context, video_path_.c_str(), nullptr, nullptr) != 0) { ROS_ERROR("Could not open input file for timestamp extraction"); avformat_free_context(temp_context); return false; } if (avformat_find_stream_info(temp_context, nullptr) < 0) { ROS_ERROR("Failed to find stream information for timestamp extraction"); avformat_close_input(&temp_context); return false; } int video_stream_index = -1; for (unsigned int i = 0; i < temp_context->nb_streams; i++) { if (temp_context->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_VIDEO) { video_stream_index = i; break; } } if (video_stream_index == -1) { ROS_ERROR("Could not find video stream for timestamp extraction"); avformat_close_input(&temp_context); return false; } AVPacket packet; av_init_packet(&packet); packet.data = nullptr; packet.size = 0; int frame_count = 0; while (av_read_frame(temp_context, &packet) >= 0) { if (packet.stream_index == video_stream_index) { // 计算时间戳(秒) AVStream* stream = temp_context->streams[packet.stream_index]; double pts = packet.pts * av_q2d(stream->time_base); video_frame_times_.push_back(pts); frame_count++; if (frame_count >= 5000) break; // 限制提取数量 } av_packet_unref(&packet); } av_packet_unref(&packet); avformat_close_input(&temp_context); ROS_INFO("Extracted %lu video frame timestamps", video_frame_times_.size()); return !video_frame_times_.empty(); } // 提取点云时间戳 bool extract_pointcloud_timestamps() { ROS_INFO("Extracting pointcloud timestamps..."); try { rosbag::Bag bag(bag_file_, rosbag::bagmode::Read); rosbag::View view(bag, rosbag::TopicQuery(topic_name_)); int message_count = 0; for (const rosbag::MessageInstance& m : view) { sensor_msgs::PointCloud2::ConstPtr msg = m.instantiate<sensor_msgs::PointCloud2>(); if (msg != nullptr) { pointcloud_times_.push_back(m.getTime().toSec()); message_count++; if (message_count % 1000 == 0) { ROS_INFO("Extracted %d pointcloud timestamps", message_count); } if (message_count >= 10000) break; // 限制提取数量 } } bag.close(); ROS_INFO("Total pointcloud messages extracted: %lu", pointcloud_times_.size()); return !pointcloud_times_.empty(); } catch (rosbag::BagException& e) { ROS_ERROR("Error opening rosbag: %s", e.what()); return false; } } // 同步点云重放 void replay_pointcloud_synced() { ROS_INFO("Starting synchronized pointcloud replay..."); if (pointcloud_times_.empty()) { ROS_ERROR("No pointcloud timestamps extracted!"); return; } // 计算同步比例 if (video_frame_times_.size() > 1 && pointcloud_times_.size() > 1) { double video_duration = video_frame_times_.back() - video_frame_times_.front(); double pointcloud_duration = pointcloud_times_.back() - pointcloud_times_.front(); if (pointcloud_duration > 0) { sync_ratio_ = video_duration / pointcloud_duration; ROS_INFO("Sync ratio: %.3f (Video: %.2fs, PointCloud: %.2fs)", sync_ratio_, video_duration, pointcloud_duration); } } try { rosbag::Bag bag(bag_file_, rosbag::bagmode::Read); rosbag::View view(bag, rosbag::TopicQuery(topic_name_)); auto start_time = std::chrono::steady_clock::now(); double bag_start_time = pointcloud_times_.front(); int message_count = 0; for (const rosbag::MessageInstance& m : view) { if (!running_ || !ros::ok()) { break; } sensor_msgs::PointCloud2::ConstPtr msg = m.instantiate<sensor_msgs::PointCloud2>(); if (!msg) continue; // 计算当前消息相对于开始的时间(应用同步比例) double msg_elapsed = (m.getTime().toSec() - bag_start_time) * sync_ratio_; auto current_time = std::chrono::steady_clock::now(); double current_elapsed = std::chrono::duration<double>(current_time - start_time).count(); // 等待直到正确的发布时间 if (current_elapsed < msg_elapsed) { double sleep_time = msg_elapsed - current_elapsed; ros::WallDuration(sleep_time).sleep(); } // 发布点云消息 pub_.publish(msg); message_count++; if (message_count % 100 == 0) { ROS_INFO("Published pointcloud message %d", message_count); } } bag.close(); ROS_INFO("Finished replaying %d pointcloud messages", message_count); } catch (rosbag::BagException& e) { ROS_ERROR("Error during pointcloud replay: %s", e.what()); } } private: // ROS相关 ros::NodeHandle nh_; ros::Publisher pub_; // 配置参数 std::string bag_file_; std::string topic_name_; std::string video_path_; int rtsp_port_; std::string rtsp_stream_name_; // 时间同步相关 std::deque<double> video_frame_times_; std::deque<double> pointcloud_times_; double sync_ratio_; // FFmpeg相关 AVFormatContext* input_context_ = nullptr; int video_stream_index_ = -1; std::unique_ptr<FFmpegRTSPStreamer> rtsp_streamer_; // 控制标志 std::atomic<bool> running_; }; int main(int argc, char** argv) { ros::init(argc, argv, "av_pointcloud_syncer"); // 配置参数 - 可从命令行或参数服务器读取 std::string bag_file = "/media/jxpy-chengb/Ubuntu 24.0/T06/TC1-20250626/_2025-06-26-10-15-10_669.bag"; std::请补充完整这个代码
09-18
内容概要:本文详细介绍了“秒杀商城”微服务架构的设计与实战全过程,涵盖系统从需求分析、服务拆分、技术选型到核心功能开发、分布式事务处理、容器化部署及监控链路追踪的完整流程。重点解决了高并发场景下的超卖问题,采用Redis预减库存、消息队列削峰、数据库乐观锁等手段保障数据一致性,并通过Nacos实现服务注册发现与配置管理,利用Seata处理跨服务分布式事务,结合RabbitMQ实现异步下单,提升系统吞吐能力。同时,项目支持Docker Compose快速部署和Kubernetes生产级编排,集成Sleuth+Zipkin链路追踪与Prometheus+Grafana监控体系,构建可观测性强的微服务系统。; 适合人群:具备Java基础和Spring Boot开发经验,熟悉微服务基本概念的中高级研发人员,尤其是希望深入理解高并发系统设计、分布式事务、服务治理等核心技术的开发者;适合工作2-5年、有志于转型微服务或提升架构能力的工程师; 使用场景及目标:①学习如何基于Spring Cloud Alibaba构建完整的微服务项目;②掌握秒杀场景下高并发、超卖控制、异步化、削峰填谷等关键技术方案;③实践分布式事务(Seata)、服务熔断降级、链路追踪、统一配置中心等企业级中间件的应用;④完成从本地开发到容器化部署的全流程落地; 阅读建议:建议按照文档提供的七个阶段循序渐进地动手实践,重点关注秒杀流程设计、服务间通信机制、分布式事务实现和系统性能优化部分,结合代码调试与监控工具深入理解各组件协作原理,真正掌握高并发微服务系统的构建能力。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值