Animating arrow
This commit is contained in:
@@ -22,6 +22,9 @@ ROBOT_COLOR_BGR = (0, 0, 255)
|
|||||||
ROBOT_HEIGHT = 16
|
ROBOT_HEIGHT = 16
|
||||||
ROBOT_WIDTH = 10
|
ROBOT_WIDTH = 10
|
||||||
|
|
||||||
|
ROBOT_HEIGHT_MM = 500
|
||||||
|
ROBOT_WIDTH_MM = 300
|
||||||
|
|
||||||
# Scan point display params
|
# Scan point display params
|
||||||
SCANPOINT_RADIUS = 1
|
SCANPOINT_RADIUS = 1
|
||||||
SCANPOINT_COLOR_BGR = (0, 255, 0)
|
SCANPOINT_COLOR_BGR = (0, 255, 0)
|
||||||
@@ -45,12 +48,19 @@ TRAJECTORY_COLOR_BGR = (255, 0, 0)
|
|||||||
|
|
||||||
import cv
|
import cv
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
|
import matplotlib.lines as lines
|
||||||
|
|
||||||
# Arbitrary font for OpenCV
|
# Arbitrary font for OpenCV
|
||||||
FONT_FACE = cv.CV_FONT_HERSHEY_COMPLEX
|
FONT_FACE = cv.CV_FONT_HERSHEY_COMPLEX
|
||||||
|
|
||||||
from math import sin, cos, radians
|
from math import sin, cos, radians
|
||||||
|
|
||||||
|
def _rotate(x, y, r, theta_deg):
|
||||||
|
theta = radians(theta_deg)
|
||||||
|
dx = r * cos(theta)
|
||||||
|
dy = r * sin(theta)
|
||||||
|
return x+dx, y+dy
|
||||||
|
|
||||||
class SlamShow(object):
|
class SlamShow(object):
|
||||||
|
|
||||||
def __init__(self, map_size_pixels, map_scale_mm_per_pixel, window_name):
|
def __init__(self, map_size_pixels, map_scale_mm_per_pixel, window_name):
|
||||||
@@ -106,26 +116,40 @@ class SlamShow(object):
|
|||||||
self.bgrbytes[1::3] = mapbytes
|
self.bgrbytes[1::3] = mapbytes
|
||||||
self.bgrbytes[2::3] = mapbytes
|
self.bgrbytes[2::3] = mapbytes
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# Put color bytes into image
|
# Put color bytes into image
|
||||||
cv.SetData(self.image, self.bgrbytes, self.map_size_pixels*3)
|
cv.SetData(self.image, self.bgrbytes, self.map_size_pixels*3)
|
||||||
|
|
||||||
|
|
||||||
def displayRobot(self, (x_mm, y_mm, theta_deg), color=ROBOT_COLOR_BGR, scale=1, line_thickness=1):
|
def displayRobot(self, (x_mm, y_mm, theta_deg), color=ROBOT_COLOR_BGR, scale=1, line_thickness=1):
|
||||||
|
|
||||||
|
# Use a very short arrow shaft to orient the head of the arrow
|
||||||
|
dx, dy = _rotate(0, 0, .1, theta_deg)
|
||||||
|
|
||||||
|
self.ax.arrow(x_mm, y_mm, dx, dy, head_width=ROBOT_WIDTH_MM, head_length=ROBOT_HEIGHT_MM, fc='r', ec='r')
|
||||||
|
|
||||||
# Get a polyline (e.g. triangle) to represent the robot icon
|
# Get a polyline (e.g. triangle) to represent the robot icon
|
||||||
robot_points = self.robot_polyline(scale)
|
robot_points = self.robot_polyline(scale)
|
||||||
|
|
||||||
# Rotate the polyline by the current angle
|
# Rotate the polyline by the current angle... would use rotate instead of this
|
||||||
robot_points = map(lambda pt: rotate(pt, theta_deg), robot_points)
|
robot_points = map(lambda pt: rotate(pt, theta_deg), robot_points)
|
||||||
|
|
||||||
# Convert the robot position from meters to pixels
|
# Convert the robot position from meters to pixels
|
||||||
x_pix, y_pix = self.mm2pix(x_mm), self.mm2pix(y_mm)
|
x_pix, y_pix = self.mm2pix(x_mm), self.mm2pix(y_mm)
|
||||||
|
|
||||||
# Move the polyline to the current robot position
|
# Move the polyline to the current robot position ... would use rotate instead of this?
|
||||||
robot_points = map(lambda pt: (x_pix+pt[0], y_pix+pt[1]), robot_points)
|
robot_points = map(lambda pt: (x_pix+pt[0], y_pix+pt[1]), robot_points)
|
||||||
|
|
||||||
# Add an icon for the robot
|
# Add an icon for the robot
|
||||||
cv.PolyLine(self.image, [robot_points], True, color, line_thickness)
|
cv.PolyLine(self.image, [robot_points], True, color, line_thickness)
|
||||||
|
|
||||||
|
# Use a very short arrow shaft to orient the head of the arrow
|
||||||
|
x = 0
|
||||||
|
y = 0
|
||||||
|
dx, dy = _rotate(x,y, .01, 0)
|
||||||
|
|
||||||
|
|
||||||
def displayScan(self, scan, offset_mm = (0,0), color=SCANPOINT_COLOR_BGR):
|
def displayScan(self, scan, offset_mm = (0,0), color=SCANPOINT_COLOR_BGR):
|
||||||
|
|
||||||
for point in scan:
|
for point in scan:
|
||||||
@@ -203,12 +227,24 @@ class SlamShow(object):
|
|||||||
# rightward and centered at (0,0).
|
# rightward and centered at (0,0).
|
||||||
# Currently builds an isoceles triangle pointing rightward
|
# Currently builds an isoceles triangle pointing rightward
|
||||||
def robot_polyline(self, scale):
|
def robot_polyline(self, scale):
|
||||||
|
|
||||||
|
dx = 500
|
||||||
|
dy = 500
|
||||||
|
|
||||||
xlft = -ROBOT_HEIGHT / 2 * scale
|
xlft = -ROBOT_HEIGHT / 2 * scale
|
||||||
xrgt = ROBOT_HEIGHT / 2 * scale
|
xrgt = ROBOT_HEIGHT / 2 * scale
|
||||||
ybot = ROBOT_WIDTH / 2 * scale
|
ybot = ROBOT_WIDTH / 2 * scale
|
||||||
ytop = -ROBOT_HEIGHT / 2 * scale
|
ytop = -ROBOT_HEIGHT / 2 * scale
|
||||||
return [(xlft,ybot), (xrgt,0), (xlft,ytop)]
|
return [(xlft,ybot), (xrgt,0), (xlft,ytop)]
|
||||||
|
|
||||||
|
#XXX possible solution to use lines instead of arrow?
|
||||||
|
def three_lines(self, pt1, pt2, pt3):
|
||||||
|
|
||||||
|
x1,y1 = pt1
|
||||||
|
x2,y2 = pt2
|
||||||
|
x3,y3 = pt3
|
||||||
|
|
||||||
|
|
||||||
# Converts millimeters to pixels
|
# Converts millimeters to pixels
|
||||||
def mm2pix(self, mm):
|
def mm2pix(self, mm):
|
||||||
return int(mm / float(self.map_scale_mm_per_pixel))
|
return int(mm / float(self.map_scale_mm_per_pixel))
|
||||||
|
|||||||
Reference in New Issue
Block a user