あかすくぱるふぇ

同人サークル「あかすくぱるふぇ」のブログです。

2019年02月

・URDF
<?xml version="1.0"?>
<robot name="tortoisebot">
<link name = "base_link">
<visual>
<geometry>
<box size="0.6 0.3 0.3"/>
</geometry>
</visual>
</link>
<link name="front_caster">
<visual>
<geometry>
<box size="0.1 0.1 0.3"/>
</geometry>
</visual>
</link>
<joint name="front_caster_joint" type="continuous">
<axis xyz="0 0 1"/>
<parent link="base_link"/>
<child link="front_caster"/>
<origin rpy="0 0 0" xyz="0.3 0 0"/>
</joint>
<link name="front_wheel">
<visual>
<geometry>
<cylinder length="0.05" radius="0.035"/>
</geometry>
</visual>
</link>
<joint name="front_wheel_joint" type="continuous">
<axis xyz="0 0 1"/>
<parent link="front_caster"/>
<child link="front_wheel"/>
<origin rpy="-1.5708 0 0" xyz="0.05 0 -0.15"/>
</joint>
</robot>

上記URDFを以下のコマンドで可視化する。
roslaunch urdf_tutorial display.launch model:=tortoisebot.urdf

・joint
jointのoriginは、先にxyzをparentの軸に沿って移動する。
その後、parentの軸に沿って回転する。

・joint_states
joint_state_publisherが、joint_statesトピックをpublish。
joint_statesトピックは、関節角を保持している。
robot_stete_publisherは、joint_statesトピックをsubscribeし、tfトピックをpublish。

・tf
tfトピックは、リンクの親リンクからの位置姿勢変換を保持している。
rvizで見るとTF名はjoint名ではなく親リンク名となっているが、定義はjointタグで行われる。
上の例では、base_link - front_caster間、front_caster - front_wheel間の変換を保持する。
姿勢はクォータニオンで保持するため、front_caster - front_wheel間のtfでは、n=(1, 0, 0), θ=-π/2より、
 [x, y, z, x] = [sin(-π/4), 0, 0, cos(-π/4)] = [-sqrt(2), 0, 0, sqrt(2)]となる。

・librealsenseのインストール
https://github.com/IntelRealSense/librealsense/blob/master/doc/distribution_linux.md


・ファームウェアの更新
pdfを参考にファームウェアを更新し、realsense-viewerで動作確認。
https://www.intel.com/content/dam/support/us/en/documents/emerging-technologies/intel-realsense-technology/Linux-RealSense-D400-DFU-Guide.pdf


・realsense2_cameraのテスト
realsense2_cameraをgit cloneして、roslaunch realsense2_camera rs_rgbd.launchを実行
rvizで/camera/color/image_rawが映ることを確認


・opencvとpub/subのテスト
opencv-pythonをインストールし、imageのsubscribe->opencv変換->publishがうまくいくか確認
#!/usr/bin/env python
import rospy
from cv_bridge import CvBridge
from sensor_msgs.msg import Image

class Aruco:
def __init__(self):
rospy.init_node('aruco_ros')
self.pub = rospy.Publisher('aruco_image', Image, queue_size=10)
self.cv_bridge = CvBridge()
rospy.Subscriber('/camera/color/image_raw', Image, self.callback)

def callback(self, data):
cv_image = self.cv_bridge.imgmsg_to_cv2(data, 'bgr8')
msg_image = self.cv_bridge.cv2_to_imgmsg(cv_image)
self.pub.publish(msg_image)

def main():
Aruco()
rospy.spin()
if __name__ == '__main__':
main()


・ボードの印刷
import cv2

nSquaresX = 5
nSquaresY = 6
square_length = 0.025
marker_length = 0.015

dictionary = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
board = cv2.aruco.CharucoBoard_create(
nSquaresX, nSquaresY, square_length, marker_length, dictionary
)
img = board.draw((1024, 1024))
cv2.imwrite('charuco.png', img)


・姿勢推定
#!/usr/bin/env python
import numpy as np
import rospy
import cv2
from cv_bridge import CvBridge
from sensor_msgs.msg import Image, CameraInfo

class Aruco:
def __init__(self):
# ros
rospy.init_node('aruco_ros')
self.pub = rospy.Publisher('aruco_image', Image, queue_size=10)
self.cv_bridge = CvBridge()
rospy.Subscriber('/camera/color/image_raw', Image, self.callback_image)
rospy.Subscriber('/camera/color/camera_info', CameraInfo, self.callback_camerainfo)

# aruco
nSquaresX = 5
nSquaresY = 6
self.square_length = 0.025
marker_length = 0.015
self.dictionary = cv2.aruco.getPredefinedDictionary(cv2.aruco.DICT_6X6_250)
self.board = cv2.aruco.CharucoBoard_create(
nSquaresX, nSquaresY, self.square_length, marker_length, self.dictionary
)

def callback_image(self, data):
# transform to opencv image
cv_image = self.cv_bridge.imgmsg_to_cv2(data, 'bgr8')

# detect marker
marker_corners, marker_ids, rejected_marker_corners = \
cv2.aruco.detectMarkers(cv_image, self.dictionary)
cv2.aruco.refineDetectedMarkers(
cv_image, self.board, marker_corners, marker_ids, rejected_marker_corners
)
draw_image = cv2.aruco.drawDetectedMarkers(cv_image, marker_corners, marker_ids)
# detect chessboard and estimate pose
if marker_ids is not None:
# detect chessboard
_, board_corners, board_ids = \
cv2.aruco.interpolateCornersCharuco(marker_corners, marker_ids, cv_image, self.board)
draw_image = cv2.aruco.drawDetectedCornersCharuco(draw_image, board_corners, board_ids)

# estimate pose
retval, rvec, tvec = cv2.aruco.estimatePoseCharucoBoard(
board_corners, board_ids, self.board, self.camera_matrix, self.dist_coeffs
)
if retval:
draw_image = cv2.aruco.drawAxis(
draw_image, self.camera_matrix, self.dist_coeffs, rvec, tvec, self.square_length
)
# transform to imgmsg
msg_image = self.cv_bridge.cv2_to_imgmsg(draw_image)
self.pub.publish(msg_image)

def callback_camerainfo(self, data):
self.camera_matrix = np.reshape(np.array(data.K), (3, 3))
self.dist_coeffs = np.array(data.D)

def main():
Aruco()
rospy.spin()
if __name__ == '__main__':
main()

・ros-kineticとGazebo9をインストール
公式wikiを参考にros-kineticをインストール
ただし、Gazebo7は不安定なので、Gazebo9をインストールするようコマンドを修正(下リンク)
http://wiki.ros.org/ja/kinetic/Installation/Ubuntu
https://medium.com/@abhiksingla10/setting-up-ros-kinetic-and-gazebo-8-or-9-70f2231af21a

・catkin buildのインストール
catkin_makeよりもcatkin buildの方が良いらしいので、こちらを使う
https://qiita.com/harumo11/items/ae604ba2e17ffda529c2

・universal_robotを動かす
MoveIt! with a simulated robotの通りにプログラムを起動する
そして、rvizのMotionPlanning/Planning/Plan and Executeでuniversal robotを動かす
https://github.com/ros-industrial/universal_robot

・重要なこと
フェリがいないと勝てない
 →極力手札に残す。二枚目は絶対に切らない。
グレモリー、ギルは引いてこれる可能性が高いので、切っていく
 →手札にあるなしで、10ターン目までの動きは変わらず
10ターン目までに最低でも体力15以下にしておく
 →できれば10以下が望ましいが、ゴブリンorルリアがいれば15で大丈夫
盤面処理、体力回復の必要が無ければ、ギルネは伏せておく

・マリガン
両方:ケルベロス、ゴブリン、2コス22(ゴブファイ)
後攻:レディグレイ、悪意(ウィッチ、ビショは戻し)

・オシリス
リアニ、ドロソ、攻撃力4

↑このページのトップヘ