add 3 contributer demos

This commit is contained in:
robin_shaun 2021-06-16 21:36:35 +08:00
parent 481bd95ca6
commit a3729a866d
34 changed files with 29485 additions and 5 deletions

View File

@ -89,13 +89,13 @@ USV
- Founders: Kun Xiao, Shaochang Tan
- Adviser: Xiangke Wang
- Developers: Kun Xiao, Shaochang Tan, Guanzheng Wang, Lan Ma, Qipeng Wang, Xinyu Hu, Wenxin Hu, Yi Bao, Ruoqiao Guan, Xinyu Hu, Keyan Chen, Gao Chen
- Developers: Kun Xiao, Shaochang Tan, Guanzheng Wang, Lan Ma, Qipeng Wang, Xinyu Hu, Ruoqiao Guan, Wenxin Hu, Feng Yi, Jiarun Yan, Yi Bao, Keyan Chen, Gao Chen
### Contributers
Sincerely thank you for your contribution to XTDrone.
Changhao Sun, Zihan Lin, Yao He
Changhao Sun, Ying Nie, Fanjie Kong, Chaoran Li, Xudong Li, Zihan Lin, Yao He

View File

@ -93,7 +93,7 @@ Xiao, K., Ma, L., Tan, S., Cong, Y., Wang, X.: Implementation of UAV Coordinatio
- 创立者:肖昆,谭劭昌
- 指导老师:王祥科
- 开发团队:肖昆,谭劭昌,王冠政,马澜,王齐鹏,胡新雨,胡文信,鲍毅,管若乔,陈科研,陈皋
- 开发团队:肖昆,谭劭昌,王冠政,马澜,王齐鹏,胡新雨,管若乔,胡文信,易丰,颜佳润,鲍毅,陈科研,陈皋
### 加入我们
@ -103,7 +103,7 @@ Xiao, K., Ma, L., Tan, S., Cong, Y., Wang, X.: Implementation of UAV Coordinatio
非常感谢你们为XTDrone的贡献
孙长浩 林梓涵 何瑶
孙长浩,聂莹,孔凡杰,李超然,李旭东,林梓涵,何瑶
### 捐赠

View File

@ -0,0 +1,22 @@
# UAV Collaborative Simulation
To simulate UAVs Collaborative for target searching , recognition and localization.
## Introduction
To run the project, do as follows:
### 1.Source Download
```bash
git clone https://codechina.csdn.net/qq_44715174/uav_collaborative_simulation.git
```
### 2.Simulation Environment
1.copy .launch and .world to px4
```bash
cd uav_collaborative_simulation
cp worlds/* ~/PX4_Firmware/Tools/sitl_gazebo/worlds/
cp launch/* ~/PX4_Firmware/launch/
```
2.run the simulation environment
```bash
roslaunch px4 cic2021.launch
```

View File

@ -0,0 +1,400 @@
/clock
/diagnostics
/gazebo/link_states
/gazebo/model_states
/gazebo/parameter_descriptions
/gazebo/parameter_updates
/gazebo/set_link_state
/gazebo/set_model_state
/rosout
/rosout_agg
/tf
/tf_static
/typhoon_h480_0/cgo3_camera/camera_info
/typhoon_h480_0/cgo3_camera/image_raw
/typhoon_h480_0/cgo3_camera/image_raw/compressed
/typhoon_h480_0/cgo3_camera/image_raw/compressed/parameter_descriptions
/typhoon_h480_0/cgo3_camera/image_raw/compressed/parameter_updates
/typhoon_h480_0/cgo3_camera/image_raw/compressedDepth
/typhoon_h480_0/cgo3_camera/image_raw/compressedDepth/parameter_descriptions
/typhoon_h480_0/cgo3_camera/image_raw/compressedDepth/parameter_updates
/typhoon_h480_0/cgo3_camera/image_raw/theora
/typhoon_h480_0/cgo3_camera/image_raw/theora/parameter_descriptions
/typhoon_h480_0/cgo3_camera/image_raw/theora/parameter_updates
/typhoon_h480_0/cgo3_camera/parameter_descriptions
/typhoon_h480_0/cgo3_camera/parameter_updates
/typhoon_h480_0/mavlink/from
/typhoon_h480_0/mavlink/gcs_ip
/typhoon_h480_0/mavlink/to
/typhoon_h480_0/mavros/actuator_control
/typhoon_h480_0/mavros/adsb/send
/typhoon_h480_0/mavros/adsb/vehicle
/typhoon_h480_0/mavros/altitude
/typhoon_h480_0/mavros/battery
/typhoon_h480_0/mavros/cam_imu_sync/cam_imu_stamp
/typhoon_h480_0/mavros/companion_process/status
/typhoon_h480_0/mavros/debug_value/debug
/typhoon_h480_0/mavros/debug_value/debug_vector
/typhoon_h480_0/mavros/debug_value/named_value_float
/typhoon_h480_0/mavros/debug_value/named_value_int
/typhoon_h480_0/mavros/debug_value/send
/typhoon_h480_0/mavros/esc_info
/typhoon_h480_0/mavros/esc_status
/typhoon_h480_0/mavros/estimator_status
/typhoon_h480_0/mavros/extended_state
/typhoon_h480_0/mavros/fake_gps/mocap/tf
/typhoon_h480_0/mavros/global_position/compass_hdg
/typhoon_h480_0/mavros/global_position/global
/typhoon_h480_0/mavros/global_position/gp_lp_offset
/typhoon_h480_0/mavros/global_position/gp_origin
/typhoon_h480_0/mavros/global_position/home
/typhoon_h480_0/mavros/global_position/local
/typhoon_h480_0/mavros/global_position/raw/fix
/typhoon_h480_0/mavros/global_position/raw/gps_vel
/typhoon_h480_0/mavros/global_position/raw/satellites
/typhoon_h480_0/mavros/global_position/rel_alt
/typhoon_h480_0/mavros/global_position/set_gp_origin
/typhoon_h480_0/mavros/gps_rtk/rtk_baseline
/typhoon_h480_0/mavros/gps_rtk/send_rtcm
/typhoon_h480_0/mavros/gpsstatus/gps1/raw
/typhoon_h480_0/mavros/gpsstatus/gps1/rtk
/typhoon_h480_0/mavros/gpsstatus/gps2/raw
/typhoon_h480_0/mavros/gpsstatus/gps2/rtk
/typhoon_h480_0/mavros/hil/actuator_controls
/typhoon_h480_0/mavros/hil/controls
/typhoon_h480_0/mavros/hil/gps
/typhoon_h480_0/mavros/hil/imu_ned
/typhoon_h480_0/mavros/hil/optical_flow
/typhoon_h480_0/mavros/hil/rc_inputs
/typhoon_h480_0/mavros/hil/state
/typhoon_h480_0/mavros/home_position/home
/typhoon_h480_0/mavros/home_position/set
/typhoon_h480_0/mavros/imu/data
/typhoon_h480_0/mavros/imu/data_raw
/typhoon_h480_0/mavros/imu/diff_pressure
/typhoon_h480_0/mavros/imu/mag
/typhoon_h480_0/mavros/imu/static_pressure
/typhoon_h480_0/mavros/imu/temperature_baro
/typhoon_h480_0/mavros/imu/temperature_imu
/typhoon_h480_0/mavros/landing_target/lt_marker
/typhoon_h480_0/mavros/landing_target/pose
/typhoon_h480_0/mavros/landing_target/pose_in
/typhoon_h480_0/mavros/local_position/accel
/typhoon_h480_0/mavros/local_position/odom
/typhoon_h480_0/mavros/local_position/pose
/typhoon_h480_0/mavros/local_position/pose_cov
/typhoon_h480_0/mavros/local_position/velocity_body
/typhoon_h480_0/mavros/local_position/velocity_body_cov
/typhoon_h480_0/mavros/local_position/velocity_local
/typhoon_h480_0/mavros/log_transfer/raw/log_data
/typhoon_h480_0/mavros/log_transfer/raw/log_entry
/typhoon_h480_0/mavros/manual_control/control
/typhoon_h480_0/mavros/manual_control/send
/typhoon_h480_0/mavros/mission/reached
/typhoon_h480_0/mavros/mission/waypoints
/typhoon_h480_0/mavros/mocap/pose
/typhoon_h480_0/mavros/mount_control/command
/typhoon_h480_0/mavros/mount_control/orientation
/typhoon_h480_0/mavros/obstacle/send
/typhoon_h480_0/mavros/odometry/in
/typhoon_h480_0/mavros/odometry/out
/typhoon_h480_0/mavros/onboard_computer/status
/typhoon_h480_0/mavros/param/param_value
/typhoon_h480_0/mavros/play_tune
/typhoon_h480_0/mavros/px4flow/ground_distance
/typhoon_h480_0/mavros/px4flow/raw/optical_flow_rad
/typhoon_h480_0/mavros/px4flow/raw/send
/typhoon_h480_0/mavros/px4flow/temperature
/typhoon_h480_0/mavros/radio_status
/typhoon_h480_0/mavros/rc/in
/typhoon_h480_0/mavros/rc/out
/typhoon_h480_0/mavros/rc/override
/typhoon_h480_0/mavros/setpoint_accel/accel
/typhoon_h480_0/mavros/setpoint_attitude/cmd_vel
/typhoon_h480_0/mavros/setpoint_attitude/thrust
/typhoon_h480_0/mavros/setpoint_position/global
/typhoon_h480_0/mavros/setpoint_position/global_to_local
/typhoon_h480_0/mavros/setpoint_position/local
/typhoon_h480_0/mavros/setpoint_raw/attitude
/typhoon_h480_0/mavros/setpoint_raw/global
/typhoon_h480_0/mavros/setpoint_raw/local
/typhoon_h480_0/mavros/setpoint_raw/target_attitude
/typhoon_h480_0/mavros/setpoint_raw/target_global
/typhoon_h480_0/mavros/setpoint_raw/target_local
/typhoon_h480_0/mavros/setpoint_trajectory/desired
/typhoon_h480_0/mavros/setpoint_trajectory/local
/typhoon_h480_0/mavros/setpoint_velocity/cmd_vel
/typhoon_h480_0/mavros/setpoint_velocity/cmd_vel_unstamped
/typhoon_h480_0/mavros/state
/typhoon_h480_0/mavros/statustext/recv
/typhoon_h480_0/mavros/statustext/send
/typhoon_h480_0/mavros/target_actuator_control
/typhoon_h480_0/mavros/time_reference
/typhoon_h480_0/mavros/timesync_status
/typhoon_h480_0/mavros/trajectory/desired
/typhoon_h480_0/mavros/trajectory/generated
/typhoon_h480_0/mavros/trajectory/path
/typhoon_h480_0/mavros/vfr_hud
/typhoon_h480_0/mavros/vision_pose/pose
/typhoon_h480_0/mavros/vision_pose/pose_cov
/typhoon_h480_0/mavros/vision_speed/speed_twist_cov
/typhoon_h480_0/mavros/wind_estimation
/typhoon_h480_1/cgo3_camera/camera_info
/typhoon_h480_1/cgo3_camera/image_raw
/typhoon_h480_1/cgo3_camera/image_raw/compressed
/typhoon_h480_1/cgo3_camera/image_raw/compressed/parameter_descriptions
/typhoon_h480_1/cgo3_camera/image_raw/compressed/parameter_updates
/typhoon_h480_1/cgo3_camera/image_raw/compressedDepth
/typhoon_h480_1/cgo3_camera/image_raw/compressedDepth/parameter_descriptions
/typhoon_h480_1/cgo3_camera/image_raw/compressedDepth/parameter_updates
/typhoon_h480_1/cgo3_camera/image_raw/theora
/typhoon_h480_1/cgo3_camera/image_raw/theora/parameter_descriptions
/typhoon_h480_1/cgo3_camera/image_raw/theora/parameter_updates
/typhoon_h480_1/cgo3_camera/parameter_descriptions
/typhoon_h480_1/cgo3_camera/parameter_updates
/typhoon_h480_1/mavlink/from
/typhoon_h480_1/mavlink/gcs_ip
/typhoon_h480_1/mavlink/to
/typhoon_h480_1/mavros/actuator_control
/typhoon_h480_1/mavros/adsb/send
/typhoon_h480_1/mavros/adsb/vehicle
/typhoon_h480_1/mavros/altitude
/typhoon_h480_1/mavros/battery
/typhoon_h480_1/mavros/cam_imu_sync/cam_imu_stamp
/typhoon_h480_1/mavros/companion_process/status
/typhoon_h480_1/mavros/debug_value/debug
/typhoon_h480_1/mavros/debug_value/debug_vector
/typhoon_h480_1/mavros/debug_value/named_value_float
/typhoon_h480_1/mavros/debug_value/named_value_int
/typhoon_h480_1/mavros/debug_value/send
/typhoon_h480_1/mavros/esc_info
/typhoon_h480_1/mavros/esc_status
/typhoon_h480_1/mavros/estimator_status
/typhoon_h480_1/mavros/extended_state
/typhoon_h480_1/mavros/fake_gps/mocap/tf
/typhoon_h480_1/mavros/global_position/compass_hdg
/typhoon_h480_1/mavros/global_position/global
/typhoon_h480_1/mavros/global_position/gp_lp_offset
/typhoon_h480_1/mavros/global_position/gp_origin
/typhoon_h480_1/mavros/global_position/home
/typhoon_h480_1/mavros/global_position/local
/typhoon_h480_1/mavros/global_position/raw/fix
/typhoon_h480_1/mavros/global_position/raw/gps_vel
/typhoon_h480_1/mavros/global_position/raw/satellites
/typhoon_h480_1/mavros/global_position/rel_alt
/typhoon_h480_1/mavros/global_position/set_gp_origin
/typhoon_h480_1/mavros/gps_rtk/rtk_baseline
/typhoon_h480_1/mavros/gps_rtk/send_rtcm
/typhoon_h480_1/mavros/gpsstatus/gps1/raw
/typhoon_h480_1/mavros/gpsstatus/gps1/rtk
/typhoon_h480_1/mavros/gpsstatus/gps2/raw
/typhoon_h480_1/mavros/gpsstatus/gps2/rtk
/typhoon_h480_1/mavros/hil/actuator_controls
/typhoon_h480_1/mavros/hil/controls
/typhoon_h480_1/mavros/hil/gps
/typhoon_h480_1/mavros/hil/imu_ned
/typhoon_h480_1/mavros/hil/optical_flow
/typhoon_h480_1/mavros/hil/rc_inputs
/typhoon_h480_1/mavros/hil/state
/typhoon_h480_1/mavros/home_position/home
/typhoon_h480_1/mavros/home_position/set
/typhoon_h480_1/mavros/imu/data
/typhoon_h480_1/mavros/imu/data_raw
/typhoon_h480_1/mavros/imu/diff_pressure
/typhoon_h480_1/mavros/imu/mag
/typhoon_h480_1/mavros/imu/static_pressure
/typhoon_h480_1/mavros/imu/temperature_baro
/typhoon_h480_1/mavros/imu/temperature_imu
/typhoon_h480_1/mavros/landing_target/lt_marker
/typhoon_h480_1/mavros/landing_target/pose
/typhoon_h480_1/mavros/landing_target/pose_in
/typhoon_h480_1/mavros/local_position/accel
/typhoon_h480_1/mavros/local_position/odom
/typhoon_h480_1/mavros/local_position/pose
/typhoon_h480_1/mavros/local_position/pose_cov
/typhoon_h480_1/mavros/local_position/velocity_body
/typhoon_h480_1/mavros/local_position/velocity_body_cov
/typhoon_h480_1/mavros/local_position/velocity_local
/typhoon_h480_1/mavros/log_transfer/raw/log_data
/typhoon_h480_1/mavros/log_transfer/raw/log_entry
/typhoon_h480_1/mavros/manual_control/control
/typhoon_h480_1/mavros/manual_control/send
/typhoon_h480_1/mavros/mission/reached
/typhoon_h480_1/mavros/mission/waypoints
/typhoon_h480_1/mavros/mocap/pose
/typhoon_h480_1/mavros/mount_control/command
/typhoon_h480_1/mavros/mount_control/orientation
/typhoon_h480_1/mavros/obstacle/send
/typhoon_h480_1/mavros/odometry/in
/typhoon_h480_1/mavros/odometry/out
/typhoon_h480_1/mavros/onboard_computer/status
/typhoon_h480_1/mavros/param/param_value
/typhoon_h480_1/mavros/play_tune
/typhoon_h480_1/mavros/px4flow/ground_distance
/typhoon_h480_1/mavros/px4flow/raw/optical_flow_rad
/typhoon_h480_1/mavros/px4flow/raw/send
/typhoon_h480_1/mavros/px4flow/temperature
/typhoon_h480_1/mavros/radio_status
/typhoon_h480_1/mavros/rc/in
/typhoon_h480_1/mavros/rc/out
/typhoon_h480_1/mavros/rc/override
/typhoon_h480_1/mavros/setpoint_accel/accel
/typhoon_h480_1/mavros/setpoint_attitude/cmd_vel
/typhoon_h480_1/mavros/setpoint_attitude/thrust
/typhoon_h480_1/mavros/setpoint_position/global
/typhoon_h480_1/mavros/setpoint_position/global_to_local
/typhoon_h480_1/mavros/setpoint_position/local
/typhoon_h480_1/mavros/setpoint_raw/attitude
/typhoon_h480_1/mavros/setpoint_raw/global
/typhoon_h480_1/mavros/setpoint_raw/local
/typhoon_h480_1/mavros/setpoint_raw/target_attitude
/typhoon_h480_1/mavros/setpoint_raw/target_global
/typhoon_h480_1/mavros/setpoint_raw/target_local
/typhoon_h480_1/mavros/setpoint_trajectory/desired
/typhoon_h480_1/mavros/setpoint_trajectory/local
/typhoon_h480_1/mavros/setpoint_velocity/cmd_vel
/typhoon_h480_1/mavros/setpoint_velocity/cmd_vel_unstamped
/typhoon_h480_1/mavros/state
/typhoon_h480_1/mavros/statustext/recv
/typhoon_h480_1/mavros/statustext/send
/typhoon_h480_1/mavros/target_actuator_control
/typhoon_h480_1/mavros/time_reference
/typhoon_h480_1/mavros/timesync_status
/typhoon_h480_1/mavros/trajectory/desired
/typhoon_h480_1/mavros/trajectory/generated
/typhoon_h480_1/mavros/trajectory/path
/typhoon_h480_1/mavros/vfr_hud
/typhoon_h480_1/mavros/vision_pose/pose
/typhoon_h480_1/mavros/vision_pose/pose_cov
/typhoon_h480_1/mavros/vision_speed/speed_twist_cov
/typhoon_h480_1/mavros/wind_estimation
/typhoon_h480_2/cgo3_camera/camera_info
/typhoon_h480_2/cgo3_camera/image_raw
/typhoon_h480_2/cgo3_camera/image_raw/compressed
/typhoon_h480_2/cgo3_camera/image_raw/compressed/parameter_descriptions
/typhoon_h480_2/cgo3_camera/image_raw/compressed/parameter_updates
/typhoon_h480_2/cgo3_camera/image_raw/compressedDepth
/typhoon_h480_2/cgo3_camera/image_raw/compressedDepth/parameter_descriptions
/typhoon_h480_2/cgo3_camera/image_raw/compressedDepth/parameter_updates
/typhoon_h480_2/cgo3_camera/image_raw/theora
/typhoon_h480_2/cgo3_camera/image_raw/theora/parameter_descriptions
/typhoon_h480_2/cgo3_camera/image_raw/theora/parameter_updates
/typhoon_h480_2/cgo3_camera/parameter_descriptions
/typhoon_h480_2/cgo3_camera/parameter_updates
/typhoon_h480_2/mavlink/from
/typhoon_h480_2/mavlink/gcs_ip
/typhoon_h480_2/mavlink/to
/typhoon_h480_2/mavros/actuator_control
/typhoon_h480_2/mavros/adsb/send
/typhoon_h480_2/mavros/adsb/vehicle
/typhoon_h480_2/mavros/altitude
/typhoon_h480_2/mavros/battery
/typhoon_h480_2/mavros/cam_imu_sync/cam_imu_stamp
/typhoon_h480_2/mavros/companion_process/status
/typhoon_h480_2/mavros/debug_value/debug
/typhoon_h480_2/mavros/debug_value/debug_vector
/typhoon_h480_2/mavros/debug_value/named_value_float
/typhoon_h480_2/mavros/debug_value/named_value_int
/typhoon_h480_2/mavros/debug_value/send
/typhoon_h480_2/mavros/esc_info
/typhoon_h480_2/mavros/esc_status
/typhoon_h480_2/mavros/estimator_status
/typhoon_h480_2/mavros/extended_state
/typhoon_h480_2/mavros/fake_gps/mocap/tf
/typhoon_h480_2/mavros/global_position/compass_hdg
/typhoon_h480_2/mavros/global_position/global
/typhoon_h480_2/mavros/global_position/gp_lp_offset
/typhoon_h480_2/mavros/global_position/gp_origin
/typhoon_h480_2/mavros/global_position/home
/typhoon_h480_2/mavros/global_position/local
/typhoon_h480_2/mavros/global_position/raw/fix
/typhoon_h480_2/mavros/global_position/raw/gps_vel
/typhoon_h480_2/mavros/global_position/raw/satellites
/typhoon_h480_2/mavros/global_position/rel_alt
/typhoon_h480_2/mavros/global_position/set_gp_origin
/typhoon_h480_2/mavros/gps_rtk/rtk_baseline
/typhoon_h480_2/mavros/gps_rtk/send_rtcm
/typhoon_h480_2/mavros/gpsstatus/gps1/raw
/typhoon_h480_2/mavros/gpsstatus/gps1/rtk
/typhoon_h480_2/mavros/gpsstatus/gps2/raw
/typhoon_h480_2/mavros/gpsstatus/gps2/rtk
/typhoon_h480_2/mavros/hil/actuator_controls
/typhoon_h480_2/mavros/hil/controls
/typhoon_h480_2/mavros/hil/gps
/typhoon_h480_2/mavros/hil/imu_ned
/typhoon_h480_2/mavros/hil/optical_flow
/typhoon_h480_2/mavros/hil/rc_inputs
/typhoon_h480_2/mavros/hil/state
/typhoon_h480_2/mavros/home_position/home
/typhoon_h480_2/mavros/home_position/set
/typhoon_h480_2/mavros/imu/data
/typhoon_h480_2/mavros/imu/data_raw
/typhoon_h480_2/mavros/imu/diff_pressure
/typhoon_h480_2/mavros/imu/mag
/typhoon_h480_2/mavros/imu/static_pressure
/typhoon_h480_2/mavros/imu/temperature_baro
/typhoon_h480_2/mavros/imu/temperature_imu
/typhoon_h480_2/mavros/landing_target/lt_marker
/typhoon_h480_2/mavros/landing_target/pose
/typhoon_h480_2/mavros/landing_target/pose_in
/typhoon_h480_2/mavros/local_position/accel
/typhoon_h480_2/mavros/local_position/odom
/typhoon_h480_2/mavros/local_position/pose
/typhoon_h480_2/mavros/local_position/pose_cov
/typhoon_h480_2/mavros/local_position/velocity_body
/typhoon_h480_2/mavros/local_position/velocity_body_cov
/typhoon_h480_2/mavros/local_position/velocity_local
/typhoon_h480_2/mavros/log_transfer/raw/log_data
/typhoon_h480_2/mavros/log_transfer/raw/log_entry
/typhoon_h480_2/mavros/manual_control/control
/typhoon_h480_2/mavros/manual_control/send
/typhoon_h480_2/mavros/mission/reached
/typhoon_h480_2/mavros/mission/waypoints
/typhoon_h480_2/mavros/mocap/pose
/typhoon_h480_2/mavros/mount_control/command
/typhoon_h480_2/mavros/mount_control/orientation
/typhoon_h480_2/mavros/obstacle/send
/typhoon_h480_2/mavros/odometry/in
/typhoon_h480_2/mavros/odometry/out
/typhoon_h480_2/mavros/onboard_computer/status
/typhoon_h480_2/mavros/param/param_value
/typhoon_h480_2/mavros/play_tune
/typhoon_h480_2/mavros/px4flow/ground_distance
/typhoon_h480_2/mavros/px4flow/raw/optical_flow_rad
/typhoon_h480_2/mavros/px4flow/raw/send
/typhoon_h480_2/mavros/px4flow/temperature
/typhoon_h480_2/mavros/radio_status
/typhoon_h480_2/mavros/rc/in
/typhoon_h480_2/mavros/rc/out
/typhoon_h480_2/mavros/rc/override
/typhoon_h480_2/mavros/setpoint_accel/accel
/typhoon_h480_2/mavros/setpoint_attitude/cmd_vel
/typhoon_h480_2/mavros/setpoint_attitude/thrust
/typhoon_h480_2/mavros/setpoint_position/global
/typhoon_h480_2/mavros/setpoint_position/global_to_local
/typhoon_h480_2/mavros/setpoint_position/local
/typhoon_h480_2/mavros/setpoint_raw/attitude
/typhoon_h480_2/mavros/setpoint_raw/global
/typhoon_h480_2/mavros/setpoint_raw/local
/typhoon_h480_2/mavros/setpoint_raw/target_attitude
/typhoon_h480_2/mavros/setpoint_raw/target_global
/typhoon_h480_2/mavros/setpoint_raw/target_local
/typhoon_h480_2/mavros/setpoint_trajectory/desired
/typhoon_h480_2/mavros/setpoint_trajectory/local
/typhoon_h480_2/mavros/setpoint_velocity/cmd_vel
/typhoon_h480_2/mavros/setpoint_velocity/cmd_vel_unstamped
/typhoon_h480_2/mavros/state
/typhoon_h480_2/mavros/statustext/recv
/typhoon_h480_2/mavros/statustext/send
/typhoon_h480_2/mavros/target_actuator_control
/typhoon_h480_2/mavros/time_reference
/typhoon_h480_2/mavros/timesync_status
/typhoon_h480_2/mavros/trajectory/desired
/typhoon_h480_2/mavros/trajectory/generated
/typhoon_h480_2/mavros/trajectory/path
/typhoon_h480_2/mavros/vfr_hud
/typhoon_h480_2/mavros/vision_pose/pose
/typhoon_h480_2/mavros/vision_pose/pose_cov
/typhoon_h480_2/mavros/vision_speed/speed_twist_cov
/typhoon_h480_2/mavros/wind_estimation

View File

@ -0,0 +1,108 @@
<?xml version="1.0"?>
<launch>
<!-- MAVROS posix SITL environment launch script -->
<!-- launches Gazebo environment and 2x: MAVROS, PX4 SITL, and spawns vehicle -->
<!-- vehicle model and world -->
<arg name="est" default="ekf2"/>
<arg name="world" default="$(find mavlink_sitl_gazebo)/worlds/cic2021.world"/>
<!-- gazebo configs -->
<arg name="gui" default="true"/>
<arg name="debug" default="false"/>
<arg name="verbose" default="false"/>
<arg name="paused" default="false"/>
<!-- Gazebo sim -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="gui" value="$(arg gui)"/>
<arg name="world_name" value="$(arg world)"/>
<arg name="debug" value="$(arg debug)"/>
<arg name="verbose" value="$(arg verbose)"/>
<arg name="paused" value="$(arg paused)"/>
</include>
<!-- typhoon_h480_0 -->
<group ns="typhoon_h480_0">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="0"/>
<arg name="ID_in_group" value="0"/>
<arg name="fcu_url" default="udp://:24540@localhost:34580"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_cic.launch">
<arg name="x" value="0"/>
<arg name="y" value="0"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="typhoon_h480"/>
<arg name="sdf" value="typhoon_h480"/>
<arg name="mavlink_udp_port" value="18570"/>
<arg name="mavlink_tcp_port" value="4560"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- typhoon_h480_1 -->
<group ns="typhoon_h480_1">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="1"/>
<arg name="ID_in_group" value="1"/>
<arg name="fcu_url" default="udp://:24541@localhost:34581"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_cic.launch">
<arg name="x" value="0"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="typhoon_h480"/>
<arg name="sdf" value="typhoon_h480"/>
<arg name="mavlink_udp_port" value="18571"/>
<arg name="mavlink_tcp_port" value="4561"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- typhoon_h480_2 -->
<group ns="typhoon_h480_2">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="2"/>
<arg name="ID_in_group" value="2"/>
<arg name="fcu_url" default="udp://:24542@localhost:34582"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_cic.launch">
<arg name="x" value="0"/>
<arg name="y" value="-3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="typhoon_h480"/>
<arg name="sdf" value="typhoon_h480"/>
<arg name="mavlink_udp_port" value="18572"/>
<arg name="mavlink_tcp_port" value="4562"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
</launch>

View File

@ -0,0 +1 @@
/opt/ros/melodic/share/catkin/cmake/toplevel.cmake

View File

@ -0,0 +1,24 @@
cmake_minimum_required(VERSION 2.8.3)
project(formation)
find_package(catkin REQUIRED COMPONENTS
geometry_msgs
rosmsg
rospy
std_msgs
message_generation
)
generate_messages(
DEPENDENCIES
std_msgs
geometry_msgs
)
catkin_package(
CATKIN_DEPENDS
std_msgs
geometry_msgs
)

View File

@ -0,0 +1,27 @@
<?xml version="1.0"?>
<package format="2">
<name>formation</name>
<version>0.0.0</version>
<description>The PX4 Formation Control package</description>
<maintainer email="yan@todo.todo">malan</maintainer>
<license>TODO</license>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>geometry_msgs</build_depend>
<build_depend>rosmsg</build_depend>
<build_depend>rospy</build_depend>
<build_depend>std_msgs</build_depend>
<build_depend>message_generation</build_depend>
<build_export_depend>geometry_msgs</build_export_depend>
<build_export_depend>rosmsg</build_export_depend>
<build_export_depend>rospy</build_export_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>geometry_msgs</exec_depend>
<exec_depend>rosmsg</exec_depend>
<exec_depend>rospy</exec_depend>
<exec_depend>std_msgs</exec_depend>
<exec_depend>message_runtime</exec_depend>
<export>
</export>
</package>

View File

@ -0,0 +1,97 @@
import numpy as np
import matplotlib.pyplot as plt
import random
class Env():
def __init__(self, vehicle_num, target_num, map_size, visualized):
self.visualized = visualized
self.vehicles_position = np.zeros(vehicle_num, dtype=np.int32)
self.vehicles_speed = np.zeros(vehicle_num, dtype=np.int32)
self.targets = np.zeros(shape=(target_num + 1, 4), dtype=np.int32)
self.distant_mat = np.zeros((target_num + 1, target_num + 1), dtype=np.float32)
self.map_size_x = map_size[0]
self.map_size_y = map_size[1]
self.speed_range = [1, 1, 1]
self.time_lim = max(self.map_size_x, self.map_size_y )/ self.speed_range[0]
self.vehicles_lefttime = np.ones(vehicle_num, dtype=np.float32) * self.time_lim
self.assignment = [[] for i in range(vehicle_num)]
self.total_reward = 0
for i in range(self.vehicles_speed.shape[0]):
speed_type = random.randint(0,2)
self.vehicles_speed[i] = self.speed_range[speed_type]
self.time_limit = max(self.map_size_x, self.map_size_y) / self.speed_range[0]
self.end = False
self.task_generator()
def task_generator(self):
for i in range(self.targets.shape[0]-1):
self.targets[i+1,0] = random.randint(1,self.map_size_x) - 0.5*self.map_size_x # x position
self.targets[i+1,1] = random.randint(1,self.map_size_y) - 0.5*self.map_size_y # y position
self.targets[i + 1, 2] = random.randint(1, 10) # reward
self.targets[i + 1, 3] = random.randint(5, 30) # time consumption to finish the mission
self.targets[self.targets.shape[0]-2, 0] = 20
self.targets[self.targets.shape[0] - 2, 1] = -27
for i in range(self.targets.shape[0]):
for j in range(self.targets.shape[0]-i):
self.distant_mat[i, j] = np.linalg.norm(self.targets[i, :2] - self.targets[j, :2])
def visualize(self):
if self.assignment == None:
plt.scatter(x=0,y=0,s=200,c='k')
plt.scatter(x=self.targets[1:,0],y=self.targets[1:,1],s=self.targets[1:,2]*10,c='r')
plt.title('Target distribution')
plt.savefig('task_pic/'+'/'+self.algorithm+ "-%d-%d.png" % (self.play,self.rond))
plt.cla()
else:
plt.title('Task assignment by '+self.algorithm +', total reward : '+str(self.total_reward))
plt.scatter(x=0,y=0,s=200,c='k')
plt.scatter(x=self.targets[1:,0],y=self.targets[1:,1],s=self.targets[1:,2]*10,c='r')
for i in range(len(self.assignment)):
trajectory = np.array([[0,0,20]])
for j in range(len(self.assignment[i])):
position = self.targets[self.assignment[i][j],:3]
trajectory = np.insert(trajectory,j+1,values=position,axis=0)
plt.scatter(x=trajectory[1:,0],y=trajectory[1:,1],s=trajectory[1:,2]*10,c='b')
plt.plot(trajectory[:,0], trajectory[:,1])
plt.savefig('task_picture/'+self.algorithm+ "-%d-%d.png" % (self.play,self.rond))
plt.cla()
def get_total_reward(self):
for i in range(len(self.assignment)):
speed = self.vehicles_speed[i]
for j in range(len(self.assignment[i])):
position = self.targets[self.assignment[i][j],:4]
self.total_reward = self.total_reward + position[2]
if j == 0:
self.vehicles_lefttime[i] = self.vehicles_lefttime[i] - np.linalg.norm(position[:2]) / speed - position[3]
else:
self.vehicles_lefttime[i] = self.vehicles_lefttime[i] - np.linalg.norm(position[:2]-position_last[:2]) / speed - position[3]
position_last = position
if self.vehicles_lefttime[i] > self.time_lim:
self.end = True
break
if self.end:
self.total_reward = 0
break
def run(self, assignment, algorithm, play, rond):
self.assignment = assignment
self.algorithm = algorithm
self.play = play
self.rond = rond
self.get_total_reward()
if self.visualized:
self.visualize()
def reset(self):
self.vehicles_position = np.zeros(self.vehicles_position.shape[0],dtype=np.int32)
self.vehicles_lefttime = np.ones(self.vehicles_position.shape[0],dtype=np.float32) * self.time_lim
self.targets[:,2] = self.targets_value
self.total_reward = 0
self.reward = 0
self.end = False

View File

@ -0,0 +1,181 @@
# -*- coding: UTF-8 -*-
"""
Framework for Formation GCS
* send cmd by ros topic
Before running this code, you need to make sure ros master started:
if not:
$ roscore # start ros master
And then, you can run this code via:
$ python formation_gcs.py # start gcs
"""
import rospy
from std_msgs.msg import String
import sys, select, os
import tty, termios
import copy
from enviroment import Env
from ga2 import GA2
from geometry_msgs.msg import PoseStamped
import math
msg2ui = """
Welcome use gcs!
Let's go!
---------------------------
1 2 3 4 5 6 7 8 9 0
t
h l
t : takeoff
l : land
h : hover
0 : search target
1 : formation 1
2 : fortion 2
3~9 : extendable mission(eg.different formation configuration)
q/Q : quit
"""
uav_type = 'typhoon_h480'
uav_bias = [[0,0,0],[0,3,0],[0,-3,0]]
class GroundControler:
def __init__(self):
self.settings = termios.tcgetattr(sys.stdin)
self.gcs_cmd = String()
self.gcs_cmd = 'start'
self.formation_mode = {'FORM_0':'search', 'FORM_1':'straight', 'FORM_2':'triangle'}
# ros publishers
self.gcs_cmd_pub = rospy.Publisher("/formation_gcs/cmd", String, queue_size=10)
#ga
self.map_size_x = 80
self.map_size_y = 80
self.map_size = [self.map_size_x, self.map_size_y]
self.vehicle_num = 3
self.target_num = 10
self.target = [PoseStamped() for i in range(self.vehicle_num)]
self.env = Env(self.vehicle_num, self.target_num, self.map_size, False)
self.ga2_result = None
self.ga2 = GA2(self.vehicle_num, self.env.vehicles_speed, self.target_num, self.env.targets, self.env.time_limit)
self.ga_flag = False
self.pos_i = [1 for i in range(self.vehicle_num)]
# ros subscribers
for i in range(self.vehicle_num):
rospy.Subscriber(uav_type+ '_' + str(i) + "/mavros/local_position/pose", PoseStamped, self.local_pose_callback, i, queue_size = 2)
# ros publishers
self.local_target_pub = [rospy.Publisher(uav_type + '_' + str(i) + '/mavros/setpoint_position/local', PoseStamped, queue_size=10) for i in range(self.vehicle_num)]
self.global_pose = [PoseStamped() for i in range(self.vehicle_num)]
print("Ground Controller Start!")
def working(self):
rospy.init_node("gcs_control_node")
rate = rospy.Rate(60)
self.print_ui()
while rospy.is_shutdown() is False:
key = self.getKey()
if key == 't' :
self.gcs_cmd = 'TAKEOFF'
self.print_ui()
print(self.gcs_cmd)
self.gcs_cmd_pub.publish(self.gcs_cmd)
elif key == 'l':
self.gcs_cmd = 'AUTO.LAND'
self.print_ui()
print(self.gcs_cmd)
self.gcs_cmd_pub.publish(self.gcs_cmd)
elif key == 'h':
self.gcs_cmd = 'HOVOR'
self.print_ui()
print(self.gcs_cmd)
self.gcs_cmd_pub.publish(self.gcs_cmd)
else:
if key == '0':
if not self.ga_flag:
self.ga2_result = self.ga2.run()[0]
# print(self.ga2_result[0])
# print(self.env.targets[self.ga2_result[0]])
# for uav_i in range(self.vehicle_num):
# for i in range(len(self.ga2_result[uav_i])):
# print(self.env.targets[self.ga2_result[uav_i]][i][0],self.env.targets[self.ga2_result[uav_i]][i][1])
self.ga_flag = True
self.gcs_cmd = 'FORM_' + key
self.print_ui()
print(self.formation_mode[self.gcs_cmd])
self.gcs_cmd_pub.publish(self.gcs_cmd)
for i in range(2):
if key == str(i+1):
self.gcs_cmd = 'FORM_'+key
self.print_ui()
print(self.formation_mode[self.gcs_cmd])
self.gcs_cmd_pub.publish(self.gcs_cmd)
if key == 'q' or key =='Q':
break
if self.ga_flag:
for uav_i in range(self.vehicle_num):
if uav_i == 1:
print(self.pos_i[uav_i],self.env.targets[self.ga2_result[uav_i]][self.pos_i[uav_i]])
if self.is_get_target(uav_i,self.env.targets[self.ga2_result[uav_i]][self.pos_i[uav_i]][0],self.env.targets[self.ga2_result[uav_i]][self.pos_i[uav_i]][1]):
self.pos_i[uav_i] += 1
if self.pos_i[uav_i] < len(self.ga2_result[uav_i]):
self.target[uav_i] = self.construct_target(self.env.targets[self.ga2_result[uav_i]][self.pos_i[uav_i]][0],self.env.targets[self.ga2_result[uav_i]][self.pos_i[uav_i]][1])
else:
self.pos_i[uav_i] -= 1
# print(self.pos_i[uav_i])
self.local_target_pub[uav_i].publish(self.target[uav_i])
print(self.target[uav_i])
rate.sleep()
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.settings)
def construct_target(self,x,y):
target_pos = PoseStamped()
target_pos.pose.position.x = x
target_pos.pose.position.y = y
target_pos.pose.position.z = 6
print(target_pos)
return target_pos
def is_get_target(self,i,x,y):
if math.sqrt((self.global_pose[i].pose.position.x-x)*(self.global_pose[i].pose.position.x-x)+\
(self.global_pose[i].pose.position.y-y)*(self.global_pose[i].pose.position.y-y))< 0.5:
return True
else:
return False
def local_pose_callback(self, msg, i):
self.global_pose[i] = copy.deepcopy(msg)
self.global_pose[i].pose.position.x += uav_bias[i][0]
self.global_pose[i].pose.position.y += uav_bias[i][1]
self.global_pose[i].pose.position.z += uav_bias[i][2]
def getKey(self):
tty.setraw(sys.stdin.fileno())
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
if rlist:
key = sys.stdin.read(1)
else:
key = ''
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, self.settings)
return key
def print_ui(self):
print(msg2ui)
if __name__ == '__main__':
groundcontroler = GroundControler()
groundcontroler.working()

View File

@ -0,0 +1,314 @@
# -*- coding: UTF-8 -*-
"""
Framework for Formation Control
* To control all UAV in Gazebo(simulation environment) using MPI
Before running this code, you need to launch your simulation Environment and px4 via:
$ roslaunch px4 cic2021.launch # 3 UAVs in simulation
And then, you can run this code via:
$ mpiexec -n 3 python formation_sim.py # 3 UAVs in simulation
"""
import time
from pyquaternion import Quaternion
from mpi4py import MPI
import rospy
from mavros_msgs.msg import State, PositionTarget
from mavros_msgs.srv import CommandBool, SetMode, SetMavFrame
from geometry_msgs.msg import PoseStamped, TwistStamped
from sensor_msgs.msg import Imu, NavSatFix
from std_msgs.msg import String
import numpy as np
import copy
from fuzzy_pid import FuzzyPID
uav_type = 'typhoon_h480'
comm = MPI.COMM_WORLD
uav_id = comm.Get_rank()
uav_num = comm.Get_size()
uav_bias = [[0,0,0],[0,3,0],[0,-3,0]]
class Px4Controller:
def __init__(self):
self.uav_id = uav_id
self.namespace = uav_type + '_' + "{proc}".format(proc=self.uav_id)
self.imu = Imu()
self.gps = NavSatFix()
self.local_pose = PoseStamped()
self.neighbor_id = []
self.current_heading = None
self.takeoff_height = 6
self.cur_target_pose = None
self.target_yaw = 0
self.takeoff_target_pose = PoseStamped()
self.hover_target_pose = PoseStamped()
self.target_pose = PoseStamped()
self.target_vel = TwistStamped()
self.global_pose = [PoseStamped() for i in range(uav_num)]
self.received_new_task = False
self.arm_state = False
self.mavros_state = State()
self.gcs_cmd = String()
self.last_gcs_cmd = String()
self.form_flag = 0
# control parameters
self.fuzzy_pid = FuzzyPID()
self.Kpx = 1
self.Kpy = 1
self.Kpz = 1
self.Kpw = 1
self.velxy_max = 1
self.velz_max = 1
self.w_max = 0.5
# ros subscribers
for i in range(uav_num):
rospy.Subscriber(uav_type+ '_' + str(i) + "/mavros/local_position/pose", PoseStamped, self.local_pose_callback, i, queue_size = 2)
# self.local_vel_sub = rospy.Subscriber(uav_type + '_' + str(i) + "/mavros/local_position/velocity_local", TwistStamped, self.local_vel_callback)
self.mavros_sub = rospy.Subscriber(self.namespace + "/mavros/state", State, self.mavros_state_callback)
self.gps_sub = rospy.Subscriber(self.namespace + "/mavros/global_position/global", NavSatFix, self.gps_callback)
self.imu_sub = rospy.Subscriber(self.namespace + "/mavros/imu/data", Imu, self.imu_callback)
self.gcs_cmd_sub = rospy.Subscriber("/formation_gcs/cmd", String, self.gcs_cmd_callback)
# ros publishers
self.local_target_pub = rospy.Publisher(self.namespace + '/mavros/setpoint_raw/local', PositionTarget, queue_size=10)
self.twist_target_pub = rospy.Publisher(self.namespace + '/mavros/setpoint_velocity/cmd_vel', TwistStamped, queue_size=10)
# ros services
self.armService = rospy.ServiceProxy(self.namespace + '/mavros/cmd/arming', CommandBool)
self.flightModeService = rospy.ServiceProxy(self.namespace + '/mavros/set_mode', SetMode)
self.frameService = rospy.ServiceProxy(self.namespace + '/mavros/setpoint_velocity/mav_frame', SetMavFrame)
print(self.namespace, ": Px4 Controller Start!")
def working(self):
rospy.init_node(self.namespace + "_control_node")
time.sleep(1) #waiting or node init 1s
rate = rospy.Rate(60)
for i in range(10):
if self.current_heading is not None:
print(self.namespace, ": initialization finished !")
break
else:
print(self.namespace, ": Waiting for initialization...")
time.sleep(0.5)
while rospy.is_shutdown() is False:
if self.gcs_cmd == 'TAKEOFF':
self.last_gcs_cmd = 'TAKEOFF'
self.form_flag = 0
if self.mavros_state != 'OFFBOARD':
self.flight_mode_set(mode='OFFBOARD')
if not self.arm_state:
self.arm()
self.target_pose = self.construct_target(self.takeoff_target_pose.pose.position.x,
self.takeoff_target_pose.pose.position.y , self.takeoff_height,
self.current_heading)
self.local_target_pub.publish(self.target_pose)
if self.takeoff_detection():
print(self.namespace, ": Takeoff Success !")
else:
print(self.namespace, ": Takeoff Failed !!!")
# self.frameService(1)
elif self.gcs_cmd == 'FORM_0':
self.last_gcs_cmd = 'FORM_0'
if self.mavros_state != 'OFFBOARD':
self.flight_mode_set(mode='OFFBOARD')
elif self.gcs_cmd == 'FORM_1':
self.last_gcs_cmd = 'FORM_1'
if self.form_flag != 1:
self.read_set_file('FORM_1_id','FORM_1_pos')
self.form_flag = 1
if self.mavros_state != 'OFFBOARD':
self.flight_mode_set(mode='OFFBOARD')
self.formation_control()
self.twist_target_pub.publish(self.target_vel)
elif self.gcs_cmd == 'FORM_2':
self.last_gcs_cmd = 'FORM_2'
if self.form_flag != 2:
self.read_set_file('FORM_2_id','FORM_2_pos')
self.form_flag = 2
if self.mavros_state != 'OFFBOARD':
self.flight_mode_set(mode='OFFBOARD')
self.formation_control()
self.twist_target_pub.publish(self.target_vel)
elif self.gcs_cmd == 'AUTO.LAND':
self.last_gcs_cmd = 'AUTO.LAND'
self.form_flag = 0
if self.mavros_state != "AUTO.LAND":
self.flight_mode_set(mode='AUTO.LAND')
if (self.mavros_state == 'AUTO.LAND') and (self.local_pose.pose.position.z < 0.05):
if self.arm_state:
self.disarm()
print(self.namespace, ": Land Success!")
elif self.gcs_cmd == 'HOVER':
self.last_gcs_cmd = 'HOVER'
self.form_flag = 0
if self.mavros_state != 'OFFBOARD':
self.flight_mode_set(mode='OFFBOARD')
if not self.arm_state:
self.arm()
self.target_pose = self.construct_target(self.hover_target_pose.pose.position.x,
self.hover_target_pose.pose.position.y, self.hover_target_pose.pose.position.z,
self.current_heading)
self.local_target_pub.publish(self.target_pose)
else:
self.gcs_cmd = self.last_gcs_cmd
self.form_flag = 0
rate.sleep()
def formation_control(self):
print('formation control here')
neighbor_num = len(self.neighbor_id)
self.target_vel.twist.linear.x = 0
self.target_vel.twist.linear.y = 0
self.target_vel.twist.linear.z = 0
self.target_vel.twist.angular.x = 0
self.target_vel.twist.angular.y = 0
self.target_vel.twist.angular.z = self.Kpw*(self.target_yaw-self.current_heading)
# print("neighbor_num",neighbor_num)
for i in range(neighbor_num):
self.target_vel.twist.linear.x += self.global_pose[self.neighbor_id[i]].pose.position.x - self.global_pose[self.uav_id].pose.position.x - \
self.all_desired_position[self.neighbor_id[i]][0] + self.all_desired_position[self.uav_id][0]
self.target_vel.twist.linear.y += self.global_pose[self.neighbor_id[i]].pose.position.y - self.global_pose[self.uav_id].pose.position.y - \
self.all_desired_position[self.neighbor_id[i]][1] + self.all_desired_position[self.uav_id][1]
self.target_vel.twist.linear.z += self.global_pose[self.neighbor_id[i]].pose.position.z - self.global_pose[self.uav_id].pose.position.z - \
self.all_desired_position[self.neighbor_id[i]][2] + self.all_desired_position[self.uav_id][2]
self.target_vel.twist.linear.x = self.limit(self.target_vel.twist.linear.x * self.Kpx, -self.velxy_max, self.velxy_max)
self.target_vel.twist.linear.y = self.limit(self.target_vel.twist.linear.y * self.Kpy, -self.velxy_max, self.velxy_max)
self.target_vel.twist.linear.z = self.limit(self.target_vel.twist.linear.z * self.Kpz, -self.velz_max, self.velz_max)
self.target_vel.twist.angular.z = self.limit(self.target_vel.twist.angular.z * self.Kpw, -self.w_max, self.w_max)
def limit(self, data, min, max):
if data <= min:
data = min
elif data >= max:
data = max
return data
def read_set_file(self,txt_id,txt_pos):
self.neighbor_id =[]
id_path='txt/'+txt_id+'.txt'
pos_path='txt/'+txt_pos+'.txt'
txt_uav_neighbor_num = np.loadtxt(id_path,dtype=int)
self.all_desired_position = np.loadtxt(pos_path)
for i in range(0, len(txt_uav_neighbor_num[:, 0])):
if txt_uav_neighbor_num[i, 0] == self.uav_id:
self.neighbor_id.append(txt_uav_neighbor_num[i, 1])
print(self.neighbor_id)
def construct_target(self, x, y, z, yaw):
target_raw_pose = PositionTarget()
target_raw_pose.header.stamp = rospy.Time.now()
target_raw_pose.coordinate_frame = 7
target_raw_pose.position.x = x
target_raw_pose.position.y = y
target_raw_pose.position.z = z
target_raw_pose.yaw = yaw
target_raw_pose.type_mask = PositionTarget.IGNORE_VX + PositionTarget.IGNORE_VY + PositionTarget.IGNORE_VZ \
+ PositionTarget.IGNORE_AFX + PositionTarget.IGNORE_AFY + PositionTarget.IGNORE_AFZ \
+ PositionTarget.IGNORE_YAW + PositionTarget.IGNORE_YAW_RATE \
+ PositionTarget.FORCE
return target_raw_pose
'''
Callback Function
'''
def gcs_cmd_callback(self, msg):
self.gcs_cmd = msg.data
def local_pose_callback(self, msg, i):
if i == uav_id:
self.local_pose = copy.deepcopy(msg)
if self.gcs_cmd != 'TAKEOFF':
self.takeoff_target_pose = copy.deepcopy(self.local_pose)
if self.gcs_cmd !='HOVER':
self.hover_target_pose = copy.deepcopy(self.local_pose)
self.global_pose[i] = copy.deepcopy(msg)
self.global_pose[i].pose.position.x += uav_bias[i][0]
self.global_pose[i].pose.position.y += uav_bias[i][1]
self.global_pose[i].pose.position.z += uav_bias[i][2]
#
# def local_vel_callback(self):
#
def mavros_state_callback(self, msg):
self.mavros_state = msg.mode
self.arm_state = msg.armed
def imu_callback(self, msg):
self.imu = msg
self.current_heading = self.q2yaw(self.imu.orientation)
def gps_callback(self, msg):
self.gps = msg
'''
return yaw from current IMU
'''
def q2yaw(self, q):
if isinstance(q, Quaternion):
rotate_z_rad = q.yaw_pitch_roll[0]
else:
q_ = Quaternion(q.w, q.x, q.y, q.z)
rotate_z_rad = q_.yaw_pitch_roll[0]
return rotate_z_rad
def arm(self):
if self.armService(True):
return True
else:
print("Vehicle arming failed!")
return False
def disarm(self):
if self.armService(False):
return True
else:
print("Vehicle disarming failed!")
return False
def flight_mode_set(self, mode):
""" mode selectable
MANUAL, ACRO, ALTCTL, POSCTL, OFFBOARD, STABILIZED, RATTITUDE
AUTO.MISSION, AUTO.LOITER, AUTO.RTL, AUTO.LAND, AUTO.RTGS, AUTO.READY, AUTO.TAKEOFF
"""
if self.flightModeService(custom_mode=mode):
return True
else:
print(self.namespace + mode + "Failed")
def takeoff_detection(self):
if self.local_pose.pose.position.z > 0.2 and self.arm_state:
return True
else:
return False
if __name__ == '__main__':
px4controller = Px4Controller()
px4controller.working()

View File

@ -0,0 +1,74 @@
# -*- coding: UTF-8 -*-
"""
Fuzzy PID Controller
* To control all UAV in Gazebo(simulation environment) using MPI
Before running this code, you need to launch your simulation Environment and px4 via:
$ from fuzzy_pid import FuzzyPID() # 3 UAVs in simulation
And then, you can run this code via:
$ mpiexec -n 3 python formation_sim.py # 3 UAVs in simulation
"""
import math
#fuzzy table
CIC_FUZZY_TABLE = [[0,1,2,3],
[1,2,3,4],
[3,4,4,5],
[5,5,6,6]]
# kp table
CIC_KP_TABLE = [0.5,0.6,0.8,0.9,1.0,1.1,1.2]
class FuzzyPID():
def __init__(self):
self.fuzzy_table = CIC_FUZZY_TABLE
self.kp_table = CIC_KP_TABLE
self.ex_range = 5.0
self.ey_range = 1.0
def get_kp(self, ex, ey):
vx = self.get_x_approximation(ex)
vy = self.get_x_approximation(ey)
vx1 = math.floor(vx)
vy1 = math.floor(vy)
vx2 = vx1 + 1
vy2 = vy1 + 1
if vx1 > 3:
vx1 = 3
if vy1 > 3:
vy1 = 3
if vx2 > 3:
vx2 = 3
if vy2 > 3:
vy2 = 3
X2Y = (self.fuzzy_table[vx1][vy2] - self.fuzzy_table[vx1][vy1]) * (vy - vy1) + self.fuzzy_table[vx1][vy1]
X1Y = (self.fuzzy_table[vx2][vy2] - self.fuzzy_table[vx2][vy1]) * (vy - vy1) + self.fuzzy_table[vx2][vy1]
Y2X = (self.fuzzy_table[vx2][vy1] - self.fuzzy_table[vx1][vy1]) * (vx - vx1) + self.fuzzy_table[vx1][vy1]
Y1X = (self.fuzzy_table[vx2][vy2] - self.fuzzy_table[vx1][vy2]) * (vx - vx1) + self.fuzzy_table[vx1][vy2]
kp_approximation = (X2Y + X1Y + Y2X + Y1X)/4.0
kp1 = math.floor(kp_approximation)
kp2 = kp1 + 1
if kp1 > 6:
kp1 = 6
if kp2 > 6:
kp2 = 6
return (self.kp_table[kp2]-self.kp_table[kp1])*(kp_approximation-kp1)+self.kp_table[kp1]
def get_x_approximation(self, ex):
if ex < 0:
ex = -ex
return 3*ex/self.ex_range #divide into 3 parts
def get_y_approximation(self, ey):
if ey < 0:
ey = -ey
return 3*ey/self.ey_range #divide into 3 parts
if __name__ == '__main__':
fuzzy_pid = FuzzyPID()
kp = fuzzy_pid.get_kp(10,50)
print(kp)

View File

@ -0,0 +1,195 @@
import numpy as np
import random
import time
import os
class GA1():
def __init__(self, vehicle_num, vehicles_speed, target_num, targets, time_lim):
# vehicles_speed,targets in the type of narray
self.vehicle_num = vehicle_num
self.vehicles_speed = vehicles_speed
self.target_num = target_num
self.targets = targets
self.time_lim = time_lim
self.map = np.zeros(shape=(target_num+1, target_num+1), dtype=float)
self.pop_size = 50
self.p_cross = 0.6
self.p_mutate = 0.005
for i in range(target_num+1):
self.map[i, i] = 0
for j in range(i):
self.map[j, i] = self.map[i, j] = np.linalg.norm(
targets[i, :2]-targets[j, :2])
self.pop = np.zeros(
shape=(self.pop_size, vehicle_num-1+target_num-1), dtype=np.int32)
self.ff = np.zeros(self.pop_size, dtype=float)
#use vihecle_num-1 numbers to cut the targets into pieces
#use target_num-1 numbers to code the queue of targets
#encoder()
for i in range(self.pop_size):
for j in range(vehicle_num-1):
self.pop[i, j] = random.randint(0, target_num)
for j in range(target_num-1):
self.pop[i, vehicle_num+j-1] \
= random.randint(0, target_num-j-1)
self.ff[i] = self.fitness(self.pop[i, :])
self.tmp_pop = np.array([])
self.tmp_ff = np.array([])
self.tmp_size = 0
def fitness(self, gene):
#to record the break point
ins = np.zeros(self.target_num+1, dtype=np.int32)
#to decode the queue of targets
seq = np.zeros(self.target_num, dtype=np.int32)
#ins[self.target_num] = 1
for i in range(self.vehicle_num-1):
ins[gene[i]] += 1
rest = np.array(range(1, self.target_num+1))
for i in range(self.target_num-1):
seq[i] = rest[gene[i+self.vehicle_num-1]]
rest = np.delete(rest, gene[i+self.vehicle_num-1])
seq[self.target_num-1] = rest[0]
vehicle_num_i = 0 # index of vehicle
pre = 0 # index of the last target
post = 0 # index of instant point
cost = 0
reward = 0
while vehicle_num_i < self.vehicle_num:
if ins[post] > 0:
vehicle_num_i += 1
ins[post] -= 1
pre = 0
cost = 0
else:
cost += self.targets[pre, 3]
time_cost = self.map[pre, seq[post]]/self.vehicles_speed[vehicle_num_i]
cost += time_cost
if cost < self.time_lim:
reward += self.targets[seq[post], 2]
pre = seq[post]
#print("seq[post]",pre)
post += 1
if post > self.target_num-1:
break
return reward
def selection(self):
roll = np.zeros(self.tmp_size, dtype=float)
roll[0] = self.tmp_ff[0]
for i in range(1, self.tmp_size):
roll[i] = roll[i-1]+self.tmp_ff[i]
for i in range(self.pop_size):
xx = random.uniform(0, roll[self.tmp_size-1])
j = 0
while xx > roll[j]:
j += 1
self.pop[i, :] = self.tmp_pop[j, :]
self.ff[i] = self.tmp_ff[j]
def crossover(self):
new_pop = []
new_ff = []
new_size = 0
for i in range(0, self.pop_size, 2):
if random.random() < self.p_cross:
x1 = random.randint(0, self.vehicle_num-2)
x2 = random.randint(0, self.target_num-2)+self.vehicle_num
g1 = self.pop[i, :]
g2 = self.pop[i+1, :]
g1[x1:x2] = self.pop[i+1, x1:x2]
g2[x1:x2] = self.pop[i, x1:x2]
new_pop.append(g1)
new_pop.append(g2)
new_ff.append(self.fitness(g1))
new_ff.append(self.fitness(g2))
new_size += 2
self.tmp_size = self.pop_size+new_size
self.tmp_pop = np.zeros(
shape=(self.tmp_size, self.vehicle_num-1+self.target_num-1), dtype=np.int32)
self.tmp_pop[0:self.pop_size, :] = self.pop
self.tmp_pop[self.pop_size:self.tmp_size, :] = np.array(new_pop)
self.tmp_ff = np.zeros(self.tmp_size, dtype=float)
self.tmp_ff[0:self.pop_size] = self.ff
self.tmp_ff[self.pop_size:self.tmp_size] = np.array(new_ff)
def mutation(self):
for i in range(self.tmp_size):
flag = False
for j in range(self.vehicle_num-1):
if random.random() < self.p_mutate:
self.tmp_pop[i, j] = random.randint(0, self.target_num)
flag = True
for j in range(self.target_num-1):
if random.random() < self.p_mutate:
self.tmp_pop[i, self.vehicle_num+j-1
] = random.randint(0, self.target_num-j-1)
flag = True
if flag:
self.tmp_ff[i] = self.fitness(self.tmp_pop[i, :])
def run(self):
#print("GA start, pid: %s" % os.getpid())
start_time = time.time()
gene = np.zeros(
shape=(1, self.vehicle_num+self.target_num-1), dtype=np.int32)
cut = 0
count = 0
while count < 300:
self.crossover()
self.mutation()
self.selection()
new_cut = self.tmp_ff.max()
if cut < new_cut:
cut = new_cut
count = 0
gene = self.tmp_pop[np.argmax(self.tmp_ff)]
else:
count += 1
ins = np.zeros(self.target_num + 1, dtype=np.int32)
seq = np.zeros(self.target_num, dtype=np.int32)
#ins[self.target_num] = 1
for i in range(self.vehicle_num-1):
ins[gene[i]] += 1
rest = np.array(range(1, self.target_num + 1))
for i in range(self.target_num - 1):
seq[i] = rest[gene[i + self.vehicle_num-1]]
rest = np.delete(rest, gene[i + self.vehicle_num-1])
seq[self.target_num - 1] = rest[0]
#print('sequence : ', seq)
#print('ins[]: ', ins)
task_assignment = [[] for i in range(self.vehicle_num)]
i = 0 # index of vehicle
pre = 0 # index of last target
post = 0 # index of instant point
t = 0
reward = 0
while i < self.vehicle_num:
if ins[post] > 0:
i += 1
ins[post] -= 1
pre = 0
t = 0
else:
t += self.targets[pre, 3]
past = self.map[pre, seq[post]] / self.vehicles_speed[i]
t += past
task_assignment[i].append(seq[post])
if t < self.time_lim:
reward += self.targets[seq[post], 2]
pre = seq[post]
post += 1
if post > self.target_num - 1:
break
self.reward = reward
print("GA result1:", task_assignment)
end_time = time.time()
print("GA time:", end_time - start_time)
print("total reward1:", reward)
return task_assignment, end_time - start_time

View File

@ -0,0 +1,219 @@
import numpy as np
import random
import time
import os
class GA2():
def __init__(self, vehicle_num, vehicles_speed, target_num, targets, time_lim):
# vehicles_speed,targets in the type of narray
self.vehicle_num = vehicle_num
self.vehicles_speed = vehicles_speed
self.target_num = target_num
self.targets = targets
self.time_lim = time_lim
self.map = np.zeros(shape=(target_num+1, target_num+1), dtype=float)
self.pop_size = 50
self.p_cross = 0
self.p_cross1 = 0.9
self.p_cross2 = 0.6
self.p_mutate = 0
self.p_mutate1 = 0.1
self.p_mutate2 = 0.005
self.average_ff = 0
self.max_ff = 1
for i in range(target_num+1):
self.map[i, i] = 0
for j in range(i):
self.map[j, i] = self.map[i, j] = np.linalg.norm(
targets[i, :2]-targets[j, :2])
self.pop = np.zeros(
shape=(self.pop_size, vehicle_num-1+target_num-1), dtype=np.int32)
self.ff = np.zeros(self.pop_size, dtype=float)
#use vihecle_num-1 numbers to cut the targets into pieces
#use target_num-1 numbers to code the queue of targets
#encoder()
for i in range(self.pop_size):
for j in range(vehicle_num-1):
self.pop[i, j] = random.randint(0, target_num)
for j in range(target_num-1):
self.pop[i, vehicle_num+j-1] \
= random.randint(0, target_num-j-1)
self.ff[i] = self.fitness(self.pop[i, :])
self.tmp_pop = np.array([])
self.tmp_ff = np.array([])
self.tmp_size = 0
def fitness(self, gene):
#to record the break point
ins = np.zeros(self.target_num+1, dtype=np.int32)
#to decode the queue of targets
seq = np.zeros(self.target_num, dtype=np.int32)
#ins[self.target_num] = 1
for i in range(self.vehicle_num-1):
ins[gene[i]] += 1
rest = np.array(range(1, self.target_num+1))
for i in range(self.target_num-1):
seq[i] = rest[gene[i+self.vehicle_num-1]]
rest = np.delete(rest, gene[i+self.vehicle_num-1])
seq[self.target_num-1] = rest[0]
vehicle_num_i = 0 # index of vehicle
pre = 0 # index of the last target
post = 0 # index of instant point
cost = 0
reward = 0
while vehicle_num_i < self.vehicle_num:
if ins[post] > 0:
vehicle_num_i += 1
ins[post] -= 1
pre = 0
cost = 0
else:
cost += self.targets[pre, 3]
time_cost = self.map[pre, seq[post]]/self.vehicles_speed[vehicle_num_i]
cost += time_cost
if cost < self.time_lim:
reward += self.targets[seq[post], 2]
pre = seq[post]
#print("seq[post]",pre)
post += 1
if post > self.target_num-1:
break
return reward
def selection(self):
roll = np.zeros(self.tmp_size, dtype=float)
roll[0] = self.tmp_ff[0]
for i in range(1, self.tmp_size):
roll[i] = roll[i-1]+self.tmp_ff[i]
for i in range(self.pop_size):
xx = random.uniform(0, roll[self.tmp_size-1])
j = 0
while xx > roll[j]:
j += 1
self.pop[i, :] = self.tmp_pop[j, :]
self.ff[i] = self.tmp_ff[j]
# adaptive ag
self.average_ff = np.mean(self.ff)
self.max_ff = max(self.ff)
if self.ff[i] >= self.average_ff:
self.p_mutate = self.p_mutate1 - \
(self.p_mutate1 - self.p_mutate2) * (self.max_ff - self.ff[i]) / (
self.max_ff - self.average_ff)
else:
self.p_mutate = self.p_mutate1
def crossover(self):
new_pop = []
new_ff = []
new_size = 0
ff_bigger = 0
for i in range(0, self.pop_size, 2):
#adaptive ag
ff_bigger = max(self.ff[i], self.ff[i+1])
if ff_bigger >= self.average_ff:
self.p_cross = self.p_cross1 -\
(self.p_cross1-self.p_cross2)/(self.max_ff-self.average_ff)
else:
self.p_cross = self.p_cross1
if random.random() < self.p_cross:
x1 = random.randint(0, self.vehicle_num-2)
x2 = random.randint(0, self.target_num-2)+self.vehicle_num
g1 = self.pop[i, :]
g2 = self.pop[i+1, :]
g1[x1:x2] = self.pop[i+1, x1:x2]
g2[x1:x2] = self.pop[i, x1:x2]
new_pop.append(g1)
new_pop.append(g2)
new_ff.append(self.fitness(g1))
new_ff.append(self.fitness(g2))
new_size += 2
self.tmp_size = self.pop_size+new_size
self.tmp_pop = np.zeros(
shape=(self.tmp_size, self.vehicle_num-1+self.target_num-1), dtype=np.int32)
self.tmp_pop[0:self.pop_size, :] = self.pop
self.tmp_pop[self.pop_size:self.tmp_size, :] = np.array(new_pop)
self.tmp_ff = np.zeros(self.tmp_size, dtype=float)
self.tmp_ff[0:self.pop_size] = self.ff
self.tmp_ff[self.pop_size:self.tmp_size] = np.array(new_ff)
def mutation(self):
for i in range(self.tmp_size):
flag = False
for j in range(self.vehicle_num-1):
if random.random() < self.p_mutate:
self.tmp_pop[i, j] = random.randint(0, self.target_num)
flag = True
for j in range(self.target_num-1):
if random.random() < self.p_mutate:
self.tmp_pop[i, self.vehicle_num+j-1
] = random.randint(0, self.target_num-j-1)
flag = True
if flag:
self.tmp_ff[i] = self.fitness(self.tmp_pop[i, :])
def run(self):
#print("GA start, pid: %s" % os.getpid())
start_time = time.time()
gene = np.zeros(
shape=(1, self.vehicle_num+self.target_num-1), dtype=np.int32)
cut = 0
count = 0
while count < 300:
self.crossover()
self.mutation()
self.selection()
new_cut = self.tmp_ff.max()
if cut < new_cut:
cut = new_cut
count = 0
gene = self.tmp_pop[np.argmax(self.tmp_ff)]
else:
count += 1
ins = np.zeros(self.target_num + 1, dtype=np.int32)
seq = np.zeros(self.target_num, dtype=np.int32)
#ins[self.target_num] = 1
for i in range(self.vehicle_num-1):
ins[gene[i]] += 1
rest = np.array(range(1, self.target_num + 1))
for i in range(self.target_num - 1):
seq[i] = rest[gene[i + self.vehicle_num-1]]
rest = np.delete(rest, gene[i + self.vehicle_num-1])
seq[self.target_num - 1] = rest[0]
#print('sequence : ', seq)
#print('ins[]: ', ins)
task_assignment = [[] for i in range(self.vehicle_num)]
i = 0 # index of vehicle
pre = 0 # index of last target
post = 0 # index of ins/seq
t = 0
reward = 0
while i < self.vehicle_num:
if ins[post] > 0:
i += 1
ins[post] -= 1
pre = 0
t = 0
else:
t += self.targets[pre, 3]
past = self.map[pre, seq[post]] / self.vehicles_speed[i]
t += past
task_assignment[i].append(seq[post])
if t < self.time_lim:
reward += self.targets[seq[post], 2]
pre = seq[post]
post += 1
if post > self.target_num - 1:
break
self.reward = reward
# print("GA result2:", task_assignment)
end_time = time.time()
# print("GA time:", end_time - start_time)
# print("total reward2:", reward)
return task_assignment, end_time - start_time

View File

@ -0,0 +1,33 @@
from enviroment import Env
from ga1 import GA1
import numpy as np
import matplotlib.pyplot as plt
from ga2 import GA2
if __name__ == '__main__':
map_size_x = 80
map_size_y = 80
map_size = [map_size_x, map_size_y]
vehicle_num = 3
target_num = 10
for i in range(5):
env = Env(vehicle_num, target_num, map_size, True)
for j in range(10):
ga1 = GA1(vehicle_num, env.vehicles_speed, target_num, env.targets, env.time_limit)
ga2 = GA2(vehicle_num, env.vehicles_speed, target_num, env.targets, env.time_limit)
ga1_result = ga1.run()
#print("result:", ga1_result[0])
ga2_result = ga2.run()
env.run(ga1_result[0], 'GA', i, j)
env.run(ga2_result[0], 'adaptGA', i, j)
#f_cost = np.zeros(21, dtype=np.int32)
#for i in range(10, 210, 10):
# ga1.run(i)
# f_cost[i//10]=ga1.reward
#plt.plot(np.linspace(10, 200, 21),f_cost,'s-',color = 'r',label = 'iteration_influence')
#plt.savefig("iteration_influence")
#plt.show()

View File

@ -0,0 +1,2 @@
1 0
2 0

View File

@ -0,0 +1,3 @@
0 0 0
-1 0 0
1 0 0

View File

@ -0,0 +1,5 @@
0 0
1 0
1 1
2 0
2 2

View File

@ -0,0 +1,3 @@
0 0 0
-1 1 0
1 1 0

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,280 @@
# encoding: utf-8
import rospy
from geometry_msgs.msg import Twist
import sys, select, os
import tty, termios
from std_msgs.msg import String
MAX_LINEAR = 20
MAX_ANG_VEL = 3
LINEAR_STEP_SIZE = 0.1
ANG_VEL_STEP_SIZE = 0.1
cmd_vel_mask = False
ctrl_leader = False #初始 控制所有无人机
msg2all = """
Control Your XTDrone!
To all drones (press g to control the leader)
---------------------------
1 2 3 4 5 6 7 8 9 0
w r t y i
a s d g j k l
x v b n ,
w/x : increase/decrease forward velocity
a/d : increase/decrease leftward velocity
i/, : increase/decrease upward velocity
j/l : increase/decrease orientation
r : return home
t/y : arm/disarm
v/n : takeoff/land
b : offboard
s/k : hover and remove the mask of keyboard control
0~9 : extendable mission(eg.different formation configuration)
this will mask the keyboard control
g : control the leader
CTRL-C to quit
"""
msg2leader = """
Control Your XTDrone!
To the leader (press g to control all drones)
---------------------------
1 2 3 4 5 6 7 8 9 0
w r t y i
a s d g j k l
x v b n ,
w/x : increase/decrease forward velocity
a/d : increase/decrease leftward velocity
i/, : increase/decrease upward velocity
j/l : increase/decrease orientation
r : return home
t/y : arm/disarm
v/n : takeoff(disenabled now)/land
b : offboard
s/k : hover and remove the mask of keyboard control
0~9 : extendable mission(eg.different formation configuration)
this will mask the keyboard control
g : control all drones
CTRL-C to quit
"""
e = """
Communications Failed
"""
def getKey(): # 获得键盘按键
tty.setraw(sys.stdin.fileno())
rlist, _, _ = select.select([sys.stdin], [], [], 0.1)
if rlist:
key = sys.stdin.read(1)
else:
key = ''
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)
return key
def print_msg(): # 打印提示信息
if ctrl_leader:
print(msg2leader)
else:
print(msg2all)
if __name__=="__main__":
settings = termios.tcgetattr(sys.stdin)
multirotor_type = sys.argv[1]
multirotor_num = int(sys.argv[2])
control_type = sys.argv[3] #vel 速度控制
'''
if multirotor_num == 18: #多无人机编队
formation_configs = ['waiting', 'cuboid', 'sphere', 'diamond'] # 0-9的参数
elif multirotor_num == 9:
formation_configs = ['waiting', 'cube', 'pyramid', 'triangle']
elif multirotor_num == 6:
formation_configs = ['waiting', 'T', 'diamond', 'triangle']
''' # 0 1 2 3
if multirotor_num == 21:
formation_configs = ['waiting', 'cube21', 'circle21', 'pyramid21', 'diamond21']
elif multirotor_num == 34:
formation_configs = ['waiting', 'CUBE', 'HEART', '520', 'NUDT', '八一']
cmd= String()
twist = Twist()
rospy.init_node('multirotor_keyboard_multi_control')
if control_type == 'vel': # 速度控制
multi_cmd_vel_flu_pub = [None]*multirotor_num
multi_cmd_pub = [None]*multirotor_num
for i in range(multirotor_num):
multi_cmd_vel_flu_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd_vel_flu', Twist, queue_size=10)
multi_cmd_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd',String,queue_size=10)
leader_cmd_vel_flu_pub = rospy.Publisher("/xtdrone/leader/cmd_vel_flu", Twist, queue_size=10)
leader_cmd_pub = rospy.Publisher("/xtdrone/leader/cmd", String, queue_size=10)
else: # 加速度控制
multi_cmd_accel_flu_pub = [None]*multirotor_num
multi_cmd_pub = [None]*multirotor_num
for i in range(multirotor_num):
multi_cmd_accel_flu_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd_accel_flu', Twist, queue_size=10)
multi_cmd_pub[i] = rospy.Publisher('/xtdrone/'+multirotor_type+'_'+str(i)+'/cmd',String,queue_size=10)
leader_cmd_accel_flu_pub = rospy.Publisher("/xtdrone/leader/cmd_accel_flu", Twist, queue_size=10)
leader_cmd_pub = rospy.Publisher("/xtdrone/leader/cmd", String, queue_size=10)
forward = 0.0
leftward = 0.0
upward = 0.0
angular = 0.0
print_msg()
while(1):
key = getKey()
if key == 'w' :
forward = forward + LINEAR_STEP_SIZE
print_msg()
if control_type == 'vel':
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
else:
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'x' :
forward = forward - LINEAR_STEP_SIZE
print_msg()
if control_type == 'vel':
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
else:
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'a' :
leftward = leftward + LINEAR_STEP_SIZE
print_msg()
if control_type == 'vel':
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
else:
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'd' :
leftward = leftward - LINEAR_STEP_SIZE
print_msg()
if control_type == 'vel':
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
else:
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'i' :
upward = upward + LINEAR_STEP_SIZE
print_msg()
if control_type == 'vel':
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
else:
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == ',' :
upward = upward - LINEAR_STEP_SIZE
print_msg()
if control_type == 'vel':
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
else:
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'j':
angular = angular + ANG_VEL_STEP_SIZE
print_msg()
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'l':
angular = angular - ANG_VEL_STEP_SIZE
print_msg()
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
elif key == 'r': # 自动返回起飞点
cmd = 'AUTO.RTL'
print_msg()
print('Returning home')
elif key == 't': #飞机解锁
cmd = 'ARM'
print_msg()
print('Arming')
elif key == 'y': # 飞机上锁
cmd = 'DISARM'
print_msg()
print('Disarming')
elif key == 'v':
cmd = 'AUTO.TAKEOFF'
cmd = ''
print_msg()
#print('Takeoff mode is disenabled now')
elif key == 'b':
cmd = 'OFFBOARD'
print_msg()
print('Offboard')
elif key == 'n': # 自动着陆
cmd = 'AUTO.LAND'
print_msg()
print('Landing')
elif key == 'g': # 开启或结束编队控制
ctrl_leader = not ctrl_leader
print_msg()
elif key in ['k', 's']: # 悬停,全部参数归零
cmd_vel_mask = False
forward = 0.0
leftward = 0.0
upward = 0.0
angular = 0.0
cmd = 'HOVER'
print_msg()
print("currently:\t forward vel %.2f\t leftward vel %.2f\t upward vel %.2f\t angular %.2f " % (forward, leftward, upward, angular))
print('Hover')
else:
for i in range(10): # 按键数字
if key == str(i):
cmd = formation_configs[i] # 编队的队形
print_msg()
print(cmd)
cmd_vel_mask = True # 有掩模,其他按键无效
if (key == '\x03'):
break
if forward > MAX_LINEAR:
forward = MAX_LINEAR
elif forward < -MAX_LINEAR:
forward = -MAX_LINEAR
if leftward > MAX_LINEAR:
leftward = MAX_LINEAR
elif leftward < -MAX_LINEAR:
leftward = -MAX_LINEAR
if upward > MAX_LINEAR:
upward = MAX_LINEAR
elif upward < -MAX_LINEAR:
upward = -MAX_LINEAR
if angular > MAX_ANG_VEL:
angular = MAX_ANG_VEL
elif angular < -MAX_ANG_VEL:
angular = - MAX_ANG_VEL
twist.linear.x = forward; twist.linear.y = leftward ; twist.linear.z = upward
twist.angular.x = 0.0; twist.angular.y = 0.0; twist.angular.z = angular
for i in range(multirotor_num): # 无人机数量
if ctrl_leader:
if control_type == 'vel':
leader_cmd_vel_flu_pub.publish(twist)
else:
leader_cmd_aceel_flu_pub.publish(twist) #无定义
leader_cmd_pub.publish(cmd)
else:
if not cmd_vel_mask: #只有在输入0-9时mask为True其余情况为F 。这里是非数字时
if control_type == 'vel':
multi_cmd_vel_flu_pub[i].publish(twist)
else:
multi_cmd_accel_flu_pub[i].publish(twist)
multi_cmd_pub[i].publish(cmd)
cmd = ''
termios.tcsetattr(sys.stdin, termios.TCSADRAIN, settings)

View File

@ -0,0 +1,54 @@
import rospy
from geometry_msgs.msg import Twist, Vector3, PoseStamped
from std_msgs.msg import String
import time
import math
import numpy
import sys
vehicle_type = sys.argv[1]
vehicle_num = int(sys.argv[2])
pose = [None]*vehicle_num
pose_sub = [None]*vehicle_num
avoid_vel_pub = [None]*vehicle_num
avoid_kp = 0.5
avoid_radius = 1.5
aid_vec1 = [1, 0, 0]
aid_vec2 = [0, 1, 0]
vehicles_avoid_vel = [Vector3()] * vehicle_num
def pose_callback(msg, id):
pose[id] = msg
rospy.init_node('avoid')
for i in range(vehicle_num):
pose_sub[i] = rospy.Subscriber(vehicle_type+'_'+str(i)+'/mavros/local_position/pose',PoseStamped,pose_callback,i)
avoid_vel_pub[i] = rospy.Publisher("/xtdrone/"+vehicle_type+'_'+str(i)+"/avoid_vel", Vector3,queue_size=10)
time.sleep(1)
rate = rospy.Rate(50)
while not rospy.is_shutdown():
for i in range(vehicle_num):
position1 = numpy.array([pose[i].pose.position.x, pose[i].pose.position.y, pose[i].pose.position.z])
for j in range(1, vehicle_num-i):
position2 = numpy.array([pose[i+j].pose.position.x, pose[i+j].pose.position.y, pose[i+j].pose.position.z])
dir_vec = position1-position2
if numpy.linalg.norm(dir_vec) < avoid_radius:
cos1 = dir_vec.dot(aid_vec1)/(numpy.linalg.norm(dir_vec) * numpy.linalg.norm(aid_vec1))
cos2 = dir_vec.dot(aid_vec2)/(numpy.linalg.norm(dir_vec) * numpy.linalg.norm(aid_vec2))
if abs(cos1) < abs(cos2):
avoid_vel = avoid_kp * numpy.cross(dir_vec, aid_vec1)/numpy.linalg.norm(numpy.cross(dir_vec, aid_vec1))
else:
avoid_vel = avoid_kp * numpy.cross(dir_vec, aid_vec2)/numpy.linalg.norm(numpy.cross(dir_vec, aid_vec2))
if dir_vec[2] * avoid_vel[2] > 0:
vehicles_avoid_vel[i] = Vector3(vehicles_avoid_vel[i].x+avoid_vel[0],vehicles_avoid_vel[i].y+avoid_vel[1],vehicles_avoid_vel[i].z+avoid_vel[2])
vehicles_avoid_vel[i+j] = Vector3(vehicles_avoid_vel[i+j].x-avoid_vel[0],vehicles_avoid_vel[i+j].y-avoid_vel[1],vehicles_avoid_vel[i+j].z-avoid_vel[2])
else:
vehicles_avoid_vel[i] = Vector3(vehicles_avoid_vel[i].x-avoid_vel[0],vehicles_avoid_vel[i].y-avoid_vel[1],vehicles_avoid_vel[i].z-avoid_vel[2])
vehicles_avoid_vel[i+j] = Vector3(vehicles_avoid_vel[i+j].x+avoid_vel[0],vehicles_avoid_vel[i+j].y+avoid_vel[1],vehicles_avoid_vel[i+j].z+avoid_vel[2])
for i in range(vehicle_num):
avoid_vel_pub[i].publish(vehicles_avoid_vel[i])
vehicles_avoid_vel = [Vector3()] * vehicle_num
rate.sleep()

View File

@ -0,0 +1,260 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
### This code is about the distributed formation control of consensus protocol with a certain
### Laplacian matrix and the formation transformation based on a task allocation algorithm——
### KM for the shorest distances of all the UAVs to achieve the new pattern.
### For more information of these two algorithms, please see the latest paper on https://arxiv.org/abs/2005.01125
import rospy
from geometry_msgs.msg import Twist, Vector3, PoseStamped, TwistStamped
from std_msgs.msg import String
import sys
# formation patterns
#if sys.argv[3] == '6':
# from formation_dict import formation_dict_6 as formation_dict
#elif sys.argv[3] == '9':
# from formation_dict import formation_dict_9 as formation_dict
#elif sys.argv[3] == '18':
# from formation_dict import formation_dict_18 as formation_dict
if sys.argv[3] == '21':
from my_formation_dict import formation_dict_my as formation_dict
elif sys.argv[3] == '34':
from my_formation_dict import formation_dict_my as formation_dict
import numpy
import Queue
class Follower:
def __init__(self, uav_type, uav_id, uav_num):
self.hover = "HOVER"
self.offboard = "OFFBOARD"
self.uav_type = uav_type
self.id = uav_id
self.uav_num = uav_num
self.f = 100 # control/communication rate
self.local_pose = PoseStamped()
self.local_pose_queue = Queue.Queue(self.f/10)
for i in range(self.f/10):
self.local_pose_queue.put(PoseStamped())
self.local_velocity = TwistStamped()
self.cmd_vel_enu = Twist()
self.avoid_vel = Vector3()
self.following_switch = False # determine whether the formation pattern is required to be changed
self.arrive_print = True # determine whether the target position has been reached
self.following_ids = [] # followers of this uav
self.formation_config = 'waiting'
self.following_count = 0 # the number of followers of this uav
self.Kp = 1
self.velxy_max = 1 #0.8
self.velz_max = 1
self.following_local_pose = [PoseStamped() for i in range(self.uav_num)] # local position of other uavs, and only the position of followers of this uav is not zero
self.following_local_pose_sub = [None]*self.uav_num
self.arrive_count = 0
###############起飞位置偏置
self.bias = [ [3, 3, 0],[6, 3, 0],[9, 3, 0],[12, 3, 0],[15, 3, 0],[18, 3, 0], [0, 6, 0],[3, 6, 0],[6, 6, 0],[9, 6, 0],[12, 6, 0],[15, 6, 0],[18, 6, 0], [0, 9, 0],[3, 9, 0],[6, 9, 0],[9, 9, 0],[12, 9, 0],[15, 9, 0],[18, 9, 0] ]
self.local_pose_sub = rospy.Subscriber(self.uav_type+'_'+str(self.id)+"/mavros/local_position/pose", PoseStamped, self.local_pose_callback)
self.avoid_vel_sub = rospy.Subscriber("/xtdrone/"+self.uav_type+'_'+str(self.id)+"/avoid_vel", Vector3, self.avoid_vel_callback)
self.formation_switch_sub = rospy.Subscriber("/xtdrone/formation_switch",String, self.formation_switch_callback)
self.vel_enu_pub = rospy.Publisher('/xtdrone/'+self.uav_type+'_'+str(self.id)+'/cmd_vel_enu', Twist, queue_size=10)
self.info_pub = rospy.Publisher('/xtdrone/'+self.uav_type+'_'+str(self.id)+'/info', String, queue_size=10)
self.cmd_pub = rospy.Publisher('/xtdrone/'+self.uav_type+'_'+str(self.id)+'/cmd',String,queue_size=10)
self.first_formation = True
self.orig_formation = None
self.new_formation = None
def local_pose_callback(self, msg):
self.local_pose = msg
self.local_pose.pose.position.x += self.bias[self.id-1][0]###########起飞位置偏置
self.local_pose.pose.position.y += self.bias[self.id-1][1]
pose_comparison = self.local_pose_queue.get()
self.local_pose_queue.put(self.local_pose)
comparison = (self.local_pose.pose.position.x - pose_comparison.pose.position.x)**2+(self.local_pose.pose.position.y - pose_comparison.pose.position.y)**2+(self.local_pose.pose.position.z - pose_comparison.pose.position.z)**2
if comparison < float(self.velxy_max**2+self.velxy_max**2+self.velz_max**2)/1e5: # if the target position is reached, arrive_count ++1
self.arrive_count += 1
else:
self.arrive_count = 0
def following_local_pose_callback(self, msg, id):
self.following_local_pose[id] = msg
self.following_local_pose[id].pose.position.x += self.bias[id][0]#############起飞位置偏置
self.following_local_pose[id].pose.position.y += self.bias[id][1]
# the order of changing the formation pattern
def formation_switch_callback(self, msg):
if not self.formation_config == msg.data:
self.following_switch = True
self.formation_config = msg.data
def avoid_vel_callback(self, msg):
self.avoid_vel = msg
def loop(self):
rospy.init_node('follower'+str(self.id-1))
rate = rospy.Rate(self.f)
while not rospy.is_shutdown():
if self.arrive_count > 2000 and self.arrive_print:
print("Follower"+str(self.id-1)+":Arrived")
self.arrive_print = False
if self.following_switch:
self.following_switch = False
self.arrive_print = True
self.arrive_count = 0
for i in range(self.f/10):
self.cmd_pub.publish(self.offboard)
self.info_pub.publish("Received")
print("Follower"+str(self.id-1)+": Switch to Formation "+self.formation_config)
# The Laplacian matrix is invarible in this code, and you can change it if necessary.
if self.formation_config=='waiting':
self.L_matrix = self.get_L_central_matrix()
else:
# Change from the original pattern to the first pattern without KM.
if self.first_formation:
self.first_formation=False
self.orig_formation=formation_dict[self.formation_config]
self.L_matrix = self.get_L_central_matrix()
else:
self.adj_matrix = self.build_graph(self.orig_formation,formation_dict[self.formation_config])
# These variables are determined for KM algorithm, see examples of KM algorithm on Github.
self.label_left = numpy.max(self.adj_matrix, axis=1) # init label for the left
self.label_right = numpy.array([0]*(self.uav_num-1)) # init label for the right set
self.match_right = numpy.array([-1] *(self.uav_num-1))
self.visit_left = numpy.array([0]*(self.uav_num-1))
self.visit_right = numpy.array([0]*(self.uav_num-1))
self.slack_right = numpy.array([100]*(self.uav_num-1))
self.change_id = self.KM()
# Get a new formation pattern of UAVs based on KM.
self.new_formation=self.get_new_formation(self.change_id,formation_dict[self.formation_config])
self.L_matrix = self.get_L_central_matrix()
self.orig_formation=self.new_formation
if self.id == 3:
print(self.L_matrix)
# Get the followers of this uav based on the Laplacian matrix, and update the position of the followers.
self.following_ids = numpy.argwhere(self.L_matrix[self.id,:] == 1)
self.following_count = 0
for i in range(self.uav_num):
if not self.following_local_pose_sub[i] == None:
self.following_local_pose_sub[i].unregister()
for following_id in self.following_ids:
self.following_local_pose_sub[following_id[0]] = rospy.Subscriber(self.uav_type+'_'+str(following_id[0])+"/mavros/local_position/pose", PoseStamped , self.following_local_pose_callback,following_id[0])
self.following_count += 1
self.cmd_vel_enu.linear = Vector3(0, 0, 0)
# Code of the consensus protocol, see details on the paper.
for following_id in self.following_ids:
#print(self.id,"following: ", self.following_ids)
self.cmd_vel_enu.linear.x += self.following_local_pose[following_id[0]].pose.position.x - self.local_pose.pose.position.x + self.new_formation[0, self.id-1]
self.cmd_vel_enu.linear.y += self.following_local_pose[following_id[0]].pose.position.y - self.local_pose.pose.position.y + self.new_formation[1, self.id-1]
self.cmd_vel_enu.linear.z += self.following_local_pose[following_id[0]].pose.position.z - self.local_pose.pose.position.z + self.new_formation[2, self.id-1]
if not following_id[0] == 0:
self.cmd_vel_enu.linear.x -= self.new_formation[0, following_id[0]-1]
self.cmd_vel_enu.linear.y -= self.new_formation[1, following_id[0]-1]
self.cmd_vel_enu.linear.z -= self.new_formation[2, following_id[0]-1]
self.cmd_vel_enu.linear.x = self.Kp * self.cmd_vel_enu.linear.x + self.avoid_vel.x
self.cmd_vel_enu.linear.y = self.Kp * self.cmd_vel_enu.linear.y + self.avoid_vel.y
self.cmd_vel_enu.linear.z = self.Kp * self.cmd_vel_enu.linear.z + self.avoid_vel.z
if self.cmd_vel_enu.linear.x > self.velxy_max: #越界限制
self.cmd_vel_enu.linear.x = self.velxy_max
elif self.cmd_vel_enu.linear.x < - self.velxy_max:
self.cmd_vel_enu.linear.x = - self.velxy_max
if self.cmd_vel_enu.linear.y > self.velxy_max:
self.cmd_vel_enu.linear.y = self.velxy_max
elif self.cmd_vel_enu.linear.y < - self.velxy_max:
self.cmd_vel_enu.linear.y = - self.velxy_max
if self.cmd_vel_enu.linear.z > self.velz_max:
self.cmd_vel_enu.linear.z = self.velz_max
elif self.cmd_vel_enu.linear.z < - self.velz_max:
self.cmd_vel_enu.linear.z = - self.velz_max
if not self.formation_config == 'waiting':
self.vel_enu_pub.publish(self.cmd_vel_enu)
if (self.cmd_vel_enu.linear.x)**2+(self.cmd_vel_enu.linear.y)**2+(self.cmd_vel_enu.linear.z)**2<0.2: #到达目标位置
self.arrive_count += 1
else:
self.arrive_count = 0
rate.sleep()
# 'build_graph', 'find_path' and 'KM' functions are all determined for KM algorithm.
# A graph of UAVs is established based on distances between them in 'build_graph' function.
def build_graph(self,orig_formation,change_formation):
distance=[[0 for i in range(self.uav_num-1)]for j in range(self.uav_num-1)] #二维0矩阵行列都为跟随者个数
for i in range(self.uav_num-1):
for j in range(self.uav_num-1):
distance[i][j]=numpy.linalg.norm(orig_formation[:,i]-change_formation[:,j])
distance[i][j]=int(50-distance[i][j])
return distance
# Determine whether a path has been found.
def find_path(self,i):
self.visit_left[i] = True
for j, match_weight in enumerate(self.adj_matrix[i],start=0):
if self.visit_right[j]:
continue
gap = self.label_left[i] + self.label_right[j] - match_weight
if gap == 0 :
self.visit_right[j] = True
if self.match_right[j]==-1 or self.find_path(self.match_right[j]):
self.match_right[j] = i
return True
else:
self.slack_right[j]=min(gap,self.slack_right[j])
return False
# Main body of KM algorithm.
def KM(self):
for i in range(self.uav_num-1):
self.slack_right = numpy.array([100]*(self.uav_num-1))
while True:
self.visit_left = numpy.array([0]*(self.uav_num-1))
self.visit_right = numpy.array([0]*(self.uav_num-1))
if self.find_path(i):
break
d = numpy.inf
for j, slack in enumerate(self.slack_right):
if not self.visit_right[j] :
d = min(d,slack)
for k in range(self.uav_num-1):
if self.visit_left[k]:
self.label_left[k] -= d
if self.visit_right[k]:
self.label_right[k] += d
else:
self.slack_right[k] -=d
return self.match_right
# The formation patterns designed in the formation dictionaries are random (the old ones),
# and a new formation pattern based on the distances of UAVs of the current pattern is designed as follows.
# Note that only the desired position of each UAV has changed, while the form of the new pattern is the same as the one in the dictionary.
def get_new_formation(self,change_id,change_formation):
new_formation=numpy.zeros((3,self.uav_num-1))
position=numpy.zeros((3,self.uav_num-1))
change_id=[i + 1 for i in change_id]
for i in range(0,self.uav_num-1):
position[:,i]=change_formation[:,i]
for i in range(0,self.uav_num-1):
for j in range(0,self.uav_num-1):
if (j+1)==change_id[i]:
new_formation[:,i]=position[:,j]
return new_formation
# Laplacian matrix
def get_L_central_matrix(self):
L=numpy.zeros((self.uav_num,self.uav_num))
for i in range(1,self.uav_num):
L[i][0]=1
L[i][i]=-1
#L=numpy.array([[-0. ,0. , 0., 0., 0., 0.],[ 1. ,-1. , 0. , 0. , 0. , 0.],[ 0., 1. ,-1. , 0. , 0. , 0.],[ 0., 0., 1. ,-1. , 0. , 0.],[ 0. , 0. , 0. , 1. ,-1. , 0.],[ 0. , 0. , 0. , 0. , 1. ,-1.]])
return L
if __name__ == '__main__':
follower = Follower(sys.argv[1],int(sys.argv[2]),int(sys.argv[3]))
follower.loop()

View File

@ -0,0 +1,380 @@
# encoding: utf-8
import numpy as np
import random
import matplotlib.pyplot as plt
import math
import os
UAV_NUM = 33 #无人机数量-10 0 0位置不动
POP_SIZE = 200 #种群数量
N_GENERATIONS = 200 #迭代次数迭代50轮
CROSSOVER_RATE = 0.8
# MUTATION_RATE = 0.2
formation_dict_my = {}
# formation_dict_my["origin34"] = [ # XTDrone中简化仿真的初始位置
# # [0, 0, 0],
# [0, 1, 0], [0, 2, 0], [1, 0, 0], [1, 1, 0], [1, 2, 0],
# [2, 0, 0], [2, 1, 0], [2, 2, 0], [3, 0, 0], [3, 1, 0], [3, 2, 0],
# [4, 0, 0], [4, 1, 0], [4, 2, 0], [5, 0, 0], [5, 1, 0], [5, 2, 0],
# [6, 0, 0], [6, 1, 0], [6, 2, 0], [7, 0, 0], [7, 1, 0], [7, 2, 0],
# [8, 0, 0], [8, 1, 0], [8, 2, 0], [9, 0, 0], [9, 1, 0], [9, 2, 0],
# [10, 0, 0], [10, 1, 0], [10, 2, 0], [11, 0, 0] ]
formation_dict_my["origin34"] = [ # XTDrone中gazebo仿真的初始位置
# [0, 3, 0],
[3, 3, 0], [6, 3, 0], [9, 3, 0], [12, 3, 0],
[0, 6, 0], [3, 6, 0], [6, 6, 0], [9, 6, 0], [12, 6, 0],
[0, 9, 0], [3, 9, 0], [6, 9, 0], [9, 9, 0], [12, 9, 0],
[0, 12, 0], [3, 12, 0], [6, 12, 0], [9, 12, 0], [12, 12, 0],
[0, 15, 0], [3, 15, 0], [6, 15, 0], [9, 15, 0], [12, 15, 0],
[0, 18, 0], [3, 18, 0], [6, 18, 0], [9, 18, 0], [12, 18, 0],
[0, 21, 0], [3, 21, 0], [6, 21, 0], [9, 21, 0] ]
formation_dict_my["CUBE"] = [ #自定义位置1立方体
# [0, 0, 0],
[0, 0, 0],
[-15, -15, 15], [-15, 15, 15], [15, 15, 15], [15, -15, 15], #上顶点
[-15, -15, -15], [-15, 15, -15], [15, 15, -15], [15, -15, -15], #下顶点
[-15, -5, 15], [-15, 5, 15], [-5, 15, 15], [5, 15, 15], #上棱
[15, 5, 15], [15, -5, 15], [5, -15, 15], [-5, -15, 15], #上棱
[-15, -5, -15], [-15, 5, -15], [-5, 15, -15], [5, 15, -15], #下棱
[15, 5, -15], [15, -5, -15], [5, -15, -15], [-5, -15, -15], #下棱
[-15, -15, -5], [-15, -15, 5], [15, -15, -5], [15, -15, 5], #中棱
[-15, 15, -5], [-15, 15, 5], [15, 15, -5], [15, 15, 5] ] #中棱
formation_dict_my["HEART"] = [ #自定义位置2心形
# [-0.00000000e+00, 0.00000000e+00, 0.00000000e+00],
[ 1.00000000e+01, 0.00000000e+00, 0.00000000e+00],
[ 8.33179844e+00, 1.31962721e+00, 0.00000000e+00],
[ 6.57163890e+00, 2.13525495e+00, 0.00000000e+00],
[ 4.86498026e+00, 2.47883127e+00, 0.00000000e+00],
[ 3.33488737e+00, 2.42293749e+00, 0.00000000e+00],
[ 2.07106782e+00, 2.07106781e+00, 0.00000000e+00],
[ 1.12256994e+00, 1.54508498e+00, 0.00000000e+00],
[-1.12256995e+00, 1.54508497e+00, 0.00000000e+00],
[-2.07106781e+00, 2.07106781e+00, 0.00000000e+00],
[-3.33488736e+00, 2.42293751e+00, 0.00000000e+00],
[-4.86498028e+00, 2.47883124e+00, 0.00000000e+00],
[-6.57163891e+00, 2.13525491e+00, 0.00000000e+00],
[-8.33179843e+00, 1.31962724e+00, 0.00000000e+00],
[-1.00000000e+01, 3.58979303e-08, 0.00000000e+00],
[-1.14219684e+01,-1.80906211e+00, 0.00000000e+00],
[-1.24494914e+01,-4.04508498e+00, 0.00000000e+00],
[-1.29551502e+01,-6.60097872e+00, 0.00000000e+00],
[-1.28454526e+01,-9.33276749e+00, 0.00000000e+00],
[-1.20710678e+01,-1.20710678e+01, 0.00000000e+00],
[-1.06331351e+01,-1.46352549e+01, 0.00000000e+00],
[-8.62130925e+00,-1.69202720e+01, 0.00000000e+00],
[-6.15270291e+00,-1.89360728e+01, 0.00000000e+00],
[-3.28150749e+00,-2.07186232e+01, 0.00000000e+00],
[-8.84786534e-09,-2.30000000e+01, 0.00000000e+00],
[ 3.28150747e+00,-2.07186232e+01, 0.00000000e+00],
[ 6.15270308e+00,-1.89360727e+01, 0.00000000e+00],
[ 8.62130924e+00,-1.69202720e+01, 0.00000000e+00],
[ 1.06331351e+01,-1.46352549e+01, 0.00000000e+00],
[ 1.20710678e+01,-1.20710679e+01, 0.00000000e+00],
[ 1.28454526e+01,-9.33276750e+00, 0.00000000e+00],
[ 1.29551502e+01,-6.60097873e+00, 0.00000000e+00],
[ 1.24494914e+01,-4.04508499e+00, 0.00000000e+00],
[ 1.14219684e+01,-1.80906212e+00, 0.00000000e+00] ]
formation_dict_my["520"] = [ #自定义位置3520
# [0, 0, 0],
[-3, 0, 0], [3, 0, 0], [3, -3, 0], [3, -6, 0], [0, -6, 0],#2
[-3, -6, 0], [-3, -9, 0], [-3, -12, 0], [0, -12, 0], [3, -12, 0],
[-9, 0, 0], [-12, 0, 0], [-15, 0, 0], [-15, -3, 0], [-15, -6, 0], [-12, -6, 0], #5
[-9, -6, 0], [-9, -9, 0], [-9, -12, 0], [-12, -12, 0], [-15, -12, 0],
[9, 0, 0], [12, 0, 0], [15, 0, 0], [15, -3, 0], [15, -6, 0], [15, -9, 0], #0
[15, -12, 0], [12, -12, 0], [9, -12, 0], [9, -9, 0], [9, -6, 0], [9, -3, 0] ]
formation_dict_my["NUDT"] = [ #自定义位置4国防科大
# [0, 0, 0],
[0, -4, 0], [0, -8, 0], [-1.2, -11, 0], #U
[-7, 0, 0], [-7, -4, 0], [-7, -8, 0], [-5.8, -11, 0], [-3.5, -12, 0],
[-12, 0, 0], [-12, -6, 0], [-12, -12, 0], #N
[-18, 0, 0], [-18, -6, 0], [-18, -12, 0],
[-16.5, -3, 0], [-15, -6, 0], [-13.5, -9, 0],
[5, 0, 0], [5, -3, 0], [5, -6, 0], [5, -9, 0], [5, -12, 0], #D
[8, -0.5, 0], [9.5, -3, 0], [10.5, -6, 0], [9.5, -9, 0], [8, -11.5, 0],
[15, 0, 0], [18, 0, 0], [21, 0, 0], [18, -4, 0], [18, -8, 0], [18, -12, 0] ]#T
formation_dict_my["八一"] = [ #自定义位置5八一军徽
# [0, 0, 0],
[-2, 0, 0], [2, 0, 0], [-2, -3, 0], [-2.5, -4, 0], [-3.5, -4.5, 0],
[2, -1, 0], [2.5, -2, 0], [3, -3, 0], [4, -4.5, 0], #八
[-3, -8, 0], [-1, -8, 0], [1, -8, 0], [3, -8, 0], #一
[-22, 2, -5], [-13.4, 2, -5], [-5.2, 2, -5], [-2.6, 10, -5], [0, 18, -5],
[2.6, 10, -5], [5.2, 2, -5], [13.4, 2, -5], [22, 2, -5], #上
[15.2, -3, -5], [8.4, -8, -5], [11, -16, -5], [13.4, -24, -5], [6.8, -19, -5],
[0, -14, -5], [-6.8, -19, -5], [-13.6, -24, -5], [-11, -16, -5], [-8.4, -8, -5], [-15.2, -3, -5] ] #下
def plot_uav_pos():
###画无人机位置
pre_x = np.zeros((1, UAV_NUM)) #初始位置
pre_y = np.zeros((1, UAV_NUM))
pre_z = np.zeros((1, UAV_NUM))
past_x = np.zeros((1, UAV_NUM)) #编队后位置
past_y = np.zeros((1, UAV_NUM))
past_z = np.zeros((1, UAV_NUM))
for i in range(UAV_NUM):
pre_x[0][i] = UAV_pre[i][0]
pre_y[0][i] = UAV_pre[i][1]
pre_z[0][i] = UAV_pre[i][2]
past_x[0][i] = UAV_past[i][0]
past_y[0][i] = UAV_past[i][1]
past_z[0][i] = UAV_past[i][2]
fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.set_xlim(-10, 10)#坐标轴范围
ax.set_ylim(-10, 10)
ax.set_zlim(-10, 10)
ax.set_xlabel('X Axes')
ax.set_ylabel('Y Axes')
ax.set_zlabel('Z Axes')
sc = ax.scatter3D(pre_x, pre_y, pre_z, color='r', alpha=0.7, marker='1', linewidth = 10) #初始位置 红
sc = ax.scatter3D(past_x, past_y, past_z, color='y', alpha=0.7, marker='1', linewidth = 10) #编队后位置 黄
#画无人机位置的辅助线
#编队后位置
# DING_LIST = [[-4, -3], [6, -3], [6, 9], [-4, 9]]
# DingX, DingY = [], []
# for each in DING_LIST:
# DingX.append(each[0])
# DingY.append(each[1])
# DingX.append(DING_LIST[0][0]) #X和Y行程闭环
# DingY.append(DING_LIST[0][1])
# ax.plot(DingX, DingY, color = 'black', linestyle = ':')
# #初始位置
# r = 5
# a, b = (0,0)
# x = np.arange( a-r, a+r+1e-3, 0.1)
# y = b + np.sqrt( r**2 - (x - a)**2)
# ax.plot(x, y, color = 'black', linestyle = ':') # 上半部
# ax.plot(x, -y, color = 'black', linestyle = ':') # 下半部
# plt.show()
###计算全部无人机从初始位置分别到终止位置的距离
def calu_pre2past_dis():
distance = []
for i in range(UAV_NUM):
single_pre = UAV_pre[i]
pre = np.tile(single_pre, (UAV_NUM ,1 ))#矩阵增广,用于将 原先的位置-编队后的位置
dis_pre2past = np.sqrt( np.dot( (pre - UAV_past)**2, np.array([ [1],[1],[1] ]) ) ) #计算无人机编队前后的距离
#编队前位置-编队后位置再对x和y分别平方再相加最后开方。两点间的距离
dis_pre2past = dis_pre2past.reshape(-1,) #(10,1)转化为(10,)
distance.append( dis_pre2past ) #每一行代表初始的一架无人机,变换到编队后所有位置的距离
distance = np.array(distance) # distance[x][y]表示初始第x号飞到编队后第y号位置的距离
return distance
###初始化种群
def initpop():
pop = np.zeros((POP_SIZE, UAV_NUM), int)
#100行 * 10列用来表示初始的x架无人机0~9编队后到达的位置的下标0~9
# print(pop)
# print(type(pop[1][1]))
for i in range(POP_SIZE):
select = [x for x in range( UAV_NUM )] #随机产生种群的每个个体
random.shuffle(select) #产生一种随机的分配方案
pop[i, :] = select
return pop
# print(pop)
###交叉 变异
def crossover_and_mutation(pop):
pre_pop = pop.copy() #prechoose是不经过交叉变异的newchoose后期经过交叉变异
for row in range(0, (np.shape(pop))[0], 2): # 两个为一组互相交叉
if CROSSOVER_RATE > random.random():
gen_1 = pop[row, :].copy()
gen_2 = pop[row + 1, :].copy()
select = [x for x in range(UAV_NUM)]
random.shuffle(select)
p1 = select[0] #保证两个交叉点的位置不一样
p2 = select[1]
p1, p2 = min(p1, p2), max(p1, p2) # 保证 p1 < p2
cross1, cross2 = gen_1[p1:p2 + 1].copy(), gen_2[p1:p2 + 1].copy() #两个基因的交叉片段
# print(p1, p2, cross1, cross2)
for cro_pos_i in range(p2 - p1 + 1): # 遍历交叉片段
gen_pos1 = np.where(gen_1 == cross2[cro_pos_i])
gen_1[gen_pos1] = (gen_1[p1:p2 + 1])[cro_pos_i].copy()
# a = gen_1
for cro_pos_i in range(p2 - p1 + 1):
gen_pos2 = np.where(gen_2 == cross1[cro_pos_i])
gen_2[gen_pos2] = (gen_2[p1:p2 + 1])[cro_pos_i].copy()
# b = gen_2
gen_1[p1:p2 + 1] = cross2.copy() #gen2的交叉片段给gen1
gen_2[p1:p2 + 1] = cross1.copy()
pop[row, :] = gen_1.copy() #放回到种群中
pop[row + 1, :] = gen_2.copy()
for row in range(0, (np.shape(pop))[0]): #遍历每个基因,以一定概率变异
if MUTATION_RATE > random.random():
select = [x for x in range(UAV_NUM)]
random.shuffle(select)
p1 = select[0] #保证变异的两个点位不一样
p2 = select[1]
gen = pop[row, :].copy()
gen[p1], gen[p2] = gen[p2], gen[p1] #交换两个变异的点位
pop[row, :] = gen.copy() #放回到种群中
# print(p1,p2,gen[p1],gen[p2])
# print(pop,'--------')
# print(pre_pop)
pop = np.append(pre_pop, pop, 0)
#经过交叉变异的种群和未经过的组合成一个两倍于POPSIZE的种群下一轮会选择前POPSIZE个
return pop
# print(pop.shape)
###计算每一种分配情况,最远距离和最近距离之差
def calu_allocate_dis(pop, dist):
all_pop_dis = [] #种群100个个体分配情况的时间列表行向量
for allocate_i in pop: #遍历每一种分配方案
distances = np.zeros(UAV_NUM)
for i in range(UAV_NUM):
uav_no_ = allocate_i[i]
distances[i] = dist[uav_no_][i]
all_pop_dis.append(max(distances) - min(distances))
all_pop_dis = np.array(all_pop_dis).reshape(-1, 1) # 列表转列向量
# unselect_pop_n = all_pop_dis.shape[0]
return all_pop_dis #每种分配方案的距离
# print(all_pop_dis)
# ###计算每一种分配的总距离
# def calu_allocate_dis(pop, dist):
# all_pop_dis = [] #种群100个个体分配情况的时间列表行向量
# for allocate_i in pop: #遍历每一种分配方案
# single_array_sum_time = 0 #一种分配情况的总时间
# for i in range(UAV_NUM):
# uav_no_ = allocate_i[i]
# single_array_sum_time += dist[uav_no_][i]
# all_pop_dis.append(single_array_sum_time)
# all_pop_dis = np.array(all_pop_dis).reshape(-1, 1) # 列表转列向量
# # unselect_pop_n = all_pop_dis.shape[0]
# return all_pop_dis #每种分配方案的距离
###排序并计算适应度
def get_fitness(all_pop_dis, pop):
index = np.argsort(all_pop_dis, 0) #升序排列,下标
all_pop_dis = all_pop_dis[index].reshape(all_pop_dis.shape[0], 1)[0:POP_SIZE, :]
#距离升序排列种群经过交叉变异数量扩大一倍这里选择前POP_SIZE个(距离最短的前n个)
pop = pop[index].reshape(pop.shape[0], UAV_NUM)[0:POP_SIZE, :] # 距离短的前n个种群个体
'''计算适值和适应度'''
fit = 1000 - all_pop_dis[:] # 适应度,时间的反比,时间短=适应度大
fitplus = np.cumsum(fit).reshape(-1, 1) # 适值向下叠加
# print(fitplus[POP_SIZE-1, :])
fitlevelplus = fitplus[:] / fitplus[POP_SIZE - 1, :] # 适应度向下叠加
fitlevelplus = np.insert(fitlevelplus, 0, np.array([0]), 0) # 在第一行添加0
# print(fitlevelplus)
# a = (np.shape(fitlevelplus))[0]
return fitlevelplus, all_pop_dis, pop
###选择
def select(pop, fitlevelplus, all_pop_dis):
newchoose_pop = [] #根据适应度选择的新种群
new_pop_dis = [] #新种群的每个个体,分配方案的距离
for _ in range(POP_SIZE):
rand = random.random()
for row in range(POP_SIZE):
if rand > fitlevelplus[row, :] and rand < fitlevelplus[row + 1, :]:
newchoose_pop.append(pop[row, :])
new_pop_dis.append(all_pop_dis[row, :])
break
newchoose_pop = np.array(newchoose_pop)
new_pop_dis = np.array(new_pop_dis)
return newchoose_pop, new_pop_dis
# print(newchoose)
# print((np.shape(newchoose))[0])
# print(new_pop_dis)
#将种群和每个分配方案的距离排序
def sortdis(sortpop, dist):
index = np.argsort(dist, 0) #升序排列,下标
dist = dist[index].reshape(dist.shape[0], 1)
#距离升序排列种群经过交叉变异数量扩大一倍这里选择前POP_SIZE个(距离最短的前n个)
sortpop = sortpop[index].reshape(sortpop.shape[0], UAV_NUM)
return sortpop, dist
def plot_allocate(best_allc):#best_allc是0~9个编队后位置分给初始的第几号无人机
plot_uav_pos()
for i in range(UAV_NUM):
uav_x = []
uav_y = []
uav_z = []
uav_x.append( UAV_past[i][0] ) #编队后的位置给初始的第几号无人机
uav_y.append( UAV_past[i][1] )
uav_z.append( UAV_past[i][2] )
uav_id_pre = best_allc[i]
uav_x.append( UAV_pre[uav_id_pre][0] )
uav_y.append( UAV_pre[uav_id_pre][1] )
uav_z.append( UAV_pre[uav_id_pre][2] )
plt.plot(uav_x, uav_y, uav_z, color = 'black', linestyle = ':')
plt.show()
def outputfile(best_allc, form_name):
allo_index = np.argsort(best_allc, 0) #升序排列下标。排序后的下标是初始无人机0~9到达终止位置的第几号
# 编队结果6 3 5 9 0 1 7 2 8 4
# 排序下标4 5 7 1 9 2 0 6 8 3
# 0号对应编队第4号位置 1号对应编队第5号位置
filename = 'my_formation_dict.py'
filepath = os.getcwd() + '\\' + filename # 输出的文件所在完整路径
if not os.path.exists(filepath): #如果文件不存在,则在文件里添加第一行
with open(filename, 'w') as f:
f.write( "import numpy as np\n\n" )
f.write( "formation_dict_my = {}\n" )
with open(filename, 'a') as f:
f.write( 'formation_dict_my["' + form_name + '"] = np.array([ ' )
for i in range(0, UAV_NUM-1):
f.write( str(UAV_past[allo_index[i]]) + ",")
f.write( str(UAV_past[allo_index[UAV_NUM-1]]) + "])\n")
f.write( 'formation_dict_my["' + form_name + '"] = np.transpose(formation_dict_my["' + form_name + '"]*1)\n')
def plot_info(best_distances, dist, pop):
best_distances = np.array(best_distances)
# print(best_distances)
print(dist[0, :]) #最短距离
# print(pop[0, :]) #对应的分配方案
x = [a for a in range(1, N_GENERATIONS+1)]
y = best_distances
plt.plot(x, y)
plt.xlabel('迭代次数')
plt.ylabel('距离之差')
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.show()
def calu_best_dis(best_allc, dis):
best_dis = 0
# allo_index = np.argsort(best_allc, 0) #升序排列,下标
for i in range(UAV_NUM):
uav_no_ = best_allc[i]
best_dis += dis[uav_no_][i]
# pos_past = UAV_past[allo_index[i]]
# pos_pre = UAV_pre[i]
# curr_dis = math.sqrt((pos_pre[0] - pos_past[0]) ** 2 + (pos_pre[1] - pos_past[1]) ** 2)
# best_dis += curr_dis
print(best_dis)
if __name__ == "__main__":
dic_i = 0
for key in formation_dict_my.keys():
MUTATION_RATE = 0.2 # 每开始新的一轮循环,新的编队
form_name = key
UAV_past = formation_dict_my[key]
if dic_i:
plot_uav_pos()
plt.show() #画无人机初始位置和编队后的位置
distance = calu_pre2past_dis() #计算全部无人机从初始位置分别到终止位置的距离
pop = initpop() #初始化种群
best_distances = [] #每一轮最短的距离,用于绘图
for generation_n in range(N_GENERATIONS): #迭代N代
if generation_n == int(N_GENERATIONS/2):#迭代到一半时,变异率扩大一倍
MUTATION_RATE = MUTATION_RATE*3
pop = crossover_and_mutation(pop) #先交叉变异pop扩大为原来的两倍
all_pop_dis = calu_allocate_dis(pop, distance) #每种分配方案的距离,分配方案的数量
fitlevelplus, all_pop_dis, pop = get_fitness(all_pop_dis, pop) #种群排序取前n求适应度
# pop, all_pop_dis = select(pop, fitlevelplus, all_pop_dis) #选择
# sort_pop, sort_pop_dis = sortdis(pop, all_pop_dis)
best_distances.append(all_pop_dis[0, :]) #当前种群里,最短距离
plot_allocate(pop[0, :]) #画无人机前后分配线
outputfile(pop[0, :], form_name) #无人机位置输出到文件
plot_info(best_distances, all_pop_dis, pop) #绘制最短距离随迭代次数变化曲线
# calu_best_dis(pop[0, :], distance)
UAV_pre = formation_dict_my[key]
dic_i += 1

View File

@ -0,0 +1,101 @@
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import rospy
from geometry_msgs.msg import Twist, Vector3, PoseStamped
from std_msgs.msg import String
from pyquaternion import Quaternion
import time
import math
import numpy
import sys
#if sys.argv[2] == '6': #formation_dict是该文件夹下的文件
# from formation_dict import formation_dict_6 as formation_dict
#elif sys.argv[2] == '9':
# from formation_dict import formation_dict_9 as formation_dict
#elif sys.argv[2] == '18':
# from formation_dict import formation_dict_18 as formation_dict
if sys.argv[2] == '21':
from my_formation_dict import formation_dict_my as formation_dict
elif sys.argv[2] == '34':
from my_formation_dict import formation_dict_my as formation_dict
class Leader:
def __init__(self, uav_type, leader_id, uav_num):
self.hover = True
self.id = leader_id
self.local_pose = PoseStamped()
self.cmd_vel_enu = Twist()
self.follower_num = uav_num - 1
self.followers_info = ["Moving"]*self.follower_num
self.follower_arrived_num = 0
self.follower_all_arrived = True
self.avoid_accel = Vector3(0,0,0)
self.formation_config = 'waiting'
self.target_height_recorded = False
self.cmd = String()
self.f = 200
self.Kz = 0.5
self.local_pose_sub = rospy.Subscriber(uav_type+'_'+str(self.id)+"/mavros/local_position/pose", PoseStamped , self.local_pose_callback)
self.cmd_vel_sub = rospy.Subscriber("/xtdrone/leader/cmd_vel_flu", Twist, self.cmd_vel_callback)
self.avoid_vel_sub = rospy.Subscriber("/xtdrone/"+uav_type+'_'+str(self.id)+"/avoid_accel", Vector3, self.avoid_accel_callback)
self.leader_cmd_sub = rospy.Subscriber("/xtdrone/leader/cmd",String, self.cmd_callback)
for i in range(self.follower_num):#遍历所有跟随者
rospy.Subscriber('/xtdrone/'+uav_type+'_'+str(i+1)+'/info',String,self.followers_info_callback,i)
self.local_pose_pub = rospy.Publisher("/xtdrone/leader/pose", PoseStamped , queue_size=10)
self.formation_switch_pub = rospy.Publisher("/xtdrone/formation_switch",String, queue_size=10)
self.vel_enu_pub = rospy.Publisher('/xtdrone/'+uav_type+'_'+str(self.id)+'/cmd_vel_enu', Twist, queue_size=10)
self.cmd_pub = rospy.Publisher('/xtdrone/'+uav_type+'_'+str(self.id)+'/cmd', String, queue_size=10)
def local_pose_callback(self, msg):
self.local_pose = msg
def cmd_vel_callback(self, msg):
self.cmd_vel_enu = msg
if msg.linear.z == 0:
self.hover = True #悬停
else:
self.hover = False
def cmd_callback(self, msg):
if msg.data in formation_dict.keys():
self.formation_config = msg.data
else:
self.cmd = msg.data
def avoid_accel_callback(self, msg):
self.avoid_accel = msg
def followers_info_callback(self, msg, id):
self.followers_info[id] = msg.data
#print("follower"+str(id)+":"+ msg.data)
def loop(self):
rospy.init_node('leader')
rate = rospy.Rate(self.f)
while True:
#self.cmd_vel_enu = Twist()
for follower_info in self.followers_info:
if follower_info == "Arrived": # 一架到达
self.follower_arrived_num += 1
if self.follower_arrived_num > self.follower_num - 1:
self.follower_all_arrived = True #全部到达
if self.follower_all_arrived:
self.formation_switch_pub.publish(self.formation_config)
if self.formation_config == 'pyramid':
if not self.target_height_recorded:
target_height = self.local_pose.pose.position.z + 2
self.target_height_recorded = True
self.cmd_vel_enu.linear.z = self.Kz * (target_height - self.local_pose.pose.position.z)
self.cmd_vel_enu.linear.x += self.avoid_accel.x
self.cmd_vel_enu.linear.y += self.avoid_accel.y
self.cmd_vel_enu.linear.z += self.avoid_accel.z
self.vel_enu_pub.publish(self.cmd_vel_enu)
self.local_pose_pub.publish(self.local_pose)
self.cmd_pub.publish(self.cmd)
rate.sleep()
if __name__ == '__main__':
leader = Leader(sys.argv[1], 0, int(sys.argv[2]))
leader.loop()

View File

@ -0,0 +1,9 @@
#!/bin/bash
# -*- coding: UTF-8 -*-
python my_leader.py $1 $2 & #第一架飞机是 引领,其余飞机是 跟随。$1是飞机类型如iris$2是数量
uav_num=1
while(( $uav_num< $2 ))
do
python my_follower.py $1 $uav_num $2&
let "uav_num++"
done

View File

@ -0,0 +1,2 @@
kill -9 $(ps -ef|grep follower.py|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')
kill -9 $(ps -ef|grep leader.py|gawk '$0 !~/grep/ {print $2}' |tr -s '\n' ' ')

View File

@ -0,0 +1,631 @@
<?xml version="1.0"?>
<launch>
<!-- MAVROS posix SITL environment launch script -->
<!-- launches Gazebo environment and 2x: MAVROS, PX4 SITL, and spawns vehicle -->
<!-- vehicle model and world -->
<arg name="est" default="ekf2"/>
<arg name="world" default="$(find mavlink_sitl_gazebo)/worlds/outdoor2.world"/>
<!-- gazebo configs -->
<arg name="gui" default="true"/>
<arg name="debug" default="false"/>
<arg name="verbose" default="false"/>
<arg name="paused" default="false"/>
<!-- Gazebo sim -->
<include file="$(find gazebo_ros)/launch/empty_world.launch">
<arg name="gui" value="$(arg gui)"/>
<arg name="world_name" value="$(arg world)"/>
<arg name="debug" value="$(arg debug)"/>
<arg name="verbose" value="$(arg verbose)"/>
<arg name="paused" value="$(arg paused)"/>
</include>
<!-- iris_0 -->
<group ns="iris_0">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="0"/>
<arg name="ID_in_group" value="0"/>
<arg name="fcu_url" default="udp://:24540@localhost:34580"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="0"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18570"/>
<arg name="mavlink_tcp_port" value="4560"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_1 -->
<group ns="iris_1">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="1"/>
<arg name="ID_in_group" value="1"/>
<arg name="fcu_url" default="udp://:24541@localhost:34581"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="3"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18571"/>
<arg name="mavlink_tcp_port" value="4561"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_2 -->
<group ns="iris_2">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="2"/>
<arg name="ID_in_group" value="2"/>
<arg name="fcu_url" default="udp://:24542@localhost:34582"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="6"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18572"/>
<arg name="mavlink_tcp_port" value="4562"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_3 -->
<group ns="iris_3">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="3"/>
<arg name="ID_in_group" value="3"/>
<arg name="fcu_url" default="udp://:24543@localhost:34583"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="9"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18573"/>
<arg name="mavlink_tcp_port" value="4563"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_4 -->
<group ns="iris_4">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="4"/>
<arg name="ID_in_group" value="4"/>
<arg name="fcu_url" default="udp://:24544@localhost:34584"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="12"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18574"/>
<arg name="mavlink_tcp_port" value="4564"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_5 -->
<group ns="iris_5">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="5"/>
<arg name="ID_in_group" value="5"/>
<arg name="fcu_url" default="udp://:24545@localhost:34585"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="15"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18575"/>
<arg name="mavlink_tcp_port" value="4565"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_6 -->
<group ns="iris_6">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="6"/>
<arg name="ID_in_group" value="6"/>
<arg name="fcu_url" default="udp://:24546@localhost:34586"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="18"/>
<arg name="y" value="3"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18576"/>
<arg name="mavlink_tcp_port" value="4566"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_7 -->
<group ns="iris_7">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="7"/>
<arg name="ID_in_group" value="7"/>
<arg name="fcu_url" default="udp://:24547@localhost:34587"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="0"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18577"/>
<arg name="mavlink_tcp_port" value="4567"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_8 -->
<group ns="iris_8">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="8"/>
<arg name="ID_in_group" value="8"/>
<arg name="fcu_url" default="udp://:24548@localhost:34588"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="3"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18578"/>
<arg name="mavlink_tcp_port" value="4568"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_9 -->
<group ns="iris_9">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="9"/>
<arg name="ID_in_group" value="9"/>
<arg name="fcu_url" default="udp://:24549@localhost:34589"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="6"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18579"/>
<arg name="mavlink_tcp_port" value="4569"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_10 -->
<group ns="iris_10">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="10"/>
<arg name="ID_in_group" value="10"/>
<arg name="fcu_url" default="udp://:24550@localhost:34590"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="9"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18580"/>
<arg name="mavlink_tcp_port" value="4570"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_11 -->
<group ns="iris_11">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="11"/>
<arg name="ID_in_group" value="11"/>
<arg name="fcu_url" default="udp://:24551@localhost:34591"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="12"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18581"/>
<arg name="mavlink_tcp_port" value="4571"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_12 -->
<group ns="iris_12">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="12"/>
<arg name="ID_in_group" value="12"/>
<arg name="fcu_url" default="udp://:24552@localhost:34592"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="15"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18582"/>
<arg name="mavlink_tcp_port" value="4572"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_13 -->
<group ns="iris_13">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="13"/>
<arg name="ID_in_group" value="13"/>
<arg name="fcu_url" default="udp://:24553@localhost:34593"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="18"/>
<arg name="y" value="6"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18583"/>
<arg name="mavlink_tcp_port" value="4573"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_14 -->
<group ns="iris_14">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="14"/>
<arg name="ID_in_group" value="14"/>
<arg name="fcu_url" default="udp://:24554@localhost:34594"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="0"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18584"/>
<arg name="mavlink_tcp_port" value="4574"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_15 -->
<group ns="iris_15">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="15"/>
<arg name="ID_in_group" value="15"/>
<arg name="fcu_url" default="udp://:24555@localhost:34595"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="3"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18585"/>
<arg name="mavlink_tcp_port" value="4575"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_16 -->
<group ns="iris_16">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="16"/>
<arg name="ID_in_group" value="16"/>
<arg name="fcu_url" default="udp://:24556@localhost:34596"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="6"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18586"/>
<arg name="mavlink_tcp_port" value="4576"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_17 -->
<group ns="iris_17">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="17"/>
<arg name="ID_in_group" value="17"/>
<arg name="fcu_url" default="udp://:24557@localhost:34597"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="9"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18587"/>
<arg name="mavlink_tcp_port" value="4577"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_18 -->
<group ns="iris_18">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="18"/>
<arg name="ID_in_group" value="18"/>
<arg name="fcu_url" default="udp://:24558@localhost:34598"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="12"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18588"/>
<arg name="mavlink_tcp_port" value="4578"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_19 -->
<group ns="iris_19">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="19"/>
<arg name="ID_in_group" value="19"/>
<arg name="fcu_url" default="udp://:24559@localhost:34599"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="15"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18589"/>
<arg name="mavlink_tcp_port" value="4579"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
<!-- iris_20 -->
<group ns="iris_20">
<!-- MAVROS and vehicle configs -->
<arg name="ID" value="20"/>
<arg name="ID_in_group" value="20"/>
<arg name="fcu_url" default="udp://:24560@localhost:34600"/>
<!-- PX4 SITL and vehicle spawn -->
<include file="$(find px4)/launch/single_vehicle_spawn_xtd.launch">
<arg name="x" value="18"/>
<arg name="y" value="9"/>
<arg name="z" value="0"/>
<arg name="R" value="0"/>
<arg name="P" value="0"/>
<arg name="Y" value="0"/>
<arg name="vehicle" value="iris"/>
<arg name="sdf" value="iris_stereo_camera"/>
<arg name="mavlink_udp_port" value="18590"/>
<arg name="mavlink_tcp_port" value="4580"/>
<arg name="ID" value="$(arg ID)"/>
<arg name="ID_in_group" value="$(arg ID_in_group)"/>
</include>
<!-- MAVROS -->
<include file="$(find mavros)/launch/px4.launch">
<arg name="fcu_url" value="$(arg fcu_url)"/>
<arg name="gcs_url" value=""/>
<arg name="tgt_system" value="$(eval 1 + arg('ID'))"/>
<arg name="tgt_component" value="1"/>
</include>
</group>
</launch>
<!--the launch file is generated by XTDrone multi-vehicle generator.py -->

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,164 @@
import random
import numpy as np
import math
import time
import os
from geographiclib.geodesic import Geodesic
import math
geod = Geodesic.WGS84
# 计算方位角函数
def azimuthAngle(pos):
if(pos[0] > 0 and pos[1] > 0):
angle = math.atan(pos[1] / pos[0])
elif(pos[0] > 0 and pos[1] < 0):
angle = math.atan(pos[1] / pos[0]) + 2 * math.pi
elif(pos[0] < 0 and pos[1] > 0):
angle = math.atan(pos[1] / pos[0]) + math.pi
elif(pos[0] < 0 and pos[1] < 0):
angle = math.atan(pos[1] / pos[0]) + math.pi
return (angle * 180 / math.pi)
def angle_dis(pos):
angle = azimuthAngle(pos)
distance = math.sqrt(pow(pos[0],2)+pow(pos[1],2))
return angle, distance
class ACO():
def __init__(self, vehicle_num, target_num,vehicle_speed, target, time_lim):
self.num_type_ant = vehicle_num
self.num_city = target_num+1 #number of cities
self.group = 200 # 200组蚂蚁每组蚂蚁有6只
self.num_ant = self.group*self.num_type_ant #number of ants
self.ant_vel = vehicle_speed
self.cut_time = time_lim
self.oneee = np.zeros((4,1))
self.target = target
self.alpha = 1 #pheromone
self.beta = 2
self.k1 = 0.03
self.iter_max = 50
#matrix of the distances between cities
def distance_matrix(self):
dis_mat = []
for i in range(self.num_city):
dis_mat_each = []
for j in range(self.num_city):
dis = math.sqrt(pow(self.target[i][0]-self.target[j][0],2)+pow(self.target[i][1]-self.target[j][1],2))
dis_mat_each.append(dis)
dis_mat.append(dis_mat_each)
return dis_mat
def run(self):
print("ACO start, pid: %s" % os.getpid())
start_time = time.time()
#distances of nodes
dis_list = self.distance_matrix()
dis_mat = np.array(dis_list)
value_init = self.target[:,2].transpose()
delay_init = self.target[:,3].transpose()
pheromone_mat = np.ones((self.num_type_ant,self.num_city,self.num_city)) # 信息素矩阵6*31*316只蚂蚁在31*31条的路径上留下的信息素
#velocity of ants
path_new = [[0]for i in range (self.num_type_ant)]
count_iter = 0
while count_iter < self.iter_max:
path_sum = np.zeros((self.num_ant,1))
time_sum = np.zeros((self.num_ant,1))
value_sum = np.zeros((self.num_ant,1))
path_mat=[[0]for i in range (self.num_ant)]
value = np.zeros((self.group,1))
atten = np.ones((self.num_type_ant,1)) * 0.2
for ant in range(self.num_ant): # 对每只蚂蚁
ant_type = ant % self.num_type_ant
visit = 0 # 当前节点
if ant_type == 0:
unvisit_list=list(range(1,self.num_city))#have not visit
for j in range(1,self.num_city): # 行走的第几个城市
#choice of next city
trans_list=[]
tran_sum=0
trans=0
#if len(unvisit_list)==0:
#print('len(unvisit_list)==0')
for k in range(len(unvisit_list)): # 计算本组蚂蚁没走过的城市的启发式函数
trans +=np.power(pheromone_mat[ant_type][visit][unvisit_list[k]],self.alpha)*np.power(value_init[unvisit_list[k]]*self.ant_vel[ant_type]/(dis_mat[visit][unvisit_list[k]]*delay_init[unvisit_list[k]]),self.beta)
#trans +=np.power(pheromone_mat[ant_type][unvisit_list[k]],self.alpha)*np.power(0.05*value_init[unvisit_list[k]],self.beta)
trans_list.append(trans)
tran_sum = trans
rand = random.uniform(0,tran_sum)
for t in range(len(trans_list)): # 轮盘赌选择下一个点
if(rand <= trans_list[t]):
visit_next = unvisit_list[t]
break
else:
continue
path_mat[ant].append(visit_next) # 每只蚂蚁走过的路径
path_sum[ant] += dis_mat[path_mat[ant][j-1]][path_mat[ant][j]] # 每只蚂蚁走过的总路径长度
time_sum[ant] += path_sum[ant] / self.ant_vel[ant_type] + delay_init[visit_next] # 每只蚂蚁使用的时间
if time_sum[ant] > self.cut_time:
time_sum[ant]-=path_sum[ant] / self.ant_vel[ant_type] + delay_init[visit_next]
path_mat[ant].pop()
break
value_sum[ant] += value_init[visit_next] # 每只蚂蚁的value
unvisit_list.remove(visit_next)#update
visit = visit_next
if (ant_type) == self.num_type_ant-1:
small_group = int(ant/self.num_type_ant)
for k in range (self.num_type_ant):
value[small_group]+= value_sum[ant-k] # 每组蚂蚁的value
#iteration
if count_iter == 0:
value_new = max(value)
value = value.tolist()
for k in range (0,self.num_type_ant):
path_new[k] = path_mat[value.index(value_new)*self.num_type_ant+k] # 200组蚂蚁中value最大的蚂蚁的路径
path_new[k].remove(0) # 移除起点
else:
if max(value) > value_new:
value_new = max(value)
value = value.tolist()
for k in range (0,self.num_type_ant):
path_new[k] = path_mat[value.index(value_new)*self.num_type_ant+k]
path_new[k].remove(0)
#update pheromone
pheromone_change = np.zeros((self.num_type_ant,self.num_city,self.num_city))
for i in range(self.num_ant):
length = len(path_mat[i])
m = i%self.num_type_ant
n = int(i/self.num_type_ant)
for j in range(length-1):
pheromone_change[m][path_mat[i][j]][path_mat[i][j+1]]+= value_init[path_mat[i][j+1]]*self.ant_vel[m]/(dis_mat[path_mat[i][j]][path_mat[i][j+1]]*delay_init[path_mat[i][j+1]])
atten[m] += (value_sum[i]/(np.power((value_new-value[n]),4)+1))/self.group
for k in range (self.num_type_ant):
pheromone_mat[k]=(1-atten[k])*pheromone_mat[k]+pheromone_change[k]
count_iter += 1
print("ACO result:", path_new)
middle_point = [47.3978502, 8.5455944]
path_new_point = []
for z in range(len(path_new)):
path_new_point.append(self.target[path_new[z], 0:2])
print("ACO path points m: ", path_new_point)
path_ang_dis = []
log = []
for i in range(len(path_new_point)):
a_path_ang_dis = []
a_log = []
for j in range(len(path_new_point[i])):
angle, distance = angle_dis(path_new_point[i][j])
g = geod.Direct(middle_point[0], middle_point[1], angle, distance)
a_log.append([g['lat2'], g['lon2']])
a_path_ang_dis.append([angle, distance])
path_ang_dis.append(a_path_ang_dis)
log.append(a_log)
print("ACO angle and distance: ", path_ang_dis)
print("ACO log: ", log)
end_time = time.time()
print("ACO time:", end_time - start_time)
return path_new, end_time - start_time

View File

@ -0,0 +1,128 @@
import numpy as np
import matplotlib.pyplot as plt
import random
import pandas as pd
import copy
from aco import ACO
from geographiclib.geodesic import Geodesic
import math
geod = Geodesic.WGS84
class Env():
def __init__(self, vehicle_num, target_num, map_size, visualized=True, time_cost=None, repeat_cost=None):
self.vehicles_position = np.zeros(vehicle_num,dtype=np.int32) # 无人机位置
self.vehicles_speed = np.zeros(vehicle_num,dtype=np.int32) # 无人机速度
self.targets = np.zeros(shape=(target_num+1,4),dtype=np.int32) # 目标属性
if vehicle_num==6:
self.size='small'
self.map_size = map_size
self.speed_range = [10, 10, 10]
#self.time_lim = 1e6
self.time_lim = self.map_size / self.speed_range[1]
self.vehicles_lefttime = np.ones(vehicle_num,dtype=np.float32) * self.time_lim # 剩余的可用时间
self.distant_mat = np.zeros((target_num+1,target_num+1),dtype=np.float32)
self.total_reward = 0
self.reward = 0
self.visualized = visualized
self.time = 0
self.time_cost = time_cost
self.repeat_cost = repeat_cost
self.end = False
self.assignment = [[] for i in range(vehicle_num)] # 最终的分配路径
self.task_generator()
def task_generator(self):
for i in range(self.vehicles_speed.shape[0]): # 确定每个无人机的速度
choose = random.randint(0,2)
self.vehicles_speed[i] = self.speed_range[choose]
for i in range(self.targets.shape[0]-1): # 确定每个目标点的坐标位置和奖励、消耗值
self.targets[i+1,0] = random.randint(1,self.map_size) - 0.5*self.map_size # x position
self.targets[i+1,1] = random.randint(1,self.map_size) - 0.5*self.map_size # y position
self.targets[i+1,2] = random.randint(1,10) # reward
self.targets[i+1,3] = random.randint(5,10) # time consumption to finish the mission
for i in range(self.targets.shape[0]): # 计算距离矩阵
for j in range(self.targets.shape[0]):
self.distant_mat[i,j] = np.linalg.norm(self.targets[i,:2]-self.targets[j,:2])
self.targets_value = copy.deepcopy((self.targets[:,2]))
def run(self, assignment, algorithm, play, rond):
self.assignment = assignment
self.algorithm = algorithm
self.play = play
self.rond = rond
self.get_total_reward()
if self.visualized:
self.visualize()
def reset(self):
self.vehicles_position = np.zeros(self.vehicles_position.shape[0],dtype=np.int32)
self.vehicles_lefttime = np.ones(self.vehicles_position.shape[0],dtype=np.float32) * self.time_lim
self.targets[:,2] = self.targets_value
self.total_reward = 0
self.reward = 0
self.end = False
def get_total_reward(self):
for i in range(len(self.assignment)):
speed = self.vehicles_speed[i]
for j in range(len(self.assignment[i])):
position = self.targets[self.assignment[i][j],:4]
self.total_reward = self.total_reward + position[2]
if j == 0:
self.vehicles_lefttime[i] = self.vehicles_lefttime[i] - np.linalg.norm(position[:2]) / speed - position[3]
else:
self.vehicles_lefttime[i] = self.vehicles_lefttime[i] - np.linalg.norm(position[:2]-position_last[:2]) / speed - position[3]
position_last = position
if self.vehicles_lefttime[i] > self.time_lim:
self.end = True
break
if self.end:
self.total_reward = 0
break
def visualize(self):
if self.assignment == None:
plt.scatter(x=0,y=0,s=200,c='k')
plt.scatter(x=self.targets[1:,0],y=self.targets[1:,1],s=self.targets[1:,2]*10,c='r')
plt.title('Target distribution')
plt.savefig('task_pic/'+self.size+'/'+self.algorithm+ "-%d-%d.png" % (self.play,self.rond))
plt.cla()
else:
plt.title('Task assignment by '+self.algorithm +', total reward : '+str(self.total_reward))
plt.scatter(x=0,y=0,s=200,c='k')
plt.scatter(x=self.targets[1:,0],y=self.targets[1:,1],s=self.targets[1:,2]*10,c='r')
for i in range(len(self.assignment)):
trajectory = np.array([[0,0,20]])
for j in range(len(self.assignment[i])):
position = self.targets[self.assignment[i][j],:3]
trajectory = np.insert(trajectory,j+1,values=position,axis=0)
plt.scatter(x=trajectory[1:,0],y=trajectory[1:,1],s=trajectory[1:,2]*10,c='b')
plt.plot(trajectory[:,0], trajectory[:,1])
plt.savefig('task_pic/'+self.size+'/'+self.algorithm+ "-%d-%d.png" % (self.play,self.rond))
plt.cla()
def evaluate(vehicle_num, target_num, map_size):
if vehicle_num==6:
size='small'
re_aco=[[] for i in range(2)]
for i in range(1):
env = Env(vehicle_num,target_num,map_size,visualized=True)
for j in range(1):
aco = ACO(vehicle_num,target_num,env.vehicles_speed,env.targets,env.time_lim)
path_new, time = aco.run()
env.run(path_new,'ACO',i+1,j+1)
re_aco[i].append((env.total_reward,time))
env.reset()
if __name__=='__main__':
'''
vehicle number: scalar
speeds of vehicles: array
target number: scalar
targets: array, the first line is depot, the first column is x position, the second column is y position, the third column is reward and the forth column is time consumption to finish the mission
time limit: scalar
'''
evaluate(6,30,1e3)

View File

@ -0,0 +1,248 @@
# -*- coding: utf-8 -*-
import numpy as np
import matplotlib.pyplot as plt
import collections
import heapq
import itertools
import time
from xlrd import open_workbook
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = "kaiti"
import mpl_toolkits.mplot3d
from mpl_toolkits.mplot3d import Axes3D
def getDist(pos1, pos2):
return np.sqrt(sum([(pos1[0] - pos2[0]) ** 2, (pos1[1] - pos2[1]) ** 2, (pos1[2] - pos2[2]) ** 2]))
def heuristic_fun(initparams, k, t):
distance = getDist(k, t)
need_full_point = distance / 100 * 4 / 4
need_comfort_point = distance / 100 * 4 / 4
return need_comfort_point + need_full_point
def draw_path(sheet, path):
x = sheet.col_values(1)[1:]
y = sheet.col_values(2)[1:]
z = sheet.col_values(3)[1:]
list_length = len(sheet.col_values(4)[1:])
food_index = [i for i in range(list_length) if sheet.col_values(4)[1:][i] == 1]
fire_index = [i for i in range(list_length) if sheet.col_values(4)[1:][i] == 0]
fig = plt.figure(figsize=(10,10))
ax = fig.add_subplot(projection = '3d')
for i in range(list_length):
if i in food_index:
ax.scatter(x[i], y[i], z[i], s=10, c='k', marker='.')
else:
ax.scatter(x[i], y[i], z[i], s=10, c='r', marker='.')
ax.set_title('规划路径结果')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('z')
path = np.array(path)
ax.plot3D(path[:, 0].tolist(), path[:, 1].tolist(), path[:, 2].tolist(), 'blue')
plt.show()
class MinheapPQ:
'''
堆排序返回代价最小的可行点
已封装好使用put向堆加入可行点使用get获取代价值最小的可行点
'''
def __init__(self):
self.pq = []
self.nodes = set()
self.entry_finder = {}
self.counter = itertools.count()
self.REMOVED = '<removed-item>'
def put(self, item, priority):
if item in self.entry_finder:
self.check_remove(item)
count = next(self.counter)
entry = [priority, count, item]
self.entry_finder[item] = entry
heapq.heappush(self.pq, entry)
self.nodes.add(item)
def check_remove(self, item):
if item not in self.entry_finder:
return
entry = self.entry_finder.pop(item)
entry[-1] = self.REMOVED
self.nodes.remove(item)
def get(self):
while self.pq:
priority, count, item = heapq.heappop(self.pq)
if item is not self.REMOVED:
del self.entry_finder[item]
self.nodes.remove(item)
return item
raise KeyError('pop from an empty priority queue')
def top_key(self):
return self.pq[0][0]
def enumerate(self):
return self.pq
def allnodes(self):
return self.nodes
class Weighted_A_star(object):
def __init__(self):
self.start, self.goal = tuple(np.array([0, 500, 500])), tuple(np.array([1000, 555.67, 442.022]))
self.g = {self.start:-20,self.goal:np.inf} # 记录从起点到各个点的gg值是固定的当通过另一个点能有一个更小的g时改变
self.Parent = {self.start:self.start}
self.CLOSED = set()
self.Path = []
self.OPEN = MinheapPQ() # 存储节点及其代价
self.full = {self.start:10}
self.comfort = {self.start:10}
self.OPEN.put(self.start, self.g[self.start] + heuristic_fun(self, self.start, self.goal)) # item, priority = g + h
self.lastpoint = self.start
self.lastg = {}
self.pathparent = {}
def run(self):
xt = self.goal
xi = self.start
last_xi = xi
ban_xi = {}
flag = 0
while(1): # 当没有到达终点时循环
# 找到一个有可行食物点、篝火点的节点作为当前点
xi = self.OPEN.get()
distance = getDist(xi, self.Parent[xi])
full_change = (np.sign(xi[2] - self.Parent[xi][2]) + 5) * distance / 100
reachable_full, reachable_comfort = self.reachable_point(xi)
while((self.full[xi] > self.comfort[xi] and len(reachable_comfort) < 2 and xi[0] < 300) \
or (self.full[xi] <= self.comfort[xi] and len(reachable_full) < 2 and xi[0] < 300) \
or (self.full[xi] > self.comfort[xi] and len(reachable_comfort) < 2 and xi[0] < 300) \
or (self.full[xi] <= self.comfort[xi] and len(reachable_full) < 2 and xi[0] < 300) \
or(self.full[xi] > self.comfort[xi] and len(reachable_comfort) < 1 and xi[0] > 300) \
or(self.full[xi] <= self.comfort[xi] and len(reachable_full) < 1 and xi[0] > 300) \
or (xi in self.CLOSED) or xi[0] == 397.14 \
or xi[0] == 604.287 or xi[0] == 632.907 or (xi[0] == 686.951 and self.Parent[xi][0] == 594.039)):
ban_xi[xi] = self.g[xi] + heuristic_fun(self, xi, self.goal)
xi = self.OPEN.get()
distance = getDist(xi, self.Parent[xi])
full_change = (np.sign(xi[2] - self.Parent[xi][2]) + 5) * distance / 100
reachable_full, reachable_comfort = self.reachable_point(xi)
# 对当前点的后续处理
print(xi, self.Parent[xi], self.full[xi], self.comfort[xi], len(reachable_full), len(reachable_comfort))
self.pathparent[xi] = self.Parent[xi]
self.CLOSED.add(xi)
for xz in ban_xi:
self.OPEN.put(xz, ban_xi[xz])
ban_xi = {}
if(self.goal in reachable_full or self.goal in reachable_comfort):
self.Parent[self.goal] = xi
self.pathparent[self.goal] = xi
break
if(int(100000 * self.full[xi]) > int(100000 * self.comfort[xi])):
self.process_child(xi, reachable_comfort, False)
if(int(100000 * self.full[xi]) < int(100000 * self.comfort[xi])):
self.process_child(xi, reachable_full, True)
if(int(100000 * self.full[xi]) == int(100000 * self.comfort[xi])):
self.process_child(xi, reachable_full, True)
self.process_child(xi, reachable_comfort, False)
last_xi = xi
flag += 1
self.lastpoint = xi
self.Path = self.path()
draw_path(sheet, self.Path)
def process_child(self, xi, points, isfull):
# 对当前点后继可行节点的处理
for xj in list(points.keys()):
if xj not in self.g:
self.g[xj] = np.inf
distance = getDist(xi, xj)
if isfull:
self.full[xj] = self.full[xi] + points[xj] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
self.comfort[xj] = self.comfort[xi] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
else:
self.full[xj] = self.full[xi] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
self.comfort[xj] = self.comfort[xi] + points[xj] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
a = self.g[xi] + 1 - self.full[xj] - self.comfort[xj]
self.lastg[xj] = self.g[xj]
self.g[xj] = a
self.Parent[xj] = xi
self.OPEN.put(xj, a + heuristic_fun(self, xj, self.goal))
def path(self):
path = []
x = self.lastpoint
path.append([1000, 555.67, 442.022])
i = 1
start = self.start
while x != start:
path.append(list(x))
x = self.pathparent[x]
i += 1
path.append([0, 500, 500])
print(path)
print(i + 1)
return path
def reachable_point(self, xi):
# 输入:当前点坐标
# 返回:可行食物点坐标及补充量,可行篝火点坐标及补充量
fulldown = (self.full[xi] + 5) / 4 * 100
comfortdown = (self.comfort[xi] + 5) / 4 * 100
fullup = (self.full[xi] + 5) / 6 * 100
comfortup = (self.comfort[xi] + 5) / 6 * 100
condition = (content[:, 1] <= xi[0] + fulldown) & (content[:, 1] > xi[0] - fulldown) &\
(content[:, 2] <= xi[1] + fulldown) & (content[:, 2] >= xi[1] - fulldown) &\
(content[:, 3] >= xi[2] - fulldown) & (content[:, 3] <= xi[2] + fullup) &\
(content[:, 1] <= xi[0] + comfortdown) & (content[:, 1] > xi[0] - comfortdown) &\
(content[:, 2] <= xi[1] + comfortdown) & (content[:, 2] >= xi[1] - comfortdown) &\
(content[:, 3] >= xi[2] - comfortdown) & (content[:, 3] <= xi[2] + comfortup) & (content[:, 1] != xi[0])
full_condition = condition & (content[:, 4] == 1)
comfort_condition = condition & (content[:, 4] == 0)
reachable_full = dict(zip(list(map(tuple, content[full_condition][:, 1:4])), content[full_condition][:, -1]))
reachable_comfort = dict(zip(list(map(tuple, content[comfort_condition][:, 1:4])), content[comfort_condition][:, -1]))
for xj in list(reachable_full.keys()):
distance = getDist(xi, xj)
xj_full = self.full[xi] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
xj_comfort = self.comfort[xi] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
if xj == (1000, 555.67, 442.022) and (xj_full <-3 or xj_comfort < -3):
del reachable_full[xj]
elif(xj_full < -5 or xj_comfort < -5):
del reachable_full[xj]
for xj in list(reachable_comfort.keys()):
distance = getDist(xi, xj)
xj_full = self.full[xi] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
xj_comfort = self.comfort[xi] - (np.sign(xj[2] - xi[2]) + 5) * distance / 100
if xj == (1000, 555.67, 442.022) and (xj_full <-3 or xj_comfort < -3):
del reachable_comfort[xj]
elif(xj_full < -5 or xj_comfort < -5):
del reachable_comfort[xj]
return reachable_full, reachable_comfort
if __name__ == '__main__':
workbook = open_workbook(r'附件.xlsx')
sheet = workbook.sheet_by_index(0)
content = np.array([sheet.row_values(i) for i in range(2, 589)])
Astar = Weighted_A_star()
sta = time.time()
path = Astar.run()
print(time.time() - sta)
draw_path(sheet, path)

View File

@ -0,0 +1,108 @@
from xlrd import open_workbook
import numpy as np
import copy
def getDist(pos1, pos2):
return np.sqrt(sum([(pos1[0] - pos2[0]) ** 2, (pos1[1] - pos2[1]) ** 2, (pos1[2] - pos2[2]) ** 2]))
def judge_path(path):
full = 10
comfort = 10
for i in range(1, len(path)):
distance = getDist(path[i], path[i - 1])
full = full - (np.sign(path[i][2] - path[i-1][2]) + 5) * distance / 100
comfort = comfort - (np.sign(path[i][2] - path[i-1][2]) + 5) * distance / 100
if(full <= -5 or comfort <= -5):
return 0
if(content[np.where(content[:, 1] == path[i][0]), 4] == 0):
comfort = comfort + content[np.where(content[:, 1] == path[i][0]), 5]
else:
full = full + content[np.where(content[:, 1] == path[i][0]), 5]
if(full > -3 and comfort > -3):
if(len(path) == 22):
if(path not in all_paths):
all_paths.append(path)
return 1
else:
return 0
def compute(all_paths):
for w in range(len(all_paths)):
thispath = all_paths[w]
print('**********************************************')
print(len(thispath))
print(thispath)
path = thispath
full = 10
comfort = 10
for i in range(1, len(thispath)):
distance = getDist(path[i], path[i - 1])
full = full - (np.sign(path[i][2] - path[i-1][2]) + 5) * distance / 100
comfort = comfort - (np.sign(path[i][2] - path[i-1][2]) + 5) * distance / 100
print(full, comfort)
if(content[np.where(content[:, 1] == path[i][0]), 4] == 0):
comfort = comfort + content[np.where(content[:, 1] == path[i][0]), 5]
else:
full = full + content[np.where(content[:, 1] == path[i][0]), 5]
print(full, comfort)
if __name__ == '__main__':
all_paths = []
workbook = open_workbook(r'附件.xlsx')
sheet = workbook.sheet_by_index(0)
content = np.array([sheet.row_values(i) for i in range(1, 589)])
path = [[0, 500, 500], [49.2701, 501.378, 474.378], [66.4539, 493.45, 485.579], [205.93, 530.015, 462.304], [325.373, 562.813, 450.432], [341.06, 554.258, 440.06], [396.166, 557.686, 463.285], [414.847, 550.557, 458.839], [432.744, 544.693, 464.194], [466.047, 540.082, 447.639], [497.857, 539.374, 473.068], [518.037, 544.067, 478.518], [594.039, 532.547, 476.9], [649.996, 543.743, 471.353], [668.799, 533.409, 475.24], [686.951, 534.936, 468.021], [703.063, 520.512, 467.263], [739.278, 513.132, 452.663], [758.889, 512.304, 450.352], [803.157, 544.765, 446.707], [866.403, 557.739, 448.524], [904.524, 552.094, 445.804], [965.271, 559.438, 441.67], [979.678, 552.128, 452.517], [1000, 555.67, 442.022]]
for k in range(0, len(path) - 2):
index1 = int(np.where(content[:, 1] == path[k][0])[0]) + 1
index2 = int(np.where(content[:, 1] == path[k + 2][0])[0])
change_nodes = content[index1:index2, 1:4].tolist()
for j in range(len(change_nodes)):
path_copy1 = path.copy()
path_copy1[k+1] = change_nodes[j]
flag = judge_path(path_copy1)
if(flag == 0):
continue
for z in range(1, len(path_copy1) - 1):
pathj = path_copy1.copy()
del pathj[z]
flag = judge_path(pathj)
if(flag == 0):
continue
for a in range(1, len(pathj) - 1):
patha = pathj.copy()
del patha[a]
flag = judge_path(patha)
if(flag == 0):
continue
for b in range(1, len(patha) - 1):
pathb = patha.copy()
del pathb[b]
judge_path(pathb)
if(flag == 0):
continue
print('************************************************************')
for i in all_paths:
print(i)
print(len(all_paths))
compute(all_paths)

View File

@ -3,6 +3,6 @@ python2.7 leader.py $1 $2 &
uav_num=1
while(( $uav_num< $2 ))
do
python2.7 follower_consensus.py $1 $uav_num $2&
python2.7 follower.py $1 $uav_num $2&
let "uav_num++"
done