[2023-03-31] 3. RVIZ 오도메트리 활용
Odometry 오도메트리
-
오도미터 등의 기기의 측정값으로 움직이는 사물의 위치를 측정하는 방법
-
Odometer 오도미터
- 차량이나 로봇이 주행하며 이동한 거리를 측정한 거리
자동차 핸들과 앞 바퀴
- 앞 바퀴 2개의 회전시 꺾이는 각도가 다름
- 안쪽과 바깥쪽 회전 원의 중심이 일치해야 함
- Ackerman Steering(애커만 조향)
자동차의 위치 정보
\[현재\;위치 : (x,y) 좌표 + \Theta \\ 이동\;속도 : v + \omega \\ 조향각 : \delta\]RVIZ 기반 오도메트리 활용
-
Odometry 토픽
- /odom
-
메시지 타입 : nav_msgs/Odometry
$ rosmsg show nav_msgs/Odometry
-
odom_publisher_ex.py 작성
std_msgs/Header header
uint32 seq
time stamp
string frame_id
string child_frame_id
geometry_msgs/PoseWithCovariance pose
geometry_msgs/Pose pose
geometry_msgs/Point position # 물체의 3차원에서 x,y,z의 좌표
float64 x
float64 y
float64 z
geometry_msgs/Quaternion orientation # 롤,요,피치 대신 표현한 값(오일러 좌표계를 대신할 쿼터니언 좌표계)
float64 x
float64 y
float64 z
float64 w
float64[36] covariance
geometry_msgs/TwistWithCovariance twist
geometry_msgs/Twist twist
geometry_msgs/Vector3 linear # 선 속도
float64 x
float64 y
float64 z
geometry_msgs/Vector3 angular # 각 속도
float64 x
float64 y
float64 z
float64[36] covariance
-
odometry_publisher_ex.py
- odometry_publisher 노드를 생성하고 거기서 /odom 토픽을 1초에 한번씩 발행
X축, Y축, 이동 속도 벡터 계산
- 이동 속도 Vx, Vy
- Vx, Vy 값은 동일하게 초당 10cm
- 세타 각도 값은 0.1 라디안(5.7도)씩 꺾임
토픽 발행 파이썬 코드 odom_publisher_ex.py
- odom_publisher_ex.py 작성
#!/usr/bin/env python
import math
from math import sin, cos, pi
import rospy
import tf
from nav_msgs.msg import Odometry
from geometry_msgs.msg import Point, Pose, Quaternion, Twist, Vector3
# 노드 생성
rospy.init_node('odometry_publisher')
# 토픽 발행
odom_pub = rospy.Publisher("odom", Odometry, queue_size=50)
odom_broadcaster = tf.TransformBroadcaster()
# 초기 위치(0, 0, 0)
x = 0.0
y = 0.0
th = 0.0
# x축 속도 10cm/s, y축 속도 -10cm/s, 주행 방향 0.1라디안 (5.7도)
vx = 0.1
vy = -0.1
vth = 0.1
# 시간 정보 계산용 변수
current_time = rospy.Time.now()
last_time = rospy.Time.now()
# 1초에 한번씩 루프 돌기
r = rospy.Rate(1.0)
while not rospy.is_shutdown():
current_time = rospy.Time.now()
# compute odometry in a typical way given the velocities of the robot
dt = (current_time - last_time).to_sec()
delta_x = (vx * cos(th) - vy * sin(th)) * dt
delta_y = (vx * sin(th) + vy * cos(th)) * dt
delta_th = vth * dt
x += delta_x
y += delta_y
th += delta_th
# 오일러 값에서 쿼터니언 값을 계산해 냄
# since all odometry is 6DOF we'll need a quaternion created from yaw
odom_quat = tf.transformations.quaternion_from_euler(0, 0, th)
# 위치정보(자세정보)자에 대한 발행을 준비한다.
# odom과 base_link를 연결하는 효과
# first, we'll publish the transform over tf
odom_broadcaster.sendTransform(
(x, y, 0.),
odom_quat,
current_time,
"base_link",
"odom"
)
# Odometry 메시지의 헤더 만들기
# next, we'll publish the odometry message over ROS
odom = Odometry()
odom.header.stamp = current_time
odom.header.frame_id = "odom"
# Position 값 채우기
# set the position
odom.pose.pose = Pose(Point(x, y, 0.), Quaternion(*odom_quat))
# 속도값 채우기
# set the velocity
odom.child_frame_id = "base_link"
odom.twist.twist = Twist(Vector3(vx, vy, 0), Vector3(0, 0, vth))
# /odom 토픽 발행하기
# publish the message
odom_pub.publish(odom)
# 잠깐 쉬웠다가 루프 처음으로 되돌아감
last_time = current_time
r.sleep()
$ chmod +x odom_publisher_ex.py
$ roscore
$ rosrun ex_urdf odom_publisher_ex.py
$ rostopic list
$ rostopic info odom
-
$ rqt_graph
$ rosmsg show nav_msgs/Odometry
-
$ rostopic echo odom
$ rostopic list
$ rostopic info odom
$ rostopic show nav_msgs/Odometry
$ rqt_graph
$ rostopic echo odom
RVIZ 가상공간에서 물체 이동시키기
- 기존 ex_urdf 패키지를 이용
- odom_pub.launch 작성
<launch>
<arg name="model" />
<param name="robot_description" textfile="$(find ex_urdf)/urdf/pan_tilt.urdf" />
<!-- Setting gui parameter to true for display joint slider -->
<param name="use_gui" value="true"/>
<!-- Starting Joint state publisher node which will publish the joint values -->
<node name="joint_state_publisher" pkg="joint_state_publisher" type="joint_state_publisher" />
<!-- Starting robot state publish which will publish tf -->
<node name="robot_state_publisher" pkg="robot_state_publisher" type="state_publisher" />
<!-- Launch visualization in rviz -->
<node name="rviz" pkg="rviz" type="rviz" args="-d $(find ex_urdf)/urdf.rviz" required="True" />
<node name="odom_publisher" pkg="ex_urdf" type="odom_publisher_ex.py" />
</launch>
- 실행결과