Skip to content

FemPosSmoother

src.python_motion_planning.curve_generation.fem_pos_smooth.FemPosSmoother

Bases: Curve

Class for Fem-pos smoother.

Parameters:

Examples:

Python Console Session
>>> from python_motion_planning.curve_generation import FemPosSmoother
>>>     points = [(0, 0, 0), (10, 10, -90), (20, 5, 60)]
>>> generator = FemPosSmoother(w_smooth, w_length, w_ref, dx_l, dx_u, dy_l, dy_u)
>>> generator.run(points)
Source code in src\python_motion_planning\curve_generation\fem_pos_smooth.py
Python
class FemPosSmoother(Curve):
	"""
	Class for Fem-pos smoother.

	Parameters:

	Examples:
		>>> from python_motion_planning.curve_generation import FemPosSmoother
		>>>	points = [(0, 0, 0), (10, 10, -90), (20, 5, 60)]
		>>> generator = FemPosSmoother(w_smooth, w_length, w_ref, dx_l, dx_u, dy_l, dy_u)
		>>> generator.run(points)
	"""
	def __init__(self, w_smooth: float, w_length: float, w_ref: float,
		dx_l: float, dx_u: float, dy_l: float, dy_u: float) -> None:
		super().__init__(0.1)
		self.w_smooth = w_smooth
		self.w_length = w_length
		self.w_ref = w_ref
		self.dx_l = dx_l
		self.dx_u = dx_u
		self.dy_l = dy_l
		self.dy_u = dy_u

	def __str__(self) -> str:
		return "Fem-pos Smoother"

	def generation(self, start_pose: tuple, goal_pose: tuple):
		pass

	def run(self, points: list, display: bool = True):
		"""
		Running both generation and animation.

		Parameters:
			points (list[tuple]): path points
		"""
		assert len(points) >= 3, "Number of points should be at least 3."
		if len(points[0]) == 3:
			points = [(ix, iy) for ix, iy, _ in points]
		import matplotlib.pyplot as plt

		n = len(points)
		P = np.zeros((2 * n, 2 * n))

		X = np.eye(2) * self.w_smooth
		Y = np.eye(2) * self.w_length
		Z = np.eye(2) * self.w_ref

		P[0:2, 0:2] = X + Y + Z
		P[0:2, 2:4] = -2 * X - Y
		P[2:4, 2:4] = 5 * X + 2 * Y + Z
		P[2 * n - 2:2 * n, 2 * n - 2:2 * n] =  X + Y + Z
		P[2 * n - 4:2 * n - 2, 2 * n - 4:2 * n - 2] =  5 * X + 2 * Y + Z
		P[2 * n - 4:2 * n - 2, 2 * n - 2:2 * n] =  -2 * X - Y

		for i in range(2, n - 2):
			P[2 * i:2 * i + 2, 2 * i:2 * i + 2] = 6 * X + 2 * Y + Z
		for i in range(2, n - 1):
			P[2 * i - 2:2 * i, 2 * i:2 * i + 2] = -4 * X - Y
		for i in range(2, n):
			P[2 * i - 4:2 * i - 2, 2 * i:2 * i + 2] = X

		A_I = np.eye(2 * n)
		g = np.zeros((2 * n, 1))
		lower = np.zeros((2 * n, 1))
		upper = np.zeros((2 * n, 1))
		for i, p in enumerate(points):
			g[2 * i], g[2 * i + 1] = -2 * self.w_ref * p[0], -2 * self.w_ref * p[1]
			lower[2 * i], lower[2 * i + 1] = p[0] - self.dx_l, p[1] - self.dy_l
			upper[2 * i], upper[2 * i + 1] = p[0] + self.dx_u, p[1] + self.dy_u

		# solve
		solver = osqp.OSQP()
		solver.setup(sparse.csc_matrix(P), g, sparse.csc_matrix(A_I), lower, upper, verbose=False)
		res = solver.solve()
		opt = res.x

		path_x, path_y = [], []
		for i in range(n):
			path_x.append(opt[2 * i])
			path_y.append(opt[2 * i + 1])

		if display:
			plt.figure("curve generation")
			plt.plot(path_x, path_y, linewidth=2, c="#ff0000", marker="o", label="smooth path")
			raw_x, raw_y = [], []
			for i, (x, y) in enumerate(points):
				# label = "bounding box" if i == 0 else None
				# plt.gca().add_patch(
				# 	plt.Rectangle(xy=(x - self.dx_l, y - self.dy_l), width=self.dx_u + self.dx_l,
				# 	height=self.dy_u + self.dy_l, color='red', linestyle="--", fill=False, label=label)
				# )
				raw_x.append(x)
				raw_y.append(y)
			plt.plot(raw_x, raw_y, linewidth=2, c="#1f77b4", marker="x", label="raw path")
			# plt.axis("equal")
			plt.legend()
			plt.title(str(self))

			plt.show()

		return [(ix, iy) for (ix, iy) in zip(path_x, path_y)]

run(points, display=True)

Running both generation and animation.

Parameters:

Name Type Description Default
points list[tuple]

path points

required
Source code in src\python_motion_planning\curve_generation\fem_pos_smooth.py
Python
def run(self, points: list, display: bool = True):
	"""
	Running both generation and animation.

	Parameters:
		points (list[tuple]): path points
	"""
	assert len(points) >= 3, "Number of points should be at least 3."
	if len(points[0]) == 3:
		points = [(ix, iy) for ix, iy, _ in points]
	import matplotlib.pyplot as plt

	n = len(points)
	P = np.zeros((2 * n, 2 * n))

	X = np.eye(2) * self.w_smooth
	Y = np.eye(2) * self.w_length
	Z = np.eye(2) * self.w_ref

	P[0:2, 0:2] = X + Y + Z
	P[0:2, 2:4] = -2 * X - Y
	P[2:4, 2:4] = 5 * X + 2 * Y + Z
	P[2 * n - 2:2 * n, 2 * n - 2:2 * n] =  X + Y + Z
	P[2 * n - 4:2 * n - 2, 2 * n - 4:2 * n - 2] =  5 * X + 2 * Y + Z
	P[2 * n - 4:2 * n - 2, 2 * n - 2:2 * n] =  -2 * X - Y

	for i in range(2, n - 2):
		P[2 * i:2 * i + 2, 2 * i:2 * i + 2] = 6 * X + 2 * Y + Z
	for i in range(2, n - 1):
		P[2 * i - 2:2 * i, 2 * i:2 * i + 2] = -4 * X - Y
	for i in range(2, n):
		P[2 * i - 4:2 * i - 2, 2 * i:2 * i + 2] = X

	A_I = np.eye(2 * n)
	g = np.zeros((2 * n, 1))
	lower = np.zeros((2 * n, 1))
	upper = np.zeros((2 * n, 1))
	for i, p in enumerate(points):
		g[2 * i], g[2 * i + 1] = -2 * self.w_ref * p[0], -2 * self.w_ref * p[1]
		lower[2 * i], lower[2 * i + 1] = p[0] - self.dx_l, p[1] - self.dy_l
		upper[2 * i], upper[2 * i + 1] = p[0] + self.dx_u, p[1] + self.dy_u

	# solve
	solver = osqp.OSQP()
	solver.setup(sparse.csc_matrix(P), g, sparse.csc_matrix(A_I), lower, upper, verbose=False)
	res = solver.solve()
	opt = res.x

	path_x, path_y = [], []
	for i in range(n):
		path_x.append(opt[2 * i])
		path_y.append(opt[2 * i + 1])

	if display:
		plt.figure("curve generation")
		plt.plot(path_x, path_y, linewidth=2, c="#ff0000", marker="o", label="smooth path")
		raw_x, raw_y = [], []
		for i, (x, y) in enumerate(points):
			# label = "bounding box" if i == 0 else None
			# plt.gca().add_patch(
			# 	plt.Rectangle(xy=(x - self.dx_l, y - self.dy_l), width=self.dx_u + self.dx_l,
			# 	height=self.dy_u + self.dy_l, color='red', linestyle="--", fill=False, label=label)
			# )
			raw_x.append(x)
			raw_y.append(y)
		plt.plot(raw_x, raw_y, linewidth=2, c="#1f77b4", marker="x", label="raw path")
		# plt.axis("equal")
		plt.legend()
		plt.title(str(self))

		plt.show()

	return [(ix, iy) for (ix, iy) in zip(path_x, path_y)]