Skip to content

Commit

Permalink
近似长方形的机器人碰撞检测优化
Browse files Browse the repository at this point in the history
  • Loading branch information
wangzheng authored and Aglargil committed Jul 23, 2024
1 parent 33b0339 commit 1931dd8
Show file tree
Hide file tree
Showing 8 changed files with 267 additions and 20 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,7 @@ jobs:
restore-keys: |
mkdocs-material-
- run: pip install mkdocs-material
- run: pip install mkdocs-glightbox
- run: pip install mkdocs-rss-plugin
- run: pip install mkdocs-awesome-pages-plugin
- run: mkdocs gh-deploy --force
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,5 @@

# Custom rules (everything added below won't be overriden by 'Generate .gitignore File' if you use 'Update' option)

site/
site/
.cache/
4 changes: 4 additions & 0 deletions docs/.pages
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
nav:
- Home: index.md
- Blog: blog
- RSS: feed_rss_created.xml
2 changes: 2 additions & 0 deletions docs/blog/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Blog

164 changes: 164 additions & 0 deletions docs/blog/posts/近似长方形的机器人碰撞检测优化.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
---
date:
created: 2024-07-23
updated: 2024-07-23
categories:
- 机器人
---

# 近似长方形的机器人碰撞检测优化

机器人是多边形,用12个圆形覆盖这个contour
### 优化问题

- 优化变量:12个圆形的x, y, r
- 目标函数:所有圆的并集(union_area)不属于 contour 部分的面积最小
- 约束条件:
* bound: -1 < x < 1, -1 < y < 0, r > 0.05
* 所有圆的并集(union_area)和 contour的交集 (covered_area) 占 多边形的面积比大于**98%**

<!-- more -->

### 代码
```python linenums="1"
from scipy.optimize import minimize
from shapely.geometry import Point, Polygon
import matplotlib.pyplot as plt


# 定义多边形
polygon_coords = [
(0.177, 0),
(0.176, -0.0375),
(0.175, -0.075),
(0.165, -0.1125),
(0.155, -0.15),
(0.1335, -0.176),
(0.112, -0.202),
(0.06413, -0.202),
(0.01626, -0.202),
(-0.03161, -0.202),
(-0.07948, -0.202),
(-0.12735, -0.202),
(-0.17522, -0.202),
(-0.22309, -0.202),
(-0.27096, -0.202),
(-0.31883, -0.202),
(-0.3667, -0.202),
(-0.395, -0.1963),
(-0.4115, -0.1739),
(-0.428, -0.1515),
(-0.432925, -0.113625),
(-0.43785, -0.07575),
(-0.442775, -0.037875),
(-0.4477, 0),
(-0.442775, 0.037875),
(-0.43785, 0.07575),
(-0.432925, 0.113625),
(-0.428, 0.1515),
(-0.4115, 0.1739),
(-0.395, 0.1963),
(-0.3667, 0.202),
(-0.31883, 0.202),
(-0.27096, 0.202),
(-0.22309, 0.202),
(-0.17522, 0.202),
(-0.12735, 0.202),
(-0.07948, 0.202),
(-0.03161, 0.202),
(0.01626, 0.202),
(0.06413, 0.202),
(0.112, 0.202),
(0.1335, 0.176),
(0.155, 0.15),
(0.165, 0.1125),
(0.175, 0.075),
(0.176, 0.0375),
(0.177, 0),
]
polygon = Polygon(polygon_coords)
polygon_area = polygon.area
print("多边形面积:", polygon_area)

# 圆的数量
num_circles = 12 # 可以根据需要调整这个值

# 初始化猜测
xs = [-0.13, -0.13, -0.03, -0.03, -0.23, -0.23, 0.07, 0.07, -0.33, -0.33, -0.34, 0.07]
ys = [0.1, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1, -0.1, 0.1, -0.1, 0, 0]
rs = [0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.11, 0.11]
initial_guess = xs + ys + rs

# 边界条件
x_bounds = [(-1, 1) for _ in range(num_circles)]
y_bounds = [(-1, 1) for _ in range(num_circles)]
r_bounds = [(0.05, None) for _ in range(num_circles)]
bounds = x_bounds + y_bounds + r_bounds


# 定义目标函数
def objective(vars):
xs = vars[0:num_circles]
ys = vars[num_circles : 2 * num_circles]
rs = vars[2 * num_circles : 3 * num_circles]
circles = [Point(xs[i], ys[i]).buffer(rs[i]) for i in range(num_circles)]
union_area = circles[0]
sum_area = circles[0].area
for circle in circles[1:]:
sum_area += circle.area
union_area = union_area.union(circle)
return union_area.area - union_area.intersection(polygon).area


def coverage_constraint(vars):
xs = vars[0:num_circles]
ys = vars[num_circles : 2 * num_circles]
rs = vars[2 * num_circles : 3 * num_circles]
circles = [Point(xs[i], ys[i]).buffer(rs[i]) for i in range(num_circles)]
union_area = circles[0]
for circle in circles[1:]:
union_area = union_area.union(circle)
covered_area = union_area.intersection(polygon).area
return covered_area - 0.98 * polygon_area


# 约束条件
constraints = [
{"type": "ineq", "fun": coverage_constraint},
]


# 执行优化
result = minimize(
objective, initial_guess, method="SLSQP", bounds=bounds, constraints=constraints
)

# 解析结果
xs = result.x[0:num_circles]
ys = result.x[num_circles : 2 * num_circles]
rs = result.x[2 * num_circles : 3 * num_circles]

print("最优解:", result.fun)

# 绘制结果
fig, ax = plt.subplots()
for x, y, r in zip(xs, ys, rs):
print("x: ", x, "y: ", y, "r: ", r)
circle = plt.Circle((x, y), r, color="blue", fill=True, alpha=0.3)
ax.add_patch(circle)

x, y = polygon.exterior.xy
ax.plot(x, y, "r")
ax.set_xlim(-1, 1)
ax.set_ylim(-1, 1)
ax.set_aspect("equal")
plt.show()

```
### 结果
- 初始解
![初始解](https://picgo-1257309505.cos.ap-guangzhou.myqcloud.com/image.png)
- 最优解
![最优解](https://picgo-1257309505.cos.ap-guangzhou.myqcloud.com/20240723155012.png)

!!! note "初始解的选取很重要"
20 changes: 3 additions & 17 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,5 @@
# Welcome to MkDocs
# 欢迎来到AglarGil的个人博客

For full documentation visit [mkdocs.org](https://www.mkdocs.org).
!!! quote

## Commands

* `mkdocs new [dir-name]` - Create a new project.
* `mkdocs serve` - Start the live-reloading docs server.
* `mkdocs build` - Build the documentation site.
* `mkdocs -h` - Print help message and exit.

## Project layout

mkdocs.yml # The configuration file.
docs/
index.md # The documentation homepage.
... # Other markdown pages, images and other files.

I'm Wz
思绪来得快去得也快,偶尔会在这里停留 -- 云风
74 changes: 72 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,74 @@
site_name: My site
site_url: https://mydomain.org/mysite
site_description: Aglargil's Blog
site_name: Aglargil's Blog
site_url: https://aglargil.github.io/

repo_url: https://github.com/Aglargil/Aglargil.github.io
repo_name: Aglargil/Aglargil.github.io

theme:
name: material
custom_dir: overrides
features:
- content.code.copy
- content.code.select
- content.code.annotate
- navigation.instant
- navigation.tabs
- navigation.path
- navigation.top
- navigation.indexes
- toc.follow
language: zh
palette:
# Palette toggle for automatic mode
- media: "(prefers-color-scheme)"
toggle:
icon: material/brightness-auto
name: Switch to light mode

# Palette toggle for light mode
- media: "(prefers-color-scheme: light)"
scheme: default
toggle:
icon: material/brightness-7
name: Switch to dark mode

# Palette toggle for dark mode
- media: "(prefers-color-scheme: dark)"
scheme: slate
toggle:
icon: material/brightness-4
name: Switch to system preference

plugins:
- awesome-pages
- blog
- glightbox
- rss:
match_path: blog/posts/.*
abstract_chars_count: -1
date_from_meta:
as_creation: date.created
as_update: date.updated
categories:
- categories
- tags
- search

markdown_extensions:
- pymdownx.highlight:
anchor_linenums: true
line_spans: __span
pygments_lang_class: true
- pymdownx.inlinehilite
- pymdownx.snippets
- pymdownx.superfences
- pymdownx.details
- admonition
- attr_list
- md_in_html
- def_list
- pymdownx.tasklist:
custom_checkbox: true

copyright: 版权所有
17 changes: 17 additions & 0 deletions overrides/partials/comments.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<script src="https://giscus.app/client.js"
data-repo="Aglargil/Aglargil.github.io"
data-repo-id="R_kgDOH6FCzA"
data-category="Announcements"
data-category-id="DIC_kwDOH6FCzM4ChF5D"
data-mapping="pathname"
data-strict="0"
data-reactions-enabled="1"
data-emit-metadata="0"
data-input-position="top"
data-theme="preferred_color_scheme"
data-lang="zh-CN"
data-loading="lazy"
crossorigin="anonymous"
async>
</script>

0 comments on commit 1931dd8

Please sign in to comment.