こんにちは、トロボです。前回の続きです。
今回は、『ROS+シミュレータ(Gazebo)』のPID制御をチューニングする方法について説明します。
なお、ROS_ControlのPID制御の詳細についてMoriKen氏が丁寧に説明してくださっています。ここではその情報を拝借しながら、私が実際にROS+Gazeboで試した所感も踏まえて概要を説明させていただきます。
ROS_Controlでは、Gazeboのロボットアーム関節(Joint)に入力する操作量として「①位置(Position)操作」「②速度(Velocity)操作」「③力(Effort)操作」の3種類のいずれかを選べます。Gazeboに渡すtorobo.transmission.xacroファイルのhardwareInterfaceで設定します。例えば下記では速度制御にするためにVelocityJointInterfaceと記載しています。
<robot xmlns:xacro="http://ros.org/wiki/xacro"> <xacro:macro name="arm_simple_transmission" params="name reduction"> <transmission name="${name}_transmission"> <type>transmission_interface/SimpleTransmission</type> <actuator name="${name}_motor"> <mechanicalReduction>${reduction}</mechanicalReduction> <hardwareInterface>PositionJointInterface</hardwareInterface> </actuator> <joint name="${name}_joint"> <hardwareInterface>PositionJointInterface</hardwareInterface> </joint> </transmission> </xacro:macro> </robot>
ここで注意が必要なのが、「①位置(Position)操作」を選ぶとPID制御とはならないということです。なぜなら、関節(Joint)の位置を操作しても、速度や力は決まりませんよね。そのため、「①位置(Position)操作」を選んだ場合は下図のように、Gazeboに対して速度目標値や力目標値は与えられず、位置目標値をGazeboに転送するだけとなります。下図の黄色いブロックはROS_Control、黒いブロックはGazeboです。
すなわち、ROS_ControlのControllerと、GazeboのJointInterfaceとの関係は、下表のようになっています。
Gazebo Position I/F | Gazebo Velocity I/F | Gazebo Effort I/F | |
Position Controller | 〇 | 〇 | 〇 |
Velocity Controller | × | 〇 | 〇 |
Effort Controller | × | × | 〇 |
次に、Gazeboのロボットアーム関節(Joint)に入力する操作量として「②速度(Velocity)操作」を指定した場合を説明しましょう。この場合はPID制御ループが実現されます。下図はJoint Position Controllerからの位置目標値との位置偏差が小さくなるようにPID Controllerが速度操作量を制御します。
ここにさらにJoint Velocity Controllerをつなげたらどうなるでしょうか。下図のように位置偏差だけでなく速度偏差も小さくなるようにPID Controllerが速度操作量を制御します。
なお、PID Controller (Velocity I/F用)は内部で位置偏差にKpゲインを掛けることで速度偏差に変換しています。速度偏差に対してはKdゲインを掛けています。そして位置偏差の総和(積分)に対してはKiゲインをかけています。すなわち、下記の式によるPID制御を行っています。下記式のeはJointの位置(=関節角度)を表します。
このKp、Ki、Kdの3つのゲインをチューニングすれば実機の動作に近づけることができます。これらはroslaunch時にrosparamとして読み込ませるyamlファイルで指定することができます。
toroboarm: Position Controllers --------------------------------------- joint1_position_controller: type: position_controllers/JointPositionController joint: first_joint pid: {p: 100.0, i: 0.01, d: 10.0}
実際にチューニングを試した所感ですが、ROS_ControlのPID制御ではうまく制御できないことが多くありました。GazeboEncoderから取得される速度値を見ると振動しているため、PID制御のような高周期では速度制御が難しいのかもしれません。
回避策として、PID制御をやめて「①位置(Position)操作」を選ぶのも1つの手です。「位置操作では速度目標値を指定できないため実機の挙動と合わせられないのでは?」という疑問が残るかと思います。ROS_ControlではJointTrajectoryという遷移時間を含んだメッセージをサポートしており、これを使えば速度目標値を指定できます。このJointTrajectoryについては、ROS_ControlではPID制御を行わずにTFライブラリによる軌道計算を行ってロボットアームのJointの位置制御をしているものと思われます。
以上、長くなりましたが、『ROS+シミュレータ(Gazebo)』のPID制御のチューニング方法をメインに解説してきました。シミュレータと実機の挙動を完全に合わせることは難しいですが、『ROS+シミュレータ(Gazebo)』をより多くの分野で活用できるように知見を深めていきたいと考えています。ありがとうございました。