Terrain Generating

Terrain Generating


在飞行模拟中或在一些需要实时产生地形的游戏中,用了Voxel的技术。Voxel这个词从Pixel(像素)中来,即“volumetric pixel”。如果Pixel代表了二维世界中的一各矩形,那voxel就是三维世界的一个立方块。如图一:
(if i have time i'll make better pictures)


Voxel的data就是由x(宽度),z(深度,从屏幕往里)加上高度y组成的。

在生成地形时,光有这些粒粒还不行,要看上去象地形,还得Render它们。可用不同的颜色表示地形的高低和远近。有几种方法可以render它们,光线跟踪(ray tracing)就是其中一种。光线跟踪的基本方法是从视点投射一束光线(ray casting),直到这束光线被障碍物阻挡为止。然后向另一个方向再投射一束光线,依此类推。最后,光线中止的点的集合就构成了地形。在飞行模拟中多用这个方法,在如Quake/Doom类的游戏中也用了光线跟踪。

如图二,


把三维的ray casting拆成二维,就有了图三Y-Z,和图四X-Z:


我们用到的数学只是三角比例关系。(图五)


这个算法可以这样来表示:
p=当前点
while (不是屏幕上的最后一点)
{

从视点投射光线去p点。
穿过p点后,光线继续。
if ( 光线碰到障碍物)
{ 以障碍物的位置的不同,根据高低远近给于p点以不同的颜色。}
p指向下一个屏幕像素。

}


飞行模拟中的地形模拟就是这么回事,简单不简单?(说“简单”)。如果你的回答是“复杂”,这里有一个对简单地图Render的
实例

现实和理论总有不同,其结果能差好多好多倍,比如在理论上我是个好人,而在实际上,我是个....hum....很好很好的人。当光线跟踪被军方使用时,他们用了几台超级电脑系统。才能使画面保持实时的效果。在我们PC based的游戏系统上,要能维持20fps以上的连续画面,在换帧之间完成所有地形的光线跟踪,是很困难的。因而,在PC game里,我们有更好的光线跟踪近似算法,实际的效果比标准的光线跟踪算法快约一千倍。

标准的光线跟踪方法慢的原因是因为对屏幕上每个像素点都要投射一次光线,并做相应的运算。在典型的640X480的分辨率中共有307200个像素,需要投射307200条光线并做计算。这些计算花去了太多的时间。但如果我们仅仅投射少量的光线。比如说640条,其余的让它自动生成,就会快得多。

简化的方法是,先投射一条光线去屏幕最下面的像素。等光线碰到地形障碍物后,不是再从视点投射另一条,而是让光线自己顺着地形的起伏爬。所以对每一列屏幕像素,只需投射一条光线。在640x480的例子里,我们只要投射640条光线。(图六)


那么怎样才能让光线爬行并返回我们要的数值呢?这里有一些数学的技巧。经过这些数学的运算,可以得出这样的一个结论:(图七)


最后,我们有了一个优化的算法:
for (像素列从0到639)
{
   //由于在SIN,COS的运算会耗去50-80个CPU时钟数,所以事先
  //算好每一个角度的正,余弦值,放在COS_LOOK,SIN_LOOK表中。
  //用时差表就快多了。
   dx=COS_LOOK[当前角度];
   dy=SIN_LOOK[当前角度];
   dz=斜度*(试点夹角-屏幕高度);
   画点;
   当前角度递减--;
}

如果你是个“拿来主义者”,或对算法本身不感兴趣,下面的子程式可以整个抄去你的主程式。
这里是一个完整的Render地形的子程式。
这个子程式的原作者为David Lindauer,后经过许多人许多次修改,最后定型。

void  Render_Terrain( int  vp_x,
          
int  vp_y,
          
int  vp_z,
          
int  vp_ang_x,
          
int  vp_ang_y,
          
int  vp_ang_z,
          UCHAR 
* dest_buffer)
{
// this function renders the terrain

//at the given position and orientation


    
int xr,yr,
    curr_column,
    curr_step, 
//current step ray is at
    raycast_ang, //current angle of ray being cast
    dx,dy,dz, //general deltas for ray to move from
              
//pt to pt
    curr_voxel_scale, //current scaling factor to draw each voxel line
    column_height, //height of the column intersected and being rendered
    curr_row, //number of rows processed in current column
    x_ray,y_ray,z_ray, // the position of the tip of the ray
    map_addr; //temp var used to hold the addr of data bytes

    CHAR color, 
//color of pixel being rendered
    ? dest_column_ptr;    //address screen pixel being rendered
    
//convert needed vars to fixed point

    vp_x
=(vp_x<<FIXP_SHIFT);
    vp_y
=(vp_y<<FIXP_SHIFT);
    vp_z
=(vp_z<<FIXP_SHIFT);    //push down destination buffer to bottom of screen
    dest_buffer += (SCREEN_WIDTH * (SCREEN_HEIGHT-1));    //compute starting angle
    raycast_ang=vp_ang_y+ANGLE_30;    //cast a ray for each column of the screen
    for (curr_column=0; curr_column < SCREEN_WIDTH-1;curr_column++)
    
{
        
//seed starting point for cast
        x_ray=vp_x;
        y_ray
=vp_y;
        z_ray
=vp_z;        //compute deltas to project ray at, note the spherical cancelation factor
        dx=COS_LOOK(raycast_ang)<<1;
        dy
=SIN_LOOK(raycast_ang)<<1;        //dz is a bit complex, remember dz is the slope of the ray we are casting,
        
//therefore, we need to take into consideration the
        
//down angle, or x axis angle, the more we are looking down the
        
//larger the initial dz must be
        dz=dslope*(vp_ang_x-SCREEN_HEIGHT);        // reset current voxel scale
        curr_voxel_scale=0;        //reset row
        curr_row=0;        //get starting address of bottom of current video column
        dest_column_ptr=dest_buffer;        //enter into casting loop
        for(curr_step=0;curr_step<MAX_STEPS;curr_step++)
        
{
            
//compute pixel in height map to process
            
//note that the ray is converted back to an int
            
//and it is clipped to stay positive and in range
            xr=(x_ray>>FIXP_SHIFT);
            yr
=(y_ray >> FIXP_SHIFT);
            xr
=(xr&(HFIELD_WIDTH-1));
            yr
=(yr&(HFIELD_HEIGHT-1));
            map_addr
=(xr+(yr<<HFIELD_BIT_SHIFT));            //get current height in height map, note the conversion to
            
//fixed point and the added multiplication factor used to
            
//scale the mountains
            column_height=(heigth_map_ptr[map_addr]<<(FIXP_SHIFT+TERRAIN_SCALE_X2));            //test if column height is greater than current voxel height
            
//for current step from initial projection point
            if(column_height>z_ray)
            
{
                
//get the color for the voxel
                color=color_map_ptr[map_addr];                //draw vertical column voxel
                while(1)
                
{
                    
//draw a pixel
                    *dest_column_ptr=color;                    //now we need to push the ray upward on z axis
                    
//so increment the slope
                    dz+=dslope;                    //now translate the current z position of the ray by
                    
//the current voxel scale per unit
                    z_ray+=curr_voxel_scale;                    //move up one video line
                    dest_column_ptr-=SCREEN_HEIGHT)
                    
if(++curr_row>=SCREEN_HEIGHT)
                    
{
                        
//force exit of outer stepping loop
                        
//cheezy, but better than GOTO!
                        curr_step=MAX_STEPS;
                        
break;
                    }
//endif                    //test if we can break out of the loop
                    if(z_ray>column_height)break;
                }
//end while            }//endif            //update the position of the ray
            x_ray+=dx;
            y_ray
+=dy;
            z_ray
+=dz;            //update the current voxel scale, remember each step out
            
//means the scale increases by the delta scale
            curr_voxel_scale+=dslope;        }
//end for curr_step        //advance video pointer ot bottom of next column          dest_buffer++;        //advance to next angle
        raycast_ang--;    }
//end for curr_col}//end render_terrain

 

 
lixing@lixing:~/PX4-Autopilot$ make px4_sitl gazebo [0/1072] git submodule src/drivers/gps/devices [10/1072] git submodule src/modules/mavlink/mavlink [12/1072] git submodule Tools/simulation/gazebo-classic/sitl_gazebo-classic [13/1072] git submodule src/modules/uxrce_dds_client/Micro-XRCE-DDS-Client [18/1072] Performing configure step for 'sitl_gazebo-classic' -- install-prefix: /usr/local -- cmake build type: RelWithDebInfo -- Using C++17 standard -- ccache enabled (export CCACHE_DISABLE=1 to disable) -- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found suitable version "1.71.0", minimum required is "1.58") found components: system thread filesystem -- Found DART: /usr/include (Required is at least version "6.6") found components: dart -- Found Boost: /usr/lib/x86_64-linux-gnu/cmake/Boost-1.71.0/BoostConfig.cmake (found suitable version "1.71.0", minimum required is "1.40.0") found components: thread system filesystem program_options regex iostreams date_time -- Looking for ignition-math6 -- found version 6.15.1 -- Searching for dependencies of ignition-math6 -- Looking for OGRE... -- Found Ogre Ghadamon (1.9.0) -- Looking for OGRE_Paging... -- Found OGRE_Paging: optimized;/usr/lib/x86_64-linux-gnu/libOgrePaging.so;debug;/usr/lib/x86_64-linux-gnu/libOgrePaging.so -- Looking for OGRE_Terrain... -- Found OGRE_Terrain: optimized;/usr/lib/x86_64-linux-gnu/libOgreTerrain.so;debug;/usr/lib/x86_64-linux-gnu/libOgreTerrain.so -- Looking for OGRE_Property... -- Found OGRE_Property: optimized;/usr/lib/x86_64-linux-gnu/libOgreProperty.so;debug;/usr/lib/x86_64-linux-gnu/libOgreProperty.so -- Looking for OGRE_RTShaderSystem... -- Found OGRE_RTShaderSystem: optimized;/usr/lib/x86_64-linux-gnu/libOgreRTShaderSystem.so;debug;/usr/lib/x86_64-linux-gnu/libOgreRTShaderSystem.so -- Looking for OGRE_Volume... -- Found OGRE_Volume: optimized;/usr/lib/x86_64-linux-gnu/libOgreVolume.so;debug;/usr/lib/x86_64-linux-gnu/libOgreVolume.so -- Looking for OGRE_Overlay... -- Found OGRE_Overlay: optimized;/usr/lib/x86_64-linux-gnu/libOgreOverlay.so;debug;/usr/lib/x86_64-linux-gnu/libOgreOverlay.so -- Looking for ignition-math6 -- found version 6.15.1 -- Looking for ignition-transport8 -- found version 8.5.0 -- Searching for dependencies of ignition-transport8 -- Config-file not installed for ZeroMQ -- checking for pkg-config -- Checking for module 'libzmq >= 4' -- Found libzmq , version 4.3.2 -- Checking for module 'uuid' -- Found uuid, version 2.34.0 -- Looking for ignition-msgs5 -- found version 5.11.0 -- Searching for dependencies of ignition-msgs5 -- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so;-lpthread (found suitable version "3.6.1", minimum required is "3") -- Looking for ignition-math6 -- found version 6.15.1 -- Checking for module 'tinyxml2' -- Found tinyxml2, version 6.2.0 -- Looking for ignition-msgs5 -- found version 5.11.0 -- Looking for ignition-common3 -- found version 3.17.0 -- Searching for dependencies of ignition-common3 -- Looking for dlfcn.h - found -- Looking for libdl - found -- Searching for <ignition-common3> component [graphics] -- Looking for ignition-common3-graphics -- found version 3.17.0 -- Searching for dependencies of ignition-common3-graphics -- Looking for ignition-math6 -- found version 6.15.1 -- Looking for ignition-fuel_tools4 -- found version 4.9.1 -- Searching for dependencies of ignition-fuel_tools4 -- Checking for module 'jsoncpp' -- Found jsoncpp, version 1.7.4 -- Checking for module 'yaml-0.1' -- Found yaml-0.1, version 0.2.2 -- Checking for module 'libzip' -- Found libzip, version 1.5.1 -- Looking for ignition-common3 -- found version 3.17.0 -- Looking for ignition-math6 -- found version 6.15.1 -- Looking for ignition-msgs5 -- found version 5.11.0 -- Building klt_feature_tracker without catkin -- Building OpticalFlow with OpenCV -- catkin DISABLED -- Found Protobuf: /usr/lib/x86_64-linux-gnu/libprotobuf.so;-lpthread (found version "3.6.1") -- Gazebo version: 11.15 -- Found GStreamer: adding gst_camera_plugin -- Found GStreamer: adding gst_video_stream_widget -- Configuring done -- Generating done -- Build files have been written to: /home/lixing/PX4-Autopilot/build/px4_sitl_default/build_gazebo-classic [68/1072] Performing configure step for 'libmicroxrceddsclient_project' -- libmicroxrceddsclient_project configure command succeeded. See also /home/lixing/PX4-Autopilot/build/px4_sitl_default/src/modules/uxrce_dds_client/src/libmicroxrceddsclient_project-stamp/libmicroxrceddsclient_project-configure-*.log [69/1072] Performing build step for 'libmicroxrceddsclient_project' -- libmicroxrceddsclient_project build command succeeded. See also /home/lixing/PX4-Autopilot/build/px4_sitl_default/src/modules/uxrce_dds_client/src/libmicroxrceddsclient_project-stamp/libmicroxrceddsclient_project-build-*.log [70/1072] Performing install step for 'libmicroxrceddsclient_project' -- libmicroxrceddsclient_project install command succeeded. See also /home/lixing/PX4-Autopilot/build/px4_sitl_default/src/modules/uxrce_dds_client/src/libmicroxrceddsclient_project-stamp/libmicroxrceddsclient_project-install-*.log [884/1072] Performing build step for 'sitl_gazebo-classic' [38/115] Generating /home/lixing/PX4-A...dels/quadtailsitter/quadtailsitter.sdf /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/quadtailsitter/quadtailsitter.sdf.jinja -> /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/quadtailsitter/quadtailsitter.sdf [40/115] Generating /home/lixing/PX4-A..._gazebo-classic/models/plane/plane.sdf /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/plane/plane.sdf.jinja -> /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/plane/plane.sdf [46/115] Generating /home/lixing/PX4-A...ebo-classic/models/px4flow/px4flow.sdf /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/px4flow/px4flow.sdf.jinja -> /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/models/px4flow/px4flow.sdf [66/115] Building CXX object CMakeFile...ugin.dir/src/gazebo_aruco_plugin.cpp.o FAILED: CMakeFiles/gazebo_aruco_plugin.dir/src/gazebo_aruco_plugin.cpp.o /usr/bin/ccache /usr/bin/c++ -DBOOST_ALL_NO_LIB -DBOOST_ATOMIC_DYN_LINK -DBOOST_DATE_TIME_DYN_LINK -DBOOST_FILESYSTEM_DYN_LINK -DBOOST_IOSTREAMS_DYN_LINK -DBOOST_PROGRAM_OPTIONS_DYN_LINK -DBOOST_REGEX_DYN_LINK -DBOOST_SYSTEM_DYN_LINK -DBOOST_TEST_DYN_LINK -DBOOST_THREAD_DYN_LINK -DLIBBULLET_VERSION=2.88 -DLIBBULLET_VERSION_GT_282 -Dgazebo_aruco_plugin_EXPORTS -I/home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/include -I. -I/usr/local/include/eigen3/eigen3 -I/usr/include/gazebo-11/gazebo/msgs -I/home/lixing/PX4-Autopilot/build/px4_sitl_default/mavlink -I/home/lixing/PX4-Autopilot/build/px4_sitl_default/mavlink/mavlink/v2.0 -I/usr/include/Paging -I/home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/external/OpticalFlow/include -I/usr/include/gstreamer-1.0 -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /usr/include/gazebo-11 -isystem /usr/include/bullet -isystem /usr/include/simbody -isystem /usr/include/sdformat-9.10 -isystem /usr/include/ignition/math6 -isystem /usr/include/OGRE -isystem /usr/include/OGRE/Terrain -isystem /usr/include/OGRE/Paging -isystem /usr/include/ignition/transport8 -isystem /usr/include/ignition/msgs5 -isystem /usr/include/ignition/common3 -isystem /usr/include/ignition/fuel_tools4 -isystem /usr/include/x86_64-linux-gnu/qt5 -isystem /usr/include/x86_64-linux-gnu/qt5/QtCore -isystem /usr/lib/x86_64-linux-gnu/qt5/mkspecs/linux-g++ -isystem /usr/local/include/eigen3 -isystem /usr/local/opencv3.4/include/opencv4 -isystem /usr/include/sdformat-9.10/sdf/.. -isystem /usr/include/ignition/cmake2 -isystem /usr/include/uuid -O2 -g -DNDEBUG -fPIC -Wno-deprecated-declarations -Wno-address-of-packed-member -I/usr/include/uuid -std=gnu++17 -MD -MT CMakeFiles/gazebo_aruco_plugin.dir/src/gazebo_aruco_plugin.cpp.o -MF CMakeFiles/gazebo_aruco_plugin.dir/src/gazebo_aruco_plugin.cpp.o.d -o CMakeFiles/gazebo_aruco_plugin.dir/src/gazebo_aruco_plugin.cpp.o -c /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/src/gazebo_aruco_plugin.cpp In file included from /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/src/gazebo_aruco_plugin.cpp:31: /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/include/gazebo_aruco_plugin.h:42:10: fatal error: opencv2/aruco.hpp: 没有那个文件或目录 42 | #include <opencv2/aruco.hpp> | ^~~~~~~~~~~~~~~~~~~ compilation terminated. [77/115] Building CXX object CMakeFile...ir/src/gazebo_user_camera_plugin.cpp.o ninja: build stopped: subcommand failed. [1068/1072] Linking CXX executable bin/px4 FAILED: external/Stamp/sitl_gazebo-classic/sitl_gazebo-classic-build cd /home/lixing/PX4-Autopilot/build/px4_sitl_default/build_gazebo-classic && /usr/bin/cmake --build /home/lixing/PX4-Autopilot/build/px4_sitl_default/build_gazebo-classic -- -j 12 ninja: build stopped: subcommand failed. make: *** [Makefile:227:px4_sitl] 错误 1 lixing@lixing:~/PX4-Autopilot$
07-23
<think>我们正在分析用户提供的编译错误日志。错误发生在构建PX4 SITL Gazebo仿真环境时,具体是在构建`sitl_gazebo-classic`的`gazebo_aruco_plugin`插件时,出现了头文件缺失的问题: ``` /home/lixing/PX4-Autopilot/Tools/simulation/gazebo-classic/sitl_gazebo-classic/include/gazebo_aruco_plugin.h:42:10: fatal error: opencv2/aruco.hpp: 没有那个文件或目录 42 | #include <opencv2/aruco.hpp> ``` 这表明系统缺少OpenCV的ArUco模块。ArUco是OpenCV的一个用于二维码标记检测的库。 ### 解决方法: 1. **安装OpenCV的ArUco模块**:通常,ArUco模块包含在OpenCV的contrib模块中。如果用户已经安装了OpenCV但没有安装contrib模块,则需要安装它。 - 在Ubuntu系统中,可以通过安装`libopencv-contrib`包来获取。具体命令可能是: ```bash sudo apt-get install libopencv-contrib-dev ``` - 如果用户是自己编译的OpenCV,需要确保在编译时启用了`opencv_contrib`,并且设置了`OPENCV_EXTRA_MODULES_PATH`指向contrib模块的路径。 2. **检查OpenCV版本**:确保安装的OpenCV版本与PX4兼容。PX4通常需要OpenCV 3.x或4.x。如果用户安装的是OpenCV 4,那么ArUco模块已经包含在核心库中,但头文件路径可能发生了变化(例如,在OpenCV4中,ArUco相关头文件位于`opencv2/objdetect/aruco.hpp`)。然而,从错误信息看,插件期望的是`opencv2/aruco.hpp`,这通常是OpenCV3的路径。 3. **调整代码(如果必要)**:如果用户安装的是OpenCV4,可能需要修改插件的源代码,将`#include <opencv2/aruco.hpp>`改为`#include <opencv2/objdetect/aruco.hpp>`。但是,这取决于插件的编写方式。在PX4的sitl_gazebo中,可能已经有人处理过这个问题。建议先尝试安装OpenCV3的contrib版本。 ### 具体步骤建议: - 安装OpenCV3的完整版(包括contrib): ```bash sudo apt-get install libopencv-dev libopencv-contrib-dev ``` 如果用户已经安装了OpenCV4,可能需要降级到OpenCV3,或者尝试使用OpenCV4并修改插件代码。 - 如果用户希望继续使用OpenCV4,可以尝试修改`gazebo_aruco_plugin.h`和`gazebo_aruco_plugin.cpp`中的包含路径,将`opencv2/aruco.hpp`替换为`opencv2/objdetect/aruco.hpp`,并检查函数调用是否与OpenCV4兼容(因为OpenCV4中ArUco的API有变化)。 ### 其他可能的问题: - 确保OpenCV的路径被正确包含在编译环境中。如果OpenCV安装在非标准路径,可能需要设置`PKG_CONFIG_PATH`或使用`cmake`参数指定OpenCV路径。 ### 重新编译: 安装完所需的OpenCV库后,重新运行`make px4_sitl gazebo`。 ### 注意: 用户提供的错误日志中,还显示了一些其他步骤成功完成,所以问题集中在`gazebo_aruco_plugin`的编译上。 ### 总结: 主要问题是缺少OpenCV的ArUco模块。安装相应的开发包即可解决。 §§相关问题§§ 1. 如何检查Ubuntu系统中安装的OpenCV版本? 2. 如果安装OpenCV contrib后仍然出现同样错误,可能的原因是什么? 3. 在PX4的sitl_gazebo中,除了ArUco插件,还有哪些插件可能依赖OpenCV? 4. 如何修改CMakeLists.txt来指定使用特定版本的OpenCV? 5. 在OpenCV4中,ArUco模块的使用与OpenCV3有哪些主要区别?</think>### 问题分析 在编译PX4 SITL Gazebo时出现错误: ``` fatal error: opencv2/aruco.hpp: 没有那个文件或目录 ``` 这表明系统缺少OpenCV的ArUco模块(用于二维码识别的计算机视觉库)。常见原因是: 1. **未安装OpenCV contrib模块**(包含ArUco) 2. OpenCV版本不兼容(PX4推荐3.4.x) 3. Gazebo插件未正确链接OpenCV --- ### 解决方案 #### 步骤1:安装OpenCV contrib模块 ```bash # 卸载可能存在的旧版本 sudo apt-get purge libopencv* # 安装带contrib的OpenCV 3.4 sudo apt-get install libopencv-dev libopencv-contrib-dev libopencv-core-dev ``` #### 步骤2:验证OpenCV安装 ```bash # 检查ArUco头文件是否存在 ls /usr/include/opencv2/aruco.hpp # 检查版本 pkg-config --modversion opencv # 应显示3.4.x ``` #### 步骤3:清理并重新编译 ```bash cd ~/PX4-Autopilot make clean # 清理旧编译文件 make px4_sitl gazebo -j$(nproc) # 重新编译 ``` #### 备选方案:手动修复头文件路径 如果已安装OpenCV但路径错误,可临时修改源码: ```cpp // 在 gazebo_aruco_plugin.h 中修改 #include <opencv2/objdetect/aruco.hpp> // OpenCV4的路径 // 替代原 #include <opencv2/aruco.hpp> ``` --- ### 常见问题预防 1. **Ubuntu版本兼容性**:推荐Ubuntu 20.04(官方支持) 2. **环境冲突**:避免同时安装多版本OpenCV 3. **Gazebo版本**:需11.x(非Gazebo Fortress)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值