diff --git a/src/无人机端代码/.gitignore b/src/无人机端代码/.gitignore
deleted file mode 100644
index 56481e16..00000000
--- a/src/无人机端代码/.gitignore
+++ /dev/null
@@ -1,44 +0,0 @@
-# compilation and distribution
-__pycache__
-_ext
-*.pyc
-nano.save
-.catkin_workspace
-
-build/
-devel/
-dist/
-.vscode/
-Modules/object_detection_landing/
-Modules/object_detection_persistence/
-Modules/object_detection_yolov5openvino/
-Modules/object_detection_yolov5tensorrt/
-Modules/object_detection_circlex/
-Modules/data/
-Modules/object_detection_oneshot/
-
-
-# pytorch/python/numpy formats
-# *.pth
-*.pkl
-*.npy
-
-# ipython/jupyter notebooks
-*.ipynb
-**/.ipynb_checkpoints/
-
-# Editor temporaries
-*.swn
-*.swo
-*.swp
-*~
-
-# Pycharm editor settings
-.idea
-
-# project dirs
-/datasets
-/models
-
-ORBvoc.txt
-
diff --git a/src/无人机端代码/.gitmodules b/src/无人机端代码/.gitmodules
deleted file mode 100644
index 36ec78b3..00000000
--- a/src/无人机端代码/.gitmodules
+++ /dev/null
@@ -1,6 +0,0 @@
-[submodule "Modules/swarm_control"]
- path = Modules/swarm_control
- url = https://gitee.com/amovlab/swarm_control.git
-[submodule "Modules/matlab_bridge"]
- path = Modules/matlab_bridge
- url = https://gitee.com/amovlab1/matlab_bridge.git
diff --git a/src/无人机端代码/Experiment/CMakeLists.txt b/src/无人机端代码/Experiment/CMakeLists.txt
deleted file mode 100644
index bd32d374..00000000
--- a/src/无人机端代码/Experiment/CMakeLists.txt
+++ /dev/null
@@ -1,118 +0,0 @@
-cmake_minimum_required(VERSION 2.8.3)
-project(prometheus_experiment)
-
-## Compile as C++11, supported in ROS Kinetic and newer
-# add_compile_options(-std=c++11)
-
-## Find catkin macros and libraries
-## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
-## is used, also find other catkin packages
-find_package(catkin REQUIRED COMPONENTS
- message_generation
- roscpp
- geometry_msgs
- nav_msgs
- sensor_msgs
- mavros
- std_msgs
- std_srvs
- tf2_ros
- tf2_eigen
- mavros_msgs
- prometheus_msgs
-)
-
-## System dependencies are found with CMake's conventions
-find_package(Boost REQUIRED COMPONENTS system)
-
-
-
-################################################
-## Declare ROS messages, services and actions ##
-################################################
-
-## Generate added messages and services with any dependencies listed here
-generate_messages(
- DEPENDENCIES
- geometry_msgs
- nav_msgs
- sensor_msgs
- std_msgs
-)
-
-
-
-###########
-## Build ##
-###########
-
-## Specify additional locations of header files
-## Your package locations should be listed before other locations
-include_directories(
- include
- ${catkin_INCLUDE_DIRS}
-)
-
-
-###############################
-## 声明可执行cpp文件 ##
-###############################
-
-###### Main File ##########
-
-##px4_pos_controller.cpp
-#add_executable(px4_pos_controller src/px4_pos_controller.cpp)
-#add_dependencies(px4_pos_controller prometheus_control_gencpp)
-#target_link_libraries(px4_pos_controller ${catkin_LIBRARIES})
-
-#############
-## Install ##
-#############
-
-# all install targets should use catkin DESTINATION variables
-# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
-
-## Mark executable scripts (Python etc.) for installation
-## in contrast to setup.py, you can choose the destination
-# install(PROGRAMS
-# scripts/my_python_script
-# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-# )
-
-## Mark executables and/or libraries for installation
-# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
-# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
-# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
-# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-# )
-
-## Mark cpp header files for installation
-# install(DIRECTORY include/${PROJECT_NAME}/
-# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
-# FILES_MATCHING PATTERN "*.h"
-# PATTERN ".svn" EXCLUDE
-# )
-
-## Mark cpp header files for installation
-install(DIRECTORY include/${PROJECT_NAME}/
- DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
- FILES_MATCHING PATTERN "*.h"
-)
-
-## Mark other files for installation (e.g. launch and bag files, etc.)
-install(DIRECTORY launch/
- DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
-)
-
-#############
-## Testing ##
-#############
-
-## Add gtest based cpp test target and link libraries
-# catkin_add_gtest(${PROJECT_NAME}-test test/test_prometheus_control.cpp)
-# if(TARGET ${PROJECT_NAME}-test)
-# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
-# endif()
-
-## Add folders to be run by python nosetests
-# catkin_add_nosetests(test)
diff --git a/src/无人机端代码/Experiment/config/px4_config.yaml b/src/无人机端代码/Experiment/config/px4_config.yaml
deleted file mode 100644
index d9fd0eee..00000000
--- a/src/无人机端代码/Experiment/config/px4_config.yaml
+++ /dev/null
@@ -1,260 +0,0 @@
-# Common configuration for PX4 autopilot
-#
-# node:
-startup_px4_usb_quirk: true
-
-# --- system plugins ---
-
-# sys_status & sys_time connection options
-conn:
- heartbeat_rate: 1.0 # send hertbeat rate in Hertz
- timeout: 10.0 # hertbeat timeout in seconds
- timesync_rate: 10.0 # TIMESYNC rate in Hertz (feature disabled if 0.0)
- system_time_rate: 1.0 # send system time to FCU rate in Hertz (disabled if 0.0)
-
-# sys_status
-sys:
- min_voltage: 10.0 # diagnostics min voltage
- disable_diag: false # disable all sys_status diagnostics, except heartbeat
-
-# sys_time
-time:
- time_ref_source: "fcu" # time_reference source
- timesync_mode: MAVLINK
- timesync_avg_alpha: 0.6 # timesync averaging factor
-
-# --- mavros plugins (alphabetical order) ---
-
-# 3dr_radio
-tdr_radio:
- low_rssi: 40 # raw rssi lower level for diagnostics
-
-# actuator_control
-# None
-
-# command
-cmd:
- use_comp_id_system_control: false # quirk for some old FCUs
-
-# dummy
-# None
-
-# ftp
-# None
-
-# global_position
-global_position:
- frame_id: "map" # origin frame
- child_frame_id: "base_link" # body-fixed frame
- rot_covariance: 99999.0 # covariance for attitude?
- gps_uere: 1.0 # User Equivalent Range Error (UERE) of GPS sensor (m)
- use_relative_alt: true # use relative altitude for local coordinates
- tf:
- send: false # send TF?
- frame_id: "map" # TF frame_id
- global_frame_id: "earth" # TF earth frame_id
- child_frame_id: "base_link" # TF child_frame_id
-
-# imu_pub
-imu:
- frame_id: "base_link"
- # need find actual values
- linear_acceleration_stdev: 0.0003
- angular_velocity_stdev: 0.0003490659 // 0.02 degrees
- orientation_stdev: 1.0
- magnetic_stdev: 0.0
-
-# local_position
-local_position:
- frame_id: "world"
- tf:
- send: true
- frame_id: "world"
- child_frame_id: "base_link"
- send_fcu: false
-
-# param
-# None, used for FCU params
-
-# rc_io
-# None
-
-# safety_area
-safety_area:
- p1: {x: 1.0, y: 1.0, z: 1.0}
- p2: {x: -1.0, y: -1.0, z: -1.0}
-
-# setpoint_accel
-setpoint_accel:
- send_force: false
-
-# setpoint_attitude
-setpoint_attitude:
- reverse_thrust: false # allow reversed thrust
- use_quaternion: false # enable PoseStamped topic subscriber
- tf:
- listen: false # enable tf listener (disable topic subscribers)
- frame_id: "map"
- child_frame_id: "target_attitude"
- rate_limit: 50.0
-
-setpoint_raw:
- thrust_scaling: 1.0 # used in setpoint_raw attitude callback.
- # Note: PX4 expects normalized thrust values between 0 and 1, which means that
- # the scaling needs to be unitary and the inputs should be 0..1 as well.
-
-# setpoint_position
-setpoint_position:
- tf:
- listen: false # enable tf listener (disable topic subscribers)
- frame_id: "map"
- child_frame_id: "target_position"
- rate_limit: 50.0
- mav_frame: LOCAL_NED
-
-# setpoint_velocity
-setpoint_velocity:
- mav_frame: LOCAL_NED
-
-# vfr_hud
-# None
-
-# waypoint
-mission:
- pull_after_gcs: true # update mission if gcs updates
-
-# --- mavros extras plugins (same order) ---
-
-# adsb
-# None
-
-# debug_value
-# None
-
-# distance_sensor
-## Currently available orientations:
-# Check http://wiki.ros.org/mavros/Enumerations
-##
-distance_sensor:
- hrlv_ez4_pub:
- id: 0
- frame_id: "hrlv_ez4_sonar"
- orientation: PITCH_270 # RPY:{0.0, 270.0, 0.0} - downward-facing
- field_of_view: 0.0 # XXX TODO
- send_tf: true
- sensor_position: {x: 0.0, y: 0.0, z: -0.1}
- lidarlite_pub:
- id: 1
- frame_id: "lidarlite_laser"
- orientation: PITCH_270
- field_of_view: 0.0 # XXX TODO
- send_tf: true
- sensor_position: {x: 0.0, y: 0.0, z: -0.1}
- sonar_1_sub:
- subscriber: true
- id: 2
- orientation: PITCH_270
- laser_1_sub:
- subscriber: true
- id: 3
- orientation: PITCH_270
-
-# image_pub
-image:
- frame_id: "px4flow"
-
-# fake_gps
-fake_gps:
- # select data source
- use_mocap: true # ~mocap/pose
- mocap_transform: true # ~mocap/tf instead of pose
- use_vision: false # ~vision (pose)
- # origin (default: Zürich)
- geo_origin:
- lat: 47.3667 # latitude [degrees]
- lon: 8.5500 # longitude [degrees]
- alt: 408.0 # altitude (height over the WGS-84 ellipsoid) [meters]
- eph: 2.0
- epv: 2.0
- satellites_visible: 5 # virtual number of visible satellites
- fix_type: 3 # type of GPS fix (default: 3D)
- tf:
- listen: false
- send: false # send TF?
- frame_id: "map" # TF frame_id
- child_frame_id: "fix" # TF child_frame_id
- rate_limit: 10.0 # TF rate
- gps_rate: 5.0 # GPS data publishing rate
-
-# landing_target
-landing_target:
- listen_lt: false
- mav_frame: "LOCAL_NED"
- land_target_type: "VISION_FIDUCIAL"
- image:
- width: 640 # [pixels]
- height: 480
- camera:
- fov_x: 2.0071286398 # default: 115 [degrees]
- fov_y: 2.0071286398
- tf:
- send: true
- listen: false
- frame_id: "landing_target"
- child_frame_id: "camera_center"
- rate_limit: 10.0
- target_size: {x: 0.3, y: 0.3}
-
-# mocap_pose_estimate
-mocap:
- # select mocap source
- use_tf: false # ~mocap/tf
- use_pose: true # ~mocap/pose
-
-# odom
-odometry:
- fcu:
- odom_parent_id_des: "map" # desired parent frame rotation of the FCU's odometry
- odom_child_id_des: "base_link" # desired child frame rotation of the FCU's odometry
-
-# px4flow
-px4flow:
- frame_id: "px4flow"
- ranger_fov: 0.118682 # 6.8 degrees at 5 meters, 31 degrees at 1 meter
- ranger_min_range: 0.3 # meters
- ranger_max_range: 5.0 # meters
-
-# vision_pose_estimate
-vision_pose:
- tf:
- listen: false # enable tf listener (disable topic subscribers)
- frame_id: "map"
- child_frame_id: "vision_estimate"
- rate_limit: 10.0
-
-# vision_speed_estimate
-vision_speed:
- listen_twist: true # enable listen to twist topic, else listen to vec3d topic
- twist_cov: true # enable listen to twist with covariance topic
-
-# vibration
-vibration:
- frame_id: "base_link"
-
-# wheel_odometry
-wheel_odometry:
- count: 2 # number of wheels to compute odometry
- use_rpm: false # use wheel's RPM instead of cumulative distance to compute odometry
- wheel0: {x: 0.0, y: -0.15, radius: 0.05} # x-, y-offset (m,NED) and radius (m)
- wheel1: {x: 0.0, y: 0.15, radius: 0.05} # x-, y-offset (m,NED) and radius (m)
- send_raw: true # send wheel's RPM and cumulative distance (~/wheel_odometry/rpm, ~/wheel_odometry/distance)
- send_twist: false # send geometry_msgs/TwistWithCovarianceStamped instead of nav_msgs/Odometry
- frame_id: "map" # origin frame
- child_frame_id: "base_link" # body-fixed frame
- vel_error: 0.1 # wheel velocity measurement error 1-std (m/s)
- tf:
- send: false
- frame_id: "map"
- child_frame_id: "base_link"
-
-# vim:set ts=2 sw=2 et:
diff --git a/src/无人机端代码/Experiment/config/px4_pluginlists.yaml b/src/无人机端代码/Experiment/config/px4_pluginlists.yaml
deleted file mode 100644
index 145d2629..00000000
--- a/src/无人机端代码/Experiment/config/px4_pluginlists.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
-plugin_blacklist:
-- actuator_control
-- adsb
-- safety_area
-- 3dr_radio
-- cam_imu_sync
-- altitude
-- distance_sensor
-- fake_gps
-- gps_rtk
-- hil
-- home_position
-- landing_target
-- mocap_pose_estimate
-- mount_control
-- obstacle_distance
-- rc_io
-- vfr_hud
-- waypoint
-- wind_estimation
-- px4flow
-- global_position
-- companion_process_status
-- debug_value
-- wheel_odometry
-- vibration
-- odom
-- setpoint_attitude
-- setpoint_position
-- setpoint_accel
-- setpoint_velocity
-plugin_whitelist: []
-#- 'sys_*'
\ No newline at end of file
diff --git a/src/无人机端代码/Experiment/config/uav_control_indoor.yaml b/src/无人机端代码/Experiment/config/uav_control_indoor.yaml
deleted file mode 100644
index 4e751727..00000000
--- a/src/无人机端代码/Experiment/config/uav_control_indoor.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
-## parameter for uav_control
-
-control:
- ## 控制器编号:0 for PX4_ORIGIN, 1 for PID, 2 for UDE, 3 for NE
- pos_controller : 0
- # 是否支持外部控制
- enable_external_control : false
- ## 起飞高度
- Takeoff_height : 1.5
- ## 降落速度
- Land_speed : 0.2
- ## 上锁高度
- Disarm_height : 0.1
- ## 定位源: 0 for MOCAP, 1 for T265, 2 for GAZEBO, 3 for FAKE_ODOM, 4 for GPS, 5 for RTK, 6 for UWB
- location_source : 2
- ## 最大安全速度
- maximum_safe_vel_xy : 2.0
- maximum_safe_vel_z : 1.5
- ## 最大vision/px4速度误差
- maximum_vel_error_for_vision : 1.0
-
-## 地理围栏
-geo_fence:
- x_min: -100.0
- x_max: 100.0
- y_min: -100.0
- y_max: 100.0
- z_min: -0.5
- z_max: 100.0
diff --git a/src/无人机端代码/Experiment/launch/prometheus_experiment.launch b/src/无人机端代码/Experiment/launch/prometheus_experiment.launch
deleted file mode 100644
index 831b026a..00000000
--- a/src/无人机端代码/Experiment/launch/prometheus_experiment.launch
+++ /dev/null
@@ -1,34 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/src/无人机端代码/Experiment/package.xml b/src/无人机端代码/Experiment/package.xml
deleted file mode 100644
index de76d1d5..00000000
--- a/src/无人机端代码/Experiment/package.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
- prometheus_experiment
- 0.0.0
- The prometheus_experiment package
-
-
- Yuhua Qi
- Yuhua Qi
- TODO
-
- https://www.amovlab.com
- https://github.com/potato77/prometheus_experiment.git
-
- message_generation
- message_runtime
-
- catkin
- std_msgs
- std_msgs
- std_msgs
-
-
-
-
-
-
-
-
diff --git a/src/无人机端代码/LICENSE b/src/无人机端代码/LICENSE
deleted file mode 100644
index 7a61a724..00000000
--- a/src/无人机端代码/LICENSE
+++ /dev/null
@@ -1,60 +0,0 @@
-Apache License
-Version 2.0, January 2004
-http://www.apache.org/licenses/
-
-TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
-1. Definitions.
-
-"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
-
-"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
-
-"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
-
-"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
-
-"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
-
-"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
-
-"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
-
-"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
-
-"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
-
-"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
-
-2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
-
-3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
-
-4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
-
- a.You must give any other recipients of the Work or Derivative Works a copy of this License; and
- b.You must cause any modified files to carry prominent notices stating that You changed the files; and
- c.You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
- d.If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
-
- You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
-
-5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
-
-6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
-
-7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
-
-8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
-
-9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
-
-END OF TERMS AND CONDITIONS
-
-Copyright 2022 AMOVLAB
-
-Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
-
-http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/future_aircraft/CMakeLists.txt b/src/无人机端代码/Modules/future_aircraft/CMakeLists.txt
deleted file mode 100644
index 4898dbc5..00000000
--- a/src/无人机端代码/Modules/future_aircraft/CMakeLists.txt
+++ /dev/null
@@ -1,145 +0,0 @@
-cmake_minimum_required(VERSION 2.8.3)
-project(prometheus_future_aircraft)
-
-## Compile as C++11, supported in ROS Kinetic and newer
-# add_compile_options(-std=c++11)
-add_compile_options(-std=c++17)
-
-## Find catkin macros and libraries
-## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
-## is used, also find other catkin packages
-find_package(OpenCV REQUIRED)
-find_package(catkin REQUIRED COMPONENTS
- message_generation
- roscpp
- rospy
- geometry_msgs
- sensor_msgs
- mavros
- nav_msgs
- std_msgs
- std_srvs
- tf2_ros
- tf2_eigen
- mavros_msgs
- prometheus_msgs
- cv_bridge
- image_transport
-)
-
-## System dependencies are found with CMake's conventions
-find_package(Boost REQUIRED COMPONENTS system)
-
-
-################################################
-## Declare ROS messages, services and actions ##
-################################################
-
-## Generate added messages and services with any dependencies listed here
-generate_messages(
- DEPENDENCIES
- geometry_msgs
- sensor_msgs
- std_msgs
-)
-
-catkin_package(
- CATKIN_DEPENDS message_runtime
-)
-
-
-###########
-## Build ##
-###########
-
-## Specify additional locations of header files
-## Your package locations should be listed before other locations
-include_directories(
- include ../tutorial_demo/advanced/autonomous_landing/include
- ${catkin_INCLUDE_DIRS}
- ../common/include
-)
-
-
-###############################
-## 声明可执行cpp文件 ##
-###############################
-# add_executable(autonomous_landing autonomous_landing/autonomous_landing.cpp)
-# target_link_libraries(autonomous_landing ${catkin_LIBRARIES})
-
-#add_executable(waypoint_tracking waypoint_tracking/waypoint_tracking.cpp)
-#target_link_libraries(waypoint_tracking ${catkin_LIBRARIES})
-
-#add_executable(object_tracking object_tracking/object_tracking.cpp)
-#target_link_libraries(object_tracking ${catkin_LIBRARIES})
-
-#add_executable(takeoff takeoff/takeoff.cpp)
-#target_link_libraries(takeoff ${catkin_LIBRARIES})
-
-#add_executable(formation_control formation_control/formation_control.cpp)
-#target_link_libraries(formation_control ${catkin_LIBRARIES})
-add_executable(future_aircraft src/future_aircraft.cpp)
-target_link_libraries(future_aircraft ${catkin_LIBRARIES})
-
-add_executable(ellipse_det
- src/ellipse_det.cpp
- src/ellipse_detector/ellipse_detector.cpp
-)
-target_include_directories(ellipse_det PUBLIC
- src/ellipse_detector/
-)
-target_link_libraries(ellipse_det ${catkin_LIBRARIES} ${OpenCV_LIBS} yaml-cpp)
-
-
-#############
-## Install ##
-#############
-
-# all install targets should use catkin DESTINATION variables
-# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
-
-## Mark executable scripts (Python etc.) for installation
-## in contrast to setup.py, you can choose the destination
-install(PROGRAMS
- scripts/locus.py
- DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-)
-
-## Mark executables and/or libraries for installation
-# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
-# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
-# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
-# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
-# )
-
-## Mark cpp header files for installation
-# install(DIRECTORY include/${PROJECT_NAME}/
-# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
-# FILES_MATCHING PATTERN "*.h"
-# PATTERN ".svn" EXCLUDE
-# )
-
-## Mark cpp header files for installation
-install(DIRECTORY include/${PROJECT_NAME}/
- DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
- FILES_MATCHING PATTERN "*.h"
-)
-
-## Mark other files for installation (e.g. launch and bag files, etc.)
-install(DIRECTORY launch/
- DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
-)
-
-#############
-## Testing ##
-#############
-
-
-## Add gtest based cpp test target and link libraries
-# catkin_add_gtest(${PROJECT_NAME}-test test/test_prometheus_demo.cpp)
-# if(TARGET ${PROJECT_NAME}-test)
-# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
-# endif()
-
-## Add folders to be run by python nosetests
-# catkin_add_nosetests(test)
diff --git a/src/无人机端代码/Modules/future_aircraft/conf/calib.yaml b/src/无人机端代码/Modules/future_aircraft/conf/calib.yaml
deleted file mode 100644
index eb2442d5..00000000
--- a/src/无人机端代码/Modules/future_aircraft/conf/calib.yaml
+++ /dev/null
@@ -1,20 +0,0 @@
-%YAML:1.0
----
-calibration_time: "Thu 14 Jul 2022 11:46:13 AM CST"
-image_width: 640
-image_height: 480
-flags: 0
-camera_matrix: !!opencv-matrix
- rows: 3
- cols: 3
- dt: d
- data: [ 6.7570491275428003e+02, 0., 3.4702214961185257e+02, 0.,
- 6.7652907115648509e+02, 2.5917548194106814e+02, 0., 0., 1. ]
-distortion_coefficients: !!opencv-matrix
- rows: 1
- cols: 5
- dt: d
- data: [ -4.3154114726977300e-01, 2.7199122166782413e-01,
- -1.5471282947090615e-03, -6.6196646287719843e-04,
- -4.9889322933567892e-01 ]
-avg_reprojection_error: 4.7592643246496424e-01
diff --git a/src/无人机端代码/Modules/future_aircraft/conf/calib_sitl.yaml b/src/无人机端代码/Modules/future_aircraft/conf/calib_sitl.yaml
deleted file mode 100644
index 58c2ff5a..00000000
--- a/src/无人机端代码/Modules/future_aircraft/conf/calib_sitl.yaml
+++ /dev/null
@@ -1,17 +0,0 @@
-%YAML:1.0
----
-calibration_time: "Thu 14 Jul 2022 11:46:13 AM CST"
-image_width: 640
-image_height: 480
-flags: 0
-camera_matrix: !!opencv-matrix
- rows: 3
- cols: 3
- dt: d
- data: [369.502083, 0.0, 640.0, 0.0, 369.502083, 360.0, 0.0, 0.0, 1.0]
-distortion_coefficients: !!opencv-matrix
- rows: 1
- cols: 5
- dt: d
- data: [0,0,0,0,0]
-avg_reprojection_error: 4.7592643246496424e-01
diff --git a/src/无人机端代码/Modules/future_aircraft/launch/future_aircraft.launch b/src/无人机端代码/Modules/future_aircraft/launch/future_aircraft.launch
deleted file mode 100644
index ede28625..00000000
--- a/src/无人机端代码/Modules/future_aircraft/launch/future_aircraft.launch
+++ /dev/null
@@ -1,22 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/future_aircraft/launch/test.launch b/src/无人机端代码/Modules/future_aircraft/launch/test.launch
deleted file mode 100644
index ef4d0877..00000000
--- a/src/无人机端代码/Modules/future_aircraft/launch/test.launch
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/future_aircraft/package.xml b/src/无人机端代码/Modules/future_aircraft/package.xml
deleted file mode 100644
index e7fa468f..00000000
--- a/src/无人机端代码/Modules/future_aircraft/package.xml
+++ /dev/null
@@ -1,21 +0,0 @@
-
-
- prometheus_future_aircraft
- 0.0.0
- The prometheus_demo package
-
- Yuhua Qi
-
- TODO
-
- message_generation
- message_runtime
- catkin
- std_msgs
- std_msgs
- std_msgs
-
-
-
-
-
diff --git a/src/无人机端代码/Modules/future_aircraft/readme.md b/src/无人机端代码/Modules/future_aircraft/readme.md
deleted file mode 100644
index 34e96243..00000000
--- a/src/无人机端代码/Modules/future_aircraft/readme.md
+++ /dev/null
@@ -1,286 +0,0 @@
-# future_aircraft 功能包使用介绍
-
-## 一、介绍及使用
-
-- 本功能包为第二届大学生未来飞行器挑战赛的实践类仿真demo
- - 设置比赛区域(10 * 20 * 6 m,暂定)场地内随机模拟圆形标靶 3 个;其中, 2 个随
- 机固定在场地位置, 1 个固定于移动的无人车上面,无人车以≤ 1m/s 的速度在
- 8 字形轮廓进行移动。
- - 无人机由指定的位置一键起飞后,立即转换为自动模式,开始通过机载传感器
- 自主搜索这些目标标靶,并向目标标靶投掷模拟子弹;完成所有的投掷任务后,
- 自主回到起飞点降落。以投中目标的数量和完成时间来综合计分。
- - 模拟子弹选用与标靶粘接的子弹,以减少因弹性或是风力影响。
- - 主办方在赛场内提供 UWB 基站信号覆盖,参赛队伍可以自主选择目标识别和
- 定位方式。
-
-
-
-- 编译必要的文件(在Prometheus跟目录下运行)
-
- - ```
- ./Modules/future_aircraft/compile_aircraft_sitle.sh
- ```
-
-- 仿真运行:(需要连接遥控器)
-
- - 启动仿真环境:
-
- - ```
- roslaunch prometheus_future_aircraft future_aircraft.launch
- ```
-
- - 启动控制demo:(后续融合到一个launch文件中)
-
- - ```
- rosrun prometheus_future_aircraft future_aircraft
- ```
-
-
-
-
-
-## 二、任务控制demo说明
-
-- 控制需要有一定基础,可以熟悉了解 [控制demo模块](https://wiki.amovlab.com/public/prometheus-wiki/%E6%97%A0%E4%BA%BA%E6%9C%BA%E6%8E%A7%E5%88%B6%E6%A8%A1%E5%9D%97-uav_control/%E6%97%A0%E4%BA%BA%E6%9C%BA%E6%8E%A7%E5%88%B6%E6%A8%A1%E5%9D%97-uav_control.html)
-- 针对比赛以及实际情况,选择合适的控制接口进行控制。本demo中会使用惯性系与机体系下的位置和速度控制
-
-### 任务状态机
-
-- 状态机:
-
- - TAKEOFF 起飞状态机
-
- - 直接调用起飞函数
-
- - ```
- uav_command.header.stamp = ros::Time::now();
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Init_Pos_Hover;
- ```
- - SEARCH 搜寻状态机
-
- - 使用惯性系或者机体系下的位置控制
-
- - ```
- uav_command.header.stamp = ros::Time::now();
- uav_command.header.frame_id = "BODY";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XYZ_POS_BODY;
- uav_command.position_ref[0] = waypoint1[0];
- uav_command.position_ref[1] = waypoint1[1];
- uav_command.position_ref[2] = waypoint1[2];
- uav_command.yaw_ref = 0.0;
- ```
-
- - ```
- uav_command.header.stamp = ros::Time::now();
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XYZ_POS;
- uav_command.position_ref[0] = waypoint4[0];
- uav_command.position_ref[1] = waypoint4[1];
- uav_command.position_ref[2] = waypoint4[2];
- uav_command.yaw_ref = 0.0;
- ```
-
- - TRACKING 跟踪状态机
-
- - 使用机体系下的水平方向速度控制,垂直方向高度控制
-
- - ```
- //坐标系
- uav_command.header.frame_id = "BODY";
- // Move模式
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- // 机体系下的速度控制
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XY_VEL_Z_POS_BODY;
- uav_command.velocity_ref[0] = 0.5 * now_arucos_info.position[0];
- uav_command.velocity_ref[1] = 0.5 * now_arucos_info.position[1];
- uav_command.position_ref[2] = 1.0;
- uav_command.yaw_ref = 0.0;
- ```
-
- - LOST 目标丢失状态机
-
- - RETURN 返航状态机(返航以及降落状态机)
-
-### 视觉端处理
-
-- 坐标系变换说明(Prometheus\Modules\tutorial_demo\advanced\autonomous_landing\include\mission_utils.h)
-
- - 接受图像话题
-
- ```
- /prometheus/ellipse_det
- ```
-
- - 识别算法发布的目标位置位于**相机坐标系**(从相机往前看,物体在相机右方x为正,下方y为正,前方z为正)
-
- - 首先,从相机坐标系转换至**机体坐标系**(从机体往前看,物体在相机前方x为正,左方y为正,上方z为正):`camera_offset`为相机安装偏移量,此处为下置摄像头,参看 `p450_future_aircraft.sdf`可知,相机安装于机体质心下方0.05米,因此,`camera_offset[0] = 0.0`,`camera_offset[1] = 0.0`,`camera_offset[2] = -0.05` 。
-
- - ```
- ellipse_det.pos_body_frame[0] = -ellipse_det.Detection_info.position[1] + camera_offset[0];
- ellipse_det.pos_body_frame[1] = -ellipse_det.Detection_info.position[0] + camera_offset[1];
- ellipse_det.pos_body_frame[2] = -ellipse_det.Detection_info.position[2] + camera_offset[2];
- ```
-
- - 从机体坐标系转换至**与机体固连的ENU系**(原点位于质心,x轴指向yaw=0的方向,y轴指向yaw=90的方向,z轴指向上的坐标系):直接乘上机体系到惯性系的旋转矩阵即可 R_Body_to_ENU = get_rotation_matrix(_DroneState.attitude[0], _DroneState.attitude[1], _DroneState.attitude[2]);
-
- - ```
- ellipse_det.pos_body_enu_frame = R_Body_to_ENU * ellipse_det.pos_body_frame;
- ```
-
- - 机体惯性系 再变化为 惯性系
-
- - ```
- ellipse_det.pos_enu_frame[0] = uav_state.position[0] + ellipse_det.pos_body_enu_frame[0];
- ellipse_det.pos_enu_frame[1] = uav_state.position[1] + ellipse_det.pos_body_enu_frame[1];
- ellipse_det.pos_enu_frame[2] = uav_state.position[2] + ellipse_det.pos_body_enu_frame[2];
- ```
-
-
-
-## 三、无人机视觉
-
-- 需要有一定基础
-- 完成比赛中不一定会用到所有讲解的知识
-- 才疏学浅,如果有大佬发现错误,欢迎留言指正
-
-### Prometheus视觉模块简介
-
-1. [概览](https://wiki.amovlab.com/public/prometheus-wiki/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E6%A8%A1%E5%9D%97-object_detection/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E6%A8%A1%E5%9D%97%E4%BB%8B%E7%BB%8D/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E6%A8%A1%E5%9D%97%E4%BB%8B%E7%BB%8D.html)
-
-2. 椭圆识别演示
-
-电脑插上摄像头,输入一下命令运行,默认读取ID为0的摄像
-```bash
-roslaunch prometheus_detection ellipse_det.launch
-```
-
-
-
-
-### 椭圆检测流程简介
-
-OPENCV版本: 霍夫椭圆检测,更慢
-
-
-1. 图像去噪声, 去除图像中到椒盐噪声
-2. 弧检测,挑选出可能为弧的对象
-3. 弧分类,判定弧属于四个象限中的那个一个
-
-
-
-4. 弧过滤,运用两段弧约束, CNC约束(三段弧约束),过滤不满足要求的弧
-
-5. 椭圆估计,在剩下的四个象限的弧中进行排列组合,使用优化算法,通过4个弧线估计一个椭圆
-
-6. 椭圆打分,使用特定打分算法,计算椭圆与4个弧线的拟合程度,给椭圆打分,最后选出得分较高的椭圆
-
-### 相机模型简介
-
-世界平面到图像平面(根据小孔成像原理)
-
-
-
-图像平面到像素平面, 将图像平面原点映射到像素平面原点
-- $x,y$图像尺寸, $u,v$像素尺寸
-- $u_0,v_0$是图像坐标系原点到像素坐标系原点的偏移
-- $dx, dy$ 每个像素在图像平面$x$和$y$方向上的物理尺寸
-
-
-
-世界坐标系到像素坐标系变换(_下图中,图像坐标系到像素坐标系转换矩阵添加畸变矫正参数矫正_)
-
-
-
-这里我们假设已知目标在相机坐标系下的位置$(X_c, Y_c, Z_c)$,将前两个变换矩阵相乘得到`camera_matrix`(也叫相机内参),最后得到相机坐标系到像素坐标系的关系:
-
-$$
-\begin{bmatrix}
- u\\
- v\\
- 1
-\end{bmatrix}=
-\begin{bmatrix}
-\frac{f}{dx} & 0 & u_{0} \\
- 0 & \frac{f}{dy} & v_{0}\\
- 0 & 0 & 1
-\end{bmatrix}\begin{bmatrix}
- \frac{X_{c}}{Z_{c}} \\
- \frac{Y_{c}}{Z_{c}} \\
- 1
-\end{bmatrix}
-$$
-
-实际中,一般像素坐标$u,v$以及$Z_c$已知,通过目标的像素位置、相机内参和深度信息,就可以反解目标世界坐标,通过上述公式,变换可得:
-$$
-\begin{array}{c}
-X_c = Z_c * (u - u_0) /(\frac{f}{dx}) \\
-Y_c = Z_c * (v - v_0) /(\frac{f}{dy}) \\
-\end{array}
-$$
-
-其中$Z_c$一般可以通过传感器直接获得,或者通过事先已知目标真实尺寸,像素尺寸通过相似三角形比值关系获得,具体可以看[配置目标的实际长宽](https://wiki.amovlab.com/public/prometheus-wiki/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E6%A8%A1%E5%9D%97-object_detection/%E6%89%A9%E5%B1%95%E9%98%85%E8%AF%BB/%E9%85%8D%E7%BD%AE%E7%9B%AE%E6%A0%87%E7%9A%84%E5%AE%9E%E9%99%85%E9%95%BF%E5%AE%BD.html)进行学习。
-
-### 相机标定
-> [相机标定程序](https://wiki.amovlab.com/public/prometheus-wiki/%E7%9B%AE%E6%A0%87%E6%A3%80%E6%B5%8B%E6%A8%A1%E5%9D%97-object_detection/%E6%89%A9%E5%B1%95%E9%98%85%E8%AF%BB/%E7%9B%B8%E6%9C%BA%E6%A0%87%E5%AE%9A.html)
-1. 获取相机内参
-2. 去除相机畸变
-
-
-
-
-
-某个相机的标定文件
-```yaml
-%YAML:1.0
----
-calibration_time: "Thu 14 Jul 2022 11:46:13 AM CST"
-image_width: 640
-image_height: 480
-flags: 0
-camera_matrix: !!opencv-matrix
- rows: 3
- cols: 3
- dt: d
- data: [ 6.7570491275428003e+02, 0., 3.4702214961185257e+02, 0.,
- 6.7652907115648509e+02, 2.5917548194106814e+02, 0., 0., 1. ]
-distortion_coefficients: !!opencv-matrix
- rows: 1
- cols: 5
- dt: d
- data: [ -4.3154114726977300e-01, 2.7199122166782413e-01,
- -1.5471282947090615e-03, -6.6196646287719843e-04,
- -4.9889322933567892e-01 ]
-avg_reprojection_error: 4.7592643246496424e-01
-```
-
-### 代码解析
-
-[ellipse_det.cpp](../object_detection/cpp_nodes/ellipse_det.cpp)
-
-- 整个代码逻辑
-- 可调节参数
-- 去除图像畸变
-- 目标位置估计
-- 区分起飞点和靶标
-
-### messge定义
-
-[DetectionInfo](../common/prometheus_msgs/msg/DetectionInfo.msg)
-
-[MultiDetectionInfo](../common/prometheus_msgs/msg/MultiDetectionInfo.msg)
-
-### 椭圆检测launch文件
-```
-
-
-
-
-
-```
-
-### 问题
-
-- 飞行过程中无人机姿态变化,会导致估计的目标位置误差加大,该怎么解决?
diff --git a/src/无人机端代码/Modules/future_aircraft/scripts/locus.py b/src/无人机端代码/Modules/future_aircraft/scripts/locus.py
deleted file mode 100644
index cd9f918e..00000000
--- a/src/无人机端代码/Modules/future_aircraft/scripts/locus.py
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/usr/bin/env python3
-import rospy
-import math
-import time as t
-from geometry_msgs.msg import Twist
-from gazebo_msgs.msg import ModelState, ModelStates
-from gazebo_msgs.srv import SetModelState, SetModelStateRequest, SetModelStateResponse
-
-
-client = rospy.ServiceProxy("/gazebo/set_model_state", SetModelState)
-client.wait_for_service()
-
-def init_pose():
- req = SetModelStateRequest()
- req.model_state.model_name = "future_aircraft_car"
- req.model_state.pose.position.x = 0
- req.model_state.pose.position.y = 0
- req.model_state.pose.position.z = 0
- client.call(req)
-
-landing_pad = None
-def get_pos(info: ModelStates):
- global landing_pad
- for i , name in enumerate(info.name):
- if name == "future_aircraft_car":
- landing_pad = info.pose[i].position
- # print(landing_pad)
- return
-
-
-def pose_publisher_circle():
- pub = rospy.Publisher('gazebo/set_model_state', ModelState, queue_size=10)
- pose_msg = ModelState()
- pose_msg.model_name = 'landing_pad'
- pose_msg.pose.position.x = 0
- pose_msg.pose.position.y = 0
- pose_msg.pose.position.z = 0
-
- rate = rospy.Rate(30)
- pub = rospy.Publisher('/wheeltec/cmd_vel', Twist, queue_size=10)
- pose_msg = Twist()
- rate = rospy.Rate(60)
- circle_radius = 1.5
- linear_vel = 1
- omega = math.fabs(linear_vel / circle_radius)
- # cycle = math.pi * 2 / omega
- past_time = t.time()
- while not rospy.is_shutdown():
- pose_msg.linear.x = linear_vel
- pose_msg.angular.z = omega
- if landing_pad != None and math.sqrt(landing_pad.x ** 2 + landing_pad.y**2) < 0.3 and t.time() - past_time > 1:
- pub.publish(pose_msg)
- init_pose()
- past_time = t.time()
- omega = -omega
- pub.publish(pose_msg)
- rate.sleep()
-
-
-if __name__ == '__main__':
- rospy.init_node('locus_8')
- rospy.Subscriber("/gazebo/model_states", ModelStates, get_pos)
- init_pose()
- pose_publisher_circle()
diff --git a/src/无人机端代码/Modules/future_aircraft/src/ellipse_det.cpp b/src/无人机端代码/Modules/future_aircraft/src/ellipse_det.cpp
deleted file mode 100644
index e9e1b788..00000000
--- a/src/无人机端代码/Modules/future_aircraft/src/ellipse_det.cpp
+++ /dev/null
@@ -1,168 +0,0 @@
-#include "ellipse_detector.h"
-#include
-#include "printf_utils.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-std::shared_mutex g_mutex;
-int frame_width = 640, frame_height = 480;
-
-cv::Mat g_camera_matrix, g_dist_coeffs;
-cv::Mat g_frame;
-void imageCb(const sensor_msgs::ImageConstPtr &msg)
-{
- cv_bridge::CvImagePtr cam_image = cv_bridge::toCvCopy(msg, sensor_msgs::image_encodings::BGR8);
-
- if (cam_image)
- {
- std::unique_lock lock(g_mutex);
- cv::Mat tmp = cam_image->image.clone();
- // NOTE: 图像去畸变
- // g_frame = tmp
- cv::undistort(tmp, g_frame, g_camera_matrix, g_dist_coeffs);
- frame_width = cam_image->image.size().width;
- frame_height = cam_image->image.size().height;
- }
-}
-
-float g_camera_height = 0;
-void heightCb(const std_msgs::Float32ConstPtr &msg)
-{
- g_camera_height = msg->data;
-}
-
-bool unique_ell(const std::pair &lhs, const std::pair &rhs)
-{
- float x = lhs.first - rhs.first;
- float y = lhs.second - rhs.second;
- if (std::sqrt(std::pow(x, 2) + std::pow(y, 2)) < 20)
- {
- return false;
- };
- return true;
-}
-// bool (*unique_ell_func)(const std::pair, const std::) = unique_ell;
-
-int main(int argc, char **argv)
-{
- ros::init(argc, argv, "ellipse_det");
- ros::NodeHandle nh("~");
- image_transport::ImageTransport it(nh);
- std::string input_image_topic, output_image_topic, camera_params, det_info_topic, camera_height_topic;
- nh.param("input_image_topic", input_image_topic, "/prometheus/camera/rgb/image_raw");
- nh.param("output_image_topic", output_image_topic, "/prometheus/detection/image_raw");
- nh.param("camera_height_topic", camera_height_topic, "/camera/height");
- nh.param("camera_params", camera_params, "");
- nh.param("det_info_topic", det_info_topic, "/prometheus/ellipse_det");
-
- if (camera_params.empty() || access(camera_params.c_str(), 0x00) != 0)
- {
- throw camera_params + " path does not exist or not provided";
- return -1;
- }
- cv::FileStorage fs(camera_params, cv::FileStorage::READ);
- fs["camera_matrix"] >> g_camera_matrix;
- fs["distortion_coefficients"] >> g_dist_coeffs;
-
- // 订阅图像话题
- image_transport::Subscriber image_subscriber = it.subscribe(input_image_topic, 1, imageCb);
- // 发布检测可视化图像话题
- image_transport::Publisher image_pub = it.advertise(output_image_topic, 1);
-
- // 发布MultiDetectionInfo话题
- ros::Publisher det_info_pub = nh.advertise(det_info_topic, 1);
-
- // 圆检测参数调整
- EllipseDetector ellipse_detector;
- // float fMaxCenterDistance = sqrt(float(width * width + height * height)) * 0.05f;
- // ellipse_detector.SetParameters(cv::Size(5, 5), 1.306, 1.f, fMaxCenterDistance, 9, 2.984, 0.111, 0.511, 0.470, 22, 0.946, 0.121, 0.468, 0.560, 0.202);
-
- ros::Rate rate(60);
- while (ros::ok())
- {
- prometheus_msgs::MultiDetectionInfo det_info;
- det_info.detect_or_track = 0;
- ros::spinOnce();
- if (g_frame.empty())
- {
- PCOUT(-1, YELLOW, "wait for get image data");
- continue;
- }
- cv::Mat frame;
- {
- std::unique_lock lock(g_mutex);
- frame = g_frame.clone();
- }
- std::vector ellsCned;
- double t0 = (double)cv::getTickCount();
- ellipse_detector.Detect(frame, ellsCned);
-
- sensor_msgs::ImagePtr det_output_msg = cv_bridge::CvImage(std_msgs::Header(), "bgr8", frame).toImageMsg();
-
- // cv::cvtColor(frame, frame, cv::COLOR_BGR2HSV);
- std::set, decltype(unique_ell) *> ellipse_set(unique_ell);
- for (int i = 0; i < ellsCned.size(); i++)
- {
- const Ellipse &ellipse = ellsCned[i];
- auto insert_re = ellipse_set.insert(std::make_pair(ellipse.xc_, ellipse.yc_));
- if (insert_re.first == ellipse_set.end())
- continue;
- prometheus_msgs::DetectionInfo info;
- // NOTE: 如果区分无人机起点和靶标?
- cv::Mat mask = cv::Mat::zeros(frame.size(), CV_8U);
- cv::ellipse(mask, cv::Point(cvRound(ellipse.xc_), cvRound(ellipse.yc_)), cv::Size(cvRound(ellipse.a_), cvRound(ellipse.b_)), ellipse.rad_ * 180 / CV_PI, 0, 360, cv::Scalar(255, 255, 255), -1);
- cv::Mat tmp;
- frame.copyTo(tmp, mask);
- // cv::bitwise_and(frame, cv::noArray(), tmp, mask);
- cv::inRange(tmp, cv::Scalar(150, 150, 150), cv::Scalar(255, 255, 255), tmp);
-
- int *tmpi = nullptr;
- if (static_cast(cv::countNonZero(tmp)) / cv::countNonZero(mask) > 0.1)
- {
- info.object_name = "S";
- cv::Size sz = cv::getTextSize(info.object_name, 0, 0.8, 1, tmpi);
- cv::putText(frame, info.object_name, cv::Point(ellipse.xc_ - sz.width / 2, ellipse.yc_ + sz.height / 2), cv::FONT_HERSHEY_COMPLEX, 0.5, cv::Scalar(255, 255, 0), 1);
- }
- else
- {
- info.object_name = "T";
- cv::Size sz = cv::getTextSize(info.object_name, 0, 0.8, 1, tmpi);
- cv::putText(frame, info.object_name, cv::Point(ellipse.xc_ - sz.width / 2, ellipse.yc_ + sz.height / 2), cv::FONT_HERSHEY_COMPLEX, 0.5, cv::Scalar(255, 255, 0), 1);
- }
- info.frame = 0;
- info.detected = true;
- // NOTE: 目标位置估计
- info.position[0] = g_camera_height * (ellipse.yc_ - frame_height / 2) / g_camera_matrix.at(1, 1);
- info.position[1] = g_camera_height * (ellipse.xc_ - frame_width / 2) / g_camera_matrix.at(0, 0);
- info.position[2] = g_camera_height;
- info.sight_angle[0] = (ellipse.xc_ - frame_width / 2) / (frame_width / 2) * std::atan(frame_width / (2 * g_camera_matrix.at(0, 0)));
- info.sight_angle[1] = (ellipse.yc_ - frame_height / 2) / (frame_height / 2) * std::atan(frame_height / (2 * g_camera_matrix.at(1, 1)));
- info.pixel_position[0] = ellipse.xc_;
- info.pixel_position[1] = ellipse.yc_;
- det_info.detection_infos.push_back(info);
- }
- det_info.num_objs = ellipse_set.size();
-
- double dt = ((double)cv::getTickCount() - t0) / cv::getTickFrequency();
- char msg[256];
- sprintf(msg, "FPS: %f", 1.f / dt);
- cv::putText(frame, msg, cv::Point(10, 20), cv::FONT_HERSHEY_COMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, 4, 0);
-
- ellipse_detector.DrawDetectedEllipses(frame, ellsCned, 1, 6);
- image_pub.publish(det_output_msg);
- cv::imshow("show", frame);
- cv::waitKey(1);
-
- det_info_pub.publish(det_info);
- rate.sleep();
- }
- return 0;
-}
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/future_aircraft/src/ellipse_detector/ellipse_detector.cpp b/src/无人机端代码/Modules/future_aircraft/src/ellipse_detector/ellipse_detector.cpp
deleted file mode 100644
index f256e57b..00000000
--- a/src/无人机端代码/Modules/future_aircraft/src/ellipse_detector/ellipse_detector.cpp
+++ /dev/null
@@ -1,3855 +0,0 @@
-#include "ellipse_detector.h"
-#include
-#include
-
-
-using namespace std;
-using namespace cv;
-
-
-
-#ifndef USE_OMP
-int omp_get_max_threads() { return 1; }
-int omp_get_thread_num() { return 0; }
-// int omp_set_num_threads(int){ return 0; }
-#endif
-
-
-void _list_dir(std::string dir, std::vector& files, std::string suffixs, bool r) {
- // assert(_endswith(dir, "/") || _endswith(dir, "\\"));
-
- DIR *pdir;
- struct dirent *ent;
- string childpath;
- string absolutepath;
- pdir = opendir(dir.c_str());
- assert(pdir != NULL);
-
- vector suffixd(0);
- if (!suffixs.empty() && suffixs != "") {
- suffixd = _split(suffixs, "|");
- }
-
- while ((ent = readdir(pdir)) != NULL) {
- if (ent->d_type & DT_DIR) {
- if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
- continue;
- }
- if (r) { // If need to traverse subdirectories
- childpath = dir + ent->d_name;
- _list_dir(childpath, files);
- }
- }
- else {
- if (suffixd.size() > 0) {
- bool can_push = false;
- for (int i = 0; i < (int)suffixd.size(); i++) {
- if (_endswith(ent->d_name, suffixd[i]))
- can_push = true;
- }
- if (can_push) {
- absolutepath = dir + ent->d_name;
- files.push_back(ent->d_name); // filepath
- }
- }
- else {
- absolutepath = dir + ent->d_name;
- files.push_back(ent->d_name); // filepath
- }
- }
- }
- sort(files.begin(), files.end()); //sort names
-}
-
-vector _split(const string& srcstr, const string& delimeter)
-{
- vector ret(0); //use ret save the spilted reault
- if (srcstr.empty()) //judge the arguments
- {
- return ret;
- }
- string::size_type pos_begin = srcstr.find_first_not_of(delimeter); //find first element of srcstr
-
- string::size_type dlm_pos; //the delimeter postion
- string temp; //use third-party temp to save splited element
- while (pos_begin != string::npos) //if not a next of end, continue spliting
- {
- dlm_pos = srcstr.find(delimeter, pos_begin); //find the delimeter symbol
- if (dlm_pos != string::npos)
- {
- temp = srcstr.substr(pos_begin, dlm_pos - pos_begin);
- pos_begin = dlm_pos + delimeter.length();
- }
- else
- {
- temp = srcstr.substr(pos_begin);
- pos_begin = dlm_pos;
- }
- if (!temp.empty())
- ret.push_back(temp);
- }
- return ret;
-}
-
-bool _startswith(const std::string& str, const std::string& start)
-{
- size_t srclen = str.size();
- size_t startlen = start.size();
- if (srclen >= startlen)
- {
- string temp = str.substr(0, startlen);
- if (temp == start)
- return true;
- }
-
- return false;
-}
-
-bool _endswith(const std::string& str, const std::string& end)
-{
- size_t srclen = str.size();
- size_t endlen = end.size();
- if (srclen >= endlen)
- {
- string temp = str.substr(srclen - endlen, endlen);
- if (temp == end)
- return true;
- }
-
- return false;
-}
-
-int inline randint(int l, int u)
-{
- return l + rand() % (u - l + 1);
- // rand() % (u-l+1) -> [0, u-l]
- // [0, u-l] -> [l, u]
-}
-
-void _randperm(int n, int m, int arr[], bool sort_)
-{
- int* x = (int*)malloc(sizeof(int)*n);
- for (int i = 0; i < n; ++i)
- x[i] = i;
- for (int i = 0; i < m; ++i)
- {
- int j = randint(i, n - 1);
- int t = x[i]; x[i] = x[j]; x[j] = t; // swap(x[i], x[j]);
- }
- if (sort_)
- sort(x, x + m);
- for (int i = 0; i < m; ++i)
- arr[i] = x[i];
- free(x);
-}
-
-#define FL_PI 3.14159265358979323846f
-#define FL_1_2_PI 1.57079632679f
-#define FL_2__PI 6.28318530718
-float _atan2(float y, float x)
-{
- float ang(0);
- if (x > 0)
- ang = atanf(y / x);
- else if (y >= 0 && x < 0)
- ang = atanf(y / x) + FL_PI;
- else if (y < 0 && x < 0)
- ang = atanf(y / x) - FL_PI;
- else if (y > 0 && x == 0)
- ang = FL_1_2_PI;
- else if (y < 0 && x == 0)
- ang = -FL_1_2_PI;
- else // (y == 0 && x == 0)
- ang = INFINITY;
- // if (ang < 0) ang += FL_2__PI;
- return ang;
-}
-
-void _mean_std(std::vector& vec, float& mean, float& std)
-{
- float sum = std::accumulate(std::begin(vec), std::end(vec), 0.0);
- mean = sum / vec.size();
-
- float accum = 0.0;
- std::for_each(std::begin(vec), std::end(vec), [&](const double d) {
- accum += (d - mean)*(d - mean);
- });
-
- std = sqrt(accum / (vec.size() - 1));
-}
-
-float _get_min_angle_PI(float alpha, float beta)
-{
- float pi = float(CV_PI);
- float pi2 = float(2.0 * CV_PI);
-
- //normalize data in [0, 2*pi]
- float a = fmod(alpha + pi2, pi2);
- float b = fmod(beta + pi2, pi2);
-
- //normalize data in [0, pi]
- if (a > pi)
- a -= pi;
- if (b > pi)
- b -= pi;
-
- if (a > b)
- {
- swap(a, b);
- }
-
- float diff1 = b - a;
- float diff2 = pi - diff1;
- return min(diff1, diff2);
-}
-
-
-void _load_ellipse_GT(const string& gt_file_name, vector& gt_ellipses, bool is_angle_radians)
-{
- ifstream in(gt_file_name);
- if (!in.good())
- {
- cout << "Error opening: " << gt_file_name << endl;
- return;
- }
-
- unsigned n;
- in >> n;
-
- gt_ellipses.clear();
- gt_ellipses.reserve(n);
-
- while (in.good() && n--)
- {
- Ellipse e;
- in >> e.xc_ >> e.yc_ >> e.a_ >> e.b_ >> e.rad_;
-
- if (!is_angle_radians)
- {
- // convert to radians
- e.rad_ = float(e.rad_ * CV_PI / 180.0);
- }
-
- if (e.a_ < e.b_)
- {
- float temp = e.a_;
- e.a_ = e.b_;
- e.b_ = temp;
-
- e.rad_ = e.rad_ + float(0.5*CV_PI);
- }
-
- e.rad_ = fmod(float(e.rad_ + 2.f*CV_PI), float(CV_PI));
- e.score_ = 1.f;
- gt_ellipses.push_back(e);
- }
- in.close();
-}
-
-void _load_ellipse_DT(const string& dt_file_name, vector& dt_ellipses, bool is_angle_radians)
-{
- ifstream in(dt_file_name);
- if (!in.good())
- {
- cout << "Error opening: " << dt_file_name << endl;
- return;
- }
-
- unsigned n;
- in >> n;
-
- dt_ellipses.clear();
- dt_ellipses.reserve(n);
-
- while (in.good() && n--)
- {
- Ellipse e;
- in >> e.xc_ >> e.yc_ >> e.a_ >> e.b_ >> e.rad_ >> e.score_;
-
- if (!is_angle_radians)
- {
- // convert to radians
- e.rad_ = float(e.rad_ * CV_PI / 180.0);
- }
-
- if (e.a_ < e.b_)
- {
- float temp = e.a_;
- e.a_ = e.b_;
- e.b_ = temp;
-
- e.rad_ = e.rad_ + float(0.5*CV_PI);
- }
-
- e.rad_ = fmod(float(e.rad_ + 2.f*CV_PI), float(CV_PI));
- e.score_ = 1.f;
- dt_ellipses.push_back(e);
- }
- in.close();
-}
-
-bool _ellipse_overlap(const Mat1b& gt, const Mat1b& dt, float th)
-{
- float f_and = float(countNonZero(gt & dt));
- float f_or = float(countNonZero(gt | dt));
- float f_sim = f_and / f_or;
-
- return (f_sim >= th);
-}
-
-float _ellipse_overlap_real(const Mat1b& gt, const Mat1b& dt)
-{
- float f_and = float(countNonZero(gt & dt));
- float f_or = float(countNonZero(gt | dt));
- float f_sim = f_and / f_or;
-
- return f_sim;
-}
-
-int _bool_count(const std::vector vb)
-{
- int counter = 0;
- for (unsigned i = 0; i& ell_gt, const vector& ell_dt, const Mat3b& img)
-{
- float threshold_overlap = 0.8f;
- // float threshold = 0.95f;
-
- unsigned sz_gt = ell_gt.size();
- unsigned sz_dt = ell_dt.size();
-
- unsigned sz_dt_min = unsigned(min(1000, int(sz_dt)));
-
- vector mat_gts(sz_gt);
- vector mat_dts(sz_dt_min);
-
- // Draw each ground-Truth ellipse
- for (unsigned i = 0; i vec_gt(sz_gt, false);
- vector vec_dt(sz_dt_min, false);
-
- // Each row in the matrix has one means the ellipse be found
- for (unsigned int i = 0; i < sz_dt_min; ++i)
- {
- for (unsigned int j = 0; j < sz_gt; ++j)
- {
- bool b_found = overlap(j, i) != 0;
- if (b_found)
- {
- vec_gt[j] = true;
- vec_dt[i] = true;
- }
- }
- }
-
- float tp = _bool_count(vec_gt);
- float fn = int(sz_gt) - tp;
- float fp = sz_dt - _bool_count(vec_dt); // !!!! sz_dt - _bool_count(vec_dt); //
-
- float pr(0.f);
- float re(0.f);
- float fmeasure(0.f);
-
- if (tp == 0) {
- if (fp == 0) {
- pr = 1.f;
- re = 0.f;
- fmeasure = (2.f * pr * re) / (pr + re);
- }
- else {
- pr = 0.f;
- re = 0.f;
- fmeasure = 0.f;
- }
- }
- else {
- pr = float(tp) / float(tp + fp);
- re = float(tp) / float(tp + fn);
- fmeasure = (2.f * pr * re) / (pr + re);
- }
-
- return fmeasure;
-}
-
-float _ellipse_evaluate(vector& image_fns, vector& gt_fns, vector& dt_fns, bool gt_angle_radians)
-{
- float fmeasure(0.f);
- for (int i = 0; i < image_fns.size(); i++) {
- Mat3b image = imread(image_fns[i]);
-
- vector ell_gt, ell_dt;
- _load_ellipse_GT(gt_fns[i], ell_gt, gt_angle_radians);
- _load_ellipse_DT(dt_fns[i], ell_dt);
-
- int tp, fn, fp;
- fmeasure += _ellipse_evaluate_one(ell_gt, ell_dt, image);
-
- }
-
- fmeasure /= image_fns.size();
- return fmeasure;
-}
-
-Point2f inline _lineCrossPoint(Point2f l1p1, Point2f l1p2, Point2f l2p1, Point2f l2p2)
-{
- Point2f crossPoint;
- float k1, k2, b1, b2;
- if (l1p1.x == l1p2.x&&l2p1.x == l2p2.x) {
- crossPoint = Point2f(0, 0); // invalid point
- return crossPoint;
- }
- if (l1p1.x == l1p2.x)
- {
- crossPoint.x = l1p1.x;
- k2 = (l2p2.y - l2p1.y) / (l2p2.x - l2p1.x);
- b2 = l2p1.y - k2*l2p1.x;
- crossPoint.y = k2*crossPoint.x + b2;
- return crossPoint;
- }
- if (l2p1.x == l2p2.x)
- {
- crossPoint.x = l2p1.x;
- k2 = (l1p2.y - l1p1.y) / (l1p2.x - l1p1.x);
- b2 = l1p1.y - k2*l1p1.x;
- crossPoint.y = k2*crossPoint.x + b2;
- return crossPoint;
- }
-
- k1 = (l1p2.y - l1p1.y) / (l1p2.x - l1p1.x);
- k2 = (l2p2.y - l2p1.y) / (l2p2.x - l2p1.x);
- b1 = l1p1.y - k1*l1p1.x;
- b2 = l2p1.y - k2*l2p1.x;
- if (k1 == k2)
- {
- crossPoint = Point2f(0, 0); // invalid point
- }
- else
- {
- crossPoint.x = (b2 - b1) / (k1 - k2);
- crossPoint.y = k1*crossPoint.x + b1;
- }
- return crossPoint;
-}
-
-void inline _point2Mat(Point2f p1, Point2f p2, float mat[2][2])
-{
- mat[0][0] = p1.x;
- mat[0][1] = p1.y;
- mat[1][0] = p2.x;
- mat[1][1] = p2.y;
-}
-
-float _value4SixPoints(cv::Point2f p3, cv::Point2f p2, cv::Point2f p1, cv::Point2f p4, cv::Point2f p5, cv::Point2f p6)
-{
- float result = 1;
- Mat A, B, C;
- float matB[2][2], matC[2][2];
- Point2f v, w, u;
- v = _lineCrossPoint(p1, p2, p3, p4);
- w = _lineCrossPoint(p5, p6, p3, p4);
- u = _lineCrossPoint(p5, p6, p1, p2);
-
- _point2Mat(u, v, matB);
- _point2Mat(p1, p2, matC);
- B = Mat(2, 2, CV_32F, matB);
- C = Mat(2, 2, CV_32F, matC);
- A = C*B.inv();
-
- // cout<<"u:\t"<(0, 0)*A.at(1, 0) / (A.at(0, 1)*A.at(1, 1));
-
- _point2Mat(p3, p4, matC);
- _point2Mat(v, w, matB);
- B = Mat(2, 2, CV_32F, matB);
- C = Mat(2, 2, CV_32F, matC);
- A = C*B.inv();
- result *= A.at(0, 0)*A.at(1, 0) / (A.at(0, 1)*A.at(1, 1));
-
- _point2Mat(p5, p6, matC);
- _point2Mat(w, u, matB);
- B = Mat(2, 2, CV_32F, matB);
- C = Mat(2, 2, CV_32F, matC);
- A = C*B.inv();
- result *= A.at(0, 0)*A.at(1, 0) / (A.at(0, 1)*A.at(1, 1));
- return result;
-}
-
-/*----------------------------------------------------------------------------*/
-/** Compute ellipse foci, given ellipse params.
-*/
-void _ellipse_foci(float *param, float *foci)
-{
- float f;
- /* check parameters */
- if (param == NULL) fprintf(stderr, "ellipse_foci: invalid input ellipse.");
- if (foci == NULL) fprintf(stderr, "ellipse_foci: 'foci' must be non null.");
-
- f = sqrt(param[2] * param[2] - param[3] * param[3]);
- foci[0] = param[0] + f * cos(param[4]);
- foci[1] = param[1] + f * sin(param[4]);
- foci[2] = param[0] - f * cos(param[4]);
- foci[3] = param[1] - f * sin(param[4]);
-}
-
-/*----------------------------------------------------------------------------*/
-/** Signed angle difference.
-*/
-float angle_diff_signed(float a, float b)
-{
- a -= b;
- while (a <= -M_PI) a += M_2__PI;
- while (a > M_PI) a -= M_2__PI;
- return a;
-}
-
-/*----------------------------------------------------------------------------*/
-/** Absolute value angle difference.
-*/
-float _angle_diff(float a, float b)
-{
- a -= b;
- while (a <= -M_PI) a += M_2__PI;
- while (a > M_PI) a -= M_2__PI;
- if (a < 0.0) a = -a;
- return a;
-}
-
-/*----------------------------------------------------------------------------*/
-/** Compute the angle of the normal to a point belonging to an ellipse
-using the focal property.
-*/
-float _ellipse_normal_angle(float x, float y, float *foci)
-{
- float tmp1, tmp2, tmp3, theta;
- /* check parameters */
- if (foci == NULL) fprintf(stderr, "ellipse_normal_angle: 'foci' must be non null");
-
- tmp1 = atan2(y - foci[1], x - foci[0]);
- tmp2 = atan2(y - foci[3], x - foci[2]);
- tmp3 = angle_diff_signed(tmp1, tmp2);
-
- theta = tmp1 - tmp3 / 2.0;
- while (theta <= -M_PI) theta += M_2__PI;
- while (theta > M_PI) theta -= M_2__PI;
- return theta;
-}
-
-
-void cv_canny(const void* srcarr, void* dstarr,
- void* dxarr, void* dyarr,
- int aperture_size, bool L2gradient, double percent_ne) {
-
- cv::AutoBuffer buffer;
- std::vector stack;
- uchar **stack_top = 0, **stack_bottom = 0;
-
- CvMat srcstub, *src = cvGetMat(srcarr, &srcstub); // IplImage to cvMat
- CvMat dststub, *dst = cvGetMat(dstarr, &dststub);
-
- CvMat dxstub, *dx = cvGetMat(dxarr, &dxstub);
- CvMat dystub, *dy = cvGetMat(dyarr, &dystub);
-
- if (CV_MAT_TYPE(src->type) != CV_8UC1 ||
- CV_MAT_TYPE(dst->type) != CV_8UC1 ||
- CV_MAT_TYPE(dx->type) != CV_16SC1 ||
- CV_MAT_TYPE(dy->type) != CV_16SC1)
- CV_Error(CV_StsUnsupportedFormat, "");
-
- if (!CV_ARE_SIZES_EQ(src, dst))
- CV_Error(CV_StsUnmatchedSizes, "");
-
- aperture_size &= INT_MAX;
- if ((aperture_size & 1) == 0 || aperture_size < 3 || aperture_size > 7)
- CV_Error(CV_StsBadFlag, "");
-
- int i, j;
- CvSize size;
- size.width = src->cols;
- size.height = src->rows;
-
- cvSobel(src, dx, 1, 0, aperture_size);
- cvSobel(src, dy, 0, 1, aperture_size);
-
- // double min, max;
- // cv::minMaxLoc(Mat(dx->rows, dx->cols, CV_16SC1, dx->data.fl), &min, &max);
- // cout << "min: " << min << ", max: " << max << endl;
-
- Mat1f magGrad(size.height, size.width, 0.f);
- float maxGrad(0);
- float val(0);
- for (i = 0; i < size.height; ++i)
- {
- float* _pmag = magGrad.ptr(i);
- const short* _dx = (short*)(dx->data.ptr + dx->step*i);
- const short* _dy = (short*)(dy->data.ptr + dy->step*i);
- for (j = 0; j < size.width; ++j)
- {
- val = float(abs(_dx[j]) + abs(_dy[j]));
- _pmag[j] = val;
- maxGrad = (val > maxGrad) ? val : maxGrad;
- }
- }
- // cout << "maxGrad: " << maxGrad << endl;
-
- // set magic numbers
- const int NUM_BINS = 64;
- const double percent_of_pixels_not_edges = percent_ne;
- const double threshold_ratio = 0.3;
-
- // compute histogram
- int bin_size = cvFloor(maxGrad / float(NUM_BINS) + 0.5f) + 1;
- if (bin_size < 1) bin_size = 1;
- int bins[NUM_BINS] = { 0 };
- for (i = 0; i < size.height; ++i)
- {
- float *_pmag = magGrad.ptr(i);
- for (j = 0; j < size.width; ++j)
- {
- int hgf = int(_pmag[j]);
- bins[int(_pmag[j]) / bin_size]++;
- }
- }
- // for (int i = 0; i < NUM_BINS; i++)
- // cout << "BIN " << i << " :" << bins[i] << endl;
-
- // Select the thresholds
- float total(0.f);
- float target = float(size.height * size.width * percent_of_pixels_not_edges);
- int low_thresh, high_thresh(0);
-
- while (total < target)
- {
- total += bins[high_thresh];
- high_thresh++;
- }
- high_thresh *= bin_size;
- low_thresh = cvFloor(threshold_ratio * float(high_thresh));
- // cout << "low_thresh: " << low_thresh << ", high_thresh: " << high_thresh << endl;
-
- int low, high, maxsize;
- int* mag_buf[3];
- uchar* map;
- ptrdiff_t mapstep;
-
- if (L2gradient) {
- Cv32suf ul, uh;
- ul.f = (float)low_thresh;
- uh.f = (float)high_thresh;
-
- low = ul.i;
- high = uh.i;
- }
- else {
- low = cvFloor(low_thresh);
- high = cvFloor(high_thresh);
- }
-
- buffer.allocate((size.width + 2)*(size.height + 2) + (size.width + 2) * 3 * sizeof(int));
- // cout << sizeof(int) << ", " << (size.width + 2)*(size.height + 2) + (size.width + 2) * 3 * sizeof(int) << endl;
- mag_buf[0] = (int*)(char*)buffer;
- mag_buf[1] = mag_buf[0] + size.width + 2;
- mag_buf[2] = mag_buf[1] + size.width + 2;
- map = (uchar*)(mag_buf[2] + size.width + 2);
- mapstep = size.width + 2;
-
- maxsize = MAX(1 << 10, size.width*size.height / 10);
- stack.resize(maxsize);
- stack_top = stack_bottom = &stack[0];
-
- memset(mag_buf[0], 0, (size.width + 2) * sizeof(int));
- memset(map, 1, mapstep);
- memset(map + mapstep*(size.height + 1), 1, mapstep);
-
- /* sector numbers
- (Top-Left Origin)
-
- 1 2 3
- * * *
- * * *
- 0*******0
- * * *
- * * *
- 3 2 1
- */
-
-#define CANNY_PUSH(d) *(d) = (uchar)2, *stack_top++ = (d)
-#define CANNY_POP(d) (d) = *--stack_top
-
- CvMat mag_row = cvMat(1, size.width, CV_32F);
-
- // Mat push_show = Mat::zeros(size.height+1, size.width+1, CV_8U);
-
- // calculate magnitude and angle of gradient, perform non-maxima supression.
- // fill the map with one of the following values:
- // 0 - the pixel might belong to an edge
- // 1 - the pixel can not belong to an edge
- // 2 - the pixel does belong to an edge
- for (i = 0; i <= size.height; i++)
- {
- int* _mag = mag_buf[(i > 0) + 1] + 1;
- float* _magf = (float*)_mag;
- const short* _dx = (short*)(dx->data.ptr + dx->step*i);
- const short* _dy = (short*)(dy->data.ptr + dy->step*i);
- uchar* _map;
- int x, y;
- ptrdiff_t magstep1, magstep2;
- int prev_flag = 0;
-
- if (i < size.height)
- {
- _mag[-1] = _mag[size.width] = 0;
-
- if (!L2gradient)
- for (j = 0; j < size.width; j++)
- _mag[j] = abs(_dx[j]) + abs(_dy[j]);
- else
- {
- for (j = 0; j < size.width; j++)
- {
- x = _dx[j]; y = _dy[j];
- _magf[j] = (float)std::sqrt((double)x*x + (double)y*y);
- }
- }
- }
- else
- memset(_mag - 1, 0, (size.width + 2) * sizeof(int));
-
- // at the very beginning we do not have a complete ring
- // buffer of 3 magnitude rows for non-maxima suppression
- if (i == 0)
- continue;
-
- _map = map + mapstep*i + 1;
- _map[-1] = _map[size.width] = 1;
-
- _mag = mag_buf[1] + 1; // take the central row
- _dx = (short*)(dx->data.ptr + dx->step*(i - 1));
- _dy = (short*)(dy->data.ptr + dy->step*(i - 1));
-
- magstep1 = mag_buf[2] - mag_buf[1];
- magstep2 = mag_buf[0] - mag_buf[1];
-
- if ((stack_top - stack_bottom) + size.width > maxsize)
- {
- int sz = (int)(stack_top - stack_bottom);
- maxsize = MAX(maxsize * 3 / 2, maxsize + 8);
- stack.resize(maxsize);
- stack_bottom = &stack[0];
- stack_top = stack_bottom + sz;
- }
-
-#define CANNY_SHIFT 15
-#define TG22 (int)(0.4142135623730950488016887242097*(1< low)
- {
- int tg22x = x * TG22;
- int tg67x = tg22x + ((x + x) << CANNY_SHIFT);
- int tmp = 1 << CANNY_SHIFT;
- y <<= CANNY_SHIFT;
-
- if (y < tg22x) {
- if (m > _mag[j - 1] && m >= _mag[j + 1]) {
- if (m > high && !prev_flag && _map[j - mapstep] != 2) {
- CANNY_PUSH(_map + j); // push_show.at(i, j) = 255;
- prev_flag = 1;
- }
- else {
- _map[j] = (uchar)0;
- }
- continue;
- }
- }
- else if (y > tg67x) {
- if (m > _mag[j + magstep2] && m >= _mag[j + magstep1]) {
- if (m > high && !prev_flag && _map[j - mapstep] != 2) {
- CANNY_PUSH(_map + j); // push_show.at(i, j) = 255;
- prev_flag = 1;
- }
- else {
- _map[j] = (uchar)0;
- }
- continue;
- }
- }
- else {
- s = s < 0 ? -1 : 1;
- if (m > _mag[j + magstep2 - s] && m > _mag[j + magstep1 + s]) {
- if (m > high && !prev_flag && _map[j - mapstep] != 2) {
- CANNY_PUSH(_map + j); // push_show.at(i, j) = 255;
- prev_flag = 1;
- }
- else {
- _map[j] = (uchar)0;
- }
- continue;
- }
- }
- }
- prev_flag = 0;
- _map[j] = (uchar)1;
- }
-
- // scroll the ring buffer
- _mag = mag_buf[0];
- mag_buf[0] = mag_buf[1];
- mag_buf[1] = mag_buf[2];
- mag_buf[2] = _mag;
- }
-
- // imshow("mag", push_show); waitKey();
- // now track the edges (hysteresis thresholding)
- while (stack_top > stack_bottom)
- {
- uchar* m;
- if ((stack_top - stack_bottom) + 8 > maxsize)
- {
- int sz = (int)(stack_top - stack_bottom);
- maxsize = MAX(maxsize * 3 / 2, maxsize + 8);
- stack.resize(maxsize);
- stack_bottom = &stack[0];
- stack_top = stack_bottom + sz;
- }
-
- CANNY_POP(m);
-
- if (!m[-1])
- CANNY_PUSH(m - 1);
- if (!m[1])
- CANNY_PUSH(m + 1);
- if (!m[-mapstep - 1])
- CANNY_PUSH(m - mapstep - 1);
- if (!m[-mapstep])
- CANNY_PUSH(m - mapstep);
- if (!m[-mapstep + 1])
- CANNY_PUSH(m - mapstep + 1);
- if (!m[mapstep - 1])
- CANNY_PUSH(m + mapstep - 1);
- if (!m[mapstep])
- CANNY_PUSH(m + mapstep);
- if (!m[mapstep + 1])
- CANNY_PUSH(m + mapstep + 1);
- }
-
- // the final pass, form the final image
- for (i = 0; i < size.height; i++) {
- const uchar* _map = map + mapstep*(i + 1) + 1;
- uchar* _dst = dst->data.ptr + dst->step*i;
-
- for (j = 0; j < size.width; j++) {
- // if (_map[j] == 2)
- // cout << (int)_map[j] << ", " << (int)(_map[j] >> 1) << ", " << (int)(uchar)-(_map[j] >> 1) << endl;
- _dst[j] = (uchar)-(_map[j] >> 1);
- }
- }
-}
-
-void _tag_canny(InputArray image, OutputArray _edges,
- OutputArray _sobel_x, OutputArray _sobel_y,
- int apertureSize, bool L2gradient, double percent_ne) {
-
- Mat src = image.getMat();
- _edges.create(src.size(), CV_8U);
- _sobel_x.create(src.size(), CV_16S);
- _sobel_y.create(src.size(), CV_16S);
-
- IplImage c_src = IplImage(src);
- IplImage c_dst = IplImage(_edges.getMat());
- IplImage c_dx = IplImage(_sobel_x.getMat());
- IplImage c_dy = IplImage(_sobel_y.getMat());
-
- cv_canny(&c_src, &c_dst,
- &c_dx, &c_dy,
- apertureSize, L2gradient, percent_ne);
-}
-
-void _find_contours_eight(cv::Mat1b& image, std::vector& segments, int iMinLength)
-{
- vector ims; ims.resize(8);
- for (int i = 0; i < 8; i++) {
- ims[i] = Mat1b::zeros(image.size());
- }
- for (int r = 0; r < image.rows; r++) {
- uchar* _e8 = image.ptr(r);
- vector _es; _es.resize(8);
- for (int i = 0; i < 8; i++)
- _es[i] = ims[i].ptr(r);
-
- for (int c = 0; c < image.cols; c++) {
- for (int i = 0; i < 8; i++) {
- if (_e8[c] == (uchar)(i + 1)) {
- _es[i][c] = (uchar)255;
- }
- }
- }
- }
-
- segments.resize(8);
- for (int i = 0; i < 8; i++) {
- _tag_find_contours(ims[i], segments[i], iMinLength);
- }
-}
-
-void _tag_find_contours(cv::Mat1b& image, VVP& segments, int iMinLength) {
-#define RG_STACK_SIZE 8192*4
-
-
- // use stack to speed up the processing of global (even at the expense of memory occupied)
- int stack2[RG_STACK_SIZE];
-#define RG_PUSH2(a) (stack2[sp2] = (a) , sp2++)
-#define RG_POP2(a) (sp2-- , (a) = stack2[sp2])
-
- // use stack to speed up the processing of global (even at the expense of memory occupied)
- Point stack3[RG_STACK_SIZE];
-#define RG_PUSH3(a) (stack3[sp3] = (a) , sp3++)
-#define RG_POP3(a) (sp3-- , (a) = stack3[sp3])
-
- int i, w, h, iDim;
- int x, y;
- int x2, y2;
- int sp2; // stack pointer
- int sp3;
-
- Mat_ src = image.clone();
- w = src.cols;
- h = src.rows;
- iDim = w*h;
-
- Point point;
- for (y = 0; y0)
- { // rg traditional
- RG_POP2(i);
- x2 = i%w;
- y2 = i / w;
-
- point.x = x2;
- point.y = y2;
-
- if (src(y2, x2))
- {
- RG_PUSH3(point);
- src(y2, x2) = 0;
- }
-
- // insert the new points in the stack only if there are
- // and they are points labelled
-
- // 4 connected
- // left
- if (x2>0 && (src(y2, x2 - 1) != 0))
- RG_PUSH2(i - 1);
- // up
- if (y2>0 && (src(y2 - 1, x2) != 0))
- RG_PUSH2(i - w);
- // down
- if (y20 && y2>0 && (src(y2 - 1, x2 - 1) != 0))
- RG_PUSH2(i - w - 1);
- if (x2>0 && y20 && (src(y2 - 1, x2 + 1) != 0))
- RG_PUSH2(i - w + 1);
- if (x2= iMinLength)
- {
- vector component;
- component.reserve(sp3);
-
- // push it to the points
- for (i = 0; i src = image.clone();
- w = src.cols;
- h = src.rows;
- iDim = w*h;
-
- Point point;
- for (y = 0; y component;
- point.x = x;
- point.y = y;
- component.push_back(point);
- x2 = x;
- y2 = y;
-
- bool found = true;
- sp2 = 0;
- while (found && component.size() < 3)
- {
- found = false;
- if (x2 > 0 && y2 < h - 1 && (src(y2 + 1, x2 - 1) != 0))
- {
- src(y2 + 1, x2 - 1) = 0; if (!found) { found = true; point.x = x2 - 1; point.y = y2 + 1; component.push_back(point); }
- }
- if (x2 < w - 1 && y2 < h - 1 && (src(y2 + 1, x2 + 1) != 0))
- {
- src(y2 + 1, x2 + 1) = 0; if (!found) { found = true; point.x = x2 + 1; point.y = y2 + 1; component.push_back(point); }
- }
- if (y2 < h - 1 && (src(y2 + 1, x2) != 0))
- {
- src(y2 + 1, x2) = 0; if (!found) { found = true; point.x = x2; point.y = y2 + 1; component.push_back(point); }
- }
- if (x2 > 0 && (src(y2, x2 - 1) != 0))
- {
- src(y2, x2 - 1) = 0; if (!found) { found = true; point.x = x2 - 1; point.y = y2; component.push_back(point); }
- }
- if (x2 < w - 1 && (src(y2, x2 + 1) != 0))
- {
- src(y2, x2 + 1) = 0; if (!found) { found = true; point.x = x2 + 1; point.y = y2; component.push_back(point); }
- }
- if (x2 > 0 && y2 > 0 && (src(y2 - 1, x2 - 1) != 0))
- {
- src(y2 - 1, x2 - 1) = 0; if (!found) { found = true; point.x = x2 - 1; point.y = y2 - 1; component.push_back(point); }
- }
- if (x2 < w - 1 && y2 > 0 && (src(y2 - 1, x2 + 1) != 0))
- {
- src(y2 - 1, x2 + 1) = 0; if (!found) { found = true; point.x = x2 + 1; point.y = y2 - 1; component.push_back(point); }
- }
- if (y2 > 0 && (src(y2 - 1, x2) != 0))
- {
- src(y2 - 1, x2) = 0; if (!found) { found = true; point.x = x2; point.y = y2 - 1; component.push_back(point); }
- }
- if (found)
- {
- sp2++; x2 = component[sp2].x; y2 = component[sp2].y;
- }
- }
-
- if (component.size() < 3) continue;
- ang = _atan2(component[2].y - component[0].y, component[2].x - component[0].x);
- sp1 = 0;
-
- found = true;
- while (found)
- {
- ang_dmin = 1e3;
- found = false;
- if (x2 > 0 && y2 < h - 1 && (src(y2 + 1, x2 - 1) != 0))
- {
- ang_t = _atan2(y2 + 1 - component[sp1].y, x2 - 1 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2 + 1, x2 - 1) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2 - 1; yn = y2 + 1; }
- }
- if (x2 < w - 1 && y2 < h - 1 && (src(y2 + 1, x2 + 1) != 0))
- {
- ang_t = _atan2(y2 + 1 - component[sp1].y, x2 + 1 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2 + 1, x2 + 1) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2 + 1; yn = y2 + 1; }
- }
- if (y2 < h - 1 && (src(y2 + 1, x2) != 0))
- {
- ang_t = _atan2(y2 + 1 - component[sp1].y, x2 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2 + 1, x2) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2; yn = y2 + 1; }
- }
- if (x2 > 0 && (src(y2, x2 - 1) != 0))
- {
- ang_t = _atan2(y2 - component[sp1].y, x2 - 1 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2, x2 - 1) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2 - 1; yn = y2; }
- }
- if (x2 < w - 1 && (src(y2, x2 + 1) != 0))
- {
- ang_t = _atan2(y2 - component[sp1].y, x2 + 1 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2, x2 + 1) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2 + 1; yn = y2; }
- }
- if (x2 > 0 && y2 > 0 && (src(y2 - 1, x2 - 1) != 0))
- {
- ang_t = _atan2(y2 - 1 - component[sp1].y, x2 - 1 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2 - 1, x2 - 1) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2 - 1; yn = y2 - 1; }
- }
- if (x2 < w - 1 && y2 > 0 && (src(y2 - 1, x2 + 1) != 0))
- {
- ang_t = _atan2(y2 - 1 - component[sp1].y, x2 + 1 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2 - 1, x2 + 1) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2 + 1; yn = y2 - 1; }
- }
- if (y2 > 0 && (src(y2 - 1, x2) != 0))
- {
- ang_t = _atan2(y2 - 1 - component[sp1].y, x2 - component[sp1].x);
- ang_d = abs(ang - ang_t);
- src(y2 - 1, x2) = 0; if (ang_d < ang_dmin) { ang_dmin = ang_d; ang_i = ang_t; xn = x2; yn = y2 - 1; }
- }
- if (ang_dmin < M_1_2_PI)
- {
- found = true; point.x = xn; point.y = yn; component.push_back(point);
- x2 = xn;
- y2 = yn;
- sp1++; sp2++;
- if (sp2 >= 9 && sp2 % 3 == 0)
- {
- float a1 = _atan2(component[sp2 - 6].y - component[sp2 - 9].y, component[sp2 - 6].x - component[sp2 - 9].x);
- float a2 = _atan2(component[sp2 - 3].y - component[sp2 - 6].y, component[sp2 - 3].x - component[sp2 - 6].x);
- theta_s = a1 - a2;
-
- a1 = _atan2(component[sp2 - 3].y - component[sp2 - 6].y, component[sp2 - 3].x - component[sp2 - 6].x);
- a2 = _atan2(component[sp2].y - component[sp2 - 3].y, component[sp2].x - component[sp2 - 3].x);
- theta_i = a1 - a2;
- if (abs(theta_s - theta_i) > 0.6) break;
- }
- ang = ang_i;
- }
- }
-
- if (component.size() >= iMinLength)
- {
- segments.push_back(component);
- }
- }
- }
- }
-}
-
-
-
-void _tag_show_contours(cv::Mat1b& image, VVP& segments, const char* title)
-{
- Mat3b contoursIm(image.rows, image.cols, Vec3b(0, 0, 0));
- for (size_t i = 0; i& segments8, const char* title)
-{
- Mat3b contoursIm(image.rows, image.cols, Vec3b(0, 0, 0));
- for (size_t i = 0; i < segments8.size(); ++i)
- {
- Vec3b color(rand() % 255, 128 + rand() % 127, 128 + rand() % 127);
- for (size_t j = 0; j < segments8[i].size(); ++j)
- {
- for (size_t k = 0; k < segments8[i][j].size(); ++k)
- contoursIm(segments8[i][j][k]) = color;
- }
- }
- imshow(title, contoursIm);
-}
-
-bool _SortBottomLeft2TopRight(const Point& lhs, const Point& rhs)
-{
- if (lhs.x == rhs.x)
- {
- return lhs.y > rhs.y;
- }
- return lhs.x < rhs.x;
-}
-
-bool _SortBottomLeft2TopRight2f(const Point2f& lhs, const Point2f& rhs)
-{
- if (lhs.x == rhs.x)
- {
- return lhs.y > rhs.y;
- }
- return lhs.x < rhs.x;
-}
-
-bool _SortTopLeft2BottomRight(const Point& lhs, const Point& rhs)
-{
- if (lhs.x == rhs.x)
- {
- return lhs.y < rhs.y;
- }
- return lhs.x < rhs.x;
-}
-
-
-
-
-
-
-// #define DEBUG_SPEED
-// #define DEBUG_ELLFIT
-// #define DEBUG_PREPROCESSING
-
-// #define DISCARD_TCN
-#define DISCARD_TCN2
-#define DISCARD_CONSTRAINT_OBOX
-
-// #define DISCARD_CONSTRAINT_CONVEXITY
-// #define DISCARD_CONSTRAINT_POSITION
-#define CONSTRAINT_CNC_1
-// #define CONSTRAINT_CNC_2
-// #define CONSTRAINT_CNC_3
-// #define DISCARD_CONSTRAINT_CENTER
-
-// #define T_CNC 0.2f
-// #define T_TCN_L 0.4f // filter lines
-// #define T_TCN_P 0.6f
-
-// #define Thre_r 0.2f
-
-
-void _concate_arcs(VP& arc1, VP& arc2, VP& arc3, VP& arc)
-{
- for (int i = 0; i < arc1.size(); i++)
- arc.push_back(arc1[i]);
- for (int i = 0; i < arc2.size(); i++)
- arc.push_back(arc2[i]);
- for (int i = 0; i < arc3.size(); i++)
- arc.push_back(arc3[i]);
-}
-
-void _concate_arcs(VP& arc1, VP& arc2, VP& arc)
-{
- for (int i = 0; i < arc1.size(); i++)
- arc.push_back(arc1[i]);
- for (int i = 0; i < arc2.size(); i++)
- arc.push_back(arc2[i]);
-}
-
-EllipseDetector::EllipseDetector(void)
-{
- // Default Parameters Settings
- szPreProcessingGaussKernel_ = Size(5, 5);
- dPreProcessingGaussSigma_ = 1.0;
- fThrArcPosition_ = 1.0f;
- fMaxCenterDistance_ = 100.0f * 0.05f;
- fMaxCenterDistance2_ = fMaxCenterDistance_ * fMaxCenterDistance_;
- iMinEdgeLength_ = 16;
- fMinOrientedRectSide_ = 3.0f;
- fDistanceToEllipseContour_ = 0.1f;
- fMinScore_ = 0.7f;
- fMinReliability_ = 0.5f;
- uNs_ = 16;
- dPercentNe_ = 0.9;
-
- fT_CNC_ = 0.2f;
- fT_TCN_L_ = 0.4f; // filter lines
- fT_TCN_P_ = 0.6f;
- fThre_r_ = 0.2f;
-
- srand(unsigned(time(NULL)));
-}
-
-EllipseDetector::~EllipseDetector(void)
-{
-}
-
-void EllipseDetector::SetParameters(Size szPreProcessingGaussKernel,
- double dPreProcessingGaussSigma, // 高斯模糊,去噪声
- float fThPosition, // 位置约束,阈值,低于阈值不要
- float fMaxCenterDistance, // 中心点约束
- int iMinEdgeLength, // 最小弧度常识,一般 8-16, 小于的弧不要
- float fMinOrientedRectSide, // 筛选弧参数,最小外接矩形,短边长度
- float fDistanceToEllipseContour, // fitting得分d, 一般几个像素
- float fMinScore, // 0.5 - 0.7, 最终椭圆得分阈值
- float fMinReliability, // 弧长与椭圆周长比值阈值
- int iNs, // 中心性约数, 2个弧中心与椭圆中心距离 一般22
- double dPercentNe, // 边缘检测阈值, 越大保留的弧数量越多 0.9 - 0.99
- float fT_CNC, // 判读集合CNC, 一般不会调
- float fT_TCN_L,
- float fT_TCN_P,
- float fThre_r
-)
-{
- szPreProcessingGaussKernel_ = szPreProcessingGaussKernel;
- dPreProcessingGaussSigma_ = dPreProcessingGaussSigma;
- fThrArcPosition_ = fThPosition;
- fMaxCenterDistance_ = fMaxCenterDistance;
- iMinEdgeLength_ = iMinEdgeLength;
- fMinOrientedRectSide_ = fMinOrientedRectSide;
- fDistanceToEllipseContour_ = fDistanceToEllipseContour;
- fMinScore_ = fMinScore;
- fMinReliability_ = fMinReliability;
- uNs_ = iNs;
- dPercentNe_ = dPercentNe;
-
- fT_CNC_ = fT_CNC;
- fT_TCN_L_ = fT_TCN_L; // filter lines
- fT_TCN_P_ = fT_TCN_P;
- fThre_r_ = fThre_r;
-
- fMaxCenterDistance2_ = fMaxCenterDistance_ * fMaxCenterDistance_;
-}
-
-void EllipseDetector::RemoveStraightLine(VVP& segments, VVP& segments_update, int id)
-{
- int countedges = 0;
- // For each edge
- for (int i = 0; i < segments.size(); ++i)
- {
- VP& edgeSegment = segments[i];
-
-#ifndef DISCARD_CONSTRAINT_OBOX
- // Selection strategy - Step 1 - See Sect [3.1.2] of the paper
- // Constraint on axes aspect ratio
- RotatedRect oriented = minAreaRect(edgeSegment);
- float o_min = min(oriented.size.width, oriented.size.height);
-
- if (o_min < fMinOrientedRectSide_)
- {
- countedges++;
- continue;
- }
-#endif
-
- // Order edge points of the same arc
- if (id == 0 || id == 1 || id == 4 || id == 5) {
- sort(edgeSegment.begin(), edgeSegment.end(), _SortTopLeft2BottomRight);
- }
- else if (id == 2 || id == 3 || id == 6 || id == 7) {
- sort(edgeSegment.begin(), edgeSegment.end(), _SortBottomLeft2TopRight);
- }
-
- int iEdgeSegmentSize = int(edgeSegment.size());
-
- // Get extrema of the arc
- Point& left = edgeSegment[0];
- Point& right = edgeSegment[iEdgeSegmentSize - 1];
-
-#ifndef DISCARD_TCN
-#ifndef DISCARD_TCN2
- int flag = 0;
- for (int j = 0; j fT_TCN_L_) {
- flag = 1;
- break;
- }
- }
- if (0 == flag) {
- countedges++;
- continue;
- }
-#endif
-#ifndef DISCARD_TCN1
- Point& mid = edgeSegment[iEdgeSegmentSize / 2];
- float data[] = { float(left.x), float(left.y), 1.0f, float(mid.x), float(mid.y),
- 1.0f, float(right.x), float(right.y), 1.0f };
- Mat threePoints(Size(3, 3), CV_32FC1, data);
- double ans = determinant(threePoints);
-
- float dx = 1.0f*(left.x - right.x);
- float dy = 1.0f*(left.y - right.y);
- float edgelength2 = dx*dx + dy*dy;
- // double TCNl = ans / edgelength2;
- double TCNl = ans / (2 * pow(edgelength2, fT_TCN_P_));
- if (abs(TCNl) < fT_TCN_L_) {
- countedges++;
- continue;
- }
-#endif
-#endif
-
- segments_update.push_back(edgeSegment);
- }
-}
-
-void EllipseDetector::Detect(cv::Mat& I, std::vector& ellipses)
-{
- countOfFindEllipse_ = 0;
- countOfGetFastCenter_ = 0;
-
- Mat1b gray;
- cvtColor(I, gray, CV_BGR2GRAY);
-
-
- // Set the image size
- szIm_ = I.size();
-
- // Initialize temporary data structures
- Mat1b DP = Mat1b::zeros(szIm_); // arcs along positive diagonal
- Mat1b DN = Mat1b::zeros(szIm_); // arcs along negative diagonal
-
-
- ACC_N_SIZE = 101;
- ACC_R_SIZE = 180;
- ACC_A_SIZE = max(szIm_.height, szIm_.width);
-
- // Allocate accumulators
- accN = new int[ACC_N_SIZE];
- accR = new int[ACC_R_SIZE];
- accA = new int[ACC_A_SIZE];
-
-
- // Other temporary
-
- unordered_map centers; // hash map for reusing already computed EllipseData
-
- PreProcessing(gray, DP, DN);
-
-
- points_1.clear();
- points_2.clear();
- points_3.clear();
- points_4.clear();
- // Detect edges and find convexities
- DetectEdges13(DP, points_1, points_3);
- DetectEdges24(DN, points_2, points_4);
-
-
- Triplets124(points_1, points_2, points_4, centers, ellipses);
- Triplets231(points_2, points_3, points_1, centers, ellipses);
- Triplets342(points_3, points_4, points_2, centers, ellipses);
- Triplets413(points_4, points_1, points_3, centers, ellipses);
-
- sort(ellipses.begin(), ellipses.end());
-
-
- // Free accumulator memory
- delete[] accN;
- delete[] accR;
- delete[] accA;
-
- // Cluster detections
- ClusterEllipses(ellipses);
-}
-
-void EllipseDetector::Detect(Mat3b& I, vector& ellipses)
-{
- countOfFindEllipse_ = 0;
- countOfGetFastCenter_ = 0;
-
-#ifdef DEBUG_SPEED
- Tic(0); // prepare data structure
-#endif
-
- // Convert to grayscale
- Mat1b gray;
- cvtColor(I, gray, CV_BGR2GRAY);
-
- // Set the image size
- szIm_ = I.size();
-
- // Initialize temporary data structures
- Mat1b DP = Mat1b::zeros(szIm_); // arcs along positive diagonal
- Mat1b DN = Mat1b::zeros(szIm_); // arcs along negative diagonal
-
- // Initialize accumulator dimensions
- ACC_N_SIZE = 101;
- ACC_R_SIZE = 180;
- ACC_A_SIZE = max(szIm_.height, szIm_.width);
-
- // Allocate accumulators
- accN = new int[ACC_N_SIZE];
- accR = new int[ACC_R_SIZE];
- accA = new int[ACC_A_SIZE];
-
- // Other temporary
-
- unordered_map centers; // hash map for reusing already computed EllipseData
-
-#ifdef DEBUG_SPEED
- Toc(0, "prepare data structure"); // prepare data structure
-#endif
-
- // Preprocessing
- // From input image I, find edge point with coarse convexity along positive (DP) or negative (DN) diagonal
- PreProcessing(gray, DP, DN);
-
-#ifdef DEBUG_SPEED
- Tic(3); // preprocessing
-#endif
-
- points_1.clear();
- points_2.clear();
- points_3.clear();
- points_4.clear();
- // Detect edges and find convexities
- DetectEdges13(DP, points_1, points_3);
- DetectEdges24(DN, points_2, points_4);
-
-#ifdef DEBUG_SPEED
- Toc(3, "preprocessing_2"); // preprocessing
-#endif
-
- // #define DEBUG_PREPROCESSING_S4
-#ifdef DEBUG_PREPROCESSING_S4
- Mat3b out(I.rows, I.cols, Vec3b(0, 0, 0));
- for (unsigned i = 0; i < points_1.size(); ++i)
- {
- // Vec3b color(rand()%255, 128+rand()%127, 128+rand()%127);
- Vec3b color(255, 0, 0);
- for (unsigned j = 0; j < points_1[i].size(); ++j)
- out(points_1[i][j]) = color;
- }
- for (unsigned i = 0; i < points_2.size(); ++i)
- {
- // Vec3b color(rand()%255, 128+rand()%127, 128+rand()%127);
- Vec3b color(0, 255, 0);
- for (unsigned j = 0; j < points_2[i].size(); ++j)
- out(points_2[i][j]) = color;
- }
- for (unsigned i = 0; i < points_3.size(); ++i)
- {
- // Vec3b color(rand()%255, 128+rand()%127, 128+rand()%127);
- Vec3b color(0, 0, 255);
- for (unsigned j = 0; j < points_3[i].size(); ++j)
- out(points_3[i][j]) = color;
- }
- for (unsigned i = 0; i < points_4.size(); ++i)
- {
- // Vec3b color(rand()%255, 128+rand()%127, 128+rand()%127);
- Vec3b color(255, 0, 255);
- for (unsigned j = 0; j < points_4[i].size(); ++j)
- out(points_4[i][j]) = color;
- }
- cv::imshow("PreProcessing->Output", out);
- waitKey();
-#endif
-
-#ifdef DEBUG_SPEED
- Tic(4); // grouping
-#endif
-
-
- Triplets124(points_1, points_2, points_4, centers, ellipses);
- Triplets231(points_2, points_3, points_1, centers, ellipses);
- Triplets342(points_3, points_4, points_2, centers, ellipses);
- Triplets413(points_4, points_1, points_3, centers, ellipses);
-
-#ifdef DEBUG_SPEED
- Toc(4, "grouping"); // grouping
-#endif
-
-#ifdef DEBUG_SPEED
- Tic(5);
-#endif
-
- // Sort detected ellipses with respect to score
- sort(ellipses.begin(), ellipses.end());
-
- // Free accumulator memory
- delete[] accN;
- delete[] accR;
- delete[] accA;
-
- // Cluster detections
- ClusterEllipses(ellipses);
-
-#ifdef DEBUG_SPEED
- Toc(5, "cluster detections");
-#endif
-}
-
-void EllipseDetector::PreProcessing(Mat1b& I, Mat1b& arcs8)
-{
- GaussianBlur(I, I, szPreProcessingGaussKernel_, dPreProcessingGaussSigma_);
-
- // Temp variables
- Mat1b E; // edge mask
- Mat1s DX, DY; // sobel derivatives
-
- _tag_canny(I, E, DX, DY, 3, false, dPercentNe_); // Detect edges
-
- // Mat1f dxf, dyf;
- // normalize(DX, dxf, 0, 1, NORM_MINMAX);
- // normalize(DY, dyf, 0, 1, NORM_MINMAX);
- //Mat1f dx, dy;
- //DX.convertTo(dx, CV_32F);
- //DY.convertTo(dy, CV_32F);
- //// DYDX_ = dy / dx;
-
- ////Mat1f edx, edy;
- ////Sobel(E, edx, CV_32F, 1, 0);
- ////Sobel(E, edy, CV_32F, 0, 1);
-
- //DYDX_ = -1 / (dy / dx);
- //CV_Assert(DYDX_.type() == CV_32F);
-
- //cv::GaussianBlur(dx, dx, Size(5, 5), 0, 0);
- //cv::GaussianBlur(dy, dy, Size(5, 5), 0, 0);
- //cv::phase(dx, dy, EO_);
-
-#define SIGN(n) ((n)<=0?((n)<0?-1:0):1)
-
- // cout << SIGN(0) << " " << SIGN(-1) << " " << SIGN(1) << endl;
-
- int sign_x, sign_y, sign_xy;
- for (int i = 0; i < szIm_.height; ++i) {
- short* _dx = DX.ptr(i);
- short* _dy = DY.ptr(i);
- uchar* _e = E.ptr(i);
- uchar* _arc = arcs8.ptr(i);
-
- for (int j = 0; j < szIm_.width; ++j) {
- if (!(_e[j] <= 0)) // !!!!!!
- {
- sign_x = SIGN(_dx[j]);
- sign_y = SIGN(_dy[j]);
- sign_xy = SIGN(abs(_dx[j]) - abs(_dy[j]));
- if (sign_x == 1 && sign_y == 1 && sign_xy == 1) {
- _arc[j] = (uchar)3;
- }
- else if (sign_x == 1 && sign_y == 1 && sign_xy == -1) {
- _arc[j] = (uchar)4;
- }
- else if (sign_x == 1 && sign_y == -1 && sign_xy == -1) {
- _arc[j] = (uchar)1;
- }
- else if (sign_x == 1 && sign_y == -1 && sign_xy == 1) {
- _arc[j] = (uchar)2;
- }
- else if (sign_x == -1 && sign_y == -1 && sign_xy == 1) {
- _arc[j] = (uchar)7;
- }
- else if (sign_x == -1 && sign_y == -1 && sign_xy == -1) {
- _arc[j] = (uchar)8;
- }
- else if (sign_x == -1 && sign_y == 1 && sign_xy == -1) {
- _arc[j] = (uchar)5;
- }
- else if (sign_x == -1 && sign_y == 1 && sign_xy == 1) {
- _arc[j] = (uchar)6;
- }
- }
- }
- }
-}
-
-void EllipseDetector::PreProcessing(Mat1b& I, Mat1b& DP, Mat1b& DN)
-{
-#ifdef DEBUG_SPEED
- Tic(1); // edge detection
-#endif
-
- GaussianBlur(I, I, szPreProcessingGaussKernel_, dPreProcessingGaussSigma_);
-
- // Temp variables
- Mat1b E; // edge mask
- Mat1s DX, DY; // sobel derivatives
-
- // Detect edges
- _tag_canny(I, E, DX, DY, 3, false, dPercentNe_);
-
- Mat1f dx, dy;
- DX.convertTo(dx, CV_32F);
- DY.convertTo(dy, CV_32F);
- //// cv::GaussianBlur(dx, dx, Size(5, 5), 0, 0);
- //// cv::GaussianBlur(dy, dy, Size(5, 5), 0, 0);
- cv::phase(dx, dy, EO_);
-
-#ifdef DEBUG_PREPROCESSING
- imshow("PreProcessing->Edge", E); waitKey(50);
-#endif
-
-#ifdef DEBUG_SPEED
- Toc(1, "edge detection"); // edge detection
- Tic(2); // preprocessing
-#endif
-
- float M_3_2_PI = M_PI + M_1_2_PI;
- // For each edge points, compute the edge direction
- for (int i = 0; i < szIm_.height; ++i) {
- float* _o = EO_.ptr(i);
- uchar* _e = E.ptr(i);
- uchar* _dp = DP.ptr(i);
- uchar* _dn = DN.ptr(i);
-
- for (int j = 0; j < szIm_.width; ++j) {
- if (!(_e[j] <= 0)) // !!!!!!
- {
- if (_o[j] == 0 || _o[j] == M_1_2_PI || _o[j] == M_PI || _o[j] == M_3_2_PI) {
- _dn[j] = (uchar)255; _dp[j] = (uchar)255;
- }
- else if ((_o[j] > 0 && _o[j] < M_1_2_PI) || (_o[j] > M_PI && _o[j] < M_3_2_PI)) _dn[j] = (uchar)255;
- else _dp[j] = (uchar)255;
- }
- }
- }
-
-#ifdef DEBUG_PREPROCESSING
- imshow("PreProcessing->DP", DP); waitKey(50);
- imshow("PreProcessing->DN", DN); waitKey();
-#endif
-#ifdef DEBUG_SPEED
- Toc(2, "preprocessing"); // preprocessing
-#endif
-}
-
-void EllipseDetector::DetectEdges13(Mat1b& DP, VVP& points_1, VVP& points_3)
-{
- // Vector of connected edge points
- VVP contours;
- int countedges = 0;
- // Labeling 8-connected edge points, discarding edge too small
- _tag_find_contours(DP, contours, iMinEdgeLength_); // put small arc edges to a vector
-
-#ifdef DEBUG_PREPROCESSING
- Mat1b DP_show = DP.clone();
- _tag_show_contours(DP_show, contours, "PreProcessing->Contours13"); waitKey();
-#endif
-
-
- // For each edge
- for (int i = 0; i < contours.size(); ++i)
- {
- VP& edgeSegment = contours[i];
-
-#ifndef DISCARD_CONSTRAINT_OBOX
- // Selection strategy - Step 1 - See Sect [3.1.2] of the paper
- // Constraint on axes aspect ratio
- RotatedRect oriented = minAreaRect(edgeSegment);
- float o_min = min(oriented.size.width, oriented.size.height);
-
- if (o_min < fMinOrientedRectSide_)
- {
- countedges++;
- continue;
- }
-#endif
-
- // Order edge points of the same arc
- sort(edgeSegment.begin(), edgeSegment.end(), _SortTopLeft2BottomRight);
- int iEdgeSegmentSize = int(edgeSegment.size());
-
- // Get extrema of the arc
- Point& left = edgeSegment[0];
- Point& right = edgeSegment[iEdgeSegmentSize - 1];
-
-#ifndef DISCARD_TCN
-#ifndef DISCARD_TCN2
- int flag = 0;
- for (int j = 0; j fT_TCN_L_) {
- flag = 1;
- break;
- }
- }
- if (0 == flag) {
- countedges++;
- continue;
- }
-#endif
-#ifndef DISCARD_TCN1
- Point& mid = edgeSegment[iEdgeSegmentSize / 2];
- float data[] = { float(left.x), float(left.y), 1.0f, float(mid.x), float(mid.y),
- 1.0f, float(right.x), float(right.y), 1.0f };
- Mat threePoints(Size(3, 3), CV_32FC1, data);
- double ans = determinant(threePoints);
-
- float dx = 1.0f*(left.x - right.x);
- float dy = 1.0f*(left.y - right.y);
- float edgelength2 = dx*dx + dy*dy;
- // double TCNl = ans / edgelength2;
- double TCNl = ans / (2 * pow(edgelength2, fT_TCN_P_));
- if (abs(TCNl) < fT_TCN_L_) {
- countedges++;
- continue;
- }
-#endif
-#endif
-
- // Find convexity - See Sect [3.1.3] of the paper
- int iCountTop = 0;
- int xx = left.x;
- for (int k = 1; k < iEdgeSegmentSize; ++k)
- {
- if (edgeSegment[k].x == xx) continue;
-
- iCountTop += (edgeSegment[k].y - left.y);
- xx = edgeSegment[k].x;
- }
-
- int width = abs(right.x - left.x) + 1;
- int height = abs(right.y - left.y) + 1;
- int iCountBottom = (width * height) - iEdgeSegmentSize - iCountTop;
-
- if (iCountBottom > iCountTop)
- { // 1
- points_1.push_back(edgeSegment);
- }
- else if (iCountBottom < iCountTop)
- { // 3
- points_3.push_back(edgeSegment);
- }
- }
-
-}
-
-void EllipseDetector::DetectEdges24(Mat1b& DN, VVP& points_2, VVP& points_4)
-{
- // Vector of connected edge points
- VVP contours;
- int countedges = 0;
- /// Labeling 8-connected edge points, discarding edge too small
- _tag_find_contours(DN, contours, iMinEdgeLength_);
-
-#ifdef DEBUG_PREPROCESSING
- _tag_show_contours(DN, contours, "PreProcessing->Contours24"); waitKey();
-#endif
-
- int iContoursSize = unsigned(contours.size());
-
-
- // For each edge
- for (int i = 0; i < iContoursSize; ++i)
- {
- VP& edgeSegment = contours[i];
-
-#ifndef DISCARD_CONSTRAINT_OBOX
- // Selection strategy - Step 1 - See Sect [3.1.2] of the paper
- // Constraint on axes aspect ratio
- RotatedRect oriented = minAreaRect(edgeSegment);
- float o_min = min(oriented.size.width, oriented.size.height);
-
- if (o_min < fMinOrientedRectSide_)
- {
- countedges++;
- continue;
- }
-#endif
-
- // Order edge points of the same arc
- sort(edgeSegment.begin(), edgeSegment.end(), _SortBottomLeft2TopRight);
- int iEdgeSegmentSize = unsigned(edgeSegment.size());
-
- // Get extrema of the arc
- Point& left = edgeSegment[0];
- Point& right = edgeSegment[iEdgeSegmentSize - 1];
-
-#ifndef DISCARD_TCN
-#ifndef DISCARD_TCN2
- int flag = 0;
- for (int j = 0; j fT_TCN_L_) {
- flag = 1;
- break;
- }
- }
- if (0 == flag) {
- countedges++;
- continue;
- }
-#endif
-#ifndef DISCARD_TCN1
- Point& mid = edgeSegment[iEdgeSegmentSize / 2];
- float data[] = { float(left.x), float(left.y), 1.0f, float(mid.x), float(mid.y),
- 1.0f, float(right.x), float(right.y), 1.0f };
- Mat threePoints(Size(3, 3), CV_32FC1, data);
- double ans = determinant(threePoints);
-
- float dx = 1.0f*(left.x - right.x);
- float dy = 1.0f*(left.y - right.y);
- float edgelength2 = dx*dx + dy*dy;
- // double TCNl = ans / edgelength2;
- double TCNl = ans / (2 * pow(edgelength2, fT_TCN_P_));
- if (abs(TCNl) < fT_TCN_L_) {
- countedges++;
- continue;
- }
-#endif
-#endif
-
- // Find convexity - See Sect [3.1.3] of the paper
- int iCountBottom = 0;
- int xx = left.x;
- for (int k = 1; k < iEdgeSegmentSize; ++k)
- {
- if (edgeSegment[k].x == xx) continue;
-
- iCountBottom += (left.y - edgeSegment[k].y);
- xx = edgeSegment[k].x;
- }
-
- int width = abs(right.x - left.x) + 1;
- int height = abs(right.y - left.y) + 1;
- int iCountTop = (width *height) - iEdgeSegmentSize - iCountBottom;
-
- if (iCountBottom > iCountTop)
- {
- // 2
- points_2.push_back(edgeSegment);
- }
- else if (iCountBottom < iCountTop)
- {
- // 4
- points_4.push_back(edgeSegment);
- }
- }
-
-}
-
-float inline ed2(const cv::Point& A, const cv::Point& B)
-{
- return float(((B.x - A.x)*(B.x - A.x) + (B.y - A.y)*(B.y - A.y)));
-}
-
-
-#define T124 pjf,pjm,pjl,pif,pim,pil // origin
-#define T231 pil,pim,pif,pjf,pjm,pjl
-#define T342 pif,pim,pil,pjf,pjm,pjl
-#define T413 pif,pim,pil,pjl,pjm,pjf
-
-
-// Verify triplets of arcs with convexity: i=1, j=2, k=4
-void EllipseDetector::Triplets124(VVP& pi,
- VVP& pj,
- VVP& pk,
- unordered_map& data,
- vector& ellipses
-)
-{
- // get arcs length
- ushort sz_i = ushort(pi.size());
- ushort sz_j = ushort(pj.size());
- ushort sz_k = ushort(pk.size());
-
- // For each edge i
- for (ushort i = 0; i < sz_i; ++i)
- {
- VP& edge_i = pi[i];
- ushort sz_ei = ushort(edge_i.size());
-
- Point& pif = edge_i[0];
- Point& pim = edge_i[sz_ei / 2];
- Point& pil = edge_i[sz_ei - 1];
-
- // 1,2 -> reverse 1, swap
- VP rev_i(edge_i.size());
- reverse_copy(edge_i.begin(), edge_i.end(), rev_i.begin());
-
- // For each edge j
- for (ushort j = 0; j < sz_j; ++j)
- {
- vector ellipses_i;
-
- VP& edge_j = pj[j];
- ushort sz_ej = ushort(edge_j.size());
-
- Point& pjf = edge_j[0];
- Point& pjm = edge_j[sz_ej / 2];
- Point& pjl = edge_j[sz_ej - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
-
- //if (sqrt((pjl.x - pif.x)*(pjl.x - pif.x) + (pjl.y - pif.y)*(pjl.y - pif.y)) > MAX(edge_i.size(), edge_j.size()))
- // continue;
- double tm1 = _tic();
- // CONSTRAINTS on position
- if (pjl.x > pif.x + fThrArcPosition_) //is right
- continue;
-
-#endif
-
- tm1 = _tic();
- if (_ed2(pil, pjf) / _ed2(pif, pjl) < fThre_r_)
- continue;
-
-#ifdef CONSTRAINT_CNC_1
- tm1 = _tic();
- // cnc constraint1 2se se1//pil,pim,pif,pjf,pjm,pjl pjf,pjm,pjl,pif,pim,pil
- if (fabs(_value4SixPoints(T124) - 1) > fT_CNC_)
- continue;
-#endif
-
- tm1 = _tic();
- EllipseData data_ij;
- uint key_ij = GenerateKey(PAIR_12, i, j);
- // If the data for the pair i-j have not been computed yet
- if (data.count(key_ij) == 0)
- {
- // 1,2 -> reverse 1, swap
- // Compute data!
- GetFastCenter(edge_j, rev_i, data_ij);
- // Insert computed data in the hash table
- data.insert(pair(key_ij, data_ij));
- }
- else
- {
- // Otherwise, just lookup the data in the hash table
- data_ij = data.at(key_ij);
- }
-
- // for each edge k
- for (ushort k = 0; k < sz_k; ++k)
- {
- VP& edge_k = pk[k];
- ushort sz_ek = ushort(edge_k.size());
-
- Point& pkf = edge_k[0];
- Point& pkm = edge_k[sz_ek / 2];
- Point& pkl = edge_k[sz_ek - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- // CONSTRAINTS on position
- if (pkl.y < pil.y - fThrArcPosition_)
- continue;
-#endif
-#ifdef CONSTRAINT_CNC_2
- // cnc constraint2
- if (fabs(_value4SixPoints(pif, pim, pil, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
-#ifdef CONSTRAINT_CNC_3
- // cnc constraint3
- if (fabs(_value4SixPoints(pjf, pjm, pjl, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
-
- uint key_ik = GenerateKey(PAIR_14, i, k);
-
- // Find centers
- EllipseData data_ik;
-
- // If the data for the pair i-k have not been computed yet
- if (data.count(key_ik) == 0)
- {
- // 1,4 -> ok
- // Compute data!
- GetFastCenter(edge_i, edge_k, data_ik);
- // Insert computed data in the hash table
- data.insert(pair(key_ik, data_ik));
- }
- else
- {
- // Otherwise, just lookup the data in the hash table
- data_ik = data.at(key_ik);
- }
-
- // INVALID CENTERS
- if (!data_ij.isValid || !data_ik.isValid)
- {
- continue;
- }
-
-#ifndef DISCARD_CONSTRAINT_CENTER
- // Selection strategy - Step 3. See Sect [3.2.2] in the paper
- // The computed centers are not close enough
- if (ed2(data_ij.Cab, data_ik.Cab) > fMaxCenterDistance2_)
- {
- // discard
- continue;
- }
-#endif
-
- // If all constraints of the selection strategy have been satisfied,
- // we can start estimating the ellipse parameters
-
- // Find ellipse parameters
- // Get the coordinates of the center (xc, yc)
- Point2f center = GetCenterCoordinates(data_ij, data_ik);
-
- Ellipse ell;
- // Find remaining paramters (A,B,rho)
- FindEllipses(center, edge_i, edge_j, edge_k, data_ij, data_ik, ell);
- ellipses_i.push_back(ell);
- }
- /*-----------------------------------------------------------------*/
- int rt = -1;
- float rs = 0;
- for (int t = 0; t < (int)ellipses_i.size(); t++)
- {
- if (ellipses_i[t].score_ > rs)
- {
- rs = ellipses_i[t].score_; rt = t;
- }
- }
- if (rt > -1)
- {
- ellipses.push_back(ellipses_i[rt]);
- }
- /*-----------------------------------------------------------------*/
- }
- }
-}
-
-void EllipseDetector::Triplets231(VVP& pi,
- VVP& pj,
- VVP& pk,
- unordered_map& data,
- vector& ellipses
-)
-{
- ushort sz_i = ushort(pi.size());
- ushort sz_j = ushort(pj.size());
- ushort sz_k = ushort(pk.size());
-
- // For each edge i
- for (ushort i = 0; i < sz_i; ++i)
- {
- VP& edge_i = pi[i];
- ushort sz_ei = ushort(edge_i.size());
-
- Point& pif = edge_i[0];
- Point& pim = edge_i[sz_ei / 2];
- Point& pil = edge_i[sz_ei - 1];
-
- VP rev_i(edge_i.size());
- reverse_copy(edge_i.begin(), edge_i.end(), rev_i.begin());
-
- // For each edge j
- for (ushort j = 0; j < sz_j; ++j)
- {
- vector ellipses_i;
-
- VP& edge_j = pj[j];
- ushort sz_ej = ushort(edge_j.size());
-
- Point& pjf = edge_j[0];
- Point& pjm = edge_j[sz_ej / 2];
- Point& pjl = edge_j[sz_ej - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- //if (sqrt((pjf.x - pif.x)*(pjf.x - pif.x) + (pjf.y - pif.y)*(pjf.y - pif.y)) > MAX(edge_i.size(), edge_j.size()))
- // continue;
-
- double tm1 = _tic();
- // CONSTRAINTS on position
- if (pjf.y < pif.y - fThrArcPosition_)
- continue;
-
-#endif
-
- tm1 = _tic();
- if (_ed2(pif, pjf) / _ed2(pil, pjl) < fThre_r_)
- continue;
-
-#ifdef CONSTRAINT_CNC_1
- tm1 = _tic();
- // cnc constraint1 2es se3 // pif,pim,pil,pjf,pjm,pjl pil,pim,pif,pjf,pjm,pjl
- if (fabs(_value4SixPoints(T231) - 1) > fT_CNC_)
- continue;
-#endif
-
- tm1 = _tic();
- VP rev_j(edge_j.size());
- reverse_copy(edge_j.begin(), edge_j.end(), rev_j.begin());
-
- EllipseData data_ij;
- uint key_ij = GenerateKey(PAIR_23, i, j);
- if (data.count(key_ij) == 0)
- {
- // 2,3 -> reverse 2,3
- GetFastCenter(rev_i, rev_j, data_ij);
- data.insert(pair(key_ij, data_ij));
- }
- else
- {
- data_ij = data.at(key_ij);
- }
-
- // For each edge k
- for (ushort k = 0; k < sz_k; ++k)
- {
- VP& edge_k = pk[k];
-
- ushort sz_ek = ushort(edge_k.size());
-
- Point& pkf = edge_k[0];
- Point& pkm = edge_k[sz_ek / 2];
- Point& pkl = edge_k[sz_ek - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- // CONSTRAINTS on position
- if (pkf.x < pil.x - fThrArcPosition_)
- continue;
-#endif
-
-#ifdef CONSTRAINT_CNC_2
- // cnc constraint2
- if (fabs(_value4SixPoints(pif, pim, pil, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
-#ifdef CONSTRAINT_CNC_3
- // cnc constraint3
- if (fabs(_value4SixPoints(pjf, pjm, pjl, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
- uint key_ik = GenerateKey(PAIR_12, k, i);
-
- // Find centers
-
- EllipseData data_ik;
-
-
- if (data.count(key_ik) == 0)
- {
- // 2,1 -> reverse 1
- VP rev_k(edge_k.size());
- reverse_copy(edge_k.begin(), edge_k.end(), rev_k.begin());
-
- GetFastCenter(edge_i, rev_k, data_ik);
- data.insert(pair(key_ik, data_ik));
- }
- else
- {
- data_ik = data.at(key_ik);
- }
-
- // INVALID CENTERS
- if (!data_ij.isValid || !data_ik.isValid)
- {
- continue;
- }
-
-#ifndef DISCARD_CONSTRAINT_CENTER
- // CONSTRAINT ON CENTERS
- if (ed2(data_ij.Cab, data_ik.Cab) > fMaxCenterDistance2_)
- {
- // discard
- continue;
- }
-#endif
- // Find ellipse parameters
- Point2f center = GetCenterCoordinates(data_ij, data_ik);
-
- Ellipse ell;
- FindEllipses(center, edge_i, edge_j, edge_k, data_ij, data_ik, ell);
- ellipses_i.push_back(ell);
- }
- /*-----------------------------------------------------------------*/
- int rt = -1;
- float rs = 0;
- for (int t = 0; t < (int)ellipses_i.size(); t++)
- {
- if (ellipses_i[t].score_ > rs)
- {
- rs = ellipses_i[t].score_; rt = t;
- }
- }
- if (rt > -1)
- {
- ellipses.push_back(ellipses_i[rt]);
- }
- /*-----------------------------------------------------------------*/
- }
- }
-}
-
-void EllipseDetector::Triplets342(VVP& pi,
- VVP& pj,
- VVP& pk,
- unordered_map& data,
- vector& ellipses
-)
-{
- ushort sz_i = ushort(pi.size());
- ushort sz_j = ushort(pj.size());
- ushort sz_k = ushort(pk.size());
-
- // For each edge i
- for (ushort i = 0; i < sz_i; ++i)
- {
- VP& edge_i = pi[i];
- ushort sz_ei = ushort(edge_i.size());
-
- Point& pif = edge_i[0];
- Point& pim = edge_i[sz_ei / 2];
- Point& pil = edge_i[sz_ei - 1];
-
- VP rev_i(edge_i.size());
- reverse_copy(edge_i.begin(), edge_i.end(), rev_i.begin());
-
- // For each edge j
- for (ushort j = 0; j < sz_j; ++j)
- {
- vector ellipses_i;
-
- VP& edge_j = pj[j];
- ushort sz_ej = ushort(edge_j.size());
-
- Point& pjf = edge_j[0];
- Point& pjm = edge_j[sz_ej / 2];
- Point& pjl = edge_j[sz_ej - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- //if (sqrt((pjf.x - pil.x)*(pjf.x - pil.x) + (pjf.y - pil.y)*(pjf.y - pil.y)) > MAX(edge_i.size(), edge_j.size()))
- // continue;
-
- double tm1 = _tic();
- // CONSTRAINTS on position
- if (pjf.x < pil.x - fThrArcPosition_) // is left
- continue;
-
-#endif
-
- tm1 = _tic();
- if (_ed2(pil, pjf) / _ed2(pif, pjl) < fThre_r_)
- continue;
-
-#ifdef CONSTRAINT_CNC_1
- tm1 = _tic();
- // cnc constraint1 3se se4 // pil,pim,pif,pjf,pjm,pjl pif,pim,pil,pjf,pjm,pjl
- if (fabs(_value4SixPoints(T342) - 1) > fT_CNC_)
- continue;
-
-#endif
-
- tm1 = _tic();
- VP rev_j(edge_j.size());
- reverse_copy(edge_j.begin(), edge_j.end(), rev_j.begin());
-
- EllipseData data_ij;
- uint key_ij = GenerateKey(PAIR_34, i, j);
-
- if (data.count(key_ij) == 0)
- {
- // 3,4 -> reverse 4
-
- GetFastCenter(edge_i, rev_j, data_ij);
- data.insert(pair(key_ij, data_ij));
- }
- else
- {
- data_ij = data.at(key_ij);
- }
-
-
- // For each edge k
- for (ushort k = 0; k < sz_k; ++k)
- {
- VP& edge_k = pk[k];
- ushort sz_ek = ushort(edge_k.size());
-
- Point& pkf = edge_k[0];
- Point& pkm = edge_k[sz_ek / 2];
- Point& pkl = edge_k[sz_ek - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- // CONSTRAINTS on position
- if (pkf.y > pif.y + fThrArcPosition_)
- continue;
-#endif
-
-#ifdef CONSTRAINT_CNC_2
- // cnc constraint2
- if (fabs(_value4SixPoints(pif, pim, pil, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
-#ifdef CONSTRAINT_CNC_3
- // cnc constraint3
- if (fabs(_value4SixPoints(pjf, pjm, pjl, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
- uint key_ik = GenerateKey(PAIR_23, k, i);
-
- // Find centers
-
- EllipseData data_ik;
-
-
-
- if (data.count(key_ik) == 0)
- {
- // 3,2 -> reverse 3,2
-
- VP rev_k(edge_k.size());
- reverse_copy(edge_k.begin(), edge_k.end(), rev_k.begin());
-
- GetFastCenter(rev_i, rev_k, data_ik);
-
- data.insert(pair(key_ik, data_ik));
- }
- else
- {
- data_ik = data.at(key_ik);
- }
-
-
- // INVALID CENTERS
- if (!data_ij.isValid || !data_ik.isValid)
- {
- continue;
- }
-
-#ifndef DISCARD_CONSTRAINT_CENTER
- // CONSTRAINT ON CENTERS
- if (ed2(data_ij.Cab, data_ik.Cab) > fMaxCenterDistance2_)
- {
- // discard
- continue;
- }
-#endif
- // Find ellipse parameters
- Point2f center = GetCenterCoordinates(data_ij, data_ik);
-
- Ellipse ell;
- FindEllipses(center, edge_i, edge_j, edge_k, data_ij, data_ik, ell);
- ellipses_i.push_back(ell);
- }
- /*-----------------------------------------------------------------*/
- int rt = -1;
- float rs = 0;
- for (int t = 0; t < (int)ellipses_i.size(); t++)
- {
- if (ellipses_i[t].score_ > rs)
- {
- rs = ellipses_i[t].score_; rt = t;
- }
- }
- if (rt > -1)
- {
- ellipses.push_back(ellipses_i[rt]);
- }
- /*-----------------------------------------------------------------*/
- }
- }
-}
-
-void EllipseDetector::Triplets413(VVP& pi,
- VVP& pj,
- VVP& pk,
- unordered_map& data,
- vector& ellipses
-)
-{
- ushort sz_i = ushort(pi.size());
- ushort sz_j = ushort(pj.size());
- ushort sz_k = ushort(pk.size());
-
- // For each edge i
- for (ushort i = 0; i < sz_i; ++i)
- {
- VP& edge_i = pi[i];
- ushort sz_ei = ushort(edge_i.size());
-
- Point& pif = edge_i[0];
- Point& pim = edge_i[sz_ei / 2];
- Point& pil = edge_i[sz_ei - 1];
-
- VP rev_i(edge_i.size());
- reverse_copy(edge_i.begin(), edge_i.end(), rev_i.begin());
-
- // For each edge j
- for (ushort j = 0; j < sz_j; ++j)
- {
- vector ellipses_i;
-
- VP& edge_j = pj[j];
- ushort sz_ej = ushort(edge_j.size());
-
- Point& pjf = edge_j[0];
- Point& pjm = edge_j[sz_ej / 2];
- Point& pjl = edge_j[sz_ej - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- //if (sqrt((pjl.x - pil.x)*(pjl.x - pil.x) + (pjl.y - pil.y)*(pjl.y - pil.y)) > MAX(edge_i.size(), edge_j.size()))
- // continue;
-
- double tm1 = _tic();
- // CONSTRAINTS on position
- if (pjl.y > pil.y + fThrArcPosition_) // is below
- continue;
-
-#endif
-
- tm1 = _tic();
- if (_ed2(pif, pjf) / _ed2(pil, pjl) < fThre_r_)
- continue;
-
-#ifdef CONSTRAINT_CNC_1
- tm1 = _tic();
- // cnc constraint1 4se es1 // pif,pim,pil,pjf,pjm,pjl pil,pim,pif,pjl,pjm,pjf pif,pim,pil,pjl,pjm,pjf
- if (fabs(_value4SixPoints(T413) - 1) > fT_CNC_)
- continue;
-#endif
-
- tm1 = _tic();
- EllipseData data_ij;
- uint key_ij = GenerateKey(PAIR_14, j, i);
-
- if (data.count(key_ij) == 0)
- {
- // 4,1 -> OK
- GetFastCenter(edge_i, edge_j, data_ij);
- data.insert(pair(key_ij, data_ij));
- }
- else
- {
- data_ij = data.at(key_ij);
- }
-
- // For each edge k
- for (ushort k = 0; k < sz_k; ++k)
- {
- VP& edge_k = pk[k];
- ushort sz_ek = ushort(edge_k.size());
-
- Point& pkf = edge_k[0];
- Point& pkm = edge_k[sz_ek / 2];
- Point& pkl = edge_k[sz_ek - 1];
-
-#ifndef DISCARD_CONSTRAINT_POSITION
- // CONSTRAINTS on position
- if (pkl.x > pif.x + fThrArcPosition_)
- continue;
-#endif
-
-#ifdef CONSTRAINT_CNC_2
- // cnc constraint2
- if (fabs(_value4SixPoints(pif, pim, pil, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
-#ifdef CONSTRAINT_CNC_3
- // cnc constraint2
- if (fabs(_value4SixPoints(pjf, pjm, pjl, pkf, pkm, pkl) - 1) > fT_CNC_)
- continue;
-#endif
- uint key_ik = GenerateKey(PAIR_34, k, i);
-
- // Find centers
-
- EllipseData data_ik;
-
-
-
- if (data.count(key_ik) == 0)
- {
- // 4,3 -> reverse 4
- GetFastCenter(rev_i, edge_k, data_ik);
- data.insert(pair(key_ik, data_ik));
- }
- else
- {
- data_ik = data.at(key_ik);
- }
-
- // INVALID CENTERS
- if (!data_ij.isValid || !data_ik.isValid)
- {
- continue;
- }
-
-#ifndef DISCARD_CONSTRAINT_CENTER
- // CONSTRAIN ON CENTERS
- if (ed2(data_ij.Cab, data_ik.Cab) > fMaxCenterDistance2_)
- {
- // discard
- continue;
- }
-#endif
- // Find ellipse parameters
- Point2f center = GetCenterCoordinates(data_ij, data_ik);
-
- Ellipse ell;
- FindEllipses(center, edge_i, edge_j, edge_k, data_ij, data_ik, ell);
- ellipses_i.push_back(ell);
- }
- /*-----------------------------------------------------------------*/
- int rt = -1;
- float rs = 0;
- for (int t = 0; t < (int)ellipses_i.size(); t++)
- {
- if (ellipses_i[t].score_ > rs)
- {
- rs = ellipses_i[t].score_; rt = t;
- }
- }
- if (rt > -1)
- {
- ellipses.push_back(ellipses_i[rt]);
- }
- /*-----------------------------------------------------------------*/
- }
- }
-}
-
-int EllipseDetector::FindMaxK(const int* v) const
-{
- int max_val = 0;
- int max_idx = 0;
- for (int i = 0; i max_val) ? max_val = v[i], max_idx = i : (int)NULL;
- }
-
- return max_idx + 90;
-}
-
-int EllipseDetector::FindMaxN(const int* v) const
-{
- int max_val = 0;
- int max_idx = 0;
- for (int i = 0; i max_val) ? max_val = v[i], max_idx = i : (int)NULL;
- }
-
- return max_idx;
-}
-
-int EllipseDetector::FindMaxA(const int* v) const
-{
- int max_val = 0;
- int max_idx = 0;
- for (int i = 0; i max_val) ? max_val = v[i], max_idx = i : (int)NULL;
- }
-
- return max_idx;
-}
-
-// Most important function for detecting ellipses. See Sect[3.2.3] of the paper
-void EllipseDetector::FindEllipses(Point2f& center,
- VP& edge_i, VP& edge_j, VP& edge_k,
- EllipseData& data_ij, EllipseData& data_ik, Ellipse& ell)
-{
- countOfFindEllipse_++;
- // Find ellipse parameters
-
- // 0-initialize accumulators
- memset(accN, 0, sizeof(int)*ACC_N_SIZE);
- memset(accR, 0, sizeof(int)*ACC_R_SIZE);
- memset(accA, 0, sizeof(int)*ACC_A_SIZE);
-
- // estimation
- // Get size of the 4 vectors of slopes (2 pairs of arcs)
- int sz_ij1 = int(data_ij.Sa.size());
- int sz_ij2 = int(data_ij.Sb.size());
- int sz_ik1 = int(data_ik.Sa.size());
- int sz_ik2 = int(data_ik.Sb.size());
-
- // Get the size of the 3 arcs
- size_t sz_ei = edge_i.size();
- size_t sz_ej = edge_j.size();
- size_t sz_ek = edge_k.size();
-
- // Center of the estimated ellipse
- float a0 = center.x;
- float b0 = center.y;
-
-
- // Estimation of remaining parameters
- // Uses 4 combinations of parameters. See Table 1 and Sect [3.2.3] of the paper.
- // ij1 and ik
- {
- float q1 = data_ij.ra;
- float q3 = data_ik.ra;
- float q5 = data_ik.rb;
-
- for (int ij1 = 0; ij1 < sz_ij1; ++ij1)
- {
- float q2 = data_ij.Sa[ij1]; // need iter \A3\BF
-
- float q1xq2 = q1*q2;
- // ij1 and ik1
- for (int ik1 = 0; ik1 < sz_ik1; ++ik1)
- {
- float q4 = data_ik.Sa[ik1]; // need iter \A3\BF
-
- float q3xq4 = q3*q4;
-
- // See Eq. [13-18] in the paper
-
- float a = (q1xq2 - q3xq4); // gama
- float b = (q3xq4 + 1)*(q1 + q2) - (q1xq2 + 1)*(q3 + q4); // beta
- float Kp = (-b + sqrt(b*b + 4 * a*a)) / (2 * a); // K+
- float zplus = ((q1 - Kp)*(q2 - Kp)) / ((1 + q1*Kp)*(1 + q2*Kp));
- // check zplus and K is linear
- if (zplus >= 0.0f) continue;
-
- float Np = sqrt(-zplus); // N+
- float rho = atan(Kp); // rho tmp
- int rhoDeg;
- if (Np > 1.f)
- {
- Np = 1.f / Np;
- rhoDeg = cvRound((rho * 180 / CV_PI) + 180) % 180; // [0,180)
- }
- else
- {
- rhoDeg = cvRound((rho * 180 / CV_PI) + 90) % 180; // [0,180) rho angel rep and norm
- }
-
- int iNp = cvRound(Np * 100); // [0, 100]
-
- if (0 <= iNp && iNp < ACC_N_SIZE &&
- 0 <= rhoDeg && rhoDeg < ACC_R_SIZE
- )
- { // why iter all. beacause zplus and K is not linear?
- ++accN[iNp]; // Increment N accumulator
- ++accR[rhoDeg]; // Increment R accumulator
- }
- }
- // ij1 and ik2
- for (int ik2 = 0; ik2 < sz_ik2; ++ik2)
- {
- float q4 = data_ik.Sb[ik2];
-
- float q5xq4 = q5*q4;
-
- // See Eq. [13-18] in the paper
-
- float a = (q1xq2 - q5xq4);
- float b = (q5xq4 + 1)*(q1 + q2) - (q1xq2 + 1)*(q5 + q4);
- float Kp = (-b + sqrt(b*b + 4 * a*a)) / (2 * a);
- float zplus = ((q1 - Kp)*(q2 - Kp)) / ((1 + q1*Kp)*(1 + q2*Kp));
-
- if (zplus >= 0.0f)
- {
- continue;
- }
-
- float Np = sqrt(-zplus);
- float rho = atan(Kp);
- int rhoDeg;
- if (Np > 1.f)
- {
- Np = 1.f / Np;
- rhoDeg = cvRound((rho * 180 / CV_PI) + 180) % 180; // [0,180)
- }
- else
- {
- rhoDeg = cvRound((rho * 180 / CV_PI) + 90) % 180; // [0,180)
- }
-
- int iNp = cvRound(Np * 100); // [0, 100]
-
- if (0 <= iNp && iNp < ACC_N_SIZE &&
- 0 <= rhoDeg && rhoDeg < ACC_R_SIZE
- )
- {
- ++accN[iNp]; // Increment N accumulator
- ++accR[rhoDeg]; // Increment R accumulator
- }
- }
-
- }
- }
-
- // ij2 and ik
- {
- float q1 = data_ij.rb;
- float q3 = data_ik.rb;
- float q5 = data_ik.ra;
-
- for (int ij2 = 0; ij2 < sz_ij2; ++ij2)
- {
- float q2 = data_ij.Sb[ij2];
-
- float q1xq2 = q1*q2;
- // ij2 and ik2
- for (int ik2 = 0; ik2 < sz_ik2; ++ik2)
- {
- float q4 = data_ik.Sb[ik2];
-
- float q3xq4 = q3*q4;
-
- // See Eq. [13-18] in the paper
-
- float a = (q1xq2 - q3xq4);
- float b = (q3xq4 + 1)*(q1 + q2) - (q1xq2 + 1)*(q3 + q4);
- float Kp = (-b + sqrt(b*b + 4 * a*a)) / (2 * a);
- float zplus = ((q1 - Kp)*(q2 - Kp)) / ((1 + q1*Kp)*(1 + q2*Kp));
-
- if (zplus >= 0.0f)
- {
- continue;
- }
-
- float Np = sqrt(-zplus);
- float rho = atan(Kp);
- int rhoDeg;
- if (Np > 1.f)
- {
- Np = 1.f / Np;
- rhoDeg = cvRound((rho * 180 / CV_PI) + 180) % 180; // [0,180)
- }
- else
- {
- rhoDeg = cvRound((rho * 180 / CV_PI) + 90) % 180; // [0,180)
- }
-
- int iNp = cvRound(Np * 100); // [0, 100]
-
- if (0 <= iNp && iNp < ACC_N_SIZE &&
- 0 <= rhoDeg && rhoDeg < ACC_R_SIZE
- )
- {
- ++accN[iNp]; // Increment N accumulator
- ++accR[rhoDeg]; // Increment R accumulator
- }
- }
-
- // ij2 and ik1
- for (int ik1 = 0; ik1 < sz_ik1; ++ik1)
- {
- float q4 = data_ik.Sa[ik1];
-
- float q5xq4 = q5*q4;
-
- // See Eq. [13-18] in the paper
-
- float a = (q1xq2 - q5xq4);
- float b = (q5xq4 + 1)*(q1 + q2) - (q1xq2 + 1)*(q5 + q4);
- float Kp = (-b + sqrt(b*b + 4 * a*a)) / (2 * a);
- float zplus = ((q1 - Kp)*(q2 - Kp)) / ((1 + q1*Kp)*(1 + q2*Kp));
-
- if (zplus >= 0.0f)
- {
- continue;
- }
-
- float Np = sqrt(-zplus);
- float rho = atan(Kp);
- int rhoDeg;
- if (Np > 1.f)
- {
- Np = 1.f / Np;
- rhoDeg = cvRound((rho * 180 / CV_PI) + 180) % 180; // [0,180)
- }
- else
- {
- rhoDeg = cvRound((rho * 180 / CV_PI) + 90) % 180; // [0,180)
- }
-
- int iNp = cvRound(Np * 100); // [0, 100]
-
- if (0 <= iNp && iNp < ACC_N_SIZE &&
- 0 <= rhoDeg && rhoDeg < ACC_R_SIZE
- )
- {
- ++accN[iNp]; // Increment N accumulator
- ++accR[rhoDeg]; // Increment R accumulator
- }
- }
-
- }
- }
-
- // Find peak in N and K accumulator
- int iN = FindMaxN(accN);
- int iK = FindMaxK(accR);
-
- // Recover real values
- float fK = float(iK);
- float Np = float(iN) * 0.01f;
- float rho = fK * float(CV_PI) / 180.f; // deg 2 rad
- float Kp = tan(rho);
-
- // Estimate A. See Eq. [19 - 22] in Sect [3.2.3] of the paper
- //
- // may optm
- for (ushort l = 0; l < sz_ei; ++l)
- {
- Point& pp = edge_i[l];
- float sk = 1.f / sqrt(Kp*Kp + 1.f); // cos rho
- float x0 = ((pp.x - a0) * sk) + (((pp.y - b0)*Kp) * sk); // may optm
- float y0 = -(((pp.x - a0) * Kp) * sk) + ((pp.y - b0) * sk); // may optm
- float Ax = sqrt((x0*x0*Np*Np + y0*y0) / ((Np*Np)*(1.f + Kp*Kp)));
- int A = cvRound(abs(Ax / cos(rho))); // may optm
- if ((0 <= A) && (A < ACC_A_SIZE))
- {
- ++accA[A];
- }
- }
-
- for (ushort l = 0; l < sz_ej; ++l)
- {
- Point& pp = edge_j[l];
- float sk = 1.f / sqrt(Kp*Kp + 1.f);
- float x0 = ((pp.x - a0) * sk) + (((pp.y - b0)*Kp) * sk);
- float y0 = -(((pp.x - a0) * Kp) * sk) + ((pp.y - b0) * sk);
- float Ax = sqrt((x0*x0*Np*Np + y0*y0) / ((Np*Np)*(1.f + Kp*Kp)));
- int A = cvRound(abs(Ax / cos(rho)));
- if ((0 <= A) && (A < ACC_A_SIZE))
- {
- ++accA[A];
- }
- }
-
- for (ushort l = 0; l < sz_ek; ++l)
- {
- Point& pp = edge_k[l];
- float sk = 1.f / sqrt(Kp*Kp + 1.f);
- float x0 = ((pp.x - a0) * sk) + (((pp.y - b0)*Kp) * sk);
- float y0 = -(((pp.x - a0) * Kp) * sk) + ((pp.y - b0) * sk);
- float Ax = sqrt((x0*x0*Np*Np + y0*y0) / ((Np*Np)*(1.f + Kp*Kp)));
- int A = cvRound(abs(Ax / cos(rho)));
- if ((0 <= A) && (A < ACC_A_SIZE))
- {
- ++accA[A];
- }
- }
-
- // Find peak in A accumulator
- int A = FindMaxA(accA);
- float fA = float(A);
-
- // Find B value. See Eq [23] in the paper
- float fB = abs(fA * Np);
-
- // Got all ellipse parameters!
- // Ellipse ell(a0, b0, fA, fB, fmod(rho + float(CV_PI)*2.f, float(CV_PI)));
- ell.xc_ = a0;
- ell.yc_ = b0;
- ell.a_ = fA;
- ell.b_ = fB;
- ell.rad_ = fmod(rho + float(CV_PI)*2.f, float(CV_PI));
-
- // estimation end
- // validation start
- // Get the score. See Sect [3.3.1] in the paper
-
- // Find the number of edge pixel lying on the ellipse
- float _cos = cos(-ell.rad_);
- float _sin = sin(-ell.rad_);
-
- float invA2 = 1.f / (ell.a_ * ell.a_);
- float invB2 = 1.f / (ell.b_ * ell.b_);
-
- float invNofPoints = 1.f / float(sz_ei + sz_ej + sz_ek);
- int counter_on_perimeter = 0;
- float probc_on_perimeter = 0;
-
- for (ushort l = 0; l < sz_ei; ++l)
- {
- float tx = float(edge_i[l].x) - ell.xc_;
- float ty = float(edge_i[l].y) - ell.yc_;
- float rx = (tx*_cos - ty*_sin);
- float ry = (tx*_sin + ty*_cos);
-
- float h = (rx*rx)*invA2 + (ry*ry)*invB2;
- if (abs(h - 1.f) < fDistanceToEllipseContour_)
- {
- ++counter_on_perimeter;
- probc_on_perimeter += 1; // (fDistanceToEllipseContour_ - abs(h - 1.f)) / fDistanceToEllipseContour_;
- }
- }
-
- for (ushort l = 0; l < sz_ej; ++l)
- {
- float tx = float(edge_j[l].x) - ell.xc_;
- float ty = float(edge_j[l].y) - ell.yc_;
- float rx = (tx*_cos - ty*_sin);
- float ry = (tx*_sin + ty*_cos);
-
- float h = (rx*rx)*invA2 + (ry*ry)*invB2;
- if (abs(h - 1.f) < fDistanceToEllipseContour_)
- {
- ++counter_on_perimeter;
- probc_on_perimeter += 1; // (fDistanceToEllipseContour_ - abs(h - 1.f)) / fDistanceToEllipseContour_;
- }
- }
-
- for (ushort l = 0; l < sz_ek; ++l)
- {
- float tx = float(edge_k[l].x) - ell.xc_;
- float ty = float(edge_k[l].y) - ell.yc_;
- float rx = (tx*_cos - ty*_sin);
- float ry = (tx*_sin + ty*_cos);
-
- float h = (rx*rx)*invA2 + (ry*ry)*invB2;
- if (abs(h - 1.f) < fDistanceToEllipseContour_)
- {
- ++counter_on_perimeter;
- probc_on_perimeter += 1; // (fDistanceToEllipseContour_ - abs(h - 1.f)) / fDistanceToEllipseContour_;
- }
- }
-
-
- // no points found on the ellipse
- if (counter_on_perimeter <= 0)
- {
- // validation
- return;
- }
-
- // Compute score
- // float score = float(counter_on_perimeter) * invNofPoints;
- float score = probc_on_perimeter * invNofPoints;
- if (score < fMinScore_)
- {
- // validation
- return;
- }
-
- // Compute reliability
- // this metric is not described in the paper, mostly due to space limitations.
- // The main idea is that for a given ellipse (TD) even if the score is high, the arcs
- // can cover only a small amount of the contour of the estimated ellipse.
- // A low reliability indicate that the arcs form an elliptic shape by chance, but do not underlie
- // an actual ellipse. The value is normalized between 0 and 1.
- // The default value is 0.4.
-
- // It is somehow similar to the "Angular Circumreference Ratio" saliency criteria
- // as in the paper:
- // D. K. Prasad, M. K. Leung, S.-Y. Cho, Edge curvature and convexity
- // based ellipse detection method, Pattern Recognition 45 (2012) 3204-3221.
-
- float di, dj, dk;
- {
- Point2f p1(float(edge_i[0].x), float(edge_i[0].y));
- Point2f p2(float(edge_i[sz_ei - 1].x), float(edge_i[sz_ei - 1].y));
- p1.x -= ell.xc_;
- p1.y -= ell.yc_;
- p2.x -= ell.xc_;
- p2.y -= ell.yc_;
- Point2f r1((p1.x*_cos - p1.y*_sin), (p1.x*_sin + p1.y*_cos));
- Point2f r2((p2.x*_cos - p2.y*_sin), (p2.x*_sin + p2.y*_cos));
- di = abs(r2.x - r1.x) + abs(r2.y - r1.y);
- }
- {
- Point2f p1(float(edge_j[0].x), float(edge_j[0].y));
- Point2f p2(float(edge_j[sz_ej - 1].x), float(edge_j[sz_ej - 1].y));
- p1.x -= ell.xc_;
- p1.y -= ell.yc_;
- p2.x -= ell.xc_;
- p2.y -= ell.yc_;
- Point2f r1((p1.x*_cos - p1.y*_sin), (p1.x*_sin + p1.y*_cos));
- Point2f r2((p2.x*_cos - p2.y*_sin), (p2.x*_sin + p2.y*_cos));
- dj = abs(r2.x - r1.x) + abs(r2.y - r1.y);
- }
- {
- Point2f p1(float(edge_k[0].x), float(edge_k[0].y));
- Point2f p2(float(edge_k[sz_ek - 1].x), float(edge_k[sz_ek - 1].y));
- p1.x -= ell.xc_;
- p1.y -= ell.yc_;
- p2.x -= ell.xc_;
- p2.y -= ell.yc_;
- Point2f r1((p1.x*_cos - p1.y*_sin), (p1.x*_sin + p1.y*_cos));
- Point2f r2((p2.x*_cos - p2.y*_sin), (p2.x*_sin + p2.y*_cos));
- dk = abs(r2.x - r1.x) + abs(r2.y - r1.y);
- }
-
- // This allows to get rid of thick edges
- float rel = min(1.f, ((di + dj + dk) / (3 * (ell.a_ + ell.b_))));
-
- if (rel < fMinReliability_)
- {
- // validation
- return;
- }
- if (_isnan(rel))
- return;
-
- // Assign the new score!
- ell.score_ = (score + rel) * 0.5f; // need to change
- // ell.score_ = (score*rel); // need to change
-
- if (ell.score_ < fMinScore_)
- {
- return;
- }
- // The tentative detection has been confirmed. Save it!
- // ellipses.push_back(ell);
-
- // Validation end
-}
-
-
-
-// Ellipse clustering procedure. See Sect [3.3.2] in the paper.
-void EllipseDetector::ClusterEllipses(vector& ellipses)
-{
- float th_Da = 0.1f;
- float th_Db = 0.1f;
- float th_Dr = 0.1f;
-
- float th_Dc_ratio = 0.1f;
- float th_Dr_circle = 0.9f;
-
- int iNumOfEllipses = int(ellipses.size());
- if (iNumOfEllipses == 0) return;
-
- // The first ellipse is assigned to a cluster
- vector clusters;
- clusters.push_back(ellipses[0]);
-
- // bool bFoundCluster = false;
-
- for (int i = 1; i th_Dc)
- {
- //not same cluster
- continue;
- }
-
- // a
- float Da = abs(e1.a_ - e2.a_) / max(e1.a_, e2.a_);
- if (Da > th_Da)
- {
- //not same cluster
- continue;
- }
-
- // b
- float Db = abs(e1.b_ - e2.b_) / min(e1.b_, e2.b_);
- if (Db > th_Db)
- {
- //not same cluster
- continue;
- }
-
- // angle
- float Dr = GetMinAnglePI(e1.rad_, e2.rad_) / float(CV_PI);
- if ((Dr > th_Dr) && (ba_e1 < th_Dr_circle) && (ba_e2 < th_Dr_circle))
- {
- //not same cluster
- continue;
- }
-
- // Same cluster as e2
- bFoundCluster = true;//
- // Discard, no need to create a new cluster
- break;
- }
-
- if (!bFoundCluster)
- {
- // Create a new cluster
- clusters.push_back(e1);
- }
- }
-
- clusters.swap(ellipses);
-}
-
-float EllipseDetector::GetMedianSlope(vector& med, Point2f& M, vector& slopes)
-{
- // input med slopes, output M, return slope
- // med : vector of points
- // M : centroid of the points in med
- // slopes : vector of the slopes
-
- unsigned iNofPoints = unsigned(med.size());
- // CV_Assert(iNofPoints >= 2);
-
- unsigned halfSize = iNofPoints >> 1;
- unsigned quarterSize = halfSize >> 1;
-
- vector xx, yy;
- slopes.reserve(halfSize);
- xx.reserve(iNofPoints);
- yy.reserve(iNofPoints);
-
- for (unsigned i = 0; i < halfSize; ++i)
- {
- Point2f& p1 = med[i];
- Point2f& p2 = med[halfSize + i];
-
- xx.push_back(p1.x);
- xx.push_back(p2.x);
- yy.push_back(p1.y);
- yy.push_back(p2.y);
-
- float den = (p2.x - p1.x);
- float num = (p2.y - p1.y);
-
- if (den == 0) den = 0.00001f;
-
- slopes.push_back(num / den);
- }
-
- nth_element(slopes.begin(), slopes.begin() + quarterSize, slopes.end());
- nth_element(xx.begin(), xx.begin() + halfSize, xx.end());
- nth_element(yy.begin(), yy.begin() + halfSize, yy.end());
- M.x = xx[halfSize];
- M.y = yy[halfSize];
-
- return slopes[quarterSize];
-}
-
-int inline sgn(float val) {
- return (0.f < val) - (val < 0.f);
-}
-
-void EllipseDetector::GetFastCenter(vector& e1, vector& e2, EllipseData& data)
-{
- countOfGetFastCenter_++;
- data.isValid = true;
-
- unsigned size_1 = unsigned(e1.size());
- unsigned size_2 = unsigned(e2.size());
-
- unsigned hsize_1 = size_1 >> 1;
- unsigned hsize_2 = size_2 >> 1;
-
- Point& med1 = e1[hsize_1];
- Point& med2 = e2[hsize_2];
-
- Point2f M12, M34;
- float q2, q4;
-
- {// First to second Reference slope
- float dx_ref = float(e1[0].x - med2.x);
- float dy_ref = float(e1[0].y - med2.y);
-
- if (dy_ref == 0) dy_ref = 0.00001f;
-
- float m_ref = dy_ref / dx_ref;
- data.ra = m_ref;
-
- // Find points with same slope as reference
- vector med;
- med.reserve(hsize_2);
-
- unsigned minPoints = (uNs_ < hsize_2) ? uNs_ : hsize_2; // parallel chords
-
- vector indexes(minPoints);
- if (uNs_ < hsize_2)
- { // hsize_2 bigger than uNs_
- unsigned iSzBin = hsize_2 / unsigned(uNs_);
- unsigned iIdx = hsize_2 + (iSzBin / 2);
-
- for (unsigned i = 0; i> 1;
- while (end - begin > 2)
- {
- float x2 = float(e1[j].x);
- float y2 = float(e1[j].y);
- float res = ((x2 - x1) * dy_ref) - ((y2 - y1) * dx_ref);
- int sign_res = sgn(res);
-
- if (sign_res == 0)
- {
- // found
- med.push_back(Point2f((x2 + x1)* 0.5f, (y2 + y1)* 0.5f));
- break;
- }
-
- if (sign_res + sign_begin == 0)
- {
- sign_end = sign_res;
- end = j;
- }
- else
- {
- sign_begin = sign_res;
- begin = j;
- }
- j = (begin + end) >> 1;
- }
- // search end error ?
- med.push_back(Point2f((e1[j].x + x1)* 0.5f, (e1[j].y + y1)* 0.5f));
- }
-
- if (med.size() < 2)
- {
- data.isValid = false;
- return;
- }
-
- /****************************************
- Mat3b out(480, 640, Vec3b(0, 0, 0));
- Vec3b color(0, 255, 0);
- for (int ci = 0; ci < med.size(); ci++)
- circle(out, med[ci], 2, color);
- imshow("test", out); waitKey(100);
- ****************************************/
- q2 = GetMedianSlope(med, M12, data.Sa); //get Sa ta = q2 Ma
- }
-
- {// Second to first
- // Reference slope
- float dx_ref = float(med1.x - e2[0].x);
- float dy_ref = float(med1.y - e2[0].y);
-
- if (dy_ref == 0) dy_ref = 0.00001f;
-
- float m_ref = dy_ref / dx_ref;
- data.rb = m_ref;
-
- // Find points with same slope as reference
- vector med;
- med.reserve(hsize_1);
-
- uint minPoints = (uNs_ < hsize_1) ? uNs_ : hsize_1;
-
- vector indexes(minPoints);
- if (uNs_ < hsize_1)
- {
- unsigned iSzBin = hsize_1 / unsigned(uNs_);
- unsigned iIdx = hsize_1 + (iSzBin / 2);
-
- for (unsigned i = 0; i> 1;
-
- while (end - begin > 2)
- {
- float x2 = float(e2[j].x);
- float y2 = float(e2[j].y);
- float res = ((x2 - x1) * dy_ref) - ((y2 - y1) * dx_ref);
- int sign_res = sgn(res);
-
- if (sign_res == 0)
- {
- //found
- med.push_back(Point2f((x2 + x1)* 0.5f, (y2 + y1)* 0.5f));
- break;
- }
-
- if (sign_res + sign_begin == 0)
- {
- sign_end = sign_res;
- end = j;
- }
- else
- {
- sign_begin = sign_res;
- begin = j;
- }
- j = (begin + end) >> 1;
- }
-
- med.push_back(Point2f((e2[j].x + x1)* 0.5f, (e2[j].y + y1)* 0.5f));
- }
-
- if (med.size() < 2)
- {
- data.isValid = false;
- return;
- }
- q4 = GetMedianSlope(med, M34, data.Sb);
- }
-
- if (q2 == q4)
- {
- data.isValid = false;
- return;
- }
-
- float invDen = 1 / (q2 - q4);
- data.Cab.x = (M34.y - q4*M34.x - M12.y + q2*M12.x) * invDen;
- data.Cab.y = (q2*M34.y - q4*M12.y + q2*q4*(M12.x - M34.x)) * invDen;
- data.ta = q2;
- data.tb = q4;
- data.Ma = M12;
- data.Mb = M34;
-}
-
-float EllipseDetector::GetMinAnglePI(float alpha, float beta)
-{
- float pi = float(CV_PI);
- float pi2 = float(2.0 * CV_PI);
-
- // normalize data in [0, 2*pi]
- float a = fmod(alpha + pi2, pi2);
- float b = fmod(beta + pi2, pi2);
-
- // normalize data in [0, pi]
- if (a > pi)
- a -= pi;
- if (b > pi)
- b -= pi;
-
- if (a > b)
- {
- swap(a, b);
- }
-
- float diff1 = b - a;
- float diff2 = pi - diff1;
- return min(diff1, diff2);
-}
-
-// Get the coordinates of the center, given the intersection of the estimated lines. See Fig. [8] in Sect [3.2.3] in the paper.
-Point2f EllipseDetector::GetCenterCoordinates(EllipseData& data_ij, EllipseData& data_ik)
-{
- float xx[7];
- float yy[7];
-
- xx[0] = data_ij.Cab.x;
- xx[1] = data_ik.Cab.x;
- yy[0] = data_ij.Cab.y;
- yy[1] = data_ik.Cab.y;
-
- {
- // 1-1
- float q2 = data_ij.ta;
- float q4 = data_ik.ta;
- Point2f& M12 = data_ij.Ma;
- Point2f& M34 = data_ik.Ma;
-
- float invDen = 1 / (q2 - q4);
- xx[2] = (M34.y - q4*M34.x - M12.y + q2*M12.x) * invDen;
- yy[2] = (q2*M34.y - q4*M12.y + q2*q4*(M12.x - M34.x)) * invDen;
- }
-
- {
- // 1-2
- float q2 = data_ij.ta;
- float q4 = data_ik.tb;
- Point2f& M12 = data_ij.Ma;
- Point2f& M34 = data_ik.Mb;
-
- float invDen = 1 / (q2 - q4);
- xx[3] = (M34.y - q4*M34.x - M12.y + q2*M12.x) * invDen;
- yy[3] = (q2*M34.y - q4*M12.y + q2*q4*(M12.x - M34.x)) * invDen;
- }
-
- {
- // 2-2
- float q2 = data_ij.tb;
- float q4 = data_ik.tb;
- Point2f& M12 = data_ij.Mb;
- Point2f& M34 = data_ik.Mb;
-
- float invDen = 1 / (q2 - q4);
- xx[4] = (M34.y - q4*M34.x - M12.y + q2*M12.x) * invDen;
- yy[4] = (q2*M34.y - q4*M12.y + q2*q4*(M12.x - M34.x)) * invDen;
- }
-
- {
- // 2-1
- float q2 = data_ij.tb;
- float q4 = data_ik.ta;
- Point2f& M12 = data_ij.Mb;
- Point2f& M34 = data_ik.Ma;
-
- float invDen = 1 / (q2 - q4);
- xx[5] = (M34.y - q4*M34.x - M12.y + q2*M12.x) * invDen;
- yy[5] = (q2*M34.y - q4*M12.y + q2*q4*(M12.x - M34.x)) * invDen;
- }
-
- xx[6] = (xx[0] + xx[1]) * 0.5f;
- yy[6] = (yy[0] + yy[1]) * 0.5f;
-
-
- // Median
- nth_element(xx, xx + 3, xx + 7);
- nth_element(yy, yy + 3, yy + 7);
- float xc = xx[3];
- float yc = yy[3];
-
- return Point2f(xc, yc);
-}
-
-uint inline EllipseDetector::GenerateKey(uchar pair, ushort u, ushort v)
-{
- return (pair << 30) + (u << 15) + v;
-}
-
-// Draw at most iTopN detected ellipses.
-void EllipseDetector::DrawDetectedEllipses(Mat& output, vector& ellipses, int iTopN, int thickness)
-{
- int sz_ell = int(ellipses.size());
- int n = (iTopN == 0) ? sz_ell : min(iTopN, sz_ell);
- for (int i = 0; i < n; ++i)
- {
- Ellipse& e = ellipses[n - i - 1];
- int g = cvRound(e.score_ * 255.f);
- Scalar color(0, g, 0);
- ellipse(output, Point(cvRound(e.xc_), cvRound(e.yc_)), Size(cvRound(e.a_), cvRound(e.b_)), e.rad_*180.0 / CV_PI, 0.0, 360.0, color, thickness);
- // cv::circle(output, Point(e.xc_, e.yc_), 2, Scalar(0, 0, 255), 2);
- }
-}
-
-bool inline convex_check(VP& vp1, int start, int end)
-{
- int x_min(4096), x_max(0), y_min(4096), y_max(0);
- int integral_u(0), integral_d(0);
- for (int i = start; i <= end; i++)
- {
- Point& val = vp1[i];
- x_min = MIN(x_min, val.x);
- x_max = MAX(x_max, val.x);
- y_min = MIN(y_min, val.y);
- y_max = MAX(y_max, val.y);
- }
- for (int i = start; i <= end; i++)
- {
- Point& val = vp1[i];
- integral_u += (val.y - y_min);
- integral_d += (y_max - val.y);
- }
- if (integral_u > integral_d)
- return false;
- else
- return true;
-}
-
-bool inline concave_check(VP& vp1, int start, int end)
-{
- int x_min(4096), x_max(0), y_min(4096), y_max(0);
- int integral_u(0), integral_d(0);
- for (int i = start; i <= end; i++)
- {
- Point& val = vp1[i];
- x_min = MIN(x_min, val.x);
- x_max = MAX(x_max, val.x);
- y_min = MIN(y_min, val.y);
- y_max = MAX(y_max, val.y);
- }
- for (int i = start; i <= end; i++)
- {
- Point& val = vp1[i];
- integral_u += (val.y - y_min);
- integral_d += (y_max - val.y);
- }
- if (integral_u < integral_d)
- return false;
- else
- return true;
-}
-
-void EllipseDetector::ArcsCheck1234(VVP& points_1, VVP& points_2, VVP& points_3, VVP& points_4)
-{
- static int nchecks = 21;
- int i, j;
- VVP vps_1, vps_2, vps_3, vps_4;
- Mat3b out(480, 640, Vec3b(0, 0, 0));
- for (i = 0; i < points_2.size(); ++i)
- {
- // Vec3b color(rand()%255, 128+rand()%127, 128+rand()%127);
- Vec3b color(255, 0, 0);
- for (j = 0; j < points_2[i].size(); ++j)
- out(points_2[i][j]) = color;
- }
- imshow("out", out); waitKey();
-
- for (i = 0; i < points_1.size(); i++)
- {
- VP& vp1 = points_1[i];
- if (vp1.size() > nchecks)
- {
- VP vpn;
- for (j = 0; j <= vp1.size() - nchecks; j++)
- {
- if (convex_check(vp1, j, j + nchecks - 1))
- {
- vpn.push_back(vp1[j]);
- }
- else
- {
- vps_1.push_back(vpn); vpn.clear();
- }
- }
- vps_1.push_back(vpn);
- }
- else
- {
- cout << "==== small arc I ====" << endl;
- }
- }
- for (i = 0; i < points_2.size(); i++)
- {
- VP& vp1 = points_2[i];
- if (vp1.size() > nchecks)
- {
- VP vpn;
- for (j = 0; j <= vp1.size() - nchecks; j++)
- {
- if (concave_check(vp1, j, j + nchecks - 1))
- {
- vpn.push_back(vp1[j]);
- }
- else
- {
- vps_2.push_back(vpn); vpn.clear();
- }
- }
- vps_2.push_back(vpn);
- }
- else
- {
- cout << "==== small arc II ====" << endl;
- }
- }
- Mat3b out2(480, 640, Vec3b(0, 0, 0));
- for (i = 0; i < vps_2.size(); ++i)
- {
- // Vec3b color(rand()%255, 128+rand()%127, 128+rand()%127);
- Vec3b color(255, 0, 0);
- for (j = 0; j < vps_2[i].size(); ++j)
- out2(vps_2[i][j]) = color;
- }
- imshow("out2", out2); waitKey();
- for (i = 0; i < points_3.size(); i++)
- {
- VP& vp1 = points_3[i];
- if (vp1.size() > nchecks)
- {
- VP vpn;
- for (j = 0; j <= vp1.size() - nchecks; j++)
- {
- if (concave_check(vp1, j, j + nchecks - 1))
- {
- vpn.push_back(vp1[j]);
- }
- else
- {
- vps_3.push_back(vpn); vpn.clear();
- }
- }
- vps_3.push_back(vpn);
- }
- else
- {
- cout << "==== small arc III ====" << endl;
- }
- }
- for (i = 0; i < points_4.size(); i++)
- {
- VP& vp1 = points_4[i];
- if (vp1.size() > nchecks)
- {
- VP vpn;
- for (j = 0; j <= vp1.size() - nchecks; j++)
- {
- if (convex_check(vp1, j, j + nchecks - 1))
- {
- vpn.push_back(vp1[j]);
- }
- else
- {
- vps_4.push_back(vpn); vpn.clear();
- }
- }
- vps_4.push_back(vpn);
- }
- else
- {
- cout << "==== small arc IV ====" << endl;
- }
- }
- points_1 = vps_1; points_2 = vps_2; points_3 = vps_3; points_4 = vps_4;
-}
diff --git a/src/无人机端代码/Modules/future_aircraft/src/ellipse_detector/ellipse_detector.h b/src/无人机端代码/Modules/future_aircraft/src/ellipse_detector/ellipse_detector.h
deleted file mode 100644
index 7a8a1f90..00000000
--- a/src/无人机端代码/Modules/future_aircraft/src/ellipse_detector/ellipse_detector.h
+++ /dev/null
@@ -1,1374 +0,0 @@
-#ifndef SPIRE_ELLIPSEDETECTOR_H
-#define SPIRE_ELLIPSEDETECTOR_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-
-
-
-#ifdef _WIN32
-/*
-* Define architecture flags so we don't need to include windows.h.
-* Avoiding windows.h makes it simpler to use windows sockets in conjunction
-* with dirent.h.
-*/
-#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_IX86)
-# define _X86_
-#endif
-#if !defined(_68K_) && !defined(_MPPC_) && !defined(_X86_) && !defined(_IA64_) && !defined(_AMD64_) && defined(_M_AMD64)
-#define _AMD64_
-#endif
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-/* Indicates that d_type field is available in dirent structure */
-#define _DIRENT_HAVE_D_TYPE
-
-/* Indicates that d_namlen field is available in dirent structure */
-#define _DIRENT_HAVE_D_NAMLEN
-
-/* Entries missing from MSVC 6.0 */
-#if !defined(FILE_ATTRIBUTE_DEVICE)
-# define FILE_ATTRIBUTE_DEVICE 0x40
-#endif
-
-/* File type and permission flags for stat(), general mask */
-#if !defined(S_IFMT)
-# define S_IFMT _S_IFMT
-#endif
-
-/* Directory bit */
-#if !defined(S_IFDIR)
-# define S_IFDIR _S_IFDIR
-#endif
-
-/* Character device bit */
-#if !defined(S_IFCHR)
-# define S_IFCHR _S_IFCHR
-#endif
-
-/* Pipe bit */
-#if !defined(S_IFFIFO)
-# define S_IFFIFO _S_IFFIFO
-#endif
-
-/* Regular file bit */
-#if !defined(S_IFREG)
-# define S_IFREG _S_IFREG
-#endif
-
-/* Read permission */
-#if !defined(S_IREAD)
-# define S_IREAD _S_IREAD
-#endif
-
-/* Write permission */
-#if !defined(S_IWRITE)
-# define S_IWRITE _S_IWRITE
-#endif
-
-/* Execute permission */
-#if !defined(S_IEXEC)
-# define S_IEXEC _S_IEXEC
-#endif
-
-/* Pipe */
-#if !defined(S_IFIFO)
-# define S_IFIFO _S_IFIFO
-#endif
-
-/* Block device */
-#if !defined(S_IFBLK)
-# define S_IFBLK 0
-#endif
-
-/* Link */
-#if !defined(S_IFLNK)
-# define S_IFLNK 0
-#endif
-
-/* Socket */
-#if !defined(S_IFSOCK)
-# define S_IFSOCK 0
-#endif
-
-/* Read user permission */
-#if !defined(S_IRUSR)
-# define S_IRUSR S_IREAD
-#endif
-
-/* Write user permission */
-#if !defined(S_IWUSR)
-# define S_IWUSR S_IWRITE
-#endif
-
-/* Execute user permission */
-#if !defined(S_IXUSR)
-# define S_IXUSR 0
-#endif
-
-/* Read group permission */
-#if !defined(S_IRGRP)
-# define S_IRGRP 0
-#endif
-
-/* Write group permission */
-#if !defined(S_IWGRP)
-# define S_IWGRP 0
-#endif
-
-/* Execute group permission */
-#if !defined(S_IXGRP)
-# define S_IXGRP 0
-#endif
-
-/* Read others permission */
-#if !defined(S_IROTH)
-# define S_IROTH 0
-#endif
-
-/* Write others permission */
-#if !defined(S_IWOTH)
-# define S_IWOTH 0
-#endif
-
-/* Execute others permission */
-#if !defined(S_IXOTH)
-# define S_IXOTH 0
-#endif
-
-/* Maximum length of file name */
-#if !defined(PATH_MAX)
-# define PATH_MAX MAX_PATH
-#endif
-#if !defined(FILENAME_MAX)
-# define FILENAME_MAX MAX_PATH
-#endif
-#if !defined(NAME_MAX)
-# define NAME_MAX FILENAME_MAX
-#endif
-
-/* File type flags for d_type */
-#define DT_UNKNOWN 0
-#define DT_REG S_IFREG
-#define DT_DIR S_IFDIR
-#define DT_FIFO S_IFIFO
-#define DT_SOCK S_IFSOCK
-#define DT_CHR S_IFCHR
-#define DT_BLK S_IFBLK
-#define DT_LNK S_IFLNK
-
-/* Macros for converting between st_mode and d_type */
-#define IFTODT(mode) ((mode) & S_IFMT)
-#define DTTOIF(type) (type)
-
-/*
-* File type macros. Note that block devices, sockets and links cannot be
-* distinguished on Windows and the macros S_ISBLK, S_ISSOCK and S_ISLNK are
-* only defined for compatibility. These macros should always return false
-* on Windows.
-*/
-#if !defined(S_ISFIFO)
-# define S_ISFIFO(mode) (((mode) & S_IFMT) == S_IFIFO)
-#endif
-#if !defined(S_ISDIR)
-# define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
-#endif
-#if !defined(S_ISREG)
-# define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-#if !defined(S_ISLNK)
-# define S_ISLNK(mode) (((mode) & S_IFMT) == S_IFLNK)
-#endif
-#if !defined(S_ISSOCK)
-# define S_ISSOCK(mode) (((mode) & S_IFMT) == S_IFSOCK)
-#endif
-#if !defined(S_ISCHR)
-# define S_ISCHR(mode) (((mode) & S_IFMT) == S_IFCHR)
-#endif
-#if !defined(S_ISBLK)
-# define S_ISBLK(mode) (((mode) & S_IFMT) == S_IFBLK)
-#endif
-
-/* Return the exact length of d_namlen without zero terminator */
-#define _D_EXACT_NAMLEN(p) ((p)->d_namlen)
-
-/* Return number of bytes needed to store d_namlen */
-#define _D_ALLOC_NAMLEN(p) (PATH_MAX)
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
- /* Wide-character version */
- struct _wdirent {
- /* Always zero */
- long d_ino;
-
- /* Structure size */
- unsigned short d_reclen;
-
- /* Length of name without \0 */
- size_t d_namlen;
-
- /* File type */
- int d_type;
-
- /* File name */
- wchar_t d_name[PATH_MAX];
- };
- typedef struct _wdirent _wdirent;
-
- struct _WDIR {
- /* Current directory entry */
- struct _wdirent ent;
-
- /* Private file data */
- WIN32_FIND_DATAW data;
-
- /* True if data is valid */
- int cached;
-
- /* Win32 search handle */
- HANDLE handle;
-
- /* Initial directory name */
- wchar_t *patt;
- };
- typedef struct _WDIR _WDIR;
-
- static _WDIR *_wopendir(const wchar_t *dirname);
- static struct _wdirent *_wreaddir(_WDIR *dirp);
- static int _wclosedir(_WDIR *dirp);
- static void _wrewinddir(_WDIR* dirp);
-
-
- /* For compatibility with Symbian */
-#define wdirent _wdirent
-#define WDIR _WDIR
-#define wopendir _wopendir
-#define wreaddir _wreaddir
-#define wclosedir _wclosedir
-#define wrewinddir _wrewinddir
-
-
- /* Multi-byte character versions */
- struct dirent {
- /* Always zero */
- long d_ino;
-
- /* Structure size */
- unsigned short d_reclen;
-
- /* Length of name without \0 */
- size_t d_namlen;
-
- /* File type */
- int d_type;
-
- /* File name */
- char d_name[PATH_MAX];
- };
- typedef struct dirent dirent;
-
- struct DIR {
- struct dirent ent;
- struct _WDIR *wdirp;
- };
- typedef struct DIR DIR;
-
- static DIR *opendir(const char *dirname);
- static struct dirent *readdir(DIR *dirp);
- static int closedir(DIR *dirp);
- static void rewinddir(DIR* dirp);
-
-
- /* Internal utility functions */
- static WIN32_FIND_DATAW *dirent_first(_WDIR *dirp);
- static WIN32_FIND_DATAW *dirent_next(_WDIR *dirp);
-
- static int dirent_mbstowcs_s(
- size_t *pReturnValue,
- wchar_t *wcstr,
- size_t sizeInWords,
- const char *mbstr,
- size_t count);
-
- static int dirent_wcstombs_s(
- size_t *pReturnValue,
- char *mbstr,
- size_t sizeInBytes,
- const wchar_t *wcstr,
- size_t count);
-
- static void dirent_set_errno(int error);
-
- /*
- * Open directory stream DIRNAME for read and return a pointer to the
- * internal working area that is used to retrieve individual directory
- * entries.
- */
- static _WDIR*
- _wopendir(
- const wchar_t *dirname)
- {
- _WDIR *dirp = NULL;
- int error;
-
- /* Must have directory name */
- if (dirname == NULL || dirname[0] == '\0') {
- dirent_set_errno(ENOENT);
- return NULL;
- }
-
- /* Allocate new _WDIR structure */
- dirp = (_WDIR*)malloc(sizeof(struct _WDIR));
- if (dirp != NULL) {
- DWORD n;
-
- /* Reset _WDIR structure */
- dirp->handle = INVALID_HANDLE_VALUE;
- dirp->patt = NULL;
- dirp->cached = 0;
-
- /* Compute the length of full path plus zero terminator */
- n = GetFullPathNameW(dirname, 0, NULL, NULL);
-
- /* Allocate room for absolute directory name and search pattern */
- dirp->patt = (wchar_t*)malloc(sizeof(wchar_t) * n + 16);
- if (dirp->patt) {
-
- /*
- * Convert relative directory name to an absolute one. This
- * allows rewinddir() to function correctly even when current
- * working directory is changed between opendir() and rewinddir().
- */
- n = GetFullPathNameW(dirname, n, dirp->patt, NULL);
- if (n > 0) {
- wchar_t *p;
-
- /* Append search pattern \* to the directory name */
- p = dirp->patt + n;
- if (dirp->patt < p) {
- switch (p[-1]) {
- case '\\':
- case '/':
- case ':':
- /* Directory ends in path separator, e.g. c:\temp\ */
- /*NOP*/;
- break;
-
- default:
- /* Directory name doesn't end in path separator */
- *p++ = '\\';
- }
- }
- *p++ = '*';
- *p = '\0';
-
- /* Open directory stream and retrieve the first entry */
- if (dirent_first(dirp)) {
- /* Directory stream opened successfully */
- error = 0;
- }
- else {
- /* Cannot retrieve first entry */
- error = 1;
- dirent_set_errno(ENOENT);
- }
-
- }
- else {
- /* Cannot retrieve full path name */
- dirent_set_errno(ENOENT);
- error = 1;
- }
-
- }
- else {
- /* Cannot allocate memory for search pattern */
- error = 1;
- }
-
- }
- else {
- /* Cannot allocate _WDIR structure */
- error = 1;
- }
-
- /* Clean up in case of error */
- if (error && dirp) {
- _wclosedir(dirp);
- dirp = NULL;
- }
-
- return dirp;
- }
-
- /*
- * Read next directory entry. The directory entry is returned in dirent
- * structure in the d_name field. Individual directory entries returned by
- * this function include regular files, sub-directories, pseudo-directories
- * "." and ".." as well as volume labels, hidden files and system files.
- */
- static struct _wdirent*
- _wreaddir(
- _WDIR *dirp)
- {
- WIN32_FIND_DATAW *datap;
- struct _wdirent *entp;
-
- /* Read next directory entry */
- datap = dirent_next(dirp);
- if (datap) {
- size_t n;
- DWORD attr;
-
- /* Pointer to directory entry to return */
- entp = &dirp->ent;
-
- /*
- * Copy file name as wide-character string. If the file name is too
- * long to fit in to the destination buffer, then truncate file name
- * to PATH_MAX characters and zero-terminate the buffer.
- */
- n = 0;
- while (n + 1 < PATH_MAX && datap->cFileName[n] != 0) {
- entp->d_name[n] = datap->cFileName[n];
- n++;
- }
- dirp->ent.d_name[n] = 0;
-
- /* Length of file name excluding zero terminator */
- entp->d_namlen = n;
-
- /* File type */
- attr = datap->dwFileAttributes;
- if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
- entp->d_type = DT_CHR;
- }
- else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
- entp->d_type = DT_DIR;
- }
- else {
- entp->d_type = DT_REG;
- }
-
- /* Reset dummy fields */
- entp->d_ino = 0;
- entp->d_reclen = sizeof(struct _wdirent);
-
- }
- else {
-
- /* Last directory entry read */
- entp = NULL;
-
- }
-
- return entp;
- }
-
- /*
- * Close directory stream opened by opendir() function. This invalidates the
- * DIR structure as well as any directory entry read previously by
- * _wreaddir().
- */
- static int
- _wclosedir(
- _WDIR *dirp)
- {
- int ok;
- if (dirp) {
-
- /* Release search handle */
- if (dirp->handle != INVALID_HANDLE_VALUE) {
- FindClose(dirp->handle);
- dirp->handle = INVALID_HANDLE_VALUE;
- }
-
- /* Release search pattern */
- if (dirp->patt) {
- free(dirp->patt);
- dirp->patt = NULL;
- }
-
- /* Release directory structure */
- free(dirp);
- ok = /*success*/0;
-
- }
- else {
- /* Invalid directory stream */
- dirent_set_errno(EBADF);
- ok = /*failure*/-1;
- }
- return ok;
- }
-
- /*
- * Rewind directory stream such that _wreaddir() returns the very first
- * file name again.
- */
- static void
- _wrewinddir(
- _WDIR* dirp)
- {
- if (dirp) {
- /* Release existing search handle */
- if (dirp->handle != INVALID_HANDLE_VALUE) {
- FindClose(dirp->handle);
- }
-
- /* Open new search handle */
- dirent_first(dirp);
- }
- }
-
- /* Get first directory entry (internal) */
- static WIN32_FIND_DATAW*
- dirent_first(
- _WDIR *dirp)
- {
- WIN32_FIND_DATAW *datap;
-
- /* Open directory and retrieve the first entry */
- dirp->handle = FindFirstFileW(dirp->patt, &dirp->data);
- if (dirp->handle != INVALID_HANDLE_VALUE) {
-
- /* a directory entry is now waiting in memory */
- datap = &dirp->data;
- dirp->cached = 1;
-
- }
- else {
-
- /* Failed to re-open directory: no directory entry in memory */
- dirp->cached = 0;
- datap = NULL;
-
- }
- return datap;
- }
-
- /* Get next directory entry (internal) */
- static WIN32_FIND_DATAW*
- dirent_next(
- _WDIR *dirp)
- {
- WIN32_FIND_DATAW *p;
-
- /* Get next directory entry */
- if (dirp->cached != 0) {
-
- /* A valid directory entry already in memory */
- p = &dirp->data;
- dirp->cached = 0;
-
- }
- else if (dirp->handle != INVALID_HANDLE_VALUE) {
-
- /* Get the next directory entry from stream */
- if (FindNextFileW(dirp->handle, &dirp->data) != FALSE) {
- /* Got a file */
- p = &dirp->data;
- }
- else {
- /* The very last entry has been processed or an error occured */
- FindClose(dirp->handle);
- dirp->handle = INVALID_HANDLE_VALUE;
- p = NULL;
- }
-
- }
- else {
-
- /* End of directory stream reached */
- p = NULL;
-
- }
-
- return p;
- }
-
- /*
- * Open directory stream using plain old C-string.
- */
- static DIR*
- opendir(
- const char *dirname)
- {
- struct DIR *dirp;
- int error;
-
- /* Must have directory name */
- if (dirname == NULL || dirname[0] == '\0') {
- dirent_set_errno(ENOENT);
- return NULL;
- }
-
- /* Allocate memory for DIR structure */
- dirp = (DIR*)malloc(sizeof(struct DIR));
- if (dirp) {
- wchar_t wname[PATH_MAX];
- size_t n;
-
- /* Convert directory name to wide-character string */
- error = dirent_mbstowcs_s(&n, wname, PATH_MAX, dirname, PATH_MAX);
- if (!error) {
-
- /* Open directory stream using wide-character name */
- dirp->wdirp = _wopendir(wname);
- if (dirp->wdirp) {
- /* Directory stream opened */
- error = 0;
- }
- else {
- /* Failed to open directory stream */
- error = 1;
- }
-
- }
- else {
- /*
- * Cannot convert file name to wide-character string. This
- * occurs if the string contains invalid multi-byte sequences or
- * the output buffer is too small to contain the resulting
- * string.
- */
- error = 1;
- }
-
- }
- else {
- /* Cannot allocate DIR structure */
- error = 1;
- }
-
- /* Clean up in case of error */
- if (error && dirp) {
- free(dirp);
- dirp = NULL;
- }
-
- return dirp;
- }
-
- /*
- * Read next directory entry.
- *
- * When working with text consoles, please note that file names returned by
- * readdir() are represented in the default ANSI code page while any output to
- * console is typically formatted on another code page. Thus, non-ASCII
- * characters in file names will not usually display correctly on console. The
- * problem can be fixed in two ways: (1) change the character set of console
- * to 1252 using chcp utility and use Lucida Console font, or (2) use
- * _cprintf function when writing to console. The _cprinf() will re-encode
- * ANSI strings to the console code page so many non-ASCII characters will
- * display correcly.
- */
- static struct dirent*
- readdir(
- DIR *dirp)
- {
- WIN32_FIND_DATAW *datap;
- struct dirent *entp;
-
- /* Read next directory entry */
- datap = dirent_next(dirp->wdirp);
- if (datap) {
- size_t n;
- int error;
-
- /* Attempt to convert file name to multi-byte string */
- error = dirent_wcstombs_s(
- &n, dirp->ent.d_name, PATH_MAX, datap->cFileName, PATH_MAX);
-
- /*
- * If the file name cannot be represented by a multi-byte string,
- * then attempt to use old 8+3 file name. This allows traditional
- * Unix-code to access some file names despite of unicode
- * characters, although file names may seem unfamiliar to the user.
- *
- * Be ware that the code below cannot come up with a short file
- * name unless the file system provides one. At least
- * VirtualBox shared folders fail to do this.
- */
- if (error && datap->cAlternateFileName[0] != '\0') {
- error = dirent_wcstombs_s(
- &n, dirp->ent.d_name, PATH_MAX,
- datap->cAlternateFileName, PATH_MAX);
- }
-
- if (!error) {
- DWORD attr;
-
- /* Initialize directory entry for return */
- entp = &dirp->ent;
-
- /* Length of file name excluding zero terminator */
- entp->d_namlen = n - 1;
-
- /* File attributes */
- attr = datap->dwFileAttributes;
- if ((attr & FILE_ATTRIBUTE_DEVICE) != 0) {
- entp->d_type = DT_CHR;
- }
- else if ((attr & FILE_ATTRIBUTE_DIRECTORY) != 0) {
- entp->d_type = DT_DIR;
- }
- else {
- entp->d_type = DT_REG;
- }
-
- /* Reset dummy fields */
- entp->d_ino = 0;
- entp->d_reclen = sizeof(struct dirent);
-
- }
- else {
- /*
- * Cannot convert file name to multi-byte string so construct
- * an errornous directory entry and return that. Note that
- * we cannot return NULL as that would stop the processing
- * of directory entries completely.
- */
- entp = &dirp->ent;
- entp->d_name[0] = '?';
- entp->d_name[1] = '\0';
- entp->d_namlen = 1;
- entp->d_type = DT_UNKNOWN;
- entp->d_ino = 0;
- entp->d_reclen = 0;
- }
-
- }
- else {
- /* No more directory entries */
- entp = NULL;
- }
-
- return entp;
- }
-
- /*
- * Close directory stream.
- */
- static int
- closedir(
- DIR *dirp)
- {
- int ok;
- if (dirp) {
-
- /* Close wide-character directory stream */
- ok = _wclosedir(dirp->wdirp);
- dirp->wdirp = NULL;
-
- /* Release multi-byte character version */
- free(dirp);
-
- }
- else {
-
- /* Invalid directory stream */
- dirent_set_errno(EBADF);
- ok = /*failure*/-1;
-
- }
- return ok;
- }
-
- /*
- * Rewind directory stream to beginning.
- */
- static void
- rewinddir(
- DIR* dirp)
- {
- /* Rewind wide-character string directory stream */
- _wrewinddir(dirp->wdirp);
- }
-
- /* Convert multi-byte string to wide character string */
- static int
- dirent_mbstowcs_s(
- size_t *pReturnValue,
- wchar_t *wcstr,
- size_t sizeInWords,
- const char *mbstr,
- size_t count)
- {
- int error;
-
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-
- /* Microsoft Visual Studio 2005 or later */
- error = mbstowcs_s(pReturnValue, wcstr, sizeInWords, mbstr, count);
-
-#else
-
- /* Older Visual Studio or non-Microsoft compiler */
- size_t n;
-
- /* Convert to wide-character string (or count characters) */
- n = mbstowcs(wcstr, mbstr, sizeInWords);
- if (!wcstr || n < count) {
-
- /* Zero-terminate output buffer */
- if (wcstr && sizeInWords) {
- if (n >= sizeInWords) {
- n = sizeInWords - 1;
- }
- wcstr[n] = 0;
- }
-
- /* Length of resuting multi-byte string WITH zero terminator */
- if (pReturnValue) {
- *pReturnValue = n + 1;
- }
-
- /* Success */
- error = 0;
-
- }
- else {
-
- /* Could not convert string */
- error = 1;
-
- }
-
-#endif
-
- return error;
- }
-
- /* Convert wide-character string to multi-byte string */
- static int
- dirent_wcstombs_s(
- size_t *pReturnValue,
- char *mbstr,
- size_t sizeInBytes, /* max size of mbstr */
- const wchar_t *wcstr,
- size_t count)
- {
- int error;
-
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-
- /* Microsoft Visual Studio 2005 or later */
- error = wcstombs_s(pReturnValue, mbstr, sizeInBytes, wcstr, count);
-
-#else
-
- /* Older Visual Studio or non-Microsoft compiler */
- size_t n;
-
- /* Convert to multi-byte string (or count the number of bytes needed) */
- n = wcstombs(mbstr, wcstr, sizeInBytes);
- if (!mbstr || n < count) {
-
- /* Zero-terminate output buffer */
- if (mbstr && sizeInBytes) {
- if (n >= sizeInBytes) {
- n = sizeInBytes - 1;
- }
- mbstr[n] = '\0';
- }
-
- /* Lenght of resulting multi-bytes string WITH zero-terminator */
- if (pReturnValue) {
- *pReturnValue = n + 1;
- }
-
- /* Success */
- error = 0;
-
- }
- else {
-
- /* Cannot convert string */
- error = 1;
-
- }
-
-#endif
-
- return error;
- }
-
- /* Set errno variable */
- static void
- dirent_set_errno(
- int error)
- {
-#if defined(_MSC_VER) && _MSC_VER >= 1400
-
- /* Microsoft Visual Studio 2005 and later */
- _set_errno(error);
-
-#else
-
- /* Non-Microsoft compiler or older Microsoft compiler */
- errno = error;
-
-#endif
- }
-
-
-#ifdef __cplusplus
-}
-#endif
-#include
-#else
-#include
-// #include
-#endif
-
-#ifdef USE_OMP
-#include
-#else
-int omp_get_max_threads();
-int omp_get_thread_num();
-// int omp_set_num_threads(int);
-#endif
-
-typedef std::vector VP;
-typedef std::vector< VP > VVP;
-typedef unsigned int uint;
-
-
-void _list_dir(std::string dir, std::vector& files, std::string suffixs = "", bool r = false);
-
-std::vector _split(const std::string& srcstr, const std::string& delimeter);
-bool _startswith(const std::string& str, const std::string& start);
-bool _endswith(const std::string& str, const std::string& end);
-void _randperm(int n, int m, int arr[], bool sort_ = true);
-
-/***************** math-related functions ****************/
-float _atan2(float y, float x);
-void _mean_std(std::vector& vec, float& mean, float& std);
-int inline _sgn(float val) { return (0.f < val) - (val < 0.f); }
-float inline _ed2(const cv::Point& A, const cv::Point& B)
-{
- return float(((B.x - A.x)*(B.x - A.x) + (B.y - A.y)*(B.y - A.y)));
-}
-float _get_min_angle_PI(float alpha, float beta);
-
-double inline _tic()
-{
- return (double)cv::getTickCount();
-}
-double inline _toc(double tic) // ms
-{
- return ((double)cv::getTickCount() - tic)*1000. / cv::getTickFrequency();
-}
-inline int _isnan(double x) { return x != x; }
-
-
-void _tag_canny(cv::InputArray image, cv::OutputArray _edges,
- cv::OutputArray _sobel_x, cv::OutputArray _sobel_y,
- int apertureSize, bool L2gradient, double percent_ne);
-
-
-void _find_contours_oneway(cv::Mat1b& image, VVP& segments, int iMinLength);
-void _find_contours_eight(cv::Mat1b& image, std::vector& segments, int iMinLength);
-void _show_contours_eight(cv::Mat1b& image, std::vector& segments, const char* title);
-
-void _tag_find_contours(cv::Mat1b& image, VVP& segments, int iMinLength);
-void _tag_show_contours(cv::Mat1b& image, VVP& segments, const char* title);
-void _tag_show_contours(cv::Size& imsz, VVP& segments, const char* title);
-
-bool _SortBottomLeft2TopRight(const cv::Point& lhs, const cv::Point& rhs);
-bool _SortBottomLeft2TopRight2f(const cv::Point2f& lhs, const cv::Point2f& rhs);
-bool _SortTopLeft2BottomRight(const cv::Point& lhs, const cv::Point& rhs);
-
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-#define M_2__PI 6.28318530718
-#define M_1_2_PI 1.57079632679
-
-// Elliptical struct definition
-class Ellipse
-{
-public:
- float xc_;
- float yc_;
- float a_;
- float b_;
- float rad_;
- float score_;
-
- // Elliptic General equations Ax^2 + Bxy + Cy^2 + Dx + Ey + 1 = 0
- float A_;
- float B_;
- float C_;
- float D_;
- float E_;
- float F_;
-
- Ellipse() : xc_(0.f), yc_(0.f), a_(0.f), b_(0.f), rad_(0.f), score_(0.f),
- A_(0.f), B_(0.f), C_(0.f), D_(0.f), E_(0.f), F_(1.f) {}
- Ellipse(float xc, float yc, float a, float b, float rad, float score = 0.f) : xc_(xc), yc_(yc), a_(a), b_(b), rad_(rad), score_(score) {}
- Ellipse(const Ellipse& other) : xc_(other.xc_), yc_(other.yc_), a_(other.a_), b_(other.b_), rad_(other.rad_), score_(other.score_),
- A_(other.A_), B_(other.B_), C_(other.C_), D_(other.D_), E_(other.E_) {}
-
- void Draw(cv::Mat& img, const cv::Scalar& color, const int thickness)
- {
- if (IsValid())
- ellipse(img, cv::Point(cvRound(xc_), cvRound(yc_)), cv::Size(cvRound(a_), cvRound(b_)), rad_ * 180.0 / CV_PI, 0.0, 360.0, color, thickness);
- }
-
- void Draw(cv::Mat3b& img, const int thickness)
- {
- cv::Scalar color(0, cvFloor(255.f * score_), 0);
- if (IsValid())
- ellipse(img, cv::Point(cvRound(xc_), cvRound(yc_)), cv::Size(cvRound(a_), cvRound(b_)), rad_ * 180.0 / CV_PI, 0.0, 360.0, color, thickness);
- }
-
- bool operator<(const Ellipse& other) const
- { // use for sorting
- if (score_ == other.score_)
- {
- float lhs_e = b_ / a_;
- float rhs_e = other.b_ / other.a_;
- if (lhs_e == rhs_e)
- {
- return false;
- }
- return lhs_e > rhs_e;
- }
- return score_ > other.score_;
- }
-
- // Elliptic General equations Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
- void TransferFromGeneral() {
- float denominator = (B_*B_ - 4 * A_*C_);
-
- xc_ = (2 * C_*D_ - B_*E_) / denominator;
- yc_ = (2 * A_*E_ - B_*D_) / denominator;
-
- float pre = 2 * (A_*E_*E_ + C_*D_*D_ - B_*D_*E_ + denominator*F_);
- float lst = sqrt((A_ - C_)*(A_ - C_) + B_*B_);
-
- a_ = -sqrt(pre*(A_ + C_ + lst)) / denominator;
- b_ = -sqrt(pre*(A_ + C_ - lst)) / denominator;
-
- if (B_ == 0 && A_C_)
- rad_ = CV_PI / 2;
- else
- rad_ = atan((C_ - A_ - lst) / B_);
- }
-
- // Elliptic General equations Ax^2 + Bxy + Cy^2 + Dx + Ey + F = 0
- void TransferToGeneral() {
- A_ = a_*a_*sin(rad_)*sin(rad_) + b_*b_*cos(rad_)*cos(rad_);
- B_ = 2.f*(b_*b_ - a_*a_)*sin(rad_)*cos(rad_);
- C_ = a_*a_*cos(rad_)*cos(rad_) + b_*b_*sin(rad_)*sin(rad_);
- D_ = -2.f*A_*xc_ - B_*yc_;
- E_ = -B_*xc_ - 2.f*C_*yc_;
- F_ = A_*xc_*xc_ + B_*xc_*yc_ + C_*yc_*yc_ - a_*a_*b_*b_;
- }
-
- void GetRectangle(cv::Rect& rect) {
- float sin_theta = sin(-rad_);
- float cos_theta = cos(-rad_);
- float A = a_*a_ * sin_theta * sin_theta + b_* b_ * cos_theta * cos_theta;
- float B = 2 * (a_* a_ - b_ * b_) * sin_theta * cos_theta;
- float C = a_* a_ * cos_theta * cos_theta + b_ * b_ * sin_theta * sin_theta;
- float F = - a_ * a_ * b_ * b_;
-
- float y = sqrt(4 * A * F / (B * B - 4 * A * C));
- float y1 = -abs(y), y2 = abs(y);
- float x = sqrt(4 * C * F / (B * B - 4 * C * A));
- float x1 = -abs(x), x2 = abs(x);
-
- rect = cv::Rect(int(round(xc_ + x1)), int(round(yc_ + y1)), int(round(x2 - x1)), int(round(y2 - y1)));
- }
-
- float Perimeter() {
- // return 2*CV_PI*b_ + 4*(a_ - b_);
- return CV_PI*(3.f*(a_ + b_) - sqrt((3.f*a_ + b_)*(a_ + 3.f*b_)));
- }
-
- float Area() {
- return CV_PI*a_*b_;
- }
-
- bool IsValid() {
- bool nan = isnan(xc_) || isnan(yc_) || isnan(a_) || isnan(b_) || isnan(rad_);
- return !nan;
- }
-};
-
-// Data available after selection strategy.
-// They are kept in an associative array to:
-// 1) avoid recomputing data when starting from same arcs
-// 2) be reused in firther proprecessing
-struct EllipseData
-{
- bool isValid;
- float ta; // arc_a center line gradient
- float tb; // arc_b
- float ra; // gradient of a (slope of start of chord_1 and center of chord_2)
- float rb; // gradient of b (slope of center of chord_1 and last of chord_2)
- cv::Point2f Ma; // arc_a center of element
- cv::Point2f Mb; // arc_b
- cv::Point2f Cab; // center of ellipse
- std::vector Sa; // arc_a's center line of parallel chords
- std::vector Sb; // arc_b's center line of parallel chords
-};
-
-struct EllipseThreePoint
-{
- bool isValid;
- cv::Point Cab;
- VP ArcI;
- VP ArcJ;
- VP ArcK;
-};
-
-/********************** EllipseFitting functions **********************/
-void _ellipse_foci(float *param, float *foci);
-float _ellipse_normal_angle(float x, float y, float *foci);
-float _angle_diff(float a, float b);
-
-/*************************** CNC functions ****************************/
-float _value4SixPoints(cv::Point2f p3, cv::Point2f p2, cv::Point2f p1, cv::Point2f p4, cv::Point2f p5, cv::Point2f p6);
-
-
-/**************** ellipse-evaluation-related functions ****************/
-void _load_ellipse_GT(const std::string& gt_file_name, std::vector & gt_ellipses, bool is_angle_radians = true);
-void _load_ellipse_DT(const std::string& dt_file_name, std::vector & dt_ellipses, bool is_angle_radians = true);
-
-bool _ellipse_overlap(const cv::Mat1b& gt, const cv::Mat1b& dt, float th);
-float _ellipse_overlap_real(const cv::Mat1b& gt, const cv::Mat1b& dt);
-int _bool_count(const std::vector vb);
-float _ellipse_evaluate_one(const std::vector& ell_gt, const std::vector& ell_dt, const cv::Mat3b& img);
-float _ellipse_evaluate(std::vector& image_fns, std::vector& gt_fns, std::vector& dt_fns,
- bool gt_angle_radians = true);
-
-
-
-
-class EllipseDetector
-{
- // Parameters
-
- // Preprocessing - Gaussian filter. See Sect [] in the paper
- cv::Size szPreProcessingGaussKernel_; // size of the Gaussian filter in preprocessing step
- double dPreProcessingGaussSigma_; // sigma of the Gaussian filter in the preprocessing step
-
-
- // Selection strategy - Step 1 - Discard noisy or straight arcs. See Sect [] in the paper
- int iMinEdgeLength_; // minimum edge size
- float fMinOrientedRectSide_; // minumum size of the oriented bounding box containing the arc
- float fMaxRectAxesRatio_; // maximum aspect ratio of the oriented bounding box containing the arc
-
- // Selection strategy - Step 2 - Remove according to mutual convexities. See Sect [] in the paper
- float fThrArcPosition_;
-
- // Selection Strategy - Step 3 - Number of points considered for slope estimation when estimating the center. See Sect [] in the paper
- unsigned uNs_; // Find at most Ns parallel chords.
-
- // Selection strategy - Step 3 - Discard pairs of arcs if their estimated center is not close enough. See Sect [] in the paper
- float fMaxCenterDistance_; // maximum distance in pixel between 2 center points
- float fMaxCenterDistance2_; // _fMaxCenterDistance * _fMaxCenterDistance
-
- // Validation - Points within a this threshold are considered to lie on the ellipse contour. See Sect [] in the paper
- float fDistanceToEllipseContour_; // maximum distance between a point and the contour. See equation [] in the paper
-
- // Validation - Assign a score. See Sect [] in the paper
- float fMinScore_; // minimum score to confirm a detection
- float fMinReliability_; // minimum auxiliary score to confirm a detection
-
- double dPercentNe_;
-
- float fT_CNC_;
- float fT_TCN_L_; // filter lines
- float fT_TCN_P_;
- float fThre_r_;
-
- // auxiliary variables
- cv::Size szIm_; // input image size
-
- std::vector times_; // times_ is a vector containing the execution time of each step.
-
- int ACC_N_SIZE; // size of accumulator N = B/A
- int ACC_R_SIZE; // size of accumulator R = rho = atan(K)
- int ACC_A_SIZE; // size of accumulator A
-
- int* accN; // pointer to accumulator N
- int* accR; // pointer to accumulator R
- int* accA; // pointer to accumulator A
-
- cv::Mat1f EO_;
-
- VVP points_1, points_2, points_3, points_4; // vector of points, one for each convexity class
-
-public:
-
- // Constructor and Destructor
- EllipseDetector(void);
- ~EllipseDetector(void);
-
- // Detect the ellipses in the gray image
- void Detect(cv::Mat3b& I, std::vector& ellipses);
- void Detect(cv::Mat& I, std::vector& ellipses);
-
- // Draw the first iTopN ellipses on output
- void DrawDetectedEllipses(cv::Mat& output, std::vector& ellipses, int iTopN = 0, int thickness = 2);
-
- // Set the parameters of the detector
- void SetParameters(cv::Size szPreProcessingGaussKernelSize,
- double dPreProcessingGaussSigma,
- float fThPosition,
- float fMaxCenterDistance,
- int iMinEdgeLength,
- float fMinOrientedRectSide,
- float fDistanceToEllipseContour,
- float fMinScore,
- float fMinReliability,
- int iNs,
- double dPercentNe,
- float fT_CNC,
- float fT_TCN_L,
- float fT_TCN_P,
- float fThre_r
- );
-
- // Return the execution time
- double GetExecTime() {
- double time_all(0);
- for (size_t i = 0; i < times_.size(); i++) time_all += times_[i];
- return time_all;
- }
- std::vector GetTimes() { return times_; }
-
- float countOfFindEllipse_;
- float countOfGetFastCenter_;
-
-private:
-
- // keys for hash table
- static const ushort PAIR_12 = 0x00;
- static const ushort PAIR_23 = 0x01;
- static const ushort PAIR_34 = 0x02;
- static const ushort PAIR_14 = 0x03;
-
- // generate keys from pair and indicse
- uint inline GenerateKey(uchar pair, ushort u, ushort v);
-
- void PreProcessing(cv::Mat1b& I, cv::Mat1b& arcs8);
- void RemoveStraightLine(VVP& segments, VVP& segments_update, int id = 0);
- void PreProcessing(cv::Mat1b& I, cv::Mat1b& DP, cv::Mat1b& DN);
-
- void ClusterEllipses(std::vector& ellipses);
-
- // int FindMaxK(const std::vector& v) const;
- // int FindMaxN(const std::vector& v) const;
- // int FindMaxA(const std::vector& v) const;
-
- int FindMaxK(const int* v) const;
- int FindMaxN(const int* v) const;
- int FindMaxA(const int* v) const;
-
- float GetMedianSlope(std::vector& med, cv::Point2f& M, std::vector& slopes);
- void GetFastCenter(std::vector& e1, std::vector& e2, EllipseData& data);
- float GetMinAnglePI(float alpha, float beta);
-
- void DetectEdges13(cv::Mat1b& DP, VVP& points_1, VVP& points_3);
- void DetectEdges24(cv::Mat1b& DN, VVP& points_2, VVP& points_4);
-
- void ArcsCheck1234(VVP& points_1, VVP& points_2, VVP& points_3, VVP& points_4);
-
- void FindEllipses(cv::Point2f& center,
- VP& edge_i,
- VP& edge_j,
- VP& edge_k,
- EllipseData& data_ij,
- EllipseData& data_ik,
- Ellipse& ell
- );
-
- cv::Point2f GetCenterCoordinates(EllipseData& data_ij, EllipseData& data_ik);
-
- void Triplets124(VVP& pi,
- VVP& pj,
- VVP& pk,
- std::unordered_map& data,
- std::vector& ellipses
- );
-
- void Triplets231(VVP& pi,
- VVP& pj,
- VVP& pk,
- std::unordered_map& data,
- std::vector& ellipses
- );
-
- void Triplets342(VVP& pi,
- VVP& pj,
- VVP& pk,
- std::unordered_map& data,
- std::vector& ellipses
- );
-
- void Triplets413(VVP& pi,
- VVP& pj,
- VVP& pk,
- std::unordered_map& data,
- std::vector& ellipses
- );
-
- void Tic(unsigned idx = 0) //start
- {
- while (idx >= timesSign_.size()) {
- timesSign_.push_back(0);
- times_.push_back(.0);
- }
- timesSign_[idx] = 0;
- timesSign_[idx]++;
- times_[idx] = (double)cv::getTickCount();
- }
-
- void Toc(unsigned idx = 0, std::string step = "") //stop
- {
- assert(timesSign_[idx] == 1);
- timesSign_[idx]++;
- times_[idx] = ((double)cv::getTickCount() - times_[idx])*1000. / cv::getTickFrequency();
- // #ifdef DEBUG_SPEED
- std::cout << "Cost time: " << times_[idx] << " ms [" << idx << "] - " << step << std::endl;
- if (idx == times_.size() - 1)
- std::cout << "Totally cost time: " << this->GetExecTime() << " ms" << std::endl;
- // #endif
- }
-
-private:
- std::vector timesSign_;
-};
-
-
-
-#endif // SPIRE_ELLIPSEDETECTOR_H
diff --git a/src/无人机端代码/Modules/future_aircraft/src/future_aircraft.cpp b/src/无人机端代码/Modules/future_aircraft/src/future_aircraft.cpp
deleted file mode 100644
index a21be801..00000000
--- a/src/无人机端代码/Modules/future_aircraft/src/future_aircraft.cpp
+++ /dev/null
@@ -1,475 +0,0 @@
-/******************************************************************************
-*例程简介: 第二届大学生未来飞行器挑战赛的实践类仿真demo
-*
-*效果说明: 无人机由指定的位置一键起飞后,立即转换为自动模式,开始通过机载传感器
-* 自主搜索这些目标标靶,并向目标标靶投掷模拟子弹;完成所有的投掷任务后,
-* 自主回到起飞点降落。
-*
-*备注:该例程仅支持Prometheus仿真,真机测试需要熟练掌握相关接口的定义后以及真机适配修改后使用
-******************************************************************************/
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "printf_utils.h"
-#include "mission_utils.h"
-
-using namespace std;
-
-#define VISION_THRES 10
-#define HOLD_THRES 60
-const float PI = 3.1415926;
-
-//创建无人机相关数据变量
-prometheus_msgs::UAVCommand uav_command;
-prometheus_msgs::UAVState uav_state;
-prometheus_msgs::UAVControlState uav_control_state;
-Eigen::Matrix3f R_Body_to_ENU; // 无人机机体系至惯性系转换矩阵
-prometheus_msgs::DetectionInfo ellipse_det;
-float camera_offset[3];
-//static target1
-// 最大目标丢失计数
-constexpr int max_loss_count = 30;
-int loss_count = max_loss_count;
-int num_lost = 0; //视觉丢失计数器
-int num_regain = 0;
-bool is_detected = false;
-int hold_count = 0;
-int hold_lost = 0;
-bool is_holded = false;
-
-
-void uav_state_cb(const prometheus_msgs::UAVState::ConstPtr &msg)
-{
- uav_state = *msg;
- R_Body_to_ENU = get_rotation_matrix(uav_state.attitude[0],uav_state.attitude[1],uav_state.attitude[2]);
-
-}
-
-//无人机控制状态回调函数
-void uav_control_state_cb(const prometheus_msgs::UAVControlState::ConstPtr &msg)
-{
- uav_control_state = *msg;
-}
-
-void ellipse_det_cb(const prometheus_msgs::MultiDetectionInfo::ConstPtr &msg)
-{
- // g_ellipse_det. = false;
- for(auto &ellipes : msg->detection_infos)
- {
- ellipse_det = ellipes;
- if (ellipse_det.detected && ellipse_det.object_name == "T")
- {
- num_regain++;
- num_lost = 0;
- }
- else{
- num_regain = 0;
- num_lost++;
- }
- if(num_lost > VISION_THRES)
- {
- is_detected = false;
- // PCOUT(1, GREEN, "no detect");
- }
- if(num_regain > VISION_THRES){
- is_detected = true;
- // PCOUT(1, GREEN, "detected");
- }
- ellipse_det.sight_angle[0] = ellipes.sight_angle[1];
- ellipse_det.sight_angle[1] = ellipes.sight_angle[0];
- // ellipse_det.position[2] = -ellipes.position[2];
- }
-
-}
-// 创建圆形跟踪的相关变量
-// 整个圆形的飞行时间
-float circular_time;
-// 每次控制数据更新时的弧度增量
-float angle_increment;
-// 无人机的合速度也就是圆的线速度
-float line_velocity;
-// 无人机的控制频率
-float control_rate;
-// 圆的半径
-float radius;
-//通过设定整个圆的飞行时间,控制频率,圆的半径来获取相关参数
-void get_circular_property(float time, int rate, float radius)
-{
- //计算角速度(rad/s)
- float w = 2 * PI / time;
- //计算线速度(m/s)
- line_velocity = radius * w;
- //计算控制数据发布的弧度增量
- angle_increment = w / rate;
-}
-
-//主函数
-int main(int argc, char** argv)
-{
- //ROS初始化,设定节点名
- ros::init(argc , argv, "future_aircraft");
- //创建句柄
- ros::NodeHandle n;
- //声明起飞高度,无人机id变量
- float takeoff_height;
- int uav_id;
- //获取起飞高度参数
- ros::param::get("/uav_control_main_1/control/Takeoff_height", takeoff_height);
- ros::param::get("~uav_id", uav_id);
- // 相机安装偏移,规定为:相机在机体系(质心原点)的位置
- n.param("camera_offset_x", camera_offset[0], 0.0);
- n.param("camera_offset_y", camera_offset[1], 0.0);
- n.param("camera_offset_z", camera_offset[2], 0.0);
- //创建无人机控制命令发布者
- ros::Publisher uav_command_pub = n.advertise("/uav1/prometheus/command", 10);
- //创建无人机状态命令订阅者
- ros::Subscriber uav_state_sub = n.subscribe("/uav1/prometheus/state", 10, uav_state_cb);
- //创建无人机控制状态命令订阅者
- ros::Subscriber uav_control_state_sub = n.subscribe("/uav1/prometheus/control_state", 10, uav_control_state_cb);
-
- ros::Subscriber ellipse_det_sub = n.subscribe("/prometheus/ellipse_det", 10, ellipse_det_cb);
-
- // 圆轨迹周期
- circular_time = 40;
- control_rate = 20;
- // 圆轨迹半径
- radius = 2.5;
-
- // 获取线速度line_velocity, 角速度angle_increment
- get_circular_property(circular_time, control_rate, radius);
- int count = 0;
- bool circular_success = false;
-
- //循环频率设置为**HZ
- ros::Rate r(control_rate);
-
- Eigen::Vector3d waypoint1 = {-4.5, -3.0, 1.5};
- Eigen::Vector3d waypoint2 = {-4.5, 3.0, 1.5};
- Eigen::Vector3d waypoint3 = {4.5, 0, 2.3};
- //固定的浮点显示
- cout.setf(ios::fixed);
- // setprecision(n) 设显示小数精度为2位
- cout << setprecision(2);
- //左对齐
- cout.setf(ios::left);
- // 强制显示小数点
- cout.setf(ios::showpoint);
- // 强制显示符号
- cout.setf(ios::showpos);
-
- //打印demo相关信息
- cout << GREEN << " [fly race demo " << TAIL << endl;
- sleep(1);
- cout << GREEN << " Level: [Advance] " << TAIL << endl;
- sleep(1);
- cout << GREEN << " Please use the RC SWA to armed, and the SWB to switch the drone to [COMMAND_CONTROL] mode " << TAIL << endl;
-
- // 四种状态机
- enum EXEC_STATE
- {
- TAKEOFF,
- WAY1,
- WAY2,
- WAY3,
- SEARCH,
- SEARCH_MOVING,
- TRACKING,
- TRACKING_MOVING,
- LOST,
- RETURN,
- };
- EXEC_STATE exec_state = TAKEOFF;//志位: detected 用作标志位 ture代表识别到目标 false代表丢失目标
-
- while(ros::ok())
- {
- //调用一次回调函数
- ros::spinOnce();
- // 等待进入COMMAND_CONTROL模式
- if (uav_control_state.control_state != prometheus_msgs::UAVControlState::COMMAND_CONTROL)
- {
- PCOUT(-1, TAIL, "Waiting for enter COMMAND_CONTROL state");
- continue;
- }
- // else{
- // uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Current_Pos_Hover;
- // PCOUT(-1, TAIL, "hold for now");
- // }
-
- std::ostringstream info;
- uav_command.header.stamp = ros::Time::now();
- switch (exec_state)
- {
- case TAKEOFF:
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Init_Pos_Hover;
- PCOUT(1, GREEN, "Go to takeoff point");
- // info << "height is : " << uav_state.position[2];
- // PCOUT(1, GREEN, info.str());
- {
- if(fabs(uav_state.position[2] - takeoff_height) < 0.1)
- {
- PCOUT(1, GREEN, " UAV arrived at takeoff point");
- exec_state = WAY1;
- }
- }
- break;
- case WAY1:
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XYZ_POS;
- uav_command.position_ref[0] = waypoint1[0];
- uav_command.position_ref[1] = waypoint1[1];
- uav_command.position_ref[2] = waypoint1[2];
- uav_command.yaw_ref = 0.0;
- PCOUT(1, GREEN, "Waypoint1 ");
- // exec_state = SEARCH;
- {
- Eigen::Vector3d uav_pos = {uav_state.position[0], uav_state.position[1], uav_state.position[2]};
- float distance = (uav_pos - waypoint1).norm();
- if (distance < 0.1)
- {
- // sleep(10);
- PCOUT(1, GREEN, " UAV arrived at waypoint1 point");
- exec_state = SEARCH;
- count = 0;
- }
- }
- break;
- case WAY2:
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XYZ_POS;
- uav_command.position_ref[0] = waypoint2[0];
- uav_command.position_ref[1] = waypoint2[1];
- uav_command.position_ref[2] = waypoint2[2];
- uav_command.yaw_ref = 0.0;
- PCOUT(1, GREEN, "Waypoint2 ");
- {
- Eigen::Vector3d uav_pos = {uav_state.position[0], uav_state.position[1], uav_state.position[2]};
- float distance = (uav_pos - waypoint2).norm();
- if (distance < 0.2)
- {
- sleep(10);
- PCOUT(1, GREEN, " UAV arrived at waypoint2 point");
- exec_state = SEARCH;
- count = 0;
- }
- }
- break;
- case WAY3:
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XYZ_POS;
- uav_command.position_ref[0] = waypoint3[0];
- uav_command.position_ref[1] = waypoint3[1];
- uav_command.position_ref[2] = waypoint3[2];
- uav_command.yaw_ref = 0.0;
- PCOUT(1, GREEN, "Waypoint3 ");
- {
- Eigen::Vector3d uav_pos = {uav_state.position[0], uav_state.position[1], uav_state.position[2]};
- float distance = (uav_pos - waypoint3).norm();
- if (distance < 0.2)
- {
- sleep(10);
- PCOUT(1, GREEN, " UAV arrived at waypoint3 point");
- exec_state = SEARCH_MOVING;
- }
- }
- break;
- case SEARCH:
- // sleep(10);
- //坐标系
- uav_command.header.frame_id = "ENU";
- // Move模式
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- // Move_mode
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XY_VEL_Z_POS;
- //无人机按照圆形轨迹飞行
-
- uav_command.velocity_ref[0] = -line_velocity * std::sin(count * angle_increment);
- uav_command.velocity_ref[1] = line_velocity * std::cos(count * angle_increment);
- uav_command.velocity_ref[2] = 0;
- uav_command.position_ref[2] = 1.5;
- //发布的命令ID加1
- //发布降落命令
- //计数器
- if(count > control_rate*circular_time)
- {
- circular_success = true;
- count = 0;
- }
- count++;
- info << "Waypoint Tracking > Velocity_x: " << uav_command.velocity_ref[0] << " Veloticy_y: " << uav_command.velocity_ref[1]<< " count: " << count;
- PCOUT(1, GREEN, info.str());
- if(is_detected && circular_success)
- {
- exec_state = TRACKING;
- PCOUT(1, GREEN, "tracking");
- loss_count = max_loss_count;
- }
- break;
- case SEARCH_MOVING:
- // sleep(10);
- //坐标系
- uav_command.header.frame_id = "ENU";
- // Move模式
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- // Move_mode
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XY_VEL_Z_POS;
- //无人机按照圆形轨迹飞行
- get_circular_property(31, 40, 5);
-
- uav_command.velocity_ref[0] = -line_velocity * std::sin(count * angle_increment);
- uav_command.velocity_ref[1] = line_velocity * std::cos(count * angle_increment);
- uav_command.velocity_ref[2] = 0;
- uav_command.position_ref[2] = 2.3;
- //发布的命令ID加1
- //发布降落命令
- //计数器
- if(count > control_rate*circular_time)
- {
- circular_success = true;
- }
- count++;
- info << "Waypoint Tracking > Velocity_x: " << uav_command.velocity_ref[0] << " Veloticy_y: " << uav_command.velocity_ref[1];
- PCOUT(1, GREEN, info.str());
- if(is_detected && circular_success)
- {
- exec_state = TRACKING_MOVING;
- PCOUT(1, GREEN, "tracking");
- loss_count = max_loss_count;
- }
- break;
- case TRACKING:
- if (!is_detected)
- {
- --loss_count;
- if(loss_count < 0)
- exec_state = RETURN;
- PCOUT(0, YELLOW, "Return");
- }
- //坐标系
- uav_command.header.frame_id = "BODY";
- // Move模式
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- // 机体系下的速度控制
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XY_VEL_Z_POS_BODY;
- uav_command.velocity_ref[0] = -0.9 * ellipse_det.sight_angle[0];
- uav_command.velocity_ref[1] = 0.9 * ellipse_det.sight_angle[1];
- uav_command.velocity_ref[2] = 0;
- uav_command.position_ref[2] = 1.5;
- uav_command.yaw_ref = 0.0;
- info << "Find object,Go to the target point > velocity_x: " << uav_command.velocity_ref[0] << " [m/s] "
- << "velocity_y: " << uav_command.velocity_ref[1] << " [m/s] "
- << std::endl;
- PCOUT(1, GREEN, info.str());
- if(is_holded && circular_success){
- if(uav_state.position[0] > -9 && uav_state.position[0] < 0)
- if(uav_state.position[1] > -4 && uav_state.position[1] < 0)
- exec_state = WAY2;
- if(uav_state.position[0] > -9 && uav_state.position[0] < 0)
- if(uav_state.position[1] > 0 && uav_state.position[1] < 4)
- exec_state = WAY3;
- }
-
- if (std::abs(uav_command.velocity_ref[0]) + std::abs(uav_command.velocity_ref[1]) < 0.03)
- {
- hold_count++;
- hold_lost = 0;
- }
- else{
- hold_count = 0;
- hold_lost++;
- }
- if(hold_lost > HOLD_THRES)
- {
- is_holded = false;
- // PCOUT(1, GREEN, "no hold");
- }
- if(hold_count > HOLD_THRES){
- is_holded = true;
- // PCOUT(1, GREEN, "holded");
- }
- break;
- case TRACKING_MOVING:
- if (!is_detected)
- {
- --loss_count;
- if(loss_count < 0)
- exec_state = RETURN;
- PCOUT(0, YELLOW, "Return");
- }
- //坐标系
- uav_command.header.frame_id = "BODY";
- // Move模式
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- // 机体系下的速度控制
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XY_VEL_Z_POS_BODY;
- uav_command.velocity_ref[0] = -2.5 * ellipse_det.sight_angle[0];
- uav_command.velocity_ref[1] = 2 * ellipse_det.sight_angle[1];
- uav_command.velocity_ref[2] = 0;
- uav_command.position_ref[2] = 2.3;
- uav_command.yaw_ref = 0.0;
- info << "Find object,Go to the target point > velocity_x: " << uav_command.velocity_ref[0] << " [m/s] "
- << "velocity_y: " << uav_command.velocity_ref[1] << " [m/s] "
- << std::endl;
- PCOUT(1, GREEN, info.str());
- // if(is_holded){
- // if(uav_state.position[0] > -9 && uav_state.position[0] < 0)
- // if(uav_state.position[1] > -4 && uav_state.position[1] < 0)
- // exec_state = WAY2;
- // if(uav_state.position[0] > -9 && uav_state.position[0] < 0)
- // if(uav_state.position[1] > 0 && uav_state.position[1] < 4)
- // exec_state = WAY3;
- // }
-
- if (std::abs(uav_command.velocity_ref[0]) + std::abs(uav_command.velocity_ref[1]) < 0.03)
- {
- hold_count++;
- hold_lost = 0;
- }
- else{
- hold_count = 0;
- hold_lost++;
- }
- if(hold_lost > HOLD_THRES)
- {
- is_holded = false;
- // PCOUT(1, GREEN, "no hold");
- }
- if(hold_count > HOLD_THRES){
- is_holded = true;
- // PCOUT(1, GREEN, "holded");
- }
- break;
- case RETURN:
- // return to home
- uav_command.header.frame_id = "ENU";
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Move;
- uav_command.Move_mode = prometheus_msgs::UAVCommand::XYZ_POS;
- // uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Init_Pos_Hover;
- uav_command.position_ref[0] = 0;
- uav_command.position_ref[1] = 0;
- uav_command.position_ref[2] = 1;
- uav_command.yaw_ref = 0.0;
- cout << GREEN << "return to home" << TAIL << endl;
-
- sleep(15);
- uav_command.Agent_CMD = prometheus_msgs::UAVCommand::Land;
- cout << GREEN << "landing" << TAIL << endl;
-
- break;
- }
- uav_command.Command_ID += 1;
- uav_command_pub.publish(uav_command);
- r.sleep();
- }
- return 0;
-}
diff --git a/src/无人机端代码/Modules/motion_planning/CMakeLists.txt b/src/无人机端代码/Modules/motion_planning/CMakeLists.txt
deleted file mode 100644
index 66dd650a..00000000
--- a/src/无人机端代码/Modules/motion_planning/CMakeLists.txt
+++ /dev/null
@@ -1 +0,0 @@
-/opt/ros/melodic/share/catkin/cmake/toplevel.cmake
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/motion_planning/global_planner/CMakeLists.txt b/src/无人机端代码/Modules/motion_planning/global_planner/CMakeLists.txt
deleted file mode 100644
index 02c9edc3..00000000
--- a/src/无人机端代码/Modules/motion_planning/global_planner/CMakeLists.txt
+++ /dev/null
@@ -1,58 +0,0 @@
-cmake_minimum_required(VERSION 2.8.3)
-project(prometheus_global_planner)
-
-find_package(Eigen3 REQUIRED)
-find_package(PCL 1.7 REQUIRED)
-find_package(catkin REQUIRED COMPONENTS
- roscpp
- rospy
- std_msgs
- sensor_msgs
- laser_geometry
- geometry_msgs
- nav_msgs
- pcl_ros
- visualization_msgs
- gazebo_msgs
- prometheus_msgs
-)
-
-
-catkin_package(
- INCLUDE_DIRS include
-)
-
-include_directories(
- SYSTEM
- include
- ${PROJECT_SOURCE_DIR}/include
- ${catkin_INCLUDE_DIRS}
- ${Eigen3_INCLUDE_DIRS}
- ${PCL_INCLUDE_DIRS}
- ${PROJECT_SOURCE_DIR}/../../common/include
- )
-link_directories(${PCL_LIBRARY_DIRS})
-
-add_library(occupy_map src/occupy_map.cpp)
-target_link_libraries(occupy_map ${PCL_LIBRARIES})
-add_library(A_star src/A_star.cpp)
-target_link_libraries(A_star occupy_map)
-add_library(global_planner src/global_planner.cpp)
-target_link_libraries(global_planner A_star)
-
-add_executable(global_planner_main src/global_planner_node.cpp)
-add_dependencies(global_planner_main prometheus_global_planner_gencpp)
-target_link_libraries(global_planner_main ${catkin_LIBRARIES})
-target_link_libraries(global_planner_main ${PCL_LIBRARIES})
-target_link_libraries(global_planner_main global_planner)
-
-## Mark cpp header files for installation
-install(DIRECTORY include/${PROJECT_NAME}/
- DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
- FILES_MATCHING PATTERN "*.h"
-)
-
-## Mark other files for installation (e.g. launch and bag files, etc.)
-install(DIRECTORY launch/
- DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
-)
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/motion_planning/global_planner/global_planner.md b/src/无人机端代码/Modules/motion_planning/global_planner/global_planner.md
deleted file mode 100644
index 71824e7e..00000000
--- a/src/无人机端代码/Modules/motion_planning/global_planner/global_planner.md
+++ /dev/null
@@ -1,78 +0,0 @@
-## global_planner
-
- - 使用gazebo环境获取感知信息还是通过map_generator?
- - 使用PX4自带的动力学or fake_odom模块?
- -
-
-#### 情况讨论
-
- - 全局点云情况(测试)
- - 真实场景对应:已知全局地图
- - map_generator生成全局点云
- - 无人机不需要搭载传感器
- - PX4动力学 & fake_odom模块
-
-
-启动仿真环境
-roslaunch prometheus_simulator_utils map_generator_with_fake_odom.launch
-
- - 依次拨动swb,切换值COMMAND_CONTROL模式,无人机会自动起飞至指定高度
-
-启动规划算法
-roslaunch prometheus_global_planner sitl_global_planner_with_global_point.launch
-
- - 在RVIZ中选定目标点,或者使用终端发布rostopic pub /uav1/prometheus/motion_planning/goal xxx
-
-
-
- - 局部点云情况(todo)
- - 对应真实情况:D435i等RGBD相机,三维激光雷达
- - map_generator生成全局点云,模拟得到局部点云信息
- - 无人机不需要搭载传感器
- - PX4动力学 & fake_odom模块
-
-
-启动仿真环境
-roslaunch prometheus_simulator_utils map_generator_with_fake_odom.launch
-
- - 依次拨动swb,切换值COMMAND_CONTROL模式,无人机会自动起飞至指定高度
-
-启动规划算法
-roslaunch prometheus_global_planner sitl_global_planner_with_local_point.launch
-
- - 在RVIZ中选定目标点,或者使用终端发布rostopic pub /uav1/prometheus/motion_planning/goal xxx
-
-
- - 2dlidar情况(todo)
- - 对应真实情况:二维激光雷达
- - projector_.projectLaser(*local_point, input_laser_scan)将scan转换为点云,即对应回到局部点云情况
- - map_generator生成全局点云,模拟得到局部点云信息
- - 无人机不需要搭载传感器
- - PX4动力学 & fake_odom模块
-
-启动仿真环境
-roslaunch prometheus_simulator_utils map_generator_with_fake_odom.launch
-
- - 依次拨动swb,切换值COMMAND_CONTROL模式,无人机会自动起飞至指定高度
-
-启动规划算法
-roslaunch prometheus_global_planner sitl_global_planner_with_2dlidar.launch
-
- - 在RVIZ中选定目标点,或者使用终端发布rostopic pub /uav1/prometheus/motion_planning/goal xxx
-
-
- - 多机情况(todo)
- - 建议使用 全局点云情况 + 多个无人机
- - fake_odom模块
-
-## wiki安排
-
- 6.1 simulator_utils
- 6.1.1 map_generator
- 6.1.2 fake_odom
- 6.2 motion_planning
- 6.2.1 global_planner
- 6.2.2 local_planner
- 6.3 ego_planner
-
-
diff --git a/src/无人机端代码/Modules/motion_planning/global_planner/include/A_star.h b/src/无人机端代码/Modules/motion_planning/global_planner/include/A_star.h
deleted file mode 100644
index 87bded62..00000000
--- a/src/无人机端代码/Modules/motion_planning/global_planner/include/A_star.h
+++ /dev/null
@@ -1,181 +0,0 @@
-#ifndef _ASTAR_H
-#define _ASTAR_H
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-
-#include "occupy_map.h"
-#include "printf_utils.h"
-#include "global_planner_utils.h"
-
-using namespace std;
-
-
-
-#define IN_CLOSE_SET 'a'
-#define IN_OPEN_SET 'b'
-#define NOT_EXPAND 'c'
-#define inf 1 >> 30
-
- class Node
- {
- public:
- /* -------------------- */
- Eigen::Vector3i index;
- Eigen::Vector3d position;
- double g_score, f_score;
- Node *parent;
- char node_state;
-
- double time; // dyn
- int time_idx;
-
- Node()
- {
- parent = NULL;
- node_state = NOT_EXPAND;
- }
- ~Node(){};
- };
- typedef Node *NodePtr;
-
- // 为什么这么麻烦,不能直接比较吗
- class NodeComparator0
- {
- public:
- bool operator()(NodePtr node1, NodePtr node2)
- {
- return node1->f_score > node2->f_score;
- }
- };
-
- template
- struct matrix_hash0 : std::unary_function
- {
- std::size_t operator()(T const &matrix) const
- {
- size_t seed = 0;
- for (size_t i = 0; i < matrix.size(); ++i)
- {
- auto elem = *(matrix.data() + i);
- seed ^= std::hash()(elem) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
- }
- return seed;
- }
- };
-
- class NodeHashTable0
- {
- private:
- /* data */
- std::unordered_map> data_3d_;
-
- public:
- NodeHashTable0(/* args */)
- {
- }
- ~NodeHashTable0()
- {
- }
- void insert(Eigen::Vector3i idx, NodePtr node)
- {
- data_3d_.insert(std::make_pair(idx, node));
- }
-
- NodePtr find(Eigen::Vector3i idx)
- {
- auto iter = data_3d_.find(idx);
- return iter == data_3d_.end() ? NULL : iter->second;
- }
-
- void clear()
- {
- data_3d_.clear();
- }
- };
-
- class Astar
- {
- private:
- // 备选路径点指针容器
- std::vector path_node_pool_;
- // 使用节点计数器、迭代次数计数器
- int use_node_num_, iter_num_;
- // 扩展的节点
- NodeHashTable0 expanded_nodes_;
- // open set (根据规则已排序好)
- std::priority_queue, NodeComparator0> open_set_;
- // 最终路径点容器
- std::vector path_nodes_;
-
- // 参数
- // 启发式参数
- double lambda_heu_;
- double lambda_cost_;
- // 最大搜索次数
- int max_search_num;
- // tie breaker
- double tie_breaker_;
- bool is_2D;
- double fly_height;
-
- // 目标点
- Eigen::Vector3d goal_pos;
-
- // 地图相关
- std::vector occupancy_buffer_;
- double resolution_, inv_resolution_;
- Eigen::Vector3d origin_, map_size_3d_;
-
- // 辅助函数
- Eigen::Vector3i posToIndex(Eigen::Vector3d pt);
- void indexToPos(Eigen::Vector3i id, Eigen::Vector3d &pos);
- void retrievePath(NodePtr end_node);
-
- // 搜索启发函数,三种形式,选用其中一种即可
- double getDiagHeu(Eigen::Vector3d x1, Eigen::Vector3d x2);
- double getManhHeu(Eigen::Vector3d x1, Eigen::Vector3d x2);
- double getEuclHeu(Eigen::Vector3d x1, Eigen::Vector3d x2);
-
- public:
- Astar(){}
- ~Astar();
-
- enum
- {
- REACH_END = 1,
- NO_PATH = 2
- };
-
- // 占据图类
- Occupy_map::Ptr Occupy_map_ptr;
-
- // 重置
- void reset();
- // 初始化
- void init(ros::NodeHandle &nh);
- // 检查安全性
- bool check_safety(Eigen::Vector3d &cur_pos, double safe_distance);
- // 搜索
- int search(Eigen::Vector3d start_pt, Eigen::Vector3d end_pt);
- // 返回路径
- std::vector getPath();
- // 返回ros消息格式的路径
- nav_msgs::Path get_ros_path();
- // 返回访问过的节点
- std::vector getVisitedNodes();
-
- typedef std::shared_ptr Ptr;
- };
-
-
-
-#endif
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/motion_planning/global_planner/include/global_planner.h b/src/无人机端代码/Modules/motion_planning/global_planner/include/global_planner.h
deleted file mode 100644
index 2d21b150..00000000
--- a/src/无人机端代码/Modules/motion_planning/global_planner/include/global_planner.h
+++ /dev/null
@@ -1,121 +0,0 @@
-#ifndef GLOBAL_PLANNER
-#define GLOBAL_PLANNER
-
-#include
-
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include "A_star.h"
-#include "occupy_map.h"
-#include "printf_utils.h"
-#include "global_planner_utils.h"
-using namespace std;
-
-
- class GlobalPlanner
- {
- public:
- GlobalPlanner(ros::NodeHandle &nh);
- ros::NodeHandle global_planner_nh;
-
- private:
- // 参数
- int uav_id;
- bool sim_mode;
- int map_input_source;
- double fly_height;
- double safe_distance;
- double time_per_path;
- double replan_time;
- bool consider_neighbour;
- string global_pcl_topic_name, local_pcl_topic_name, scan_topic_name;
-
- // 订阅无人机状态、目标点、传感器数据(生成地图)
- ros::Subscriber goal_sub;
- ros::Subscriber uav_state_sub;
- // 支持2维激光雷达、3维激光雷达、D435i等实体传感器
- // 支持直接输入全局已知点云
- ros::Subscriber Gpointcloud_sub;
- ros::Subscriber Lpointcloud_sub;
- ros::Subscriber laserscan_sub;
- ros::Subscriber uav_control_state_sub;
- // 发布控制指令
- ros::Publisher uav_cmd_pub;
- ros::Publisher path_cmd_pub;
- ros::Timer mainloop_timer;
- ros::Timer track_path_timer;
- ros::Timer safety_timer;
- // A星规划器
- Astar::Ptr Astar_ptr;
-
- // laserscan2pointcloud2 投影器
- laser_geometry::LaserProjection projector_;
-
- prometheus_msgs::UAVState uav_state; // 无人机状态
- prometheus_msgs::UAVControlState uav_control_state;
- nav_msgs::Odometry uav_odom;
- Eigen::Vector3d uav_pos; // 无人机位置
- Eigen::Vector3d uav_vel; // 无人机速度
- Eigen::Quaterniond uav_quat; // 无人机四元数
- double uav_yaw;
- // 规划终端状态
- Eigen::Vector3d goal_pos, goal_vel;
- prometheus_msgs::UAVCommand uav_command;
- nav_msgs::Path path_cmd;
- double distance_to_goal;
-
- // 规划器状态
- bool odom_ready;
- bool drone_ready;
- bool sensor_ready;
- bool goal_ready;
- bool is_safety;
- bool is_new_path;
- bool path_ok;
- int start_point_index;
- int Num_total_wp;
- int cur_id;
- float desired_yaw;
-
- ros::Time last_replan_time;
-
- // 五种状态机
- enum EXEC_STATE
- {
- WAIT_GOAL,
- PLANNING,
- TRACKING,
- LANDING,
- };
- EXEC_STATE exec_state;
-
- // 回调函数
- void goal_cb(const geometry_msgs::PoseStampedConstPtr &msg);
- void uav_state_cb(const prometheus_msgs::UAVStateConstPtr &msg);
- void Gpointcloud_cb(const sensor_msgs::PointCloud2ConstPtr &msg);
- void Lpointcloud_cb(const sensor_msgs::PointCloud2ConstPtr &msg);
- void laser_cb(const sensor_msgs::LaserScanConstPtr &msg);
- void uav_control_state_cb(const prometheus_msgs::UAVControlState::ConstPtr &msg);
- void safety_cb(const ros::TimerEvent &e);
- void mainloop_cb(const ros::TimerEvent &e);
- void track_path_cb(const ros::TimerEvent &e);
- void debug_info();
- int get_start_point_id(void);
- };
-
-
-
-#endif
\ No newline at end of file
diff --git a/src/无人机端代码/Modules/motion_planning/global_planner/include/global_planner_utils.h b/src/无人机端代码/Modules/motion_planning/global_planner/include/global_planner_utils.h
deleted file mode 100644
index 6a4c455f..00000000
--- a/src/无人机端代码/Modules/motion_planning/global_planner/include/global_planner_utils.h
+++ /dev/null
@@ -1,8 +0,0 @@
-#ifndef GLOBAL_PLANNER_UTILS_H
-#define GLOBAL_PLANNER_UTILS_H
-
-#define NODE_NAME "GlobalPlanner [Astar] "
-#define MIN_DIS 0.1
-
-#endif
-
diff --git a/src/无人机端代码/Modules/motion_planning/global_planner/include/occupy_map.h b/src/无人机端代码/Modules/motion_planning/global_planner/include/occupy_map.h
deleted file mode 100644
index eaff87f9..00000000
--- a/src/无人机端代码/Modules/motion_planning/global_planner/include/occupy_map.h
+++ /dev/null
@@ -1,128 +0,0 @@
-#ifndef _OCCUPY_MAP_H
-#define _OCCUPY_MAP_H
-
-#include
-#include
-
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include