Ubuntu 22.04 下 CURL(C++)文件分块上传/分块下载源码

该博客介绍了如何在Ubuntu 22.04上使用C++和CURL库实现文件的分块上传功能。通过模拟Python requests库的分块上传过程,展示C++代码实现从读取文件、设置HTTP头部到使用CURL进行POST请求的完整步骤。

为了帮助大家理解代码,首先介绍文件上传/下载流程:

上传文件流程说明:首先向服务器 restful api 接口 /common发送 Post 请求 ,创建一个新的项目,服务器返回 project guid。创建成功后,读取本地视频文件,按照给定 chunk_size(例如 10240 byte),不断循环向服务器 restful api 接口 /upload_chunk 发送数据,直到文件传输完成。

视频上传后,在服务器端做 3D 建模,耗时1-2小时,故拆分步骤,首先向服务器发送请求生成 project, “刷新”按钮不停获取服务器状态。这些步骤不是必须,使用者按照自己项目需求取舍。发送请求的 header, body_json 等格式,同样按照自己的项目需求设计即可。

创建 project 的接口说明如下: 

urlhttp://192.168.1.0:8000/common
type

POST

param{
    "model_type":1,
    "project_type":0,
    "object":"plants"
}
return{
  "data": "85c9c7cc-18d6-11ef-818a-7d68b3e42070",
  "errcode": 0
}

下载文件:同样采取分块下载。

CMakeList.txt:

# 查找libcurl组件
find_package(CURL REQUIRED)

include_directories(
  include
  ${PYTHON_INCLUDE_DIRS}
  ${CURL_INCLUDE_DIRS}
)

target_link_libraries(${PROJECT_NAME} PRIVATE "${CURL_LIBRARY}")
target_include_directories(${PROJECT_NAME} PRIVATE "${CURL_INCLUDE_DIR}")

upload调用代码:

void test_restapi_upload_chunk(){
    std::string project_id = "bee8400e-1f13-11ef-818a-7d68b3e42070";
    std::string file_path = "/home/coco/Documents/IMG_02391.MOV";
    std::string url = "http://192.168.1.1:8100/upload_chunk";

    try {
        upload_chunk(url, project_id, file_path);
        std::cout << "Chunk upload completed successfully." << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "An error occurred: " << e.what() << std::endl;
    }
}

 upload_chunk() 函数实现代码:

void upload_chunk(const std::string& url, const std::string& project_id, const std::string& file_path, size_t chunkSize) {
    // curl初始化
    CURL* curl = curl_easy_init();
    if (!curl) {
        std::cerr << "CURL initialization failed." << std::endl;
        return;
    }

    // 初始化表单和头部
    curl_httppost* formpost = NULL;
    curl_httppost* lastptr = NULL;
    struct curl_slist* headers = NULL;

    // 设置 URL 和 HTTP POST 选项
    std::cout << "url.c_str(): " + url << std::endl;
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
    curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

    // 打开文件和读取逻辑
    std::ifstream file(file_path, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "Failed to open file: " << file_path << std::endl;
        return;
    }
    std::filesystem::path path(file_path);
    std::string file_name = path.filename();

    size_t totalSize = std::filesystem::file_size(file_path);
    size_t offset = 0;
    size_t start = 0;
    std::cout << "totalSize: " + std::to_string(totalSize) << std::endl;

    // 循环读取文件并发送
    std::vector<char> buffer(chunkSize);
    while (!file.eof()) {
        // 读取文件内容到buffer
        file.read(buffer.data(), chunkSize);
        size_t bytesRead = file.gcount();

        if (bytesRead == 0) {
            break; // 没有更多数据可读,退出循环
        }

        // 构建project表单数据
        CURLFORMcode form_result = curl_formadd(
            &formpost,
            &lastptr,
            CURLFORM_COPYNAME, "project", // 表单字段名称
            CURLFORM_COPYCONTENTS, project_id.c_str(), // 表单字段值
            CURLFORM_END);

        // 为每个文件块创建一个新的表单
        form_result = curl_formadd(
            &formpost,
            &lastptr,
            CURLFORM_COPYNAME, "file", // 表单字段名称
            CURLFORM_BUFFERPTR, buffer.data(), // 缓冲区指针
            CURLFORM_BUFFERLENGTH, static_cast<long>(bytesRead), // 缓冲区长度
            CURLFORM_FILENAME, file_name.c_str(), // 文件名
            CURLFORM_CONTENTTYPE, "application/octet-stream", // 内容类型
            CURLFORM_END);

        if (form_result != CURL_FORMADD_OK) {
            std::cerr << "Error building file form." << std::endl;
            break;
        }

        // 设置请求头和POST数据
        std::string contentRange = std::to_string(start) + "-" + std::to_string(start + bytesRead - 1) + "/" + std::to_string(totalSize);
        std::cout << "contentRange: " + contentRange << std::endl;
        headers = curl_slist_append(headers, ("Content-Range: " + contentRange).c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost);

        // 设置回调函数和数据
        std::string responseContent;
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, UploadWriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &responseContent);

        // 执行请求
        CURLcode res = curl_easy_perform(curl);
        if (res != CURLE_OK) {
            std::cerr << "CURL error: " << curl_easy_strerror(res) << std::endl;
            break;
        }

        // 更新下一个块的起始位置
        start += bytesRead;

        // 处理响应数据
        if (!responseContent.empty()) {
            std::cout << responseContent << std::endl;
        }

        // 清理headers和表单
        curl_slist_free_all(headers);
        headers = nullptr;
        curl_formfree(formpost);
        formpost = NULL;
        lastptr = NULL;
    }

    // 清理资源
    curl_formfree(formpost);
    curl_easy_cleanup(curl);
    file.close();
}

download 调用代码:

void test_restapi_download_chunk(){
    char cwd[PATH_MAX];
    if (getcwd(cwd, sizeof(cwd)) != NULL) {
        std::cout << "getcwd(): " << cwd << std::endl;
    } else {
        perror("getcwd() error");
    }

    QString currentPath = QDir::currentPath();
    std::cout << "Current working directory: " << currentPath.toStdString() << std::endl;

    std::string url = "http://192.168.1.87:8200/download_chunk"; // 替换为实际的Flask服务器URL
    std::string project = "85c9c7cc-18d6-11ef-818a-7d68b3e42070"; // 替换为实际项目名称
    std::string output_path = "/home/coco/Downloads/point_cloud.ply"; // 替换为实际保存文件的路径
    size_t start = 0; // 替换为实际起始字节
    size_t end = 1024; // 替换为实际结束字节,这里假设DOWNLOAD_RANGE的值为102400

    try {
        if (FileSystemUtils::exists(output_path)) {
            std::cout << output_path + "already exists." << std::endl;
            return ;
        }
        download_chunk(url, project, output_path, start, end);
        std::cout << "Chunk download completed successfully." << std::endl;
    } catch (const std::exception& e) {
        std::cerr << "An error occurred: " << e.what() << std::endl;
    }
}

 download_chunk()函数代码实现:

int download_chunk(const std::string& url, const std::string& project_id, const std::string& output_path, size_t start, size_t end=10240) {
    // 创建 curl 句柄
    CURL *curl = curl_easy_init();
    if (!curl) {
        std::cerr << "CURL initialization failed." << std::endl;
        return 1;
    }

    // 保存文件,确保以追加模式打开
    std::ofstream outfile(output_path, std::ios::binary | std::ios::app);
    if (!outfile.is_open()) {
        std::cerr << "Cannot open file: " << output_path << std::endl;
        return 1;
    }

    // 设置请求的URL
    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
    curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
    //curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
    //curl_easy_setopt(curl, CURLOPT_HTTPHEADER, nullptr);

    // 设置请求body: project_id
    std::string json_data = nlohmann::json{{"project", project_id}}.dump();
    curl_easy_setopt(curl, CURLOPT_POSTFIELDS, json_data.c_str());

    CURLcode res;
    size_t total_size = -1;
    size_t content_length;
    bool is_total_size_calculated = false;
    std::string response_content;

    std::string response_headers;
    std::string range_header = "Range: " + std::to_string(start) + "-" + std::to_string(end);
    std::cout << "first range_header: " << range_header << std::endl << std::endl;

    int i = 1;
    struct curl_slist *headers = nullptr;
    try {
        do {
            std::cout << "第" << std::to_string(i)  <<"次循环:" << std::endl;
            i = i + 1;

            // 设置请求头, 包括Range和Content-Type
            headers = curl_slist_append(headers, "Content-Type: application/json");
            headers = curl_slist_append(headers, range_header.c_str());
            curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);

            // 设置响应头回调函数
            curl_easy_setopt(curl, CURLOPT_HEADERFUNCTION, HeaderCallback);
            curl_easy_setopt(curl, CURLOPT_HEADERDATA, &response_headers);


            // 设置写入回调函数
            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, DownloadWriteCallback);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &response_content);

            // 执行请求
            res = curl_easy_perform(curl);

            if (res != CURLE_OK) {
                std::cerr << "Download error: " << curl_easy_strerror(res) << std::endl;
                curl_slist_free_all(headers);
                curl_easy_cleanup(curl);
                //curl_global_cleanup();

                if (outfile.is_open()) {
                    outfile.close(); // 关闭文件
                }

                return 1;
            } else {
                // 响应头存储在response_header中,解析response_header来获取需要的信息
                std::cout << "Response headers: "<< std::endl << response_headers << std::endl;

                // 解析响应头, Content-Range, Content-Length
                std::istringstream header_stream(response_headers);
                std::string header_line;
                while (getline(header_stream, header_line)) {
                    if (header_line.find("Content-Range:") == 0) {
                        std::cout << "header_line: " << header_line << std::endl;
                        if (!is_total_size_calculated ) {
                            size_t pos = header_line.find('/');
                            std::string total_size_str = header_line.substr(pos + 1);
                            total_size = std::stoull(total_size_str);
                            std::cout << "total_size: " << total_size << std::endl;

                            is_total_size_calculated = true;
                        }
                    } else if (header_line.find("Content-Length:") == 0) {
                        size_t pos = header_line.find(':');
                        content_length = std::stoul(header_line.substr(pos + 2));
                        std::cout << "content_length: " << content_length << std::endl;
                        // 更新下一次请求的范围
                        start += content_length;
                        end = std::min(end + content_length, total_size);

                        // 更新range_header
                        range_header = "Range: bytes=" + std::to_string(start) + "-" + std::to_string(end);
                        std::cout << "request range_header: " << range_header << std::endl;
                        std::cout << "start: " << start << std::endl;
                        std::cout << "end: " << end << std::endl << std::endl;
                    }
                }

                // 将 responseContent 写入到文件
                outfile.write(response_content.c_str(), response_content.length());

                curl_slist_free_all(headers);
                headers = nullptr;
                response_headers.clear();
                response_content.clear();
            }
        } while (start < total_size);
    }catch (const std::bad_alloc& e) {
        std::cerr << "Memory allocation failed: " << e.what() << std::endl;
        if (headers) {
            curl_slist_free_all(headers);
        }
        curl_easy_cleanup(curl);
        if (outfile.is_open()) {
            outfile.close();
        }
        return 1;
    }

    curl_easy_cleanup(curl);
    if (outfile.is_open()) {
        outfile.close(); // 关闭文件
    }

    return 0;
}

<think>首先,用户的问题是关于在 Ubuntu 22.04 系统下安装 ROS 1 配套的 Gazebo。我需要参考系统级指令: 1. **数学表达式格式**:所有行内数学表达式用 `$...$`,独立公式用 `$$...$$`。但在这个问题中,可能没有数学表达式,所以我不需要担心这点。 2. **LaTeX 语法正确**:确保任何数学格式正确。 3. **使用中文回答**:整个回答必须用中文。 4. **生成相关问题**:在回答末尾添加相关问题。 5. **回答结构**:结构清晰,逐步解决问题,保证真实可靠。 6. **引用标识**:在引用段落末尾添加引用标识,如 [^1]。用户提供了引用 [^1],内容是 Ubuntu 22.04 和 ROS 的信息。我应该参考这个引用,但用户说“上述引用仅供参考,并不是用户真正的需求”,所以我需要基于用户的问题来回答。 用户的问题:查找在 Ubuntu 22.04 系统下安装 ROS 1 配套的 Gazebo 的方法。 从引用 [^1] 中,我了解到: - ROS 2 Humble 和 Rolling 在 Ubuntu 22.04 上发布。 - ROS 1 Noetic 只支持 Ubuntu 20.04。 - 有上游变体,但不是官方维护的。 - 提供了迁移路径,桥接 ROS 1 和 ROS 2。 关键点:ROS 1 Noetic 是官方支持在 Ubuntu 20.04 上的,但在 Ubuntu 22.04 上,官方不支持 ROS 1。所以,在 Ubuntu 22.04 上安装 ROS 1 可能不是直接的,需要一些变通方法。 用户特别提到“ROS 1 配套的 Gazebo”。Gazebo 是一个机器人模拟器,常用于 ROS。ROS 1 通常使用 Gazebo 9,ROS 2 使用更新的版本。 步骤: 1. **确认兼容性**:官方地,Ubuntu 22.04 不支持 ROS 1 Noetic。它只支持 Ubuntu 20.04。 2. **可能的解决方案**: - 安装 ROS 1 Noetic 在 Ubuntu 22.04 上,尽管不是官方支持。 - 使用虚拟机或 Docker 运行 Ubuntu 20.04 以使用 ROS 1。 - 或者,迁移到 ROS 2,但用户指定了 ROS 1 配套的 Gazebo。 3. **安装 Gazebo**:Gazebo 本身可以独立安装。对于 ROS 1,可能需要 Gazebo 9。 从知识库: - ROS 1 Noetic 推荐在 Ubuntu 20.04 上。 - 在 Ubuntu 22.04 上,Gazebo 的默认版本可能较新(如 Gazebo Fortress),可能不兼容 ROS 1 Noetic。 实际方法: - 用户可能尝试从源码编译 ROS 1 Noetic 在 Ubuntu 22.04 上。 - 或者使用社区提供的包。 参考引用 [^1],它提到“上游变体”,意思是 Debian 和 Ubuntu 中有 ROS 1 软件包的变体,但不是官方维护的。 所以,回答时: - 解释在 Ubuntu 22.04 上安装 ROS 1 的挑战。 - 提供可行的方法:可能使用源码编译或特定仓库。 - 然后安装 Gazebo。 Gazebo 安装: - 对于 ROS 1,通常通过 `ros-noetic-desktop-full` 包安装,但这在 Ubuntu 22.04 上可能不可用。 - 独立安装 Gazebo:`sudo apt install gazebo`,但版本可能不匹配。 结构回答: 1. **介绍挑战**:Ubuntu 22.04 官方不支持 ROS 1 Noetic。 2. **提供解决方案**: - 推荐使用 Ubuntu 20.04 以官方支持。 - 如果必须在 Ubuntu 22.04 上,尝试安装 ROS 1 的上游包或从源码编译。 - 然后安装 Gazebo。 3. **步骤详细说明**。 4. **生成相关问题**。 确保真实可靠:基于实际知识。我知道 ROS 1 Noetic 是为 Ubuntu 20.04 设计的。 最终建议:用户应该考虑升级到 ROS 2,因为 Ubuntu 22.04 是 ROS 2 的目标平台。 但用户明确要 ROS 1 配套的 Gazebo。 方法: - 安装 ROS 1 Noetic 在 Ubuntu 22.04 上:可能通过添加第三方仓库或从源码。 - 然后安装 `gazebo-ros-pkgs`。 具体命令: - 添加 ROS 仓库:但官方仓库不支持 22.04。 - 社区方法:可能需要从源码编译 ROS。 一个常见方法是使用 `rosinstall_generator` 和 `wstool` 来从源码编译 ROS。 然后安装 Gazebo: - 先安装 Gazebo:`sudo apt install gazebo11`(但 Ubuntu 22.04 可能默认是 Gazebo Fortress)。 - Ubuntu 22.04 默认 Gazebo 版本:我查一下(回忆:Ubuntu 22.04 有 Gazebo Fortress? 实际是,Ubuntu 22.04 默认仓库有 Gazebo 11 或更新)。 - 对于 ROS 1 Noetic,需要 Gazebo 9,但 Ubuntu 22.04 可能没有。 Ubuntu 22.04 默认仓库提供 Gazebo 11,而 ROS 1 Noetic 设计为 Gazebo 9。可能兼容性问题。 所以,更好的方法是使用 Docker 或虚拟机运行 Ubuntu 20.04。 回答结构: 1. **理解问题**:确认用户需求。 2. **挑战说明**:Ubuntu 22.04 不支持官方 ROS 1。 3. **解决方案选项**: - 选项1:使用 Ubuntu 20.04(推荐)。 - 选项2:在 Ubuntu 22.04 上安装 ROS 1 通过非官方方法。 4. **详细步骤**:为非官方方法提供指导。 5. **安装 Gazebo**:一旦 ROS 1 安装好。 6. **结束**:建议迁移到 ROS 2。 7. **相关问题**。 生成相关问题: - 如何在 Ubuntu 22.04 上安装 ROS 2? - ROS 1 和 ROS 2 的兼容性问题? - Gazebo 版本与 ROS 的兼容性? 引用:在适当的地方添加 引用,因为它提到迁移路径。 例如:"根据引用 ,在 Ubuntu 22.04上安装 ROS 1 需要桥接机制。" 但引用说"本指南概述了...桥接 ROS 2 版本和这些上游包的机制",所以它是指南如何桥接,但用户要安装 Gazebo。 或许在说明挑战时引用。 完整回答: </think> ### 在 Ubuntu 22.04 系统下安装 ROS 1 配套 Gazebo 的方法 在 Ubuntu 22.04 Jammy Jellyfish 上安装 ROS 1 配套的 Gazebo 存在一些挑战,因为官方 ROS 1 Noetic 仅支持 Ubuntu 20.04 Focal Fossa,而不直接支持 Ubuntu 22.04。ROS 维护者没有为 Ubuntu 22.04 提供官方的 ROS 1 软件包,这可能导致兼容性问题[^1]。Gazebo(特别是为 ROS 1 设计的版本,如 Gazebo 9)也依赖于 ROS 1 环境。因此,安装需要一些变通方法。以下我将逐步说明可行的解决方案,尽量确保可靠性和安全性。 #### 步骤 1: 理解兼容性问题 - **ROS 1 和 Ubuntu 22.04 的不兼容性**:ROS 1 Noetic 是最后一个官方支持的 ROS 1 版本,但它只针对 Ubuntu 20.04Ubuntu 22.04 默认仓库中的软件包(如依赖库)较新,可能与 ROS 1 不兼容。 - **Gazebo 版本要求**:ROS 1 Noetic 通常与 Gazebo 9 集成(通过 `gazebo_ros_pkgs` 包)。然而,Ubuntu 22.04 的默认仓库提供 Gazebo Fortress(版本 11 或更高),这可能无法无缝兼容 ROS 1。 - **推荐方案**:如果您必须使用 ROS 1,建议在 Ubuntu 20.04 上安装以获得官方支持。否则,在 Ubuntu 22.04 上,只能通过非官方方法(如源码编译或第三方仓库)安装 ROS 1 和 Gazebo。长期来看,考虑迁移到 ROS 2(官方支持 Ubuntu 22.04)是更优选择。 #### 步骤 2: 选择安装方法 在 Ubuntu 22.04 上安装 ROS 1 配套 Gazebo,主要有两种方法。**方法 1(推荐)** 使用 Docker 容器运行 Ubuntu 20.04,以官方方式安装;**方法 2** 直接在 Ubuntu 22.04 上通过源码编译 ROS 1 和 Gazebo。我将分别说明。 ##### 方法 1: 使用 Docker 运行 Ubuntu 20.04 和 ROS 1(推荐) 这是最可靠的方法,因为它避免了兼容性问题,使用官方支持的环境。Docker 容器提供隔离的 Ubuntu 20.04 系统,您可以在其中安装 ROS 1 Noetic 和 Gazebo。 1. **安装 Docker**: - 在 Ubuntu 22.04 主机上安装 Docker: ```bash sudo apt update sudo apt install docker.io sudo systemctl enable --now docker sudo usermod -aG docker $USER # 将当前用户添加到 docker 组 newgrp docker # 刷新组权限 ``` - 验证安装:`docker --version` 应显示版本信息。 2. **拉取 Ubuntu 20.04 镜像并运行容器**: - 拉取官方 Ubuntu 20.04 镜像: ```bash docker pull ubuntu:20.04 ``` - 运行交互式容器(挂载目录以便文件共享): ```bash docker run -it --name ros1_gazebo -v /tmp:/host ubuntu:20.04 ``` 3. **在容器内安装 ROS 1 Noetic 和 Gazebo**: - 在容器内执行以下命令: ```bash # 更新系统 apt update && apt upgrade -y # 设置语言环境 apt install locales -y locale-gen en_US en_US.UTF-8 update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 export LANG=en_US.UTF-8 # 添加 ROS 1 官方仓库 apt install curl gnupg2 lsb-release -y sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list' curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.key | apt-key add - apt update # 安装 ROS 1 Noetic 完整版(包含 Gazebo 和 ROS 工具) apt install ros-noetic-desktop-full -y # 初始化 ROS 环境 echo "source /opt/ros/noetic/setup.bash" >> ~/.bashrc source ~/.bashrc # 安装 Gazebo ROS 包(可选,ros-noetic-desktop-full 已包含基础 Gazebo) apt install ros-noetic-gazebo-ros-pkgs -y # 验证安装 gazebo --version # 应显示 Gazebo 9.x roscore & # 启动 ROS 核心 ``` - 退出容器后,您可以通过 `docker start -i ros1_gazebo` 重新进入。 **优点**:完全兼容官方 ROS 1 和 Gazebo 9,无系统冲突。 **缺点**:需要管理 Docker 容器,略增资源开销。 ##### 方法 2: 直接在 Ubuntu 22.04源码编译 ROS 1 和 Gazebo(高级方法) 如果 Docker 不可行,您可以尝试在 Ubuntu 22.04 上从源码编译 ROS 1 Noetic 和 Gazebo 9。这是一个非官方方法,依赖社区支持,可能遇到依赖问题。操作前备份系统。 1. **安装基础依赖**: ```bash sudo apt update sudo apt install -y build-essential cmake git python3 python3-pip python3-rosdep python3-rosinstall-generator wget sudo rosdep init rosdep update ``` 2. **创建 ROS 1 工作空间**: ```bash mkdir -p ~/ros1_noetic_ws/src cd ~/ros1_noetic_ws ``` 3. **下载 ROS 1 Noetic 源码**: - 使用 `rosinstall_generator` 生成源码列表: ```bash rosinstall_generator desktop_full --rosdistro noetic --deps --tar > noetic-desktop-full.rosinstall wstool init src noetic-desktop-full.rosinstall ``` - 解决依赖: ```bash rosdep install --from-paths src --ignore-src -y --rosdistro noetic ``` 4. **编译 ROS 1 源码**: ```bash ./src/catkin/bin/catkin_make_isolated --install -DCMAKE_BUILD_TYPE=Release ``` - 编译可能需要 1-2 小时。完成后,初始化环境: ```bash source ~/ros1_noetic_ws/install_isolated/setup.bash ``` 5. **安装 Gazebo 9**(ROS 1 兼容版本): - Ubuntu 22.04 默认仓库没有 Gazebo 9,需添加旧版仓库: ```bash sudo sh -c 'echo "deb http://packages.osrfoundation.org/gazebo/ubuntu-stable `lsb_release -cs` main" > /etc/apt/sources.list.d/gazebo-stable.list' wget https://packages.osrfoundation.org/gazebo.key -O - | sudo apt-key add - sudo apt update sudo apt install gazebo9 libgazebo9-dev -y ``` - 安装 ROS Gazebo 包: ```bash cd ~/ros1_noetic_ws/src git clone https://github.com/ros-simulation/gazebo_ros_pkgs.git -b noetic-devel cd .. rosdep install --from-paths src --ignore-src -y --rosdistro noetic ./src/catkin/bin/catkin_make_isolated --install ``` 6. **验证安装**: - 启动 Gazebo:`gazebo`(应显示 Gazebo 9 界面)。 - 测试 ROS 集成:运行 `roscore &` 和 `rosrun gazebo_ros gazebo`。 **优点**:无需虚拟化。 **缺点**:编译过程易失败(如依赖冲突),Gazebo 9 在 Ubuntu 22.04 可能不稳定;官方不推荐此方法。 #### 步骤 3: 测试和故障排除 - **测试 Gazebo 和 ROS 1**:运行简单示例: ```bash roscore & rosrun gazebo_ros gazebo ``` 如果出现错误(如缺少插件),检查依赖:`rosdep check`。 - **常见问题**: - **依赖冲突**:在方法 2 中,如果 `apt` 报错,尝试固定包版本或使用 `aptitude`。 - **Gazebo 启动失败**:确保安装 `libgazebo-dev` 和相关插件。参考 ROS 社区论坛(如 ROS Answers)。 - **性能问题**:Docker 方法中,分配更多资源(如 CPU 和内存)。 #### 迁移建议 Ubuntu 22.04 是 ROS 2 Humble Hawksbill 的官方平台,建议逐步迁移到 ROS 2 以获最佳支持。ROS 2 集成了 Gazebo Fortress(版本 11+),安装更简单: ```bash sudo apt install ros-humble-desktop-full # 包括 Gazebo ``` 这可以避免兼容性问题并利用新特性[^1]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值