Add path simplification function
This commit is contained in:
17
Dockerfile
17
Dockerfile
@@ -25,19 +25,20 @@ RUN apt-get update && \
|
|||||||
apt-get install -yq python3-pil.imagetk && \
|
apt-get install -yq python3-pil.imagetk && \
|
||||||
apt-get install -yq ros-${ROS_DISTRO}-pilz-industrial-motion-planner && \
|
apt-get install -yq ros-${ROS_DISTRO}-pilz-industrial-motion-planner && \
|
||||||
apt-get install -yq tmux && \
|
apt-get install -yq tmux && \
|
||||||
|
apt-get install -yq python3-pip && \
|
||||||
apt-get install -yq ros-${ROS_DISTRO}-desktop && \
|
apt-get install -yq ros-${ROS_DISTRO}-desktop && \
|
||||||
apt-get install -yq ros-${ROS_DISTRO}-rclcpp-components
|
apt-get install -yq ros-${ROS_DISTRO}-rclcpp-components
|
||||||
|
|
||||||
### Install AxiDraw
|
### Install AxiDraw
|
||||||
RUN apt-get update && \
|
#RUN apt-get update && \
|
||||||
apt-get install -yq python3-pip && \
|
# apt-get install -yq python3-pip && \
|
||||||
pip install --upgrade --upgrade-strategy eager packaging && \
|
# pip install --upgrade --upgrade-strategy eager packaging && \
|
||||||
pip install https://cdn.evilmadscientist.com/dl/ad/public/AxiDraw_API.zip --upgrade --upgrade-strategy eager
|
# pip install https://cdn.evilmadscientist.com/dl/ad/public/AxiDraw_API.zip --upgrade --upgrade-strategy eager
|
||||||
|
|
||||||
### Install splipy
|
### Install splipy
|
||||||
RUN apt-get update && \
|
#RUN apt-get update && \
|
||||||
apt-get install -yq python3-pip && \
|
# apt-get install -yq python3-pip && \
|
||||||
pip install --upgrade --upgrade-strategy eager splipy
|
# pip install --upgrade --upgrade-strategy eager splipy
|
||||||
|
|
||||||
# Build interfaces and generic controller first
|
# Build interfaces and generic controller first
|
||||||
COPY ./src/robot_interfaces ${WS_SRC_DIR}/robot_interfaces
|
COPY ./src/robot_interfaces ${WS_SRC_DIR}/robot_interfaces
|
||||||
@@ -50,6 +51,8 @@ RUN source "/opt/ros/${ROS_DISTRO}/setup.bash" && \
|
|||||||
COPY ./src/draw_svg ${WS_SRC_DIR}/draw_svg
|
COPY ./src/draw_svg ${WS_SRC_DIR}/draw_svg
|
||||||
COPY ./src/drawing_controller ${WS_SRC_DIR}/drawing_controller
|
COPY ./src/drawing_controller ${WS_SRC_DIR}/drawing_controller
|
||||||
COPY ./src/axidraw_controller ${WS_SRC_DIR}/axidraw_controller
|
COPY ./src/axidraw_controller ${WS_SRC_DIR}/axidraw_controller
|
||||||
|
RUN pip install -r ${WS_SRC_DIR}/drawing_controller/requirements.txt
|
||||||
|
RUN pip install -r ${WS_SRC_DIR}/axidraw_controller/requirements.txt
|
||||||
RUN source "/opt/ros/${ROS_DISTRO}/setup.bash" && \
|
RUN source "/opt/ros/${ROS_DISTRO}/setup.bash" && \
|
||||||
source "${WS_INSTALL_DIR}/local_setup.bash" && \
|
source "${WS_INSTALL_DIR}/local_setup.bash" && \
|
||||||
colcon build --merge-install --symlink-install --cmake-args "-DCMAKE_BUILD_TYPE=Release" --paths ${WS_SRC_DIR}/draw_svg ${WS_SRC_DIR}/drawing_controller ${WS_SRC_DIR}/axidraw_controller && \
|
colcon build --merge-install --symlink-install --cmake-args "-DCMAKE_BUILD_TYPE=Release" --paths ${WS_SRC_DIR}/draw_svg ${WS_SRC_DIR}/drawing_controller ${WS_SRC_DIR}/axidraw_controller && \
|
||||||
|
|||||||
1
src/axidraw_controller/requirements.txt
Normal file
1
src/axidraw_controller/requirements.txt
Normal file
@@ -0,0 +1 @@
|
|||||||
|
axicli @ https://cdn.evilmadscientist.com/dl/ad/public/AxiDraw_API.zip
|
||||||
@@ -4,6 +4,7 @@ import lxml.etree as ET
|
|||||||
import splipy.curve_factory as cf
|
import splipy.curve_factory as cf
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import math
|
import math
|
||||||
|
import simplification.cutil
|
||||||
|
|
||||||
class SVGProcessor():
|
class SVGProcessor():
|
||||||
"""
|
"""
|
||||||
@@ -117,8 +118,8 @@ class SVGProcessor():
|
|||||||
# Numbers
|
# Numbers
|
||||||
if c == '+' or c == '-' or c.isdecimal():
|
if c == '+' or c == '-' or c.isdecimal():
|
||||||
s = c
|
s = c
|
||||||
isdelim = lambda x: x.isspace() or x == ',' or x.isalpha() or x == '+'
|
isdelim = lambda x: x.isspace() or x.isalpha() or x in [',', '+']
|
||||||
while i < len(pathstr) and (not (isdelim(c) or c == '-')):
|
while i < len(pathstr) and not isdelim(c):
|
||||||
c = pathstr[i]
|
c = pathstr[i]
|
||||||
if not isdelim(c):
|
if not isdelim(c):
|
||||||
s = s + c
|
s = s + c
|
||||||
@@ -139,7 +140,6 @@ class SVGProcessor():
|
|||||||
return float(path[i])
|
return float(path[i])
|
||||||
|
|
||||||
def isfloat(element):
|
def isfloat(element):
|
||||||
#If you expect None to be passed:
|
|
||||||
if element is None:
|
if element is None:
|
||||||
return False
|
return False
|
||||||
try:
|
try:
|
||||||
@@ -255,13 +255,15 @@ class SVGProcessor():
|
|||||||
control_points = np.array(control_points)
|
control_points = np.array(control_points)
|
||||||
maxval = np.amax(np.absolute(control_points))
|
maxval = np.amax(np.absolute(control_points))
|
||||||
control_points = control_points / maxval #normalize values
|
control_points = control_points / maxval #normalize values
|
||||||
n = 50
|
n = 500
|
||||||
curve = cf.cubic_curve(control_points)
|
curve = cf.cubic_curve(control_points)
|
||||||
lin = np.linspace(curve.start(0), curve.end(0), n)
|
lin = np.linspace(curve.start(0), curve.end(0), n)
|
||||||
coordinates = curve(lin)
|
coordinates = curve(lin)
|
||||||
coordinates = np.nan_to_num(coordinates)
|
coordinates = np.nan_to_num(coordinates)
|
||||||
coordinates = coordinates * maxval #denormalize values
|
coordinates = coordinates * maxval #denormalize values
|
||||||
#self.logger.info("Appending curve points: {}".format(coordinates))
|
#self.logger.info("Appending curve points: {}".format(coordinates))
|
||||||
|
#print(coordinates)
|
||||||
|
#input()
|
||||||
x = coordinates[-1][0]
|
x = coordinates[-1][0]
|
||||||
y = coordinates[-1][1]
|
y = coordinates[-1][1]
|
||||||
appendpoints(coordinates)
|
appendpoints(coordinates)
|
||||||
@@ -382,6 +384,10 @@ class SVGProcessor():
|
|||||||
|
|
||||||
mm = self.remove_homes(m)
|
mm = self.remove_homes(m)
|
||||||
mm = self.remove_redundant(mm)
|
mm = self.remove_redundant(mm)
|
||||||
|
#print('before:', len(mm))
|
||||||
|
mm = self.simplify(mm)
|
||||||
|
#print('after:', len(mm))
|
||||||
|
#input()
|
||||||
|
|
||||||
#self.logger.info("Refining:'{}...'".format(m[:3]))
|
#self.logger.info("Refining:'{}...'".format(m[:3]))
|
||||||
motions_refined.append(self.down_and_up(mm))
|
motions_refined.append(self.down_and_up(mm))
|
||||||
@@ -420,6 +426,33 @@ class SVGProcessor():
|
|||||||
mm.append(p)
|
mm.append(p)
|
||||||
return mm
|
return mm
|
||||||
|
|
||||||
|
def simplify(self, motion):
|
||||||
|
"""
|
||||||
|
Simplify line with https://pypi.org/project/simplification/
|
||||||
|
"""
|
||||||
|
# For RDP, Try an epsilon of 1.0 to start with. Other sensible values include 0.01, 0.001
|
||||||
|
epsilon = 0.0001
|
||||||
|
|
||||||
|
tmp = []
|
||||||
|
out = []
|
||||||
|
lastup = True
|
||||||
|
sf = lambda l: [ (p[0],p[1],0.0) for p in simplification.cutil.simplify_coords(l, epsilon) ]
|
||||||
|
for p in motion:
|
||||||
|
penup = p[2] > 0
|
||||||
|
if penup and not lastup:
|
||||||
|
out += sf(tmp)
|
||||||
|
tmp = []
|
||||||
|
if penup:
|
||||||
|
out.append(p)
|
||||||
|
else:
|
||||||
|
tmp.append(list(p)[:-1])
|
||||||
|
lastup = penup
|
||||||
|
|
||||||
|
if (len(tmp) > 0):
|
||||||
|
out += sf(tmp)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
def translate(self, val, lmin, lmax, rmin, rmax):
|
def translate(self, val, lmin, lmax, rmin, rmax):
|
||||||
lspan = lmax - lmin
|
lspan = lmax - lmin
|
||||||
rspan = rmax - rmin
|
rspan = rmax - rmin
|
||||||
|
|||||||
4
src/drawing_controller/requirements.txt
Normal file
4
src/drawing_controller/requirements.txt
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
lxml==4.9.2
|
||||||
|
numpy==1.24.2
|
||||||
|
Splipy==1.6.0
|
||||||
|
simplification==0.6.2
|
||||||
Reference in New Issue
Block a user