Gazebo仿真UUV水下机器人

最近准备学习一下ros,gazebo和一个水下rov模拟器。

uuv_simulator(https://github.com/uuvsimulator/uuv_simulator)是一个非常优秀的基于ROS&GAZEBO开源水下机器人仿真项目,能为水下机器人的应用与算法提供一个较为理想的仿真环境进行测试。更详细的内容请仔细研读项目的wiki资料。

项目的机器人模型有两款ROV:desistek_saga与rexrov2,两款AUV:eca_a9与lauv_gazebo。项目内都提供了链接。同时在RexROV2的项目中《Development and Commissioning of a DP system for ROV SF 30k》一文详细介绍了如何构建水下机器人模型,值得了解一下。

在这里要说明的是仿真环境毕竟是虚拟的,水下使用光学相机不可能有这么好的能见度。实际上uuv_simulator里是有水雾设定以模拟水下光的衰减的情况,具体可以阅读其论文。不过此次仿真测试没有使用。

      最后简要说一下怎么安装和测试。

首先根据网上资料安装好ros noetic和gazebo,下面是针对uuv的导入:

   安装:

    mkdir -p xxx/src
    cd xxx/src
    git clone https://github.com/uuvsimulator/uuv_simulator.git
    git clone https://github.com/cabinx/cabin_auv_simulation.git
    cd ..
    catkin_make

注意:我个人的系统为ubutu20.04,ROS版本为neotic,Gazebo版本为11.0。所以编译uuv_simulator时出现了一些问题,具体如下:

一、gazebo11与sdformat-9.2问题

sdformat版本升级后,编译器的版本支持也需要做出相应改动。大致会出现如下报错:

/usr/include/sdformat-9.2/sdf/Param.hh:72:57: error: expected constructor, destructor, or type conversion before ‘;’ token template<class T> ParamStreamer(T) -> ParamStreamer<T>; /usr/include/sdformat-9.2/sdf/Param.hh:83:47: error: ‘variant’ is not a member of ‘std’ ParamStreamer<std::variant<Ts...>> sv)

根据error的log定位到uuv_gazebo_plugins的package,在其目录下的CMakeLists.txt中添加对c++17的支持:

   set(CMAKE_CXX_STANDARD 17)
   set(CMAKE_CXX_STANDARD_REQUIRED ON)

二、gazebo11与Ignition Math库问题

Ignition Math库相应升级到了v6版本,库内一些类的命名也有所变动,导致编译时出现错误。在此给出v4版本和v6版本的API链接:

V4:https://ignitionrobotics.org/api/math/4.0/namespaceignition_1_1math.html

V6:https://ignitionrobotics.org/api/math/6.7/namespaceignition_1_1math.html

还是在uuv_gazebo_plugins的package中,http://HydrodynamicModel.cc中计算bounding box调用的类发生了改动,原代码为ignition::math::Box ,新版本更名为 ignition::math::AxisAlignedBox,而新版本的ignition::math::Box是新的实现。需要在BuoyantObject.hh,http://BuoyantObject.cchttp://HydrodynamicModel.cc中做出相应修正。

1、对于BuoyantObject.hh:

public: void SetBoundingBox(const ignition::math::Box &_bBox);
 
...
 
protected: ignition::math::Box boundingBox;

修改为:

public: void SetBoundingBox(const ignition::math::AxisAlignedBox &_bBox);
 
...
 
protected: ignition::math::AxisAlignedBox boundingBox;

2、对于http://BuoyantObject.cc

void BuoyantObject::SetBoundingBox(const ignition::math::Box &_bBox)
{
  this->boundingBox = ignition::math::Box(_bBox);
 
  gzmsg << "New bounding box for " << this->link->GetName() << "::"
    << this->boundingBox << std::endl;
}

修改为:

void BuoyantObject::SetBoundingBox(const ignition::math::AxisAlignedBox &_bBox)
{
  this->boundingBox = ignition::math::AxisAlignedBox(_bBox);
 
  gzmsg << "New bounding box for " << this->link->GetName() << "::"
    << this->boundingBox << std::endl;
}

3、对于http://HydrodynamicModel.cc

// FIXME(mam0box) This is a work around the problem of the invalid bounding
// box returned by Gazebo
  if (_sdf->HasElement("box"))
  {
    sdf::ElementPtr sdfModel = _sdf->GetElement("box");
    if (sdfModel->HasElement("width") && sdfModel->HasElement("length") &&
        sdfModel->HasElement("height"))
    {
      double width = sdfModel->Get<double>("width");
      double length = sdfModel->Get<double>("length");
      double height = sdfModel->Get<double>("height");
      ignition::math::Box boundingBox = ignition::math::Box(
        ignition::math::Vector3d(-width / 2, -length / 2, -height / 2),
        ignition::math::Vector3d(width / 2, length / 2, height / 2));
      // Setting the the bounding box from the given dimensions
      this->SetBoundingBox(boundingBox);
    }
  }

修改为:

// FIXME(mam0box) This is a work around the problem of the invalid bounding
// box returned by Gazebo
  if (_sdf->HasElement("box"))
  {
    sdf::ElementPtr sdfModel = _sdf->GetElement("box");
    if (sdfModel->HasElement("width") && sdfModel->HasElement("length") &&
        sdfModel->HasElement("height"))
    {
      double width = sdfModel->Get<double>("width");
      double length = sdfModel->Get<double>("length");
      double height = sdfModel->Get<double>("height");
      ignition::math::AxisAlignedBox boundingBox = ignition::math::AxisAlignedBox(
        ignition::math::Vector3d(-width / 2, -length / 2, -height / 2),
        ignition::math::Vector3d(width / 2, length / 2, height / 2));
      // Setting the the bounding box from the given dimensions
      this->SetBoundingBox(boundingBox);
    }
  }

三 .错误:

[ 97%] Linking CXX shared library /home/wmc/space/gazebo/uuv/devel/lib/libuuv_gazebo_ros_base_sensor_plugin.so
/home/wmc/space/gazebo/uuv/src/uuv_simulator/uuv_sensor_plugins/uuv_sensor_ros_plugins/src/gazebo_ros_image_sonar.cpp: In member function ‘cv::Mat gazebo::GazeboRosImageSonar::ConstructVisualScanImage(cv::Mat&)’:
/home/wmc/space/gazebo/uuv/src/uuv_simulator/uuv_sensor_plugins/uuv_sensor_ros_plugins/src/gazebo_ros_image_sonar.cpp:945:71: error: ‘CV_AA’ was not declared in this scope; did you mean ‘CV_AVX’?
  945 |   cv::ellipse(scan, center, axes, -90, -fov/2.-0.5, fov/2., white, 1, CV_AA); //, int lineType=LINE_8, 0);
      |                                                                       ^~~~~
      |                                                                       CV_AVX

定位gazebo_ros_image_sonar.cpp,加入头文件

#include <opencv2/imgproc/imgproc_c.h>

至此,编译顺利通过,仿真运行也没有问题。

(以上是引用的其他博主的文章和一些自己的问题,在此表示感谢!)

————————————————
版权声明:本文为CSDN博主「cabinx」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/xiekaikaibing/article/details/114984613
 

启动湖泊

roslaunch uuv_gazebo_worlds auv_underwater_world.launch

启动环境和水下机器人pid控制

执行命令:

roslaunch uuv_gazebo start_pid_demo_with_teleop.launch

(未完待续)

 

  • 6
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
MySQL函数是一种可以被调用并执行特定任务的功能性代码块。MySQL提供了许多内置函数,可以在查询过程中使用,以提供更高级的功能。 MySQL函数可以分为以下几类: 1. 字符串函数:MySQL提供了许多字符串函数,可以用来处理和操作字符串数据。例如,CONCAT()函数用于连接多个字符串,SUBSTR()函数用于提取子字符串,UPPER()函数用于将字符串转换为大写,LOWER()函数用于将字符串转换为小写,等等。 2. 数学函数:MySQL提供了丰富的数学函数,可以进行各种数值计算。常见的数学函数包括ABS()函数用于返回绝对值,ROUND()函数用于四舍五入,CEILING()函数用于向上取整,FLOOR()函数用于向下取整等。 3. 日期和时间函数:MySQL提供了许多日期和时间函数,用于在数据库中处理日期和时间数据。例如,NOW()函数用于返回当前日期和时间,DATE()函数用于提取日期部分,MONTH()函数用于提取月份,YEAR()函数用于提取年份等。 4. 聚合函数:MySQL提供了一些聚合函数,用于对数据进行汇总计算。常见的聚合函数包括SUM()函数用于求和,AVG()函数用于求平均值,MAX()函数用于获取最大值,MIN()函数用于获取最小值,等等。 5. 控制流函数:MySQL还提供了一些控制流函数,用于在查询过程中进行条件判断和控制流程。常见的控制流函数包括IF()函数用于条件判断,CASE WHEN语句用于多条件判断,等等。 通过使用这些不同类型的MySQL函数,可以方便地对数据库中的数据进行处理和计算,提高查询的效率和灵活性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值