DefaultRobotHWSim::writeSim()详解

DefaultRobotHWSim::writeSim函数详解

源码部分(已加注释)

void DefaultRobotHWSim::writeSim(ros::Time time, ros::Duration period)
{
  // If the E-stop is active, joints controlled by position commands will maintain their positions.
  // 紧急停止部分内容
  if (e_stop_active_)
  {
    if (!last_e_stop_active_)//保存当前停止位置指令
    {
      last_joint_position_command_ = joint_position_;//以当前位置 作为位置控制指令
      last_e_stop_active_ = true; // 同一时间断内得急停指令不更新
    }
    joint_position_command_ = last_joint_position_command_;// 急停时得位置作为位置控制指令
  }
  else
  {
    last_e_stop_active_ = false;//急停时位置可被更新
  }


// joint 限制相关内容
  ej_sat_interface_.enforceLimits(period);
  ej_limits_interface_.enforceLimits(period);
  pj_sat_interface_.enforceLimits(period);
  pj_limits_interface_.enforceLimits(period);
  vj_sat_interface_.enforceLimits(period);
  vj_limits_interface_.enforceLimits(period);

//遍历每个joint 
  for(unsigned int j=0; j < n_dof_; j++)
  {
    switch (joint_control_methods_[j]) // 根据不同joint 得控制接口 进行不同处理
    {
      case EFFORT: // joint 为力控制接口
        {
            // 判断是否是急停  是至0 不是 赋 joint_effort_command_  , ???此命令如何更新 应该是 ros control里发布得
          const double effort = e_stop_active_ ? 0 : joint_effort_command_[j]; 
            // 设置 gazebo 里 joint 受到得力
          sim_joints_[j]->SetForce(0, effort);
        }
        break;

      case POSITION:  // 由上面看应该不灰进才对
#if GAZEBO_MAJOR_VERSION >= 9
        sim_joints_[j]->SetPosition(0, joint_position_command_[j], true);
#else
        ROS_WARN_ONCE("The default_robot_hw_sim plugin is using the Joint::SetPosition method without preserving the link velocity.");
        ROS_WARN_ONCE("As a result, gravity will not be simulated correctly for your model.");
        ROS_WARN_ONCE("Please set gazebo_pid parameters, switch to the VelocityJointInterface or EffortJointInterface, or upgrade to Gazebo 9.");
        ROS_WARN_ONCE("For details, see https://github.com/ros-simulation/gazebo_ros_pkgs/issues/612");
        sim_joints_[j]->SetPosition(0, joint_position_command_[j]);
#endif
        break;

      case POSITION_PID: // 位置控制接口应该进这个地方
        {
          double error;
          switch (joint_types_[j]) // 根据joint 得类型 在urdf里设置得
          {
            case urdf::Joint::REVOLUTE: // joint 旋转 带限位得
            // 由当前位置 和目前位置指令 和限位信息 综合计算 更新位置偏差 error(最短角距离)
              angles::shortest_angular_distance_with_limits(joint_position_[j],
                                                            joint_position_command_[j],
                                                            joint_lower_limits_[j],
                                                            joint_upper_limits_[j],
                                                            error);
              break;
            case urdf::Joint::CONTINUOUS:// joint 旋转 无限转
                // 由当前位置 和目前位置指令 更新位置偏差 error (最短角距离)
              error = angles::shortest_angular_distance(joint_position_[j],
                                                        joint_position_command_[j]);
              break;
            default://不是上面那两种
              error = joint_position_command_[j] - joint_position_[j];//直接做差得到
          }

          const double effort_limit = joint_effort_limits_[j]; // joint得 effort 幅值限制

                  // pid_controllers_[j].computeCommand(error, period) 反馈得pid 计算结果 即joint应受得力 
                  //clamp() 对pid  计算 joint应受得力 进行幅值限制
          const double effort = clamp(pid_controllers_[j].computeCommand(error, period),
                                      -effort_limit, effort_limit);

              // 和力控制接口一样,最终都归结到 力  
          // 设置 gazebo 里 joint 受到得力
          sim_joints_[j]->SetForce(0, effort);
            // ???  既然都最终归结到力  那控制器选择 位置控制时, joint接口 为力接口, 控制器得输出是力指令吗
            // ??? 需要看 位置控制器得输出究竟是什么
           //  ???  joint_position_command_  位置得指令是怎么发布得  那应该可以直接发布一个joint_position_command_期望位置来完成joint得控制啊
              
        }
        break;

      case VELOCITY://应该不会进来
#if GAZEBO_MAJOR_VERSION > 2
//ODE(Open Dynamics Engine)  gazebo 得模式 可以先不管  应该是 ode模式
        if (physics_type_.compare("ode") == 0)
        {
          sim_joints_[j]->SetParam("vel", 0, e_stop_active_ ? 0 : joint_velocity_command_[j]);
        }
        else 
        {
          sim_joints_[j]->SetVelocity(0, e_stop_active_ ? 0 : joint_velocity_command_[j]);
        }
#else
        sim_joints_[j]->SetVelocity(0, e_stop_active_ ? 0 : joint_velocity_command_[j]);
#endif
        break;

      case VELOCITY_PID:
        double error;
        if (e_stop_active_)// 当紧急停止时 
          error = -joint_velocity_[j];  // 
        else
          error = joint_velocity_command_[j] - joint_velocity_[j];//计算期望速度与当前速度偏差

        const double effort_limit = joint_effort_limits_[j];

         // pid_controllers_[j].computeCommand(error, period) 反馈得pid 计算结果 即joint应受得力 
         //clamp() 对pid  计算 joint应受得力 进行幅值限制        
        const double effort = clamp(pid_controllers_[j].computeCommand(error, period),
                                    -effort_limit, effort_limit);//与位置控制同理
                                    
              // 和力控制接口一样,最终都归结到 力  
          // 设置 gazebo 里 joint 受到得力
        sim_joints_[j]->SetForce(0, effort);
        break;
            // ???  既然都最终归结到力  那控制器选择 速度控制时, joint接口 为力接口, 控制器得输出是力指令吗
            // ??? 需要看 速度控制器得输出究竟是什么
           //  ???  joint_velocity_command_  速度得指令是怎么发布得  那应该可以直接发布一个joint_velocity_command_期望速度来完成joint得控制啊        
    }
  }
}

对源码进行功能分块解读

由上至下

=========================================================================================================
在这里插入图片描述
紧急停止部分内容
同一时间断内得急停指令不更新
触发急停时得位置作为位置控制指令

=========================================================================================================
在这里插入图片描述
joint 限制相关内容

=========================================================================================================
在这里插入图片描述
遍历每个joint
根据不同joint 得控制接口 进行不同处理 下面不再赘述
是什么控制接口 在初始化函数 DefaultRobotHWSim::initSim() 进行了设置 详看此链接

joint 为力控制接口时
判断是否是急停 是至0 不是 赋 joint_effort_command_

  • 此命令如何更新 应该是 ros control里发布得 要看ros controller 相关内容

sim_joints_[j]->SetForce(0, effort)此函数设置 gazebo 里 joint 受到得力
下面位置控制接口与速度控制接口最后都归到调用此函数 就是用pid进行计算,得到joint应受得力

在用ros控制器时 设置得控制器为位置控制器
这篇博客
得控制器配置时 用得
应该就是直接输出了 joint_effort_command_ 指令 ,效果类似直接用位置控制接口
在这里插入图片描述

  • 具体应该看 jointpositioncontroller得源码

=========================================================================================================
在这里插入图片描述
位置控制接口应该进这个地方
根据joint 得类型 在urdf里设置得 进行不同的处理
设置如这篇博客
在这里插入图片描述

  • joint的类型可以再写篇博客介绍

REVOLUTE: joint 旋转 带限位得
处理此种joint类型时
由当前位置 和目前位置指令 和限位信息 综合计算 更新位置偏差 error(最短角距离)
CONTINUOUS: joint 旋转 无限转
由当前位置 和目前位置指令 更新位置偏差 error (最短角距离)

不是上面那两种
直接做差得到error

pid_controllers_[j].computeCommand(error, period) 反馈得pid 计算结果 即joint应受得力
clamp() 对pid 计算 joint应受得力 进行幅值限制

和力控制接口一样,最终都归结到 力
设置 gazebo 里 joint 受到得力

  • 这里存在一个疑问
    既然都最终归结到力 那控制器选择 位置控制时, joint接口 为力接口, 控制器得输出是力指令吗
    需要看 位置控制器得输出究竟是什么
    joint_position_command_ 位置得指令是怎么发布得 那应该可以直接发布一个joint_position_command_期望位置来完成joint得控制啊

=========================================================================================================

在这里插入图片描述
速度控制接口应该进这个地方
pid_controllers_[j].computeCommand(error, period) 反馈得pid 计算结果 即joint应受得力
clamp() 对pid 计算 joint应受得力 进行幅值限制
和力控制接口一样,最终都归结到 力
设置 gazebo 里 joint 受到得力

  • 这里存在一个疑问
    既然都最终归结到力 那控制器选择 位置控制时, joint接口 为力接口, 控制器得输出是力指令吗
    需要看 速度控制器得输出究竟是什么
    joint_velocity_command_速度得指令是怎么发布得 那应该可以直接发布一个joint_velocity_command_期望位置来完成joint得控制啊

=========================================================================================================

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

月照银海似蛟龙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值