cys changes src

pull/6/head
cys 10 months ago
parent e861d1e9b7
commit ba53d6fbc2

@ -1,4 +1,5 @@
#
Eazzy in the house
geekChen will carry
geekChen will carry
# 2024.5.5 aircraft src submit

@ -1,118 +0,0 @@
cmake_minimum_required(VERSION 2.8.3)
project(prometheus_experiment)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
message_generation
roscpp
geometry_msgs
nav_msgs
sensor_msgs
mavros
std_msgs
std_srvs
tf2_ros
tf2_eigen
mavros_msgs
prometheus_msgs
)
## System dependencies are found with CMake's conventions
find_package(Boost REQUIRED COMPONENTS system)
################################################
## Declare ROS messages, services and actions ##
################################################
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
geometry_msgs
nav_msgs
sensor_msgs
std_msgs
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
include
${catkin_INCLUDE_DIRS}
)
###############################
## cpp ##
###############################
###### Main File ##########
##px4_pos_controller.cpp
#add_executable(px4_pos_controller src/px4_pos_controller.cpp)
#add_dependencies(px4_pos_controller prometheus_control_gencpp)
#target_link_libraries(px4_pos_controller ${catkin_LIBRARIES})
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark cpp header files for installation
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
)
## Mark other files for installation (e.g. launch and bag files, etc.)
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
)
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_prometheus_control.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

@ -1,260 +0,0 @@
# Common configuration for PX4 autopilot
#
# node:
startup_px4_usb_quirk: true
# --- system plugins ---
# sys_status & sys_time connection options
conn:
heartbeat_rate: 1.0 # send hertbeat rate in Hertz
timeout: 10.0 # hertbeat timeout in seconds
timesync_rate: 10.0 # TIMESYNC rate in Hertz (feature disabled if 0.0)
system_time_rate: 1.0 # send system time to FCU rate in Hertz (disabled if 0.0)
# sys_status
sys:
min_voltage: 10.0 # diagnostics min voltage
disable_diag: false # disable all sys_status diagnostics, except heartbeat
# sys_time
time:
time_ref_source: "fcu" # time_reference source
timesync_mode: MAVLINK
timesync_avg_alpha: 0.6 # timesync averaging factor
# --- mavros plugins (alphabetical order) ---
# 3dr_radio
tdr_radio:
low_rssi: 40 # raw rssi lower level for diagnostics
# actuator_control
# None
# command
cmd:
use_comp_id_system_control: false # quirk for some old FCUs
# dummy
# None
# ftp
# None
# global_position
global_position:
frame_id: "map" # origin frame
child_frame_id: "base_link" # body-fixed frame
rot_covariance: 99999.0 # covariance for attitude?
gps_uere: 1.0 # User Equivalent Range Error (UERE) of GPS sensor (m)
use_relative_alt: true # use relative altitude for local coordinates
tf:
send: false # send TF?
frame_id: "map" # TF frame_id
global_frame_id: "earth" # TF earth frame_id
child_frame_id: "base_link" # TF child_frame_id
# imu_pub
imu:
frame_id: "base_link"
# need find actual values
linear_acceleration_stdev: 0.0003
angular_velocity_stdev: 0.0003490659 // 0.02 degrees
orientation_stdev: 1.0
magnetic_stdev: 0.0
# local_position
local_position:
frame_id: "world"
tf:
send: true
frame_id: "world"
child_frame_id: "base_link"
send_fcu: false
# param
# None, used for FCU params
# rc_io
# None
# safety_area
safety_area:
p1: {x: 1.0, y: 1.0, z: 1.0}
p2: {x: -1.0, y: -1.0, z: -1.0}
# setpoint_accel
setpoint_accel:
send_force: false
# setpoint_attitude
setpoint_attitude:
reverse_thrust: false # allow reversed thrust
use_quaternion: false # enable PoseStamped topic subscriber
tf:
listen: false # enable tf listener (disable topic subscribers)
frame_id: "map"
child_frame_id: "target_attitude"
rate_limit: 50.0
setpoint_raw:
thrust_scaling: 1.0 # used in setpoint_raw attitude callback.
# Note: PX4 expects normalized thrust values between 0 and 1, which means that
# the scaling needs to be unitary and the inputs should be 0..1 as well.
# setpoint_position
setpoint_position:
tf:
listen: false # enable tf listener (disable topic subscribers)
frame_id: "map"
child_frame_id: "target_position"
rate_limit: 50.0
mav_frame: LOCAL_NED
# setpoint_velocity
setpoint_velocity:
mav_frame: LOCAL_NED
# vfr_hud
# None
# waypoint
mission:
pull_after_gcs: true # update mission if gcs updates
# --- mavros extras plugins (same order) ---
# adsb
# None
# debug_value
# None
# distance_sensor
## Currently available orientations:
# Check http://wiki.ros.org/mavros/Enumerations
##
distance_sensor:
hrlv_ez4_pub:
id: 0
frame_id: "hrlv_ez4_sonar"
orientation: PITCH_270 # RPY:{0.0, 270.0, 0.0} - downward-facing
field_of_view: 0.0 # XXX TODO
send_tf: true
sensor_position: {x: 0.0, y: 0.0, z: -0.1}
lidarlite_pub:
id: 1
frame_id: "lidarlite_laser"
orientation: PITCH_270
field_of_view: 0.0 # XXX TODO
send_tf: true
sensor_position: {x: 0.0, y: 0.0, z: -0.1}
sonar_1_sub:
subscriber: true
id: 2
orientation: PITCH_270
laser_1_sub:
subscriber: true
id: 3
orientation: PITCH_270
# image_pub
image:
frame_id: "px4flow"
# fake_gps
fake_gps:
# select data source
use_mocap: true # ~mocap/pose
mocap_transform: true # ~mocap/tf instead of pose
use_vision: false # ~vision (pose)
# origin (default: Zürich)
geo_origin:
lat: 47.3667 # latitude [degrees]
lon: 8.5500 # longitude [degrees]
alt: 408.0 # altitude (height over the WGS-84 ellipsoid) [meters]
eph: 2.0
epv: 2.0
satellites_visible: 5 # virtual number of visible satellites
fix_type: 3 # type of GPS fix (default: 3D)
tf:
listen: false
send: false # send TF?
frame_id: "map" # TF frame_id
child_frame_id: "fix" # TF child_frame_id
rate_limit: 10.0 # TF rate
gps_rate: 5.0 # GPS data publishing rate
# landing_target
landing_target:
listen_lt: false
mav_frame: "LOCAL_NED"
land_target_type: "VISION_FIDUCIAL"
image:
width: 640 # [pixels]
height: 480
camera:
fov_x: 2.0071286398 # default: 115 [degrees]
fov_y: 2.0071286398
tf:
send: true
listen: false
frame_id: "landing_target"
child_frame_id: "camera_center"
rate_limit: 10.0
target_size: {x: 0.3, y: 0.3}
# mocap_pose_estimate
mocap:
# select mocap source
use_tf: false # ~mocap/tf
use_pose: true # ~mocap/pose
# odom
odometry:
fcu:
odom_parent_id_des: "map" # desired parent frame rotation of the FCU's odometry
odom_child_id_des: "base_link" # desired child frame rotation of the FCU's odometry
# px4flow
px4flow:
frame_id: "px4flow"
ranger_fov: 0.118682 # 6.8 degrees at 5 meters, 31 degrees at 1 meter
ranger_min_range: 0.3 # meters
ranger_max_range: 5.0 # meters
# vision_pose_estimate
vision_pose:
tf:
listen: false # enable tf listener (disable topic subscribers)
frame_id: "map"
child_frame_id: "vision_estimate"
rate_limit: 10.0
# vision_speed_estimate
vision_speed:
listen_twist: true # enable listen to twist topic, else listen to vec3d topic
twist_cov: true # enable listen to twist with covariance topic
# vibration
vibration:
frame_id: "base_link"
# wheel_odometry
wheel_odometry:
count: 2 # number of wheels to compute odometry
use_rpm: false # use wheel's RPM instead of cumulative distance to compute odometry
wheel0: {x: 0.0, y: -0.15, radius: 0.05} # x-, y-offset (m,NED) and radius (m)
wheel1: {x: 0.0, y: 0.15, radius: 0.05} # x-, y-offset (m,NED) and radius (m)
send_raw: true # send wheel's RPM and cumulative distance (~/wheel_odometry/rpm, ~/wheel_odometry/distance)
send_twist: false # send geometry_msgs/TwistWithCovarianceStamped instead of nav_msgs/Odometry
frame_id: "map" # origin frame
child_frame_id: "base_link" # body-fixed frame
vel_error: 0.1 # wheel velocity measurement error 1-std (m/s)
tf:
send: false
frame_id: "map"
child_frame_id: "base_link"
# vim:set ts=2 sw=2 et:

@ -1,33 +0,0 @@
plugin_blacklist:
- actuator_control
- adsb
- safety_area
- 3dr_radio
- cam_imu_sync
- altitude
- distance_sensor
- fake_gps
- gps_rtk
- hil
- home_position
- landing_target
- mocap_pose_estimate
- mount_control
- obstacle_distance
- rc_io
- vfr_hud
- waypoint
- wind_estimation
- px4flow
- global_position
- companion_process_status
- debug_value
- wheel_odometry
- vibration
- odom
- setpoint_attitude
- setpoint_position
- setpoint_accel
- setpoint_velocity
plugin_whitelist: []
#- 'sys_*'

@ -1,18 +0,0 @@
## parameter for px4_sender.cpp
## 起飞高度,建议设置小一点
## 2020.11.04测试发现飞机起飞有较大超调,未发现原因,但起飞后控制正常
Takeoff_height : 0.5
## 降落速度
Land_speed : 0.2
## 上锁高度
Disarm_height : 0.25
## 地理围栏,根据实际情况设置
geo_fence:
x_min: -100
x_max: 100
y_min: -100
y_max: 100
z_min: -100.0
z_max: 100.0

@ -1,21 +0,0 @@
Controller_Test:
Circle:
Center_x: 0.0
Center_y: 0.0
Center_z: 0.8
circle_radius: 1.5 ## m 半径越小越难追踪
linear_vel: 0.2 ## m/s 速度越大越难追踪
direction: 1.0 ##direction = 1 for CCW 逆时针, direction = -1 for CW 顺时针
Eight:
Center_x: 0.0
Center_y: 0.0
Center_z: 1.0
radial: 2.0 ## m 半径越小越难追踪
omega: 0.3 ## rad/s 角速度越大越难追踪
Step:
step_length: 2.0 ## m 长度越大越难追踪
step_interval: 5.0

@ -1,397 +0,0 @@
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /全局规划1/Reference_Path1
Splitter Ratio: 0.5617647171020508
Tree Height: 663
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /3D Nav Goal1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: PointCloud2
Preferences:
PromptSaveOnExit: true
Toolbars:
toolButtonStyle: 2
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 20
Reference Frame: <Fixed Frame>
Value: true
- Class: rviz/TF
Enabled: true
Frame Timeout: 15
Frames:
All Enabled: false
base_link:
Value: false
base_link_frd:
Value: false
lidar_link:
Value: false
map:
Value: false
map_ned:
Value: false
odom:
Value: false
odom_ned:
Value: false
world:
Value: true
Marker Scale: 1
Name: TF
Show Arrows: true
Show Axes: true
Show Names: true
Tree:
base_link:
base_link_frd:
{}
lidar_link:
{}
world:
map:
map_ned:
{}
Update Interval: 0
Value: true
- Class: rviz/Group
Displays:
- Alpha: 1
Axes Length: 1
Axes Radius: 0.10000000149011612
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Drone_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 1
Buffer Length: 30
Class: rviz/Path
Color: 255; 25; 0
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.029999999329447746
Name: Drone_Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.5
Axes Radius: 0.15000000596046448
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Reference_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /prometheus/control/ref_pose_rviz
Unreliable: false
Value: true
Enabled: true
Name: 无人机状态
- Class: rviz/Group
Displays:
- Class: octomap_rviz_plugin/OccupancyGrid
Enabled: true
Max. Height Display: 3.4028234663852886e+38
Max. Octree Depth: 16
Min. Height Display: -3.4028234663852886e+38
Name: OccupancyGrid
Octomap Topic: /octomap_full
Queue Size: 5
Value: true
Voxel Alpha: 1
Voxel Coloring: Z-Axis
Voxel Rendering: Occupied Voxels
- Alpha: 1
Autocompute Intensity Bounds: true
Autocompute Value Bounds:
Max Value: 10
Min Value: -10
Value: true
Axis: Z
Channel Name: intensity
Class: rviz/PointCloud2
Color: 255; 255; 255
Color Transformer: FlatColor
Decay Time: 0
Enabled: true
Invert Rainbow: false
Max Color: 255; 255; 255
Max Intensity: 0
Min Color: 0; 0; 0
Min Intensity: 0
Name: PointCloud2
Position Transformer: XYZ
Queue Size: 10
Selectable: true
Size (Pixels): 3
Size (m): 0.019999999552965164
Style: Flat Squares
Topic: /octomap_point_cloud_centers
Unreliable: false
Use Fixed Frame: true
Use rainbow: true
Value: true
Enabled: true
Name: Octomap建图
- Class: rviz/Group
Displays:
- Alpha: 1
Autocompute Intensity Bounds: true
Autocompute Value Bounds:
Max Value: 2.0094945430755615
Min Value: -0.19618161022663116
Value: true
Axis: Z
Channel Name: intensity
Class: rviz/PointCloud2
Color: 238; 238; 236
Color Transformer: FlatColor
Decay Time: 0
Enabled: true
Invert Rainbow: false
Max Color: 255; 255; 255
Max Intensity: 4096
Min Color: 0; 0; 0
Min Intensity: 0
Name: Realsense_Global_PCL
Position Transformer: XYZ
Queue Size: 10
Selectable: true
Size (Pixels): 5
Size (m): 0.019999999552965164
Style: Flat Squares
Topic: /rtabmap/cloud_map
Unreliable: false
Use Fixed Frame: true
Use rainbow: true
Value: true
- Alpha: 1
Buffer Length: 1
Class: rviz/Path
Color: 252; 233; 79
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.07999999821186066
Name: Reference_Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /prometheus/global_planner/path_cmd
Unreliable: false
Value: true
Enabled: true
Name: 全局规划
- Alpha: 1
Autocompute Intensity Bounds: true
Autocompute Value Bounds:
Max Value: 10
Min Value: -10
Value: true
Axis: Z
Channel Name: intensity
Class: rviz/PointCloud2
Color: 245; 121; 0
Color Transformer: FlatColor
Decay Time: 0
Enabled: true
Invert Rainbow: false
Max Color: 255; 255; 255
Max Intensity: 0
Min Color: 0; 0; 0
Min Intensity: 0
Name: PointCloud2
Position Transformer: XYZ
Queue Size: 10
Selectable: true
Size (Pixels): 3
Size (m): 0.009999999776482582
Style: Flat Squares
Topic: /prometheus/sensors/pcl2
Unreliable: false
Use Fixed Frame: true
Use rainbow: true
Value: true
- Alpha: 1
Autocompute Intensity Bounds: true
Autocompute Value Bounds:
Max Value: 10
Min Value: -10
Value: true
Axis: Z
Channel Name: intensity
Class: rviz/LaserScan
Color: 239; 41; 41
Color Transformer: FlatColor
Decay Time: 0
Enabled: true
Invert Rainbow: false
Max Color: 255; 255; 255
Max Intensity: 0
Min Color: 0; 0; 0
Min Intensity: 0
Name: LaserScan
Position Transformer: XYZ
Queue Size: 10
Selectable: true
Size (Pixels): 3
Size (m): 0.009999999776482582
Style: Flat Squares
Topic: /prometheus/sensors/2Dlidar_scan
Unreliable: false
Use Fixed Frame: true
Use rainbow: true
Value: true
- Alpha: 1
Autocompute Intensity Bounds: true
Autocompute Value Bounds:
Max Value: 10
Min Value: -10
Value: true
Axis: Z
Channel Name: intensity
Class: rviz/PointCloud2
Color: 255; 255; 255
Color Transformer: Intensity
Decay Time: 0
Enabled: false
Invert Rainbow: false
Max Color: 255; 255; 255
Max Intensity: 4096
Min Color: 0; 0; 0
Min Intensity: 0
Name: PointCloud2
Position Transformer: XYZ
Queue Size: 10
Selectable: true
Size (Pixels): 3
Size (m): 0.009999999776482582
Style: Flat Squares
Topic: /planning/global_inflate_cloud
Unreliable: false
Use Fixed Frame: true
Use rainbow: true
Value: false
Enabled: true
Global Options:
Background Color: 48; 48; 48
Default Light: true
Fixed Frame: base_link
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz_plugins/Goal3DTool
Topic: /prometheus/planning/goal
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 18.588502883911133
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: -2.3272345066070557
Y: -2.687499761581421
Z: 4.139807224273682
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 0.42520231008529663
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 3.0588293075561523
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 960
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd00000004000000000000018200000322fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d00000322000000c900fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007300000002500000012f0000005c00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000342fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073000000003d00000342000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000007800000003efc0100000002fb0000000800540069006d0065010000000000000780000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000005f80000032200000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1920
X: 0
Y: 27

@ -1,233 +0,0 @@
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
Splitter Ratio: 0.5
Tree Height: 455
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: ""
Preferences:
PromptSaveOnExit: true
Toolbars:
toolButtonStyle: 2
Visualization Manager:
Class: ""
Displays:
- Class: rviz/TF
Enabled: true
Frame Timeout: 15
Frames:
All Enabled: true
base_link:
Value: true
base_link_frd:
Value: true
map:
Value: true
map_ned:
Value: true
odom:
Value: true
odom_ned:
Value: true
uav3:
Value: true
world:
Value: true
Marker Scale: 1
Name: TF
Show Arrows: true
Show Axes: true
Show Names: true
Tree:
map:
map_ned:
{}
world:
base_link:
base_link_frd:
{}
uav3:
{}
Update Interval: 0
Value: true
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: <Fixed Frame>
Value: true
- Alpha: 1
Axes Length: 1
Axes Radius: 0.10000000149011612
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Drone_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.5
Axes Radius: 0.15000000596046448
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Ref_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /prometheus/control/ref_pose_rviz
Unreliable: false
Value: true
- Alpha: 1
Buffer Length: 30
Class: rviz/Path
Color: 255; 25; 0
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.029999999329447746
Name: Drone_Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Buffer Length: 1
Class: rviz/Path
Color: 25; 255; 0
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.05000000074505806
Name: Ref_Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /prometheus/reference_trajectory
Unreliable: false
Value: true
Enabled: true
Global Options:
Background Color: 48; 48; 48
Default Light: true
Fixed Frame: world
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
- Class: rviz/SetInitialPose
Theta std deviation: 0.2617993950843811
Topic: /initialpose
X std deviation: 0.5
Y std deviation: 0.5
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
Single click: true
Topic: /clicked_point
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 8.334606170654297
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: -1.1448005437850952
Y: 1.7814745903015137
Z: -0.4501960873603821
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 0.37539833784103394
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 0.84539794921875
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 752
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd00000004000000000000019d00000252fc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d00000252000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f00000252fc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d00000252000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000005a00000003efc0100000002fb0000000800540069006d00650100000000000005a0000002eb00fffffffb0000000800540069006d00650100000000000004500000000000000000000002e80000025200000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1440
X: 445
Y: 186

@ -1,148 +0,0 @@
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
Splitter Ratio: 0.4355083405971527
Tree Height: 465
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: Fisheye1_Image
Preferences:
PromptSaveOnExit: true
Toolbars:
toolButtonStyle: 2
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: <Fixed Frame>
Value: true
- Class: rviz/Image
Enabled: true
Image Topic: /camera_t265/fisheye1/image_raw
Max Value: 1
Median window: 5
Min Value: 0
Name: Fisheye1_Image
Normalize Range: true
Queue Size: 2
Transport Hint: raw
Unreliable: false
Value: true
- Class: rviz/Image
Enabled: true
Image Topic: /camera_t265/fisheye2/image_raw
Max Value: 1
Median window: 5
Min Value: 0
Name: Fisheye2_Image
Normalize Range: true
Queue Size: 2
Transport Hint: raw
Unreliable: false
Value: true
Enabled: true
Global Options:
Background Color: 48; 48; 48
Default Light: true
Fixed Frame: camera_t265_link
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
- Class: rviz/SetInitialPose
Theta std deviation: 0.2617993950843811
Topic: /initialpose
X std deviation: 0.5
Y std deviation: 0.5
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
Single click: true
Topic: /clicked_point
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 11.76508617401123
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: 0
Y: 0
Z: 0
Focal Shape Fixed Size: true
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 0.3153980076313019
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 5.6985650062561035
Saved: ~
Window Geometry:
Displays:
collapsed: false
Fisheye1_Image:
collapsed: false
Fisheye2_Image:
collapsed: false
Height: 1306
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd0000000400000000000001970000047cfc020000000dfb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003d0000025c000000c900fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261fb0000000a0049006d0061006700650100000269000000870000000000000000fb0000000c00430061006d0065007200610100000203000000ed0000000000000000fb0000000c00430061006d00650072006100000001a7000000870000000000000000fb0000001c00460069007300680065007900650031005f0049006d006100670065010000029f000001120000001600fffffffb0000001c00460069007300680065007900650032005f0049006d00610067006501000003b7000001020000001600ffffff000000010000010f0000047cfc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003d0000047c000000a400fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000005000000003efc0100000002fb0000000800540069006d0065010000000000000500000002eb00fffffffb0000000800540069006d006501000000000000045000000000000000000000024e0000047c00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1280
X: 1280
Y: 27

@ -1,405 +0,0 @@
Panels:
- Class: rviz/Displays
Help Height: 78
Name: Displays
Property Tree Widget:
Expanded:
- /Global Options1
- /Status1
Splitter Ratio: 0.5
Tree Height: 546
- Class: rviz/Selection
Name: Selection
- Class: rviz/Tool Properties
Expanded:
- /2D Pose Estimate1
- /2D Nav Goal1
- /Publish Point1
Name: Tool Properties
Splitter Ratio: 0.5886790156364441
- Class: rviz/Views
Expanded:
- /Current View1
Name: Views
Splitter Ratio: 0.5
- Class: rviz/Time
Experimental: false
Name: Time
SyncMode: 0
SyncSource: ""
Preferences:
PromptSaveOnExit: true
Toolbars:
toolButtonStyle: 2
Visualization Manager:
Class: ""
Displays:
- Alpha: 0.5
Cell Size: 1
Class: rviz/Grid
Color: 160; 160; 164
Enabled: true
Line Style:
Line Width: 0.029999999329447746
Value: Lines
Name: Grid
Normal Cell Count: 0
Offset:
X: 0
Y: 0
Z: 0
Plane: XY
Plane Cell Count: 10
Reference Frame: <Fixed Frame>
Value: true
- Class: rviz/Group
Displays:
- Alpha: 1
Axes Length: 1
Axes Radius: 0.20000000298023224
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav1/mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 2
Buffer Length: 1
Class: rviz/Path
Color: 25; 255; 0
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.05000000074505806
Name: Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /uav1/prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.699999988079071
Axes Radius: 0.25
Class: rviz/Pose
Color: 255; 25; 0
Enabled: false
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Ref_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav1/prometheus/control/ref_pose_rviz
Unreliable: false
Value: false
Enabled: true
Name: UAV1
- Class: rviz/Group
Displays:
- Alpha: 1
Axes Length: 1
Axes Radius: 0.20000000298023224
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav2/mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 2
Buffer Length: 1
Class: rviz/Path
Color: 0; 0; 255
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.05000000074505806
Name: Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /uav2/prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.699999988079071
Axes Radius: 0.25
Class: rviz/Pose
Color: 255; 25; 0
Enabled: false
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Ref_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav2/prometheus/control/ref_pose_rviz
Unreliable: false
Value: false
Enabled: true
Name: UAV2
- Class: rviz/Group
Displays:
- Alpha: 1
Axes Length: 1
Axes Radius: 0.20000000298023224
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav3/mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 2
Buffer Length: 1
Class: rviz/Path
Color: 0; 255; 255
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.05000000074505806
Name: Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /uav3/prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.699999988079071
Axes Radius: 0.25
Class: rviz/Pose
Color: 255; 25; 0
Enabled: false
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Ref_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav3/prometheus/control/ref_pose_rviz
Unreliable: false
Value: false
Enabled: true
Name: UAV3
- Class: rviz/Group
Displays:
- Alpha: 1
Axes Length: 1
Axes Radius: 0.20000000298023224
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav4/mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 2
Buffer Length: 1
Class: rviz/Path
Color: 255; 255; 0
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.05000000074505806
Name: Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /uav4/prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.699999988079071
Axes Radius: 0.25
Class: rviz/Pose
Color: 255; 25; 0
Enabled: false
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Ref_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav4/prometheus/control/ref_pose_rviz
Unreliable: false
Value: false
Enabled: true
Name: UAV4
- Class: rviz/Group
Displays:
- Alpha: 1
Axes Length: 1
Axes Radius: 0.20000000298023224
Class: rviz/Pose
Color: 255; 25; 0
Enabled: true
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav5/mavros/local_position/pose
Unreliable: false
Value: true
- Alpha: 2
Buffer Length: 1
Class: rviz/Path
Color: 0; 85; 0
Enabled: true
Head Diameter: 0.30000001192092896
Head Length: 0.20000000298023224
Length: 0.30000001192092896
Line Style: Billboards
Line Width: 0.05000000074505806
Name: Path
Offset:
X: 0
Y: 0
Z: 0
Pose Color: 255; 85; 255
Pose Style: None
Radius: 0.029999999329447746
Shaft Diameter: 0.10000000149011612
Shaft Length: 0.10000000149011612
Topic: /uav5/prometheus/drone_trajectory
Unreliable: false
Value: true
- Alpha: 1
Axes Length: 0.699999988079071
Axes Radius: 0.25
Class: rviz/Pose
Color: 255; 25; 0
Enabled: false
Head Length: 0.30000001192092896
Head Radius: 0.10000000149011612
Name: Ref_Pose
Shaft Length: 1
Shaft Radius: 0.05000000074505806
Shape: Axes
Topic: /uav5/prometheus/control/ref_pose_rviz
Unreliable: false
Value: false
Enabled: true
Name: UAV5
Enabled: true
Global Options:
Background Color: 48; 48; 48
Default Light: true
Fixed Frame: world
Frame Rate: 30
Name: root
Tools:
- Class: rviz/Interact
Hide Inactive Objects: true
- Class: rviz/MoveCamera
- Class: rviz/Select
- Class: rviz/FocusCamera
- Class: rviz/Measure
- Class: rviz/SetInitialPose
Theta std deviation: 0.2617993950843811
Topic: /initialpose
X std deviation: 0.5
Y std deviation: 0.5
- Class: rviz/SetGoal
Topic: /move_base_simple/goal
- Class: rviz/PublishPoint
Single click: true
Topic: /clicked_point
Value: true
Views:
Current:
Class: rviz/Orbit
Distance: 34.19184112548828
Enable Stereo Rendering:
Stereo Eye Separation: 0.05999999865889549
Stereo Focal Distance: 1
Swap Stereo Eyes: false
Value: false
Focal Point:
X: 1.4970207214355469
Y: 0.133266419172287
Z: -1.1527864933013916
Focal Shape Fixed Size: false
Focal Shape Size: 0.05000000074505806
Invert Z Axis: false
Name: Current View
Near Clip Distance: 0.009999999776482582
Pitch: 1.5697963237762451
Target Frame: <Fixed Frame>
Value: Orbit (rviz)
Yaw: 3.1504018306732178
Saved: ~
Window Geometry:
Displays:
collapsed: false
Height: 846
Hide Left Dock: false
Hide Right Dock: false
QMainWindow State: 000000ff00000000fd000000040000000000000156000002aefc0200000008fb0000001200530065006c0065006300740069006f006e00000001e10000009b0000005c00fffffffb0000001e0054006f006f006c002000500072006f007000650072007400690065007302000001ed000001df00000185000000a3fb000000120056006900650077007300200054006f006f02000001df000002110000018500000122fb000000200054006f006f006c002000500072006f0070006500720074006900650073003203000002880000011d000002210000017afb000000100044006900730070006c006100790073010000003e000002ae000000ca00fffffffb0000002000730065006c0065006300740069006f006e00200062007500660066006500720200000138000000aa0000023a00000294fb00000014005700690064006500530074006500720065006f02000000e6000000d2000003ee0000030bfb0000000c004b0069006e0065006300740200000186000001060000030c00000261000000010000010f000002aefc0200000003fb0000001e0054006f006f006c002000500072006f00700065007200740069006500730100000041000000780000000000000000fb0000000a00560069006500770073010000003e000002ae000000a600fffffffb0000001200530065006c0065006300740069006f006e010000025a000000b200000000000000000000000200000490000000a9fc0100000001fb0000000a00560069006500770073030000004e00000080000002e10000019700000003000004b00000003efc0100000002fb0000000800540069006d00650100000000000004b00000026200fffffffb0000000800540069006d006501000000000000045000000000000000000000023f000002ae00000004000000040000000800000008fc0000000100000002000000010000000a0054006f006f006c00730100000000ffffffff0000000000000000
Selection:
collapsed: false
Time:
collapsed: false
Tool Properties:
collapsed: false
Views:
collapsed: false
Width: 1200
X: 60
Y: 27

@ -1,23 +0,0 @@
<!-- 本launch为使用px4_sender进行机载控制时的地面端启动脚本 -->
<!-- 硬件清单 -->
<launch>
<!-- run the ground_station.cpp -->
<node pkg="prometheus_station" type="ground_station" name="ground_station" output="screen" launch-prefix="gnome-terminal --tab --">
</node>
<!-- run the ground_station_msg.cpp -->
<node pkg="prometheus_station" type="ground_station_msg" name="ground_station_msg" output="screen" launch-prefix="gnome-terminal --tab --">
</node>
<!-- run the terminal_control.cpp -->
<node pkg="prometheus_control" type="terminal_control" name="terminal_control" output="screen" launch-prefix="gnome-terminal --">
<rosparam command="load" file="$(find prometheus_experiment)/config/prometheus_control_config/terminal_control.yaml" />
</node>
<!-- run the rviz -->
<arg name="visualization" default="true"/>
<group if="$(arg visualization)">
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find prometheus_experiment)/config/rviz_config/rviz_controller_test.rviz" />
</group>
</launch>

@ -1,34 +0,0 @@
<!-- 本launch为使用px4_sender进行机载控制时的机载端启动脚本 -->
<launch>
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen">
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<param name="fcu_url" value="/dev/ttyUSB0:921600" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
<!-- vrpn -->
<include file="$(find vrpn_client_ros)/launch/sample.launch">
<arg name="server" value="192.168.1.2"/>
</include>
<!-- run the px4_pos_estimator.cpp -->
<node pkg="prometheus_control" type="px4_pos_estimator" name="px4_pos_estimator" output="screen">
<!-- 0 for vicon 1 for 激光SLAM, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="UAV"/>
<param name="rate_hz" value="20.0"/>
</node>
<!-- run the px4_sender.cpp -->
<node pkg="prometheus_control" type="px4_sender" name="px4_sender" output="screen">
<rosparam command="load" file="$(find prometheus_experiment)/config/prometheus_control_config/px4_sender.yaml"/>
</node>
</launch>

@ -1,56 +0,0 @@
<!-- 本launch为使用px4_sender进行地面远程控制时的启动脚本 -->
<!-- 无人机仅配备数传及飞控,不配备机载电脑 -->
<!-- 硬件清单 -->
<launch>
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.104:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
<!-- vrpn -->
<include file="$(find vrpn_client_ros)/launch/sample.launch">
<arg name="server" value="192.168.1.2"/>
</include>
<!-- run the px4_pos_estimator.cpp -->
<node pkg="prometheus_control" type="px4_pos_estimator" name="px4_pos_estimator" output="screen">
<!-- 0 for vicon 1 for 激光SLAM, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav3"/>
<!-- 运行频率建议不小于20HZ -->
<param name="rate_hz" value="50.0"/>
</node>
<!-- run the px4_sender.cpp -->
<node pkg="prometheus_control" type="px4_sender" name="px4_sender" output="screen">
<rosparam command="load" file="$(find prometheus_experiment)/config/prometheus_control_config/px4_sender.yaml"/>
</node>
<!-- run the ground_station.cpp -->
<node pkg="prometheus_station" type="ground_station" name="ground_station" output="screen" launch-prefix="gnome-terminal --tab --">
</node>
<!-- run the ground_station_msg.cpp -->
<node pkg="prometheus_station" type="ground_station_msg" name="ground_station_msg" output="screen" launch-prefix="gnome-terminal --tab --">
</node>
<!-- run the terminal_control.cpp -->
<node pkg="prometheus_control" type="terminal_control" name="terminal_control" output="screen" launch-prefix="gnome-terminal --">
<rosparam command="load" file="$(find prometheus_experiment)/config/prometheus_control_config/terminal_control.yaml" />
</node>
<!-- run the rviz -->
<arg name="visualization" default="false"/>
<group if="$(arg visualization)">
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find prometheus_experiment)/config/rviz_config/rviz_controller_test.rviz" />
</group>
</launch>

@ -1,47 +0,0 @@
<!-- 本launch为使用px4_sender进行机载控制时的机载端启动脚本 -->
<launch>
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen">
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<param name="fcu_url" value="/dev/ttyUSB0:921600" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
<!-- run the px4_pos_estimator.cpp -->
<node pkg="prometheus_control" type="fake_vicon" name="fake_vicon" output="screen">
</node>
<!-- run the px4_pos_estimator.cpp -->
<node pkg="prometheus_control" type="px4_pos_estimator" name="px4_pos_estimator" output="screen">
<!-- 0 for vicon 1 for 激光SLAM, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="UAV"/>
<param name="rate_hz" value="20.0"/>
</node>
<!-- run the px4_sender.cpp -->
<node pkg="prometheus_control" type="px4_sender" name="px4_sender" output="screen">
<rosparam command="load" file="$(find prometheus_experiment)/config/prometheus_control_config/px4_sender.yaml"/>
</node>
<!-- run the ground_station.cpp -->
<node pkg="prometheus_station" type="ground_station" name="ground_station" output="screen" launch-prefix="gnome-terminal --tab --">
</node>
<!-- run the ground_station_msg.cpp -->
<node pkg="prometheus_station" type="ground_station_msg" name="ground_station_msg" output="screen" launch-prefix="gnome-terminal --tab --">
</node>
<!-- run the terminal_control.cpp -->
<node pkg="prometheus_control" type="terminal_control" name="terminal_control" output="screen" launch-prefix="gnome-terminal --">
<rosparam command="load" file="$(find prometheus_experiment)/config/prometheus_control_config/terminal_control.yaml" />
</node>
</launch>

@ -1,213 +0,0 @@
<!-- 本launch文件适用于 仅配置WIFI数传及飞控的无人机 -->
<!-- 每个无人机通过VICON/GPS/UWB定位 -->
<!-- 每个无人机及地面电脑连接同一路由器 -->
<!-- 地面站统一给各个无人机发送控制指令,考虑到延时,只能使用位置或速度控制 -->
<!-- 硬件清单 -->
<launch>
<arg name="uav1_name" default="uav1"/>
<arg name="uav2_name" default="uav2"/>
<arg name="uav3_name" default="uav3"/>
<arg name="uav1_id" default="1"/>
<arg name="uav2_id" default="2"/>
<arg name="uav3_id" default="3"/>
<arg name="swarm_num" default="3"/>
<arg name="k_p" default="1.0"/>
<arg name="k_aij" default="0.05"/>
<arg name="k_gamma" default="1.2"/>
<arg name="Takeoff_height" default="0.4"/>
<arg name="Disarm_height" default="0.15"/>
<arg name="Land_speed" default="0.25"/>
<arg name="x_min" default="-2.5"/>
<arg name="x_max" default="2.5"/>
<arg name="y_min" default="-2.5"/>
<arg name="y_max" default="2.5"/>
<arg name="z_min" default="-1.0"/>
<arg name="z_max" default="1.5"/>
<!-- vrpn -->
<include file="$(find vrpn_client_ros)/launch/sample.launch">
<arg name="server" value="192.168.1.2"/>
</include>
<!-- 1号飞机 -->
<group ns="uav1">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.100:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- 2号飞机 -->
<group ns="uav2">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.103:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- 3号飞机 -->
<group ns="uav3">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.104:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav1" output="screen">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav1"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav1"/>
<!-- 运行频率建议不小于20HZ -->
<param name="rate_hz" value="50.0"/>
</node>
<!-- run the swarm_controller.cpp -->
<node pkg="prometheus_control" type="swarm_controller" name="swarm_controller_uav1" output="screen" launch-prefix="gnome-terminal --tab --">
<param name="swarm_num" value="$(arg swarm_num)"/>
<param name="uav_id" value="1"/>
<param name="neighbour_id1" value="2" />
<param name="neighbour_id2" value="3"/>
<param name="uav_name" value="/uav1"/>
<param name="neighbour_name1" value="/uav2" />
<param name="neighbour_name2" value="/uav3"/>
<param name="k_p" value="$(arg k_p)"/>
<param name="k_aij" value="$(arg k_aij)"/>
<param name="k_gamma" value="$(arg k_gamma)"/>
<param name="Takeoff_height" value="$(arg Takeoff_height)"/>
<param name="Disarm_height" value="$(arg Disarm_height)"/>
<param name="Land_speed" value="$(arg Land_speed)"/>
<param name="geo_fence/x_min" value="$(arg x_min)"/>
<param name="geo_fence/x_max" value="$(arg x_max)"/>
<param name="geo_fence/y_min" value="$(arg y_min)"/>
<param name="geo_fence/y_max" value="$(arg y_max)"/>
<param name="geo_fence/z_min" value="$(arg z_min)"/>
<param name="geo_fence/z_max" value="$(arg z_max)"/>
</node>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav2" output="screen">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav2"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav2"/>
<!-- 运行频率建议不小于20HZ -->
<param name="rate_hz" value="50.0"/>
</node>
<!-- run the swarm_controller.cpp -->
<node pkg="prometheus_control" type="swarm_controller" name="swarm_controller_uav2" output="screen" launch-prefix="gnome-terminal --tab --">
<param name="swarm_num" value="$(arg swarm_num)"/>
<param name="uav_id" value="2"/>
<param name="neighbour_id1" value="1" />
<param name="neighbour_id2" value="3"/>
<param name="uav_name" value="/uav2"/>
<param name="neighbour_name1" value="/uav1" />
<param name="neighbour_name2" value="/uav3"/>
<param name="k_p" value="$(arg k_p)"/>
<param name="k_aij" value="$(arg k_aij)"/>
<param name="k_gamma" value="$(arg k_gamma)"/>
<param name="Takeoff_height" value="$(arg Takeoff_height)"/>
<param name="Disarm_height" value="$(arg Disarm_height)"/>
<param name="Land_speed" value="$(arg Land_speed)"/>
<param name="geo_fence/x_min" value="$(arg x_min)"/>
<param name="geo_fence/x_max" value="$(arg x_max)"/>
<param name="geo_fence/y_min" value="$(arg y_min)"/>
<param name="geo_fence/y_max" value="$(arg y_max)"/>
<param name="geo_fence/z_min" value="$(arg z_min)"/>
<param name="geo_fence/z_max" value="$(arg z_max)"/>
</node>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav3" output="screen">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav3"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav3"/>
<!-- 运行频率建议不小于20HZ -->
<param name="rate_hz" value="50.0"/>
</node>
<!-- run the swarm_controller.cpp -->
<node pkg="prometheus_control" type="swarm_controller" name="swarm_controller_uav3" output="screen" launch-prefix="gnome-terminal --tab --">
<param name="swarm_num" value="$(arg swarm_num)"/>
<param name="uav_id" value="3"/>
<param name="neighbour_id1" value="1" />
<param name="neighbour_id2" value="2"/>
<param name="uav_name" value="/uav3"/>
<param name="neighbour_name1" value="/uav1" />
<param name="neighbour_name2" value="/uav2"/>
<param name="k_p" value="$(arg k_p)"/>
<param name="k_aij" value="$(arg k_aij)"/>
<param name="k_gamma" value="$(arg k_gamma)"/>
<param name="Takeoff_height" value="$(arg Takeoff_height)"/>
<param name="Disarm_height" value="$(arg Disarm_height)"/>
<param name="Land_speed" value="$(arg Land_speed)"/>
<param name="geo_fence/x_min" value="$(arg x_min)"/>
<param name="geo_fence/x_max" value="$(arg x_max)"/>
<param name="geo_fence/y_min" value="$(arg y_min)"/>
<param name="geo_fence/y_max" value="$(arg y_max)"/>
<param name="geo_fence/z_min" value="$(arg z_min)"/>
<param name="geo_fence/z_max" value="$(arg z_max)"/>
</node>
<node pkg="prometheus_control" type="swarm_ground_station" name="swarm_ground_station" output="screen" launch-prefix="gnome-terminal --">
<!-- 设置无人机ID才会在地面站显示 -->
<param name="swarm_num" value="3" />
<param name="uav1_name" value="/uav1" />
<param name="uav2_name" value="/uav2" />
<param name="uav3_name" value="/uav3" />
<param name="uav1_id" value="1" />
<param name="uav2_id" value="2" />
<param name="uav3_id" value="3" />
</node>
<node pkg="prometheus_mission" type="formation_flight" name="formation_flight" output="screen" launch-prefix="gnome-terminal --">
<!-- 0代表位置控制代表速度控制代表加速度控制 -->
<param name="controller_num" value="0"/>
<param name="virtual_leader_pos_x" value="0.0" />
<param name="virtual_leader_pos_y" value="0.0" />
<param name="virtual_leader_pos_z" value="0.6" />
<param name="virtual_leader_yaw" value="0.0" />
<param name="formation_size" value="1.2" />
</node>
<!-- run the rviz -->
<arg name="visualization" default="true"/>
<group if="$(arg visualization)">
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find prometheus_experiment)/config/rviz_config/swarm_rviz_config.rviz" />
</group>
</launch>

@ -1,207 +0,0 @@
<!-- 本launch文件适用于 仅配置WIFI数传及飞控的无人机 -->
<!-- 每个无人机通过VICON/GPS/UWB定位 -->
<!-- 每个无人机及地面电脑连接同一路由器 -->
<!-- 地面站统一给各个无人机发送控制指令,考虑到延时,只能使用位置或速度控制 -->
<launch>
<!-- 1号飞机 -->
<group ns="uav1">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.101:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav1" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav1"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav1"/>
</node>
<!-- 2号飞机 -->
<group ns="uav2">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.102:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav2" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav2"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav2"/>
</node>
<!-- 3号飞机 -->
<group ns="uav3">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.103:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav3" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav3"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav3"/>
</node>
<!-- 4号飞机 -->
<group ns="uav4">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.104:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav4" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav4"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav4"/>
</node>
<!-- 5号飞机 -->
<group ns="uav4">
<!-- 启动MAVROS -->
<!-- 不同机载电脑,注意修改fcu_url至正确的端口号及波特率 -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 与飞控连接方式,需要配置 -->
<param name="fcu_url" value="tcp://192.168.1.105:6000" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/config/mavros_config/px4_config.yaml" />
</node>
</group>
<!-- run the swarm_estimator.cpp -->
<node pkg="prometheus_control" type="swarm_estimator" name="swarm_estimator_uav5" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 0 for vicon, 2 for gazebo ground truth(仿真用) -->
<param name="input_source" value="0" />
<!-- 如果使用动作捕捉系统则指定刚体名称用于订阅vrpn节点发布的话题 -->
<param name="object_name" value="uav5"/>
<!-- 无人机名字,同 ns-->
<param name="uav_name" value="/uav5"/>
</node>
<!-- vrpn -->
<include file="$(find vrpn_client_ros)/launch/sample.launch">
<arg name="server" value="192.168.1.2"/>
</include>
<!-- to be continued, 到底是每个无人机启动一个控制节点,还是只启动一个控制节点? -->
<!-- run the swarm_controller.cpp -->
<arg name="swarm_num" default="5"/>
<arg name="k_p" default="1.0"/>
<arg name="k_aij" default="0.05"/>
<arg name="k_gamma" default="1.2"/>
<arg name="Takeoff_height" default="1.0"/>
<arg name="Disarm_height" default="0.1"/>
<arg name="Land_speed" default="0.2"/>
<arg name="x_min" default="-100.0"/>
<arg name="x_max" default="100.0"/>
<arg name="y_min" default="-100.0"/>
<arg name="y_max" default="100"/>
<arg name="z_min" default="-1.0"/>
<arg name="z_max" default="100.0"/>
<node pkg="prometheus_control" type="swarm_controller" name="swarm_controller_uav1" output="screen">
<param name="swarm_num" value="$(arg swarm_num)"/>
<param name="uav_id" value="1"/>
<param name="neighbour_id1" value="2" />
<param name="neighbour_id2" value="3"/>
<param name="uav_name" value="/uav1"/>
<param name="neighbour_name1" value="/uav2" />
<param name="neighbour_name2" value="/uav3"/>
<param name="k_p" value="$(arg k_p)"/>
<param name="k_aij" value="$(arg k_aij)"/>
<param name="k_gamma" value="$(arg k_gamma)"/>
<param name="Takeoff_height" value="$(arg Takeoff_height)"/>
<param name="Disarm_height" value="$(arg Disarm_height)"/>
<param name="Land_speed" value="$(arg Land_speed)"/>
<param name="geo_fence/x_min" value="$(arg x_min)"/>
<param name="geo_fence/x_max" value="$(arg x_max)"/>
<param name="geo_fence/y_min" value="$(arg y_min)"/>
<param name="geo_fence/y_max" value="$(arg y_max)"/>
<param name="geo_fence/z_min" value="$(arg z_min)"/>
<param name="geo_fence/z_max" value="$(arg z_max)"/>
</node>
<node pkg="prometheus_control" type="swarm_ground_station" name="swarm_ground_station" output="screen" launch-prefix="gnome-terminal --tab --">
<!-- 设置无人机名字才会在地面站显示 -->
<param name="uav_id" value="5" />
<param name="uav1_name" value="/none" />
<param name="uav2_name" value="/uav2" />
<param name="uav3_name" value="/uav3" />
<param name="uav4_name" value="/uav4" />
<param name="uav5_name" value="/uav5" />
<param name="uav1_id" value="1" />
<param name="uav2_id" value="2" />
<param name="uav3_id" value="3" />
<param name="uav4_id" value="4" />
<param name="uav5_id" value="5" />
</node>
<node pkg="prometheus_mission" type="formation_flight" name="formation_flight" output="screen" launch-prefix="gnome-terminal --">
<!-- 0代表位置控制代表速度控制代表加速度控制 -->
<param name="controller_num" value="0"/>
<param name="uav_id" value="5"/>
<param name="virtual_leader_pos_x" value="0.0" />
<param name="virtual_leader_pos_y" value="0.0" />
<param name="virtual_leader_pos_z" value="1.0" />
<param name="virtual_leader_yaw" value="0.0" />
<param name="formation_size" value="1.5" />
</node>
<!-- run the rviz -->
<arg name="visualization" default="true"/>
<group if="$(arg visualization)">
<node type="rviz" name="rviz" pkg="rviz" args="-d $(find prometheus_experiment)/config/rviz_config/swarm_rviz_config.rviz" />
</group>
</launch>

@ -1,257 +0,0 @@
# Common configuration for APM2 autopilot
#
# node:
startup_px4_usb_quirk: false
# --- system plugins ---
# sys_status & sys_time connection options
conn:
heartbeat_rate: 1.0 # send hertbeat rate in Hertz
heartbeat_mav_type: "ONBOARD_CONTROLLER"
timeout: 10.0 # hertbeat timeout in seconds
timesync_rate: 0.0 # TIMESYNC rate in Hertz (feature disabled if 0.0)
system_time_rate: 0.0 # send system time to FCU rate in Hertz (disabled if 0.0)
# sys_status
sys:
min_voltage: 10.0 # diagnostics min voltage
disable_diag: false # disable all sys_status diagnostics, except heartbeat
# sys_time
time:
time_ref_source: "fcu" # time_reference source
timesync_mode: MAVLINK
timesync_avg_alpha: 0.6 # timesync averaging factor
# --- mavros plugins (alphabetical order) ---
# 3dr_radio
tdr_radio:
low_rssi: 40 # raw rssi lower level for diagnostics
# actuator_control
# None
# command
cmd:
use_comp_id_system_control: false # quirk for some old FCUs
# dummy
# None
# ftp
# None
# global_position
global_position:
frame_id: "map" # origin frame
child_frame_id: "base_link" # body-fixed frame
rot_covariance: 99999.0 # covariance for attitude?
gps_uere: 1.0 # User Equivalent Range Error (UERE) of GPS sensor (m)
use_relative_alt: true # use relative altitude for local coordinates
tf:
send: false # send TF?
frame_id: "map" # TF frame_id
global_frame_id: "earth" # TF earth frame_id
child_frame_id: "base_link" # TF child_frame_id
# imu_pub
imu:
frame_id: "base_link"
# need find actual values
linear_acceleration_stdev: 0.0003
angular_velocity_stdev: 0.0003490659 // 0.02 degrees
orientation_stdev: 1.0
magnetic_stdev: 0.0
# local_position
local_position:
frame_id: "map"
tf:
send: false
frame_id: "map"
child_frame_id: "base_link"
send_fcu: false
# param
# None, used for FCU params
# rc_io
# None
# safety_area
safety_area:
p1: {x: 1.0, y: 1.0, z: 1.0}
p2: {x: -1.0, y: -1.0, z: -1.0}
# setpoint_accel
setpoint_accel:
send_force: false
# setpoint_attitude
setpoint_attitude:
reverse_thrust: false # allow reversed thrust
use_quaternion: false # enable PoseStamped topic subscriber
tf:
listen: false # enable tf listener (disable topic subscribers)
frame_id: "map"
child_frame_id: "target_attitude"
rate_limit: 50.0
# setpoint_raw
setpoint_raw:
thrust_scaling: 1.0 # specify thrust scaling (normalized, 0 to 1) for thrust (like PX4)
# setpoint_position
setpoint_position:
tf:
listen: false # enable tf listener (disable topic subscribers)
frame_id: "map"
child_frame_id: "target_position"
rate_limit: 50.0
mav_frame: LOCAL_NED
# setpoint_velocity
setpoint_velocity:
mav_frame: LOCAL_NED
# vfr_hud
# None
# waypoint
mission:
pull_after_gcs: true # update mission if gcs updates
use_mission_item_int: true # use the MISSION_ITEM_INT message instead of MISSION_ITEM
# for uploading waypoints to FCU
# --- mavros extras plugins (same order) ---
# adsb
# None
# debug_value
# None
# distance_sensor
## Currently available orientations:
# Check http://wiki.ros.org/mavros/Enumerations
##
distance_sensor:
rangefinder_pub:
id: 0
frame_id: "lidar"
#orientation: PITCH_270 # sended by FCU
field_of_view: 0.0 # XXX TODO
send_tf: false
sensor_position: {x: 0.0, y: 0.0, z: -0.1}
rangefinder_sub:
subscriber: true
id: 1
orientation: PITCH_270 # only that orientation are supported by APM 3.4+
# image_pub
image:
frame_id: "px4flow"
# fake_gps
fake_gps:
# select data source
use_mocap: true # ~mocap/pose
mocap_transform: false # ~mocap/tf instead of pose
mocap_withcovariance: false # ~mocap/pose uses PoseWithCovarianceStamped Message
use_vision: false # ~vision (pose)
use_hil_gps: true
gps_id: 4
# origin (default: Zürich)
geo_origin:
lat: 47.3667 # latitude [degrees]
lon: 8.5500 # longitude [degrees]
alt: 408.0 # altitude (height over the WGS-84 ellipsoid) [meters]
eph: 2.0
epv: 2.0
horiz_accuracy: 0.5
vert_accuracy: 0.5
speed_accuracy: 0.0
satellites_visible: 6 # virtual number of visible satellites
fix_type: 3 # type of GPS fix (default: 3D)
tf:
listen: false
send: false # send TF?
frame_id: "map" # TF frame_id
child_frame_id: "fix" # TF child_frame_id
rate_limit: 10.0 # TF rate
gps_rate: 5.0 # GPS data publishing rate
# landing_target
landing_target:
listen_lt: false
mav_frame: "LOCAL_NED"
land_target_type: "VISION_FIDUCIAL"
image:
width: 640 # [pixels]
height: 480
camera:
fov_x: 2.0071286398 # default: 115 [degrees]
fov_y: 2.0071286398
tf:
send: true
listen: false
frame_id: "landing_target"
child_frame_id: "camera_center"
rate_limit: 10.0
target_size: {x: 0.3, y: 0.3}
# mocap_pose_estimate
mocap:
# select mocap source
use_tf: false # ~mocap/tf
use_pose: true # ~mocap/pose
# odom
odometry:
frame_tf:
desired_frame: "ned"
estimator_type: 3 # check enum MAV_ESTIMATOR_TYPE in <https://mavlink.io/en/messages/common.html>
# px4flow
px4flow:
frame_id: "px4flow"
ranger_fov: 0.118682 # 6.8 degrees at 5 meters, 31 degrees at 1 meter
ranger_min_range: 0.3 # meters
ranger_max_range: 5.0 # meters
# vision_pose_estimate
vision_pose:
tf:
listen: false # enable tf listener (disable topic subscribers)
frame_id: "map"
child_frame_id: "vision_estimate"
rate_limit: 10.0
# vision_speed_estimate
vision_speed:
listen_twist: true # enable listen to twist topic, else listen to vec3d topic
twist_cov: true # enable listen to twist with covariance topic
# vibration
vibration:
frame_id: "base_link"
# wheel_odometry
wheel_odometry:
count: 2 # number of wheels to compute odometry
use_rpm: false # use wheel's RPM instead of cumulative distance to compute odometry
wheel0: {x: 0.0, y: -0.15, radius: 0.05} # x-, y-offset (m,NED) and radius (m)
wheel1: {x: 0.0, y: 0.15, radius: 0.05} # x-, y-offset (m,NED) and radius (m)
send_raw: true # send wheel's RPM and cumulative distance (~/wheel_odometry/rpm, ~/wheel_odometry/distance)
send_twist: false # send geometry_msgs/TwistWithCovarianceStamped instead of nav_msgs/Odometry
frame_id: "map" # origin frame
child_frame_id: "base_link" # body-fixed frame
vel_error: 0.1 # wheel velocity measurement error 1-std (m/s)
tf:
send: true
frame_id: "map"
child_frame_id: "base_link"
# vim:set ts=2 sw=2 et:

@ -1,18 +0,0 @@
plugin_blacklist:
# common
- actuator_control
- ftp
- safety_area
- hil
# extras
- altitude
- debug_value
- image_pub
- px4flow
- vibration
- vision_speed_estimate
- wheel_odometry
plugin_whitelist: []
#- 'sys_*'

@ -1,9 +0,0 @@
<launch>
<arg name="ugv_id" default="1"/>
<!-- fake_vicon -->
<node pkg="prometheus_ugv_control" type="fake_vicon" name="fake_vicon" output="screen">
<param name="rigid_body_name" value="/ugv$(arg ugv_id)"/>
</node>
</launch>

@ -1,12 +0,0 @@
<launch>
<arg name="swarm_num" default="1"/>
<arg name="ugv_id" default="1"/>
<arg name="sim_mode" default="false"/>
<!-- 启动地面站 -->
<node pkg="prometheus_ugv_control" type="ugv_ground_station" name="ugv_ground_station" output="screen">
<param name="swarm_num" value="$(arg swarm_num)"/>
<param name="ugv1_id" value="$(arg ugv_id)" />
</node>
</launch>

@ -1,50 +0,0 @@
<launch>
<arg name="swarm_num" default="1"/>
<arg name="ugv_id" default="1"/>
<arg name="x_min" default="-3.0"/>
<arg name="x_max" default="3.0"/>
<arg name="y_min" default="-3.0"/>
<arg name="y_max" default="3.0"/>
<arg name="sim_mode" default="false"/>
<!-- n号小车 -->
<group ns="/ugv$(arg ugv_id)">
<!-- 启动MAVROS -->
<node pkg="mavros" type="mavros_node" name="mavros" output="screen">
<param name="fcu_url" value="/dev/ttyUSB0:921600" />
<param name="gcs_url" value="" />
<param name="target_system_id" value="1" />
<param name="target_component_id" value="1" />
<rosparam command="load" file="$(find prometheus_experiment)/launch_ugv/apm_pluginlists.yaml" />
<rosparam command="load" file="$(find prometheus_experiment)/launch_ugv/apm_config.yaml" />
</node>
</group>
<!-- vrpn -->
<!-- 注意修改vicon电脑ip地址 -->
<!-- 改为T265 -->
<include file="$(find vrpn_client_ros)/launch/sample.launch">
<arg name="server" value="192.168.1.2"/>
</include>
<!-- 启动ugv_controller -->
<node pkg="prometheus_ugv_control" type="ugv_controller" name="ugv_controller_$(arg ugv_id)" output="screen">
<param name="ugv_id" value="$(arg ugv_id)"/>
<param name="sim_mode" value="$(arg sim_mode)" />
<param name="flag_printf" value="false" />
<param name="k_p" value="0.3" />
<param name="k_yaw" value="1.0" />
<param name="geo_fence/x_min" value="$(arg x_min)"/>
<param name="geo_fence/x_max" value="$(arg x_max)"/>
<param name="geo_fence/y_min" value="$(arg y_min)"/>
<param name="geo_fence/y_max" value="$(arg y_max)"/>
</node>
<!-- 启动ugv_estimator -->
<node pkg="prometheus_ugv_control" type="ugv_estimator" name="ugv_estimator_$(arg ugv_id)" output="screen">
<param name="ugv_id" value="$(arg ugv_id)"/>
<param name="sim_mode" value="$(arg sim_mode)" />
</node>
</launch>

@ -1,12 +0,0 @@
<launch>
<arg name="swarm_num" default="1"/>
<arg name="ugv_id" default="1"/>
<arg name="sim_mode" default="false"/>
<!-- 启动控制终端 -->
<node pkg="prometheus_ugv_control" type="ugv_terminal_control" name="ugv_terminal_control" output="screen">
<param name="ugv_name" value="/ugv1"/>
<param name="sim_mode" value="$(arg sim_mode)" />
</node>
</launch>

@ -1,28 +0,0 @@
<?xml version="1.0"?>
<package format="2">
<name>prometheus_experiment</name>
<version>0.0.0</version>
<description>The prometheus_experiment package</description>
<maintainer email="fatmoonqyp@126.com">Yuhua Qi</maintainer>
<author email="fatmoonqyp@126.com">Yuhua Qi</author>
<license>TODO</license>
<url type="website">http://www.amovauto.com/</url>
<url type="repository">https://github.com/potato77/prometheus_experiment.git</url>
<build_depend>message_generation</build_depend>
<exec_depend>message_runtime</exec_depend>
<buildtool_depend>catkin</buildtool_depend>
<build_depend>std_msgs</build_depend>
<build_export_depend>std_msgs</build_export_depend>
<exec_depend>std_msgs</exec_depend>
<export>
</export>
</package>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -0,0 +1,11 @@
#ifndef CONTROL_COMMON_H
#define CONTROL_COMMON_H
#include <string>
using namespace std;
#define PX4_SENDER 0
#define PX4_POS_CONTROLLER 1
#define PX4_GEO_CONTROLLER 2
#endif

@ -0,0 +1,208 @@
#ifndef CONTROL_UTILS_H
#define CONTROL_UTILS_H
#include <Eigen/Eigen>
#include <math.h>
using namespace std;
// 四元数转欧拉角
Eigen::Vector3d quaternion_to_rpy2(const Eigen::Quaterniond &q)
{
// YPR - ZYX
return q.toRotationMatrix().eulerAngles(2, 1, 0).reverse();
}
// 从(roll,pitch,yaw)创建四元数 by a 3-2-1 intrinsic Tait-Bryan rotation sequence
Eigen::Quaterniond quaternion_from_rpy(const Eigen::Vector3d &rpy)
{
// YPR - ZYX
return Eigen::Quaterniond(
Eigen::AngleAxisd(rpy.z(), Eigen::Vector3d::UnitZ()) *
Eigen::AngleAxisd(rpy.y(), Eigen::Vector3d::UnitY()) *
Eigen::AngleAxisd(rpy.x(), Eigen::Vector3d::UnitX())
);
}
// 将四元数转换至(roll,pitch,yaw) by a 3-2-1 intrinsic Tait-Bryan rotation sequence
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
// q0 q1 q2 q3
// w x y z
Eigen::Vector3d quaternion_to_euler(const Eigen::Quaterniond &q)
{
float quat[4];
quat[0] = q.w();
quat[1] = q.x();
quat[2] = q.y();
quat[3] = q.z();
Eigen::Vector3d ans;
ans[0] = atan2(2.0 * (quat[3] * quat[2] + quat[0] * quat[1]), 1.0 - 2.0 * (quat[1] * quat[1] + quat[2] * quat[2]));
ans[1] = asin(2.0 * (quat[2] * quat[0] - quat[3] * quat[1]));
ans[2] = atan2(2.0 * (quat[3] * quat[0] + quat[1] * quat[2]), 1.0 - 2.0 * (quat[2] * quat[2] + quat[3] * quat[3]));
return ans;
}
//旋转矩阵转欧拉角
void rotation_to_euler(const Eigen::Matrix3d& dcm, Eigen::Vector3d& euler_angle)
{
double phi_val = atan2(dcm(2, 1), dcm(2, 2));
double theta_val = asin(-dcm(2, 0));
double psi_val = atan2(dcm(1, 0), dcm(0, 0));
double pi = M_PI;
if (fabs(theta_val - pi / 2.0) < 1.0e-3) {
phi_val = 0.0;
psi_val = atan2(dcm(1, 2), dcm(0, 2));
} else if (fabs(theta_val + pi / 2.0) < 1.0e-3) {
phi_val = 0.0;
psi_val = atan2(-dcm(1, 2), -dcm(0, 2));
}
euler_angle(0) = phi_val;
euler_angle(1) = theta_val;
euler_angle(2) = psi_val;
}
Eigen::Vector4d rot2Quaternion(const Eigen::Matrix3d &R)
{
Eigen::Vector4d quat;
double tr = R.trace();
if (tr > 0.0) {
double S = sqrt(tr + 1.0) * 2.0; // S=4*qw
quat(0) = 0.25 * S;
quat(1) = (R(2, 1) - R(1, 2)) / S;
quat(2) = (R(0, 2) - R(2, 0)) / S;
quat(3) = (R(1, 0) - R(0, 1)) / S;
} else if ((R(0, 0) > R(1, 1)) & (R(0, 0) > R(2, 2))) {
double S = sqrt(1.0 + R(0, 0) - R(1, 1) - R(2, 2)) * 2.0; // S=4*qx
quat(0) = (R(2, 1) - R(1, 2)) / S;
quat(1) = 0.25 * S;
quat(2) = (R(0, 1) + R(1, 0)) / S;
quat(3) = (R(0, 2) + R(2, 0)) / S;
} else if (R(1, 1) > R(2, 2)) {
double S = sqrt(1.0 + R(1, 1) - R(0, 0) - R(2, 2)) * 2.0; // S=4*qy
quat(0) = (R(0, 2) - R(2, 0)) / S;
quat(1) = (R(0, 1) + R(1, 0)) / S;
quat(2) = 0.25 * S;
quat(3) = (R(1, 2) + R(2, 1)) / S;
} else {
double S = sqrt(1.0 + R(2, 2) - R(0, 0) - R(1, 1)) * 2.0; // S=4*qz
quat(0) = (R(1, 0) - R(0, 1)) / S;
quat(1) = (R(0, 2) + R(2, 0)) / S;
quat(2) = (R(1, 2) + R(2, 1)) / S;
quat(3) = 0.25 * S;
}
return quat;
}
static Eigen::Vector3d matrix_hat_inv(const Eigen::Matrix3d &m)
{
Eigen::Vector3d v;
// TODO: Sanity checks if m is skew symmetric
v << m(7), m(2), m(3);
return v;
}
Eigen::Vector4d quatMultiplication(const Eigen::Vector4d &q, const Eigen::Vector4d &p)
{
Eigen::Vector4d quat;
quat << p(0) * q(0) - p(1) * q(1) - p(2) * q(2) - p(3) * q(3), p(0) * q(1) + p(1) * q(0) - p(2) * q(3) + p(3) * q(2),
p(0) * q(2) + p(1) * q(3) + p(2) * q(0) - p(3) * q(1), p(0) * q(3) - p(1) * q(2) + p(2) * q(1) + p(3) * q(0);
return quat;
}
Eigen::Matrix3d quat2RotMatrix(const Eigen::Vector4d &q)
{
Eigen::Matrix3d rotmat;
rotmat << q(0) * q(0) + q(1) * q(1) - q(2) * q(2) - q(3) * q(3), 2 * q(1) * q(2) - 2 * q(0) * q(3),
2 * q(0) * q(2) + 2 * q(1) * q(3),
2 * q(0) * q(3) + 2 * q(1) * q(2), q(0) * q(0) - q(1) * q(1) + q(2) * q(2) - q(3) * q(3),
2 * q(2) * q(3) - 2 * q(0) * q(1),
2 * q(1) * q(3) - 2 * q(0) * q(2), 2 * q(0) * q(1) + 2 * q(2) * q(3),
q(0) * q(0) - q(1) * q(1) - q(2) * q(2) + q(3) * q(3);
return rotmat;
}
Eigen::Vector4d acc2quaternion(const Eigen::Vector3d &vector_acc, const double &yaw)
{
Eigen::Vector4d quat;
Eigen::Vector3d zb_des, yb_des, xb_des, proj_xb_des;
Eigen::Matrix3d rotmat;
proj_xb_des << std::cos(yaw), std::sin(yaw), 0.0;
zb_des = vector_acc / vector_acc.norm();
yb_des = zb_des.cross(proj_xb_des) / (zb_des.cross(proj_xb_des)).norm();
xb_des = yb_des.cross(zb_des) / (yb_des.cross(zb_des)).norm();
rotmat << xb_des(0), yb_des(0), zb_des(0), xb_des(1), yb_des(1), zb_des(1), xb_des(2), yb_des(2), zb_des(2);
quat = rot2Quaternion(rotmat);
return quat;
}
//constrain_function
float constrain_function(float data, float Max)
{
if(abs(data)>Max)
{
return (data > 0) ? Max : -Max;
}
else
{
return data;
}
}
//constrain_function2
float constrain_function2(float data, float Min,float Max)
{
if(data > Max)
{
return Max;
}
else if (data < Min)
{
return Min;
}else
{
return data;
}
}
//sign_function
float sign_function(float data)
{
if(data>0)
{
return 1.0;
}
else if(data<0)
{
return -1.0;
}
else if(data == 0)
{
return 0.0;
}
}
// min function
float min(float data1,float data2)
{
if(data1>=data2)
{
return data2;
}
else
{
return data1;
}
}
#endif

@ -0,0 +1,44 @@
/***************************************************************************************************************************
* message_utils.h
*
* Author: Jario
*
* Update Time: 2020.4.29
***************************************************************************************************************************/
#ifndef PROMETHEUS_MESSAGE_UTILS_H
#define PROMETHEUS_MESSAGE_UTILS_H
#include <string>
#include <prometheus_msgs/Message.h>
using namespace std;
// 消息发布函数
inline void pub_message(ros::Publisher& puber, int msg_type, std::string source_node, std::string msg_content)
{
prometheus_msgs::Message exect_msg;
exect_msg.header.stamp = ros::Time::now();
exect_msg.message_type = msg_type;
exect_msg.source_node = source_node;
exect_msg.content = msg_content;
puber.publish(exect_msg);
}
// 消息打印函数
inline void printf_message(const prometheus_msgs::Message& message)
{
//cout <<">>>>>>>>>>>>>>>>>>>>>>>> Message <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
if(message.message_type == prometheus_msgs::Message::NORMAL)
{
cout << "[NORMAL]" << "["<< message.source_node << "]:" << message.content <<endl;
}else if(message.message_type == prometheus_msgs::Message::WARN)
{
cout << "[WARN]" << "["<< message.source_node << "]:" <<message.content <<endl;
}else if(message.message_type == prometheus_msgs::Message::ERROR)
{
cout << "[ERROR]" << "["<< message.source_node << "]:" << message.content <<endl;
}
}
#endif

@ -0,0 +1,132 @@
#ifndef PRINTF_UTILS_H
#define PRINTF_UTILS_H
#include <string>
#include <iostream>
#include <iomanip>
#include <chrono>
#include <ctime>
using namespace std;
#define NUM_POINT 2 // 打印小数点
#define RED "\033[0;1;31m"
#define GREEN "\033[0;1;32m"
#define YELLOW "\033[0;1;33m"
#define BLUE "\033[0;1;34m"
#define PURPLE "\033[0;1;35m"
#define DEEPGREEN "\033[0;1;36m"
#define WHITE "\033[0;1;37m"
#define RED_IN_WHITE "\033[0;47;31m"
#define GREEN_IN_WHITE "\033[0;47;32m"
#define YELLOW_IN_WHITE "\033[0;47;33m"
#define TAIL "\033[0m"
class Print
{
public:
Print(float interval = 0, std::string color = TAIL)
: interval(interval), past_ts(std::chrono::system_clock::now()), color(color)
{
//固定的浮点显示
std::cout.setf(ios::fixed);
// setprecision(n) 设显示小数精度为n位
std::cout << std::setprecision(2);
//左对齐
std::cout.setf(ios::left);
// 强制显示小数点
std::cout.setf(ios::showpoint);
// 强制显示符号
std::cout.setf(ios::showpos);
};
template <typename T>
void operator()(T &&msg)
{
std::chrono::system_clock::time_point now_ts = std::chrono::system_clock::now();
auto dt = std::chrono::duration_cast<std::chrono::milliseconds>(now_ts - past_ts).count();
if (this != s_object_name)
{
std::cout << std::endl;
s_object_name = this;
}
if (interval >= 0)
{
// std::cout << this->interval << std::endl;
if (dt < this->interval * 1000)
return;
std::cout << color << msg << TAIL << std::endl;
}
else
{
if (dt < 0.1 * 1000)
return;
char now_char;
switch (times)
{
case 0:
now_char = '\\';
break;
case 1:
now_char = '|';
break;
case 2:
now_char = '/';
break;
case 3:
now_char = '-';
break;
}
times = ++times % 4;
std::cout << color << "\r " << now_char << " " << msg << TAIL << std::endl;
}
this->past_ts = now_ts;
};
float interval;
private:
std::chrono::system_clock::time_point past_ts;
std::string color;
static void *s_object_name;
unsigned int times = 0;
};
void *Print::s_object_name = nullptr;
#define PRINTF_UTILS_CONCAT_(x, y) x##y
#define PRINTF_UTILS_CONCAT(x, y) PRINTF_UTILS_CONCAT_(x, y)
#define PRINTF_UTILS_PCOUT_(interval, color, msg, sign) \
static Print PRINTF_UTILS_CONCAT(print, sign)(interval, color); \
PRINTF_UTILS_CONCAT(print, sign) \
(msg)
#define PCOUT(interval, color, msg) PRINTF_UTILS_PCOUT_(interval, color, msg, __LINE__)
// Example:
// cout << GREEN << "Test for Green text." << TAIL <<endl;
// 字背景颜色范围:40--49 字颜色: 30--39
// 40:黑 30: 黑
// 41:红 31: 红
// 42:绿 32: 绿
// 43:黄 33: 黄
// 44:蓝 34: 蓝
// 45:紫 35: 紫
// 46:深绿 36: 深绿
// 47:白色 37: 白色
// 参考资料https://blog.csdn.net/u014470361/article/details/81512330
// cout << "\033[0;1;31m" << "Hello World, Red color!" << "\033[0m" << endl;
// printf( "\033[0;30;41m color!!! \033[0m Hello \n");
// ROS_INFO("\033[1;33;41m----> Hightlight color.\033[0m");
// 其中41的位置代表字的背景色, 30的位置是代表字的颜色0 是字的一些特殊属性0代表默认关闭一些其他属性如闪烁、下划线等。
// ROS_INFO_STREAM_ONCE ("\033[1;32m---->Setting to OFFBOARD Mode....\033[0m");//绿色只打印一次
#endif

@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 2.8.3)
project(prometheus_msgs)
find_package(catkin REQUIRED COMPONENTS
message_generation
roscpp
geometry_msgs
actionlib_msgs
sensor_msgs
nav_msgs
std_msgs
std_srvs
tf2_ros
tf2_eigen
mavros_msgs
serial
)
find_package(Boost REQUIRED COMPONENTS system)
add_message_files(
DIRECTORY msg
FILES
DetectionInfo.msg
MultiDetectionInfo.msg
BoundingBox.msg
BoundingBoxes.msg
ControlCommand.msg
PositionReference.msg
AttitudeReference.msg
DroneState.msg
ControlOutput.msg
Message.msg
LogMessage.msg
LogMessageControl.msg
LogMessagePlanning.msg
LogMessageDetection.msg
SwarmCommand.msg
Formation.msg
ArucoInfo.msg
MultiArucoInfo.msg
IndoorSearch.msg
UgvState.msg
UgvCommand.msg
GimbalTrackError.msg
Cloud_platform.msg
gimbal.msg
GimbalCtl.msg
)
add_action_files(
DIRECTORY action
FILES
CheckForObjects.action
)
generate_messages(
DEPENDENCIES
actionlib_msgs
geometry_msgs
sensor_msgs
std_msgs
)
catkin_package(
CATKIN_DEPENDS
message_runtime
actionlib_msgs
geometry_msgs
sensor_msgs
message_runtime
std_msgs
)
include_directories(
include
${catkin_INCLUDE_DIRS}
)
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
)
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
)

@ -0,0 +1,17 @@
std_msgs/Header header
## aruco编码
int32 aruco_num
## 是否检测到目标
bool detected
## 目标位置-相机坐标系-(x,y,z)
## 从相机往前看物体在相机右方x为正下方y为正前方z为正
float32[3] position
## 目标姿态-四元数-(qx,qy,qz,qw)
float32[4] orientation
## 视线角度-相机系下-(右方x角度为正,下方y角度为正)
float32[2] sight_angle

@ -0,0 +1,7 @@
std_msgs/Header header
## 位置控制器输出: 期望油门 + 期望角度
float32[3] throttle_sp ## [0-1] 惯性系下的油门量
float32 desired_throttle ## [0-1] 机体系z轴
float32[3] desired_attitude ## [rad]
geometry_msgs/Quaternion desired_att_q ## 四元数

@ -0,0 +1,7 @@
string Class
float64 probability
int64 xmin
int64 ymin
int64 xmax
int64 ymax

@ -0,0 +1,3 @@
Header header
Header image_header
BoundingBox[] bounding_boxes

@ -0,0 +1,4 @@
std_msgs/Header header
uint8[59] received_data
uint8[5] get_data_com
uint8[20] gimbal_control # 控制

@ -0,0 +1,23 @@
std_msgs/Header header
## 控制命令的编号 防止接收到错误命令, 编号应该逐次递加
uint32 Command_ID
## 消息来源
string source
## 控制命令的模式
uint8 Mode
# enum Mode 控制模式枚举
uint8 Idle=0
uint8 Takeoff=1
uint8 Hold=2
uint8 Land=3
uint8 Move=4
uint8 Disarm=5
uint8 User_Mode1=6
uint8 User_Mode2=7
## 控制参考量
## 位置参考量:位置、速度、加速度、加加速度、加加加速度
## 角度参考量:偏航角、偏航角速度、偏航角加速度
PositionReference Reference_State

@ -0,0 +1,11 @@
std_msgs/Header header
## 位置控制器输出: 期望推力及期望油门
float32[3] Thrust ## [rad]
float32[3] Throttle
## NE控制器的中间变量
float32[3] u_l ## [0-1] 惯性系下的油门量
float32[3] u_d ## [rad]
float32[3] NE ## [rad]

@ -0,0 +1,32 @@
std_msgs/Header header
## 目标类别名称
string object_name
## 是否检测到目标
bool detected
## 0表示相机坐标系, 1表示机体坐标系, 2表示惯性坐标系
int32 frame
## 目标位置[相机系下右方x为正下方y为正前方z为正]
float32[3] position
## 目标姿态-欧拉角-(z,y,x)
float32[3] attitude
## 目标姿态-四元数-(qx,qy,qz,qw)
float32[4] attitude_q
## 视线角度[相机系下右方x角度为正下方y角度为正]
float32[2] sight_angle
## 像素位置[相机系下右方x为正下方y为正]
int32[2] pixel_position
## 偏航角误差
float32 yaw_error
## 类别
int32 category

@ -0,0 +1,22 @@
std_msgs/Header header
## 机载电脑是否连接上飞控true已连接false则不是
bool connected
## 是否解锁true为已解锁false则不是
bool armed
## 是否降落true为已降落false则代表在空中
bool landed
## PX4飞控当前飞行模式
string mode
bool odom_valid
## 系统启动时间
float32 time_from_start ## [s]
## 无人机状态量:位置、速度、姿态
float32[3] position ## [m]
float32 rel_alt ## [m] only for outdoor
float32[3] velocity ## [m/s]
float32[3] attitude ## [rad]
geometry_msgs/Quaternion attitude_q ## 四元数
float32[3] attitude_rate ## [rad/s]

@ -0,0 +1,6 @@
uint8 HORIZONTAL=0
uint8 TRIANGEL=1
uint8 DIAMOND=2
uint8 DIAMOND_STAGE_1=3
uint8 type

@ -0,0 +1,9 @@
float32 pitch
float32 yaw
float32 zoom
float32 focus
uint16 home
uint16 TakePicture
uint16 cameraModeChange
uint16 yawfollow
uint16 quadhome

@ -0,0 +1,12 @@
## 是否检测到目标
bool detected
# 坐标
float64 x
float64 y
# 速度
float64 velx
float64 vely
# 积分
float64 Ix
float64 Iy

@ -0,0 +1,12 @@
std_msgs/Header header
ArucoInfo Aruco1
ArucoInfo Aruco2
ArucoInfo Aruco3
ArucoInfo Aruco4
ArucoInfo Aruco5
ArucoInfo Aruco6
ArucoInfo Aruco7
ArucoInfo Aruco8
ArucoInfo Aruco9

@ -0,0 +1,17 @@
std_msgs/Header header
## 用于log的自定义消息可自行增加需要记录的话题
float32 time ## [s]
DroneState Drone_State
ControlCommand Control_Command
ControlOutput Control_Output
AttitudeReference Attitude_Reference

@ -0,0 +1,20 @@
std_msgs/Header header
## 用于控制模块的log消息可自行增加需要记录的话题
float32 time ## [s]
## 0代表px4_sender,1代表px4_pos_controller(姿态控制)
int32 control_type
DroneState Drone_State
ControlCommand Control_Command
ControlOutput Control_Output
AttitudeReference Attitude_Reference
geometry_msgs/PoseStamped ref_pose

@ -0,0 +1,17 @@
std_msgs/Header header
## 用于控制模块的log消息可自行增加需要记录的话题
float32 time ## [s]
DroneState Drone_State
ControlCommand Control_Command
ControlOutput Control_Output
AttitudeReference Attitude_Reference

@ -0,0 +1,17 @@
std_msgs/Header header
## 用于控制模块的log消息可自行增加需要记录的话题
float32 time ## [s]
DroneState Drone_State
ControlCommand Control_Command
ControlOutput Control_Output
AttitudeReference Attitude_Reference

@ -0,0 +1,12 @@
std_msgs/Header header
## 节点回传地面站的消息
uint8 message_type
# enum message_type
uint8 NORMAL = 0
uint8 WARN = 1
uint8 ERROR = 2
string source_node
string content

@ -0,0 +1,7 @@
std_msgs/Header header
## 检测到的aruco码数量
int32 num_arucos
## 每个aruco码的检测结果
ArucoInfo[] aruco_infos

@ -0,0 +1,10 @@
Header header
## 检测到的目标数量
int32 num_objs
## Detecting or Tracking (0:detect, 1:track)
int32 detect_or_track
## 每个目标的检测结果
DetectionInfo[] detection_infos

@ -0,0 +1,37 @@
std_msgs/Header header
## 位置控制参考量
## 默认为 XYZ位置追踪模式 sub_mode = 0 速度追踪启用时,控制器不考虑位置参考量及位置状态反馈
uint8 Move_mode
uint8 XYZ_POS = 0 ##0b00
uint8 XY_POS_Z_VEL = 1 ##0b01
uint8 XY_VEL_Z_POS = 2 ##0b10
uint8 XYZ_VEL = 3 ##0b11
uint8 XYZ_ACC = 4
uint8 TRAJECTORY = 5
uint8 Move_frame
# 默认情况下均为ENU_FRAME,注意轨迹追踪和XYZ_ACC一定是ENU_FRAME
uint8 ENU_FRAME = 0
uint8 BODY_FRAME = 1
uint8 MIX_FRAME = 2 ##2020.4.6 临时增加的模式后期需要统一整合该模式下xy采用机体系控制z采用enu系控制
## 时刻: 用于轨迹追踪
float32 time_from_start ## [s]
## 参考量:位置、速度、加速度、加加速度、加加加速度
float32[3] position_ref ## [m]
float32[3] velocity_ref ## [m/s]
float32[3] acceleration_ref ## [m/s^2]
## float32[3] jerk_ref ## [m/s^3]
## float32[3] snap_ref ## [m/s^4]
## 角度参考量:偏航角、偏航角速度、偏航角加速度
bool Yaw_Rate_Mode ## True 代表控制偏航角速率
float32 yaw_ref ## [rad]
float32 yaw_rate_ref ## [rad/s]
## float32 yaw_acceleration_ref ## [rad/s]

@ -0,0 +1,49 @@
std_msgs/Header header
## 控制命令的编号 防止接收到错误命令, 编号应该逐次递加
uint32 Command_ID
## 消息来源
string source
## 控制命令的模式
uint8 Mode
# enum Mode 控制模式枚举
uint8 Idle=0
uint8 Takeoff=1
uint8 Hold=2
uint8 Land=3
uint8 Disarm=4
uint8 Position_Control=5
uint8 Velocity_Control=6
uint8 Accel_Control=7
uint8 Move=8
uint8 User_Mode1=9
## 控制参考量
uint8 swarm_shape
uint8 One_column=0
uint8 Triangle=1
uint8 Square=2
uint8 Circular=3
## 默认为 XYZ位置追踪模式 sub_mode = 0 速度追踪启用时,控制器不考虑位置参考量及位置状态反馈
uint8 Move_mode
uint8 XYZ_POS = 0 ##0b00
uint8 XY_POS_Z_VEL = 1 ##0b01
uint8 XY_VEL_Z_POS = 2 ##0b10
uint8 XYZ_VEL = 3 ##0b11
uint8 XYZ_ACC = 4
uint8 TRAJECTORY = 5
float32 swarm_size
float32[3] position_ref ## [m]
float32[3] velocity_ref ## [m]
float32[3] acceleration_ref
float32 yaw_ref ## [rad]
float32 yaw_rate_ref

@ -0,0 +1,24 @@
std_msgs/Header header
## 控制命令的编号 防止接收到错误命令, 编号应该逐次递加
uint32 Command_ID
## 控制命令的模式
uint8 Mode
# enum Mode 控制模式枚举
uint8 Start=0
uint8 Hold=1
uint8 Disarm=2
uint8 Point_Control=3
uint8 Direct_Control=4
uint8 ENU_Vel_Control=5
uint8 ENU_Pos_Control=6
uint8 Path_Control=7
float32[2] position_ref ## [m]
float32 yaw_ref ## [rad]
float32[2] linear_vel ## [m/s]
float32 angular_vel ## [rad/s]

@ -0,0 +1,16 @@
std_msgs/Header header
## 机载电脑是否连接上飞控true已连接false则不是
bool connected
## 是否解锁true为已解锁false则不是
bool armed
bool guided
## PX4飞控当前飞行模式
string mode
## 无人机状态量:位置、速度、姿态
float32[3] position ## [m]
float32[3] velocity ## [m/s]
float32[3] attitude ## [rad]
geometry_msgs/Quaternion attitude_q ## 四元数
float32 battery ##

@ -0,0 +1,15 @@
float64 imu0
float64 imu1
float64 imu2
float64 rc0
float64 rc1
float64 rc2
float64 rel0 # r
float64 rel1 # p
float64 rel2 # y
float64 imuvel0
float64 imuvel1
float64 imuvel2
float64 relvel0
float64 relvel1
float64 relvel2

@ -0,0 +1,208 @@
cmake_minimum_required(VERSION 2.8.3)
project(prometheus_control)
## Compile as C++11, supported in ROS Kinetic and newer
# add_compile_options(-std=c++11)
## Find catkin macros and libraries
## if COMPONENTS list like find_package(catkin REQUIRED COMPONENTS xyz)
## is used, also find other catkin packages
find_package(catkin REQUIRED COMPONENTS
message_generation
roscpp
geometry_msgs
nav_msgs
sensor_msgs
mavros
std_msgs
std_srvs
tf
tf2_ros
tf2_eigen
mavros_msgs
prometheus_msgs
)
## System dependencies are found with CMake's conventions
find_package(Boost REQUIRED COMPONENTS system)
################################################
## Declare ROS messages, services and actions ##
################################################
## Generate added messages and services with any dependencies listed here
generate_messages(
DEPENDENCIES
geometry_msgs
nav_msgs
sensor_msgs
std_msgs
)
catkin_package(
INCLUDE_DIRS include
CATKIN_DEPENDS message_runtime
)
###########
## Build ##
###########
## Specify additional locations of header files
## Your package locations should be listed before other locations
include_directories(
include
${catkin_INCLUDE_DIRS}
../common/include
)
###############################
## cpp ##
###############################
add_library(OptiTrackFeedbackRigidBody src/lib/OptiTrackFeedBackRigidBody.cpp)
add_library(KeyboardEvent src/lib/KeyboardEvent.cpp)
###### Main File ##########
##rover_pos_controller.cpp
add_executable(rover_pos_controller src/rover_control/rover_pos_controller.cpp)
add_dependencies(rover_pos_controller prometheus_control_gencpp)
target_link_libraries(rover_pos_controller ${catkin_LIBRARIES})
##px4_pos_controller.cpp
add_executable(px4_pos_controller src/px4_pos_controller.cpp)
add_dependencies(px4_pos_controller prometheus_control_gencpp)
target_link_libraries(px4_pos_controller ${catkin_LIBRARIES})
##px4_geometry_controller.cpp
add_executable(px4_geometry_controller src/px4_geometry_controller.cpp)
add_dependencies(px4_geometry_controller prometheus_control_gencpp)
target_link_libraries(px4_geometry_controller ${catkin_LIBRARIES})
##px4_pos_estimator.cpp
add_executable(px4_pos_estimator src/px4_pos_estimator.cpp)
add_dependencies(px4_pos_estimator prometheus_control_gencpp)
target_link_libraries(px4_pos_estimator ${catkin_LIBRARIES})
target_link_libraries(px4_pos_estimator OptiTrackFeedbackRigidBody)
##ros_info_color_test.cpp
add_executable(ros_info_color_test src/Utilities/ros_info_color_test.cpp)
add_dependencies(ros_info_color_test prometheus_control_gencpp)
target_link_libraries(ros_info_color_test ${catkin_LIBRARIES})
# add_executable(planner_server src/Test/planner_server.cpp)
# add_dependencies(planner_server prometheus_control_gencpp)
# target_link_libraries(planner_server ${catkin_LIBRARIES})
###### Test File ##########
#add_executable(px4_fw_controller src/Test/px4_fw_controller.cpp)
#add_dependencies(px4_fw_controller prometheus_control_gencpp)
#target_link_libraries(px4_fw_controller ${catkin_LIBRARIES})
add_executable(px4_sender src/px4_sender.cpp)
add_dependencies(px4_sender prometheus_control_gencpp)
target_link_libraries(px4_sender ${catkin_LIBRARIES})
###### Utilities File ##########
#add_executable(keyboard_control src/Utilities/keyboard_control.cpp)
#add_dependencies(keyboard_control prometheus_control_gencpp)
#target_link_libraries(keyboard_control ${catkin_LIBRARIES})
#target_link_libraries(keyboard_control KeyboardEvent)
##px4_pos_estimator_with_noise.cpp
add_executable(px4_pos_estimator_with_noise src//Utilities/px4_pos_estimator_with_noise.cpp)
add_dependencies(px4_pos_estimator_with_noise prometheus_control_gencpp)
target_link_libraries(px4_pos_estimator_with_noise ${catkin_LIBRARIES})
target_link_libraries(px4_pos_estimator_with_noise OptiTrackFeedbackRigidBody)
add_executable(filter_tester src/Utilities/filter_tester.cpp)
add_dependencies(filter_tester prometheus_control_gencpp)
target_link_libraries(filter_tester ${catkin_LIBRARIES})
add_executable(TFmini src/Utilities/TFmini.cpp)
add_dependencies(TFmini prometheus_control_gencpp)
target_link_libraries(TFmini ${catkin_LIBRARIES})
add_executable(fake_vicon src/Utilities/fake_vicon.cpp)
add_dependencies(fake_vicon prometheus_control_gencpp)
target_link_libraries(fake_vicon ${catkin_LIBRARIES})
add_executable(terminal_control src/Utilities/terminal_control.cpp)
add_dependencies(terminal_control prometheus_control_gencpp)
target_link_libraries(terminal_control ${catkin_LIBRARIES})
target_link_libraries(terminal_control KeyboardEvent)
add_executable(terminal_control_rover src/Utilities/terminal_control_rover.cpp)
add_dependencies(terminal_control_rover prometheus_control_gencpp)
target_link_libraries(terminal_control_rover ${catkin_LIBRARIES})
add_executable(OptiTrackTest src/Utilities/OptiTrackTest.cpp)
add_dependencies(OptiTrackTest prometheus_control_gencpp)
target_link_libraries(OptiTrackTest ${catkin_LIBRARIES})
target_link_libraries(OptiTrackTest OptiTrackFeedbackRigidBody)
target_link_libraries(OptiTrackTest KeyboardEvent)
add_executable(set_mode src/Utilities/set_mode.cpp)
add_dependencies(set_mode prometheus_control_gencpp)
target_link_libraries(set_mode ${catkin_LIBRARIES})
add_executable(eigen_test src/Utilities/eigen_test.cpp)
add_dependencies(eigen_test prometheus_control_gencpp)
target_link_libraries(eigen_test ${catkin_LIBRARIES})
#############
## Install ##
#############
# all install targets should use catkin DESTINATION variables
# See http://ros.org/doc/api/catkin/html/adv_user_guide/variables.html
## Mark executable scripts (Python etc.) for installation
## in contrast to setup.py, you can choose the destination
# install(PROGRAMS
# scripts/my_python_script
# DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark executables and/or libraries for installation
# install(TARGETS ${PROJECT_NAME} ${PROJECT_NAME}_node
# ARCHIVE DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# LIBRARY DESTINATION ${CATKIN_PACKAGE_LIB_DESTINATION}
# RUNTIME DESTINATION ${CATKIN_PACKAGE_BIN_DESTINATION}
# )
## Mark cpp header files for installation
# install(DIRECTORY include/${PROJECT_NAME}/
# DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
# FILES_MATCHING PATTERN "*.h"
# PATTERN ".svn" EXCLUDE
# )
## Mark cpp header files for installation
install(DIRECTORY include/${PROJECT_NAME}/
DESTINATION ${CATKIN_PACKAGE_INCLUDE_DESTINATION}
FILES_MATCHING PATTERN "*.h"
)
## Mark other files for installation (e.g. launch and bag files, etc.)
install(DIRECTORY launch/
DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}/launch
)
#############
## Testing ##
#############
## Add gtest based cpp test target and link libraries
# catkin_add_gtest(${PROJECT_NAME}-test test/test_prometheus_control.cpp)
# if(TARGET ${PROJECT_NAME}-test)
# target_link_libraries(${PROJECT_NAME}-test ${PROJECT_NAME})
# endif()
## Add folders to be run by python nosetests
# catkin_add_nosetests(test)

@ -0,0 +1,57 @@
#ifndef HIGHPASSFILTER_H
#define HIGHPASSFILTER_H
#include <math.h>
using namespace std;
class HighPassFilter
{
public:
//构造函数
HighPassFilter(void)
{
T = 0.0f;
Output_prev = 0.0f;
Input_prev = 0.0f;
}
void set_Time_constant(float Time_constant);
float apply(float input, float dt);
// Return the cutoff frequency
float get_Time_constant() const { return T; }
private:
//Previous output
float Output_prev;
float Input_prev;
//Time constant
float T;
};
float HighPassFilter::apply(float input, float dt)
{
// do the filtering
float output = 1/(T+dt)*(T*Output_prev + input - Input_prev);
Output_prev = output;
Input_prev = input;
// return the value.
return output;
}
void HighPassFilter::set_Time_constant(float Time_constant)
{
T = Time_constant;
}
#endif

@ -0,0 +1,63 @@
#ifndef LEADLAGFILTER_H
#define LEADLAGFILTER_H
#include <math.h>
using namespace std;
class LeadLagFilter
{
public:
//构造函数
LeadLagFilter()
{
T = 0.0f;
Kd = 0.0f;
Output_prev = 0.0f;
Input_prev = 0.0f;
}
void set_Time_constant(float Time_constant,float _Kd);
float apply(float input, float dt);
// Return the cutoff frequency
float get_Time_constant() const { return T; }
float get_Kd() const { return Kd; }
private:
//Previous output
float Output_prev;
float Input_prev;
float Kd;
//Time constant
float T;
};
float LeadLagFilter::apply(float input, float dt)
{
// do the filtering
float output = 1/(T+dt)*(T*Output_prev + input - Input_prev + dt*Kd*input);
Output_prev = output;
Input_prev = input;
// return the value.
return output;
}
void LeadLagFilter::set_Time_constant(float Time_constant,float _Kd)
{
T = Time_constant;
Kd = _Kd;
}
#endif

@ -0,0 +1,52 @@
#ifndef LOWPASSFILTER_H
#define LOWPASSFILTER_H
#include <math.h>
using namespace std;
class LowPassFilter
{
public:
//构造函数
LowPassFilter(void)
{
T = 0.0f;
Output_prev = 0.0f;
}
void set_Time_constant(float Time_constant);
float apply(float input, float dt);
// Return the cutoff frequency
float get_Time_constant() const { return T; }
private:
//Previous output
float Output_prev;
//Time constant
float T;
};
float LowPassFilter::apply(float input, float dt)
{
// do the filtering
float output = T/(T+dt)*Output_prev + dt/(T+dt)*input;
Output_prev = output;
// return the value.
return output;
}
void LowPassFilter::set_Time_constant(float Time_constant)
{
T = Time_constant;
}
#endif

@ -0,0 +1,56 @@
#pragma once
#include <termios.h>
#include <sstream>
#include <vector>
#include "ros/ros.h"
# define U_KEY_NONE -1
# define U_KEY_SPACE 32
# define U_KEY_LEFT 37
# define U_KEY_UP 38
# define U_KEY_RIGHT 39
# define U_KEY_DOWN 40
# define U_KEY_0 48
# define U_KEY_1 49
# define U_KEY_2 50
# define U_KEY_3 51
# define U_KEY_4 52
# define U_KEY_5 53
# define U_KEY_6 54
# define U_KEY_7 55
# define U_KEY_8 56
# define U_KEY_9 57
# define U_KEY_A 97
# define U_KEY_D 100
# define U_KEY_E 101
# define U_KEY_F 102
# define U_KEY_H 104
# define U_KEY_K 107
# define U_KEY_L 108
# define U_KEY_M 109
# define U_KEY_O 111
# define U_KEY_P 112
# define U_KEY_Q 113
# define U_KEY_R 114
# define U_KEY_S 115
# define U_KEY_T 116
# define U_KEY_U 117
# define U_KEY_V 118
# define U_KEY_W 119
# define U_KEY_X 120
# define U_KEY_Y 121
# define U_KEY_Z 122
using namespace std;
class KeyboardEvent{
static int input_flag; //keyboard flag
static char buff; // keyboard buff
static void getch();// get keyboard input. We need all instance to use the same function to catch the keyboard
public:
KeyboardEvent();
void RosWhileLoopRun(); // this should be placed inside the ros while loop
char GetPressedKey();
};

@ -0,0 +1,78 @@
#pragma once
#include "ros/ros.h"
#include "std_msgs/Empty.h"
#include "geometry_msgs/Twist.h"
#include "geometry_msgs/PoseStamped.h"
//#include "UtilityFunctions.h"
#include <Eigen/Eigen>
//maximum window size
#ifndef max_windowsize
#define max_windowsize 10
#endif
using namespace Eigen;
struct optitrack_pose{
Vector3d Position;
double q0;
double q1;
double q2;
double q3;
double t;
Matrix<double, 3, 4> L;// Quaternion auxiliary matirx
Matrix<double, 3, 4> R;// Quaternion auxiliary matirx
Matrix3d R_IB; //
Matrix3d R_BI; //
};
struct rigidbody_state{
Vector4d quaterion;
Vector3d Position;// inertial position
Vector3d V_I; // inertial velocity
Matrix3d Omega_Cross; // angular velocity skew
Vector3d Omega_BI;// Frame B to Frame I expressed in Frame B
Matrix3d R_IB; // rotation matrix
Matrix3d R_BI; //
Vector3d Euler;// euler angle
double time_stamp;
};
class OptiTrackFeedBackRigidBody{
//-------Optitrack Related-----///
geometry_msgs::PoseStamped OptiTrackdata;
unsigned int OptiTrackFlag; // OptiTrackState 0: no data feed,: 1 data feed present
void OptiTrackCallback(const geometry_msgs::PoseStamped& msg);
unsigned int FeedbackState;// 0 no feedback, 1 has feedback
ros::Subscriber subOptiTrack;// OptiTrack Data
//--------Filter Parameters-------//
unsigned int linear_velocity_window; // window size
unsigned int angular_velocity_window; // window size
//--------Filter Buffer-----------//
// raw velocity buffer from numerical differentiation
Vector3d velocity_raw[max_windowsize];
Vector3d angular_velocity_raw[max_windowsize];
Vector3d velocity_filtered; // filtered velocity
Vector3d angular_velocity_filtered;// filtered angular velocity
optitrack_pose pose[2];/*pose info from optitrack pose[1] should be the latest mesaured value,
pose[0] is value of the last measurment (in world frame by default, if other frames
are used , please changle the frame selectioin in the launch file */
//--------Filter Methods-----------//
void CalculateVelocityFromPose();// calculate velocity info from pose update measurements
void MovingWindowAveraging();// a filter using moving window
void PushRawVelocity(Vector3d& new_linear_velocity, Vector3d& new_angular_velocity);// push newly measured velocity into raw velocity buffer
void PushPose();//push newly measured pose into dronepose buffer
void SetZeroVelocity();
//--------Update Rigid-body State ------//
rigidbody_state state;
public:
OptiTrackFeedBackRigidBody(const char* name,ros::NodeHandle& n, unsigned int linear_window, unsigned int angular_window);
~OptiTrackFeedBackRigidBody();
int GetOptiTrackState();
void GetState(rigidbody_state& state);
void GetRaWVelocity(Vector3d& linear_velocity,Vector3d& angular_velocity);
void RosWhileLoopRun();// This function should be put into ros while loop
void GetEulerAngleFromQuaterion_NormalConvention(double (&eulerangle)[3]);
void GetEulerAngleFromQuaterion_OptiTrackYUpConvention(double (&eulerangle)[3]);
void Veemap(Matrix3d& cross_matrix, Vector3d& vector);
void Hatmap(Vector3d& vector, Matrix3d& cross_matrix);
};

@ -0,0 +1,301 @@
/***************************************************************************************************************************
* geometry_controller.h
*
* Author: Qyp
*
* Update Time: 2021.3.0
*
* Introduction: Geometry Controller
***************************************************************************************************************************/
#ifndef geometry_controller_H
#define geometry_controller_H
#include <math.h>
#include <command_to_mavros.h>
#include <prometheus_control_utils.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
#define ERROR_QUATERNION 1
#define ERROR_GEOMETRIC 2
using namespace std;
class geometry_controller
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
geometry_controller(void):
nh("~")
{
/// 读取参数
// 控制模式
nh.param<int>("geometry_controller/ctrl_mode", ctrl_mode_, ERROR_GEOMETRIC);
// 是否使用速度来控制偏航角
// 是:使用速度期望值计算当前期望偏航角,否:使用系统预设的偏航角
nh.param<bool>("geometry_controller/velocity_yaw", velocity_yaw_, false);
// 最大加速度反馈部分
nh.param<double>("geometry_controller/max_acc", max_fb_acc_, 9.0);
// 预设的期望偏航角如果velocity_yaw_设置为true则此设置无效
nh.param<double>("geometry_controller/yaw_heading", mavYaw_, 0.0);
// rotor drag
nh.param<double>("geometry_controller/drag_dx", dx_, 0.0);
nh.param<double>("geometry_controller/drag_dy", dy_, 0.0);
nh.param<double>("geometry_controller/drag_dz", dz_, 0.0);
// 常数,不清楚作用
nh.param<double>("geometry_controller/attctrl_constant", attctrl_tau_, 0.1);
// 推力相关参数,不清楚作用
nh.param<double>("geometry_controller/normalizedthrust_constant", norm_thrust_const_, 0.05); // 1 / max acceleration
nh.param<double>("geometry_controller/normalizedthrust_offset", norm_thrust_offset_, 0.1); // 1 / max acceleration
// 控制参数
nh.param<double>("geometry_controller/Kp_x", Kpos_x_, 8.0);
nh.param<double>("geometry_controller/Kp_y", Kpos_y_, 8.0);
nh.param<double>("geometry_controller/Kp_z", Kpos_z_, 10.0);
nh.param<double>("geometry_controller/Kv_x", Kvel_x_, 1.5);
nh.param<double>("geometry_controller/Kv_y", Kvel_y_, 1.5);
nh.param<double>("geometry_controller/Kv_z", Kvel_z_, 3.3);
// 初始目标值
nh.param<double>("geometry_controller/init_pos_x", initTargetPos_x_, 0.0);
nh.param<double>("geometry_controller/init_pos_y", initTargetPos_y_, 0.0);
nh.param<double>("geometry_controller/init_pos_z", initTargetPos_z_, 2.0);
targetPos_ << initTargetPos_x_, initTargetPos_y_, initTargetPos_z_; // Initial Position
targetVel_ << 0.0, 0.0, 0.0;
mavPos_ << 0.0, 0.0, 0.0;
mavVel_ << 0.0, 0.0, 0.0;
g_ << 0.0, 0.0, -9.8;
Kpos_ << -Kpos_x_, -Kpos_y_, -Kpos_z_;
Kvel_ << -Kvel_x_, -Kvel_y_, -Kvel_z_;
D_ << dx_, dy_, dz_;
}
// 控制模式
int ctrl_mode_;
bool velocity_yaw_;
// 初始目标值
double initTargetPos_x_, initTargetPos_y_, initTargetPos_z_;
// 目标位置、速度、加速度
Eigen::Vector3d targetPos_, targetVel_, targetAcc_, targetJerk_, targetSnap_;
Eigen::Vector3d targetPos_prev_, targetVel_prev_;
// 预设的期望偏航角如果velocity_yaw_设置为true则此设置无效
double mavYaw_;
// 无人机状态信息 - 位置、速度、角速度
Eigen::Vector3d mavPos_, mavVel_, mavRate_;
// 重力加速度
Eigen::Vector3d g_;
// 无人机姿态,期望姿态
Eigen::Vector4d mavAtt_, q_des;
// 期望角速度及推力
Eigen::Vector4d cmdBodyRate_; //{wx, wy, wz, Thrust}
// rotor drag
double dx_, dy_, dz_;
Eigen::Vector3d D_;
// 控制参数
double Kpos_x_, Kpos_y_, Kpos_z_, Kvel_x_, Kvel_y_, Kvel_z_;
Eigen::Vector3d Kpos_, Kvel_;
// 最大 反馈加速度
double max_fb_acc_;
// 不清楚作用的变量
double attctrl_tau_;
double norm_thrust_const_, norm_thrust_offset_;
//Printf the PID parameter
void printf_param();
void printf_result();
// Position control main function
Eigen::Vector4d pos_controller(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State);
private:
ros::NodeHandle nh;
static double getVelocityYaw(const Eigen::Vector3d velocity) { return atan2(velocity(1), velocity(0)); };
void computeBodyRateCmd(Eigen::Vector4d &bodyrate_cmd, const Eigen::Vector3d &target_pos,
const Eigen::Vector3d &target_vel, const Eigen::Vector3d &target_acc);
Eigen::Vector4d geometric_attcontroller(const Eigen::Vector4d &ref_att, const Eigen::Vector3d &ref_acc,
Eigen::Vector4d &curr_att);
Eigen::Vector4d attcontroller(const Eigen::Vector4d &ref_att, const Eigen::Vector3d &ref_acc,
Eigen::Vector4d &curr_att);
Eigen::Vector4d acc2quaternion(const Eigen::Vector3d &vector_acc, const double &yaw);
};
Eigen::Vector4d geometry_controller::pos_controller(
const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State)
{
// 变量转换
for (int i=0; i<3; i++)
{
// 此处可能会存在更新频率较低的问题因为不是直接订阅的mavros消息
mavPos_[i] = _DroneState.position[i];
mavVel_[i] = _DroneState.velocity[i];
mavRate_[i] = _DroneState.attitude_rate[i];
targetPos_[i] = _Reference_State.position_ref[i];
targetVel_[i] = _Reference_State.velocity_ref[i];
targetAcc_[i] = _Reference_State.acceleration_ref[i];
}
mavAtt_(0) = _DroneState.attitude_q.w;
mavAtt_(1) = _DroneState.attitude_q.x;
mavAtt_(2) = _DroneState.attitude_q.y;
mavAtt_(3) = _DroneState.attitude_q.z;
// 计算
computeBodyRateCmd(cmdBodyRate_, targetPos_, targetVel_, targetAcc_);
return cmdBodyRate_;
}
// 计算角速率指令
void geometry_controller::computeBodyRateCmd(Eigen::Vector4d &bodyrate_cmd, const Eigen::Vector3d &target_pos,
const Eigen::Vector3d &target_vel, const Eigen::Vector3d &target_acc)
{
/// Compute BodyRate commands using differential flatness
/// 该控制器基于Faessler 2017论文论文名称
const Eigen::Vector3d a_ref = target_acc;
if (velocity_yaw_)
{
// 根据速度计算偏航角
mavYaw_ = getVelocityYaw(mavVel_);
}
const Eigen::Vector4d q_ref = acc2quaternion(a_ref - g_, mavYaw_);
const Eigen::Matrix3d R_ref = quat2RotMatrix(q_ref);
const Eigen::Vector3d pos_error = mavPos_ - target_pos;
const Eigen::Vector3d vel_error = mavVel_ - target_vel;
// 加速度 - 反馈部分
// 根据位置、速度误差计算同时设置限幅即max_fb_acc_
// Kpos_ 是三维向量Kpos_.asDiagonal()变成对角矩阵
Eigen::Vector3d a_fb =
Kpos_.asDiagonal() * pos_error + Kvel_.asDiagonal() * vel_error; // feedforward term for trajectory error
if (a_fb.norm() > max_fb_acc_)
a_fb = (max_fb_acc_ / a_fb.norm()) * a_fb; // Clip acceleration if reference is too large
/// Rotor drag
// 默认情况下D_为0
const Eigen::Vector3d a_rd = R_ref * D_.asDiagonal() * R_ref.transpose() * target_vel;
// 期望加速度 = 加速度反馈部分 + 加速度参考值 - rotor drag - 重力加速度
const Eigen::Vector3d a_des = a_fb + a_ref - a_rd - g_;
// 计算期望四元数
q_des = acc2quaternion(a_des, mavYaw_);
/// 计算 期望姿态角速度默认使用geometric_attcontroller
if (ctrl_mode_ == ERROR_GEOMETRIC)
{
bodyrate_cmd = geometric_attcontroller(q_des, a_des, mavAtt_); // Calculate BodyRate
} else {
bodyrate_cmd = attcontroller(q_des, a_des, mavAtt_); // Calculate BodyRate
}
}
Eigen::Vector4d geometry_controller::geometric_attcontroller(const Eigen::Vector4d &ref_att, const Eigen::Vector3d &ref_acc,
Eigen::Vector4d &curr_att)
{
// Geometric attitude controller
// Attitude error is defined as in Lee, Taeyoung, Melvin Leok, and N. Harris McClamroch. "Geometric tracking control
// of a quadrotor UAV on SE (3)." 49th IEEE conference on decision and control (CDC). IEEE, 2010.
// The original paper inputs moment commands, but for offboard control angular rate commands are sent
Eigen::Vector4d ratecmd;
Eigen::Matrix3d rotmat; // Rotation matrix of current atttitude
Eigen::Matrix3d rotmat_d; // Rotation matrix of desired attitude
Eigen::Vector3d zb;
Eigen::Vector3d error_att;
rotmat = quat2RotMatrix(curr_att);
rotmat_d = quat2RotMatrix(ref_att);
error_att = 0.5 * matrix_hat_inv(rotmat_d.transpose() * rotmat - rotmat.transpose() * rotmat);
ratecmd.head(3) = (2.0 / attctrl_tau_) * error_att;
rotmat = quat2RotMatrix(mavAtt_);
zb = rotmat.col(2);
ratecmd(3) =
std::max(0.0, std::min(1.0, norm_thrust_const_ * ref_acc.dot(zb) + norm_thrust_offset_)); // Calculate thrust
return ratecmd;
}
Eigen::Vector4d geometry_controller::attcontroller(const Eigen::Vector4d &ref_att, const Eigen::Vector3d &ref_acc,
Eigen::Vector4d &curr_att) {
// Geometric attitude controller
// Attitude error is defined as in Brescianini, Dario, Markus Hehn, and Raffaello D'Andrea. Nonlinear quadrocopter
// attitude control: Technical report. ETH Zurich, 2013.
Eigen::Vector4d ratecmd;
Eigen::Vector4d qe, q_inv, inverse;
Eigen::Matrix3d rotmat;
Eigen::Vector3d zb;
inverse << 1.0, -1.0, -1.0, -1.0;
q_inv = inverse.asDiagonal() * curr_att;
qe = quatMultiplication(q_inv, ref_att);
ratecmd(0) = (2.0 / attctrl_tau_) * std::copysign(1.0, qe(0)) * qe(1);
ratecmd(1) = (2.0 / attctrl_tau_) * std::copysign(1.0, qe(0)) * qe(2);
ratecmd(2) = (2.0 / attctrl_tau_) * std::copysign(1.0, qe(0)) * qe(3);
rotmat = quat2RotMatrix(mavAtt_);
zb = rotmat.col(2);
ratecmd(3) =
std::max(0.0, std::min(1.0, norm_thrust_const_ * ref_acc.dot(zb) + norm_thrust_offset_)); // Calculate thrust
return ratecmd;
}
Eigen::Vector4d geometry_controller::acc2quaternion(const Eigen::Vector3d &vector_acc, const double &yaw)
{
Eigen::Vector4d quat;
Eigen::Vector3d zb_des, yb_des, xb_des, proj_xb_des;
Eigen::Matrix3d rotmat;
proj_xb_des << std::cos(yaw), std::sin(yaw), 0.0;
zb_des = vector_acc / vector_acc.norm();
yb_des = zb_des.cross(proj_xb_des) / (zb_des.cross(proj_xb_des)).norm();
xb_des = yb_des.cross(zb_des) / (yb_des.cross(zb_des)).norm();
rotmat << xb_des(0), yb_des(0), zb_des(0), xb_des(1), yb_des(1), zb_des(1), xb_des(2), yb_des(2), zb_des(2);
quat = rot2Quaternion(rotmat);
return quat;
}
void geometry_controller::printf_result()
{
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
}
// 【打印参数函数】
void geometry_controller::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Geometry Control Parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"norm_thrust_const_ : "<< norm_thrust_const_ << endl;
cout <<"norm_thrust_offset_ : "<< norm_thrust_offset_ << endl;
}
#endif

@ -0,0 +1,318 @@
/***************************************************************************************************************************
* pos_controller_NE.h
*
* Author: Qyp
*
* Update Time: 2021.3.5
*
* Introduction: Position Controller using NE+UDE method
***************************************************************************************************************************/
#ifndef POS_CONTROLLER_NE_H
#define POS_CONTROLLER_NE_H
#include <Eigen/Eigen>
#include <math.h>
#include <command_to_mavros.h>
#include <prometheus_control_utils.h>
#include <math_utils.h>
#include <Filter/LowPassFilter.h>
#include <Filter/HighPassFilter.h>
#include <Filter/LeadLagFilter.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
using namespace std;
class pos_controller_NE
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
pos_controller_NE(void):
pos_NE_nh("~")
{
pos_NE_nh.param<float>("Quad/mass", Quad_MASS, 1.0);
pos_NE_nh.param<float>("Pos_ne/Kp_xy", Kp[0], 1.0);
pos_NE_nh.param<float>("Pos_ne/Kp_xy", Kp[1], 1.0);
pos_NE_nh.param<float>("Pos_ne/Kp_z", Kp[2], 1.0);
pos_NE_nh.param<float>("Pos_ne/Kd_xy", Kd[0], 2.0);
pos_NE_nh.param<float>("Pos_ne/Kd_xy", Kd[1], 2.0);
pos_NE_nh.param<float>("Pos_ne/Kd_z", Kd[2], 2.0);
pos_NE_nh.param<float>("Pos_ne/T_ude_xy", T_ude[0], 1.0);
pos_NE_nh.param<float>("Pos_ne/T_ude_xy", T_ude[1], 1.0);
pos_NE_nh.param<float>("Pos_ne/T_ude_z", T_ude[2], 1.0);
pos_NE_nh.param<float>("Pos_ne/T_ne", T_ne, 1.0);
pos_NE_nh.param<float>("Limit/pxy_error_max", pos_error_max[0], 0.6);
pos_NE_nh.param<float>("Limit/pxy_error_max", pos_error_max[1], 0.6);
pos_NE_nh.param<float>("Limit/pz_error_max" , pos_error_max[2], 1.0);
pos_NE_nh.param<float>("Limit/vxy_error_max", vel_error_max[0], 0.3);
pos_NE_nh.param<float>("Limit/vxy_error_max", vel_error_max[1], 0.3);
pos_NE_nh.param<float>("Limit/vz_error_max" , vel_error_max[2], 1.0);
pos_NE_nh.param<float>("Limit/pxy_int_max" , int_max[0], 0.5);
pos_NE_nh.param<float>("Limit/pxy_int_max" , int_max[1], 0.5);
pos_NE_nh.param<float>("Limit/pz_int_max" , int_max[2], 0.5);
pos_NE_nh.param<float>("Limit/tilt_max", tilt_max, 20.0);
pos_NE_nh.param<float>("Limit/int_start_error" , int_start_error, 0.3);
u_l = Eigen::Vector3f(0.0,0.0,0.0);
u_d = Eigen::Vector3f(0.0,0.0,0.0);
integral = Eigen::Vector3f(0.0,0.0,0.0);
integral_LLF = Eigen::Vector3f(0.0,0.0,0.0);
NoiseEstimator = Eigen::Vector3f(0.0,0.0,0.0);
output_LLF = Eigen::Vector3f(0.0,0.0,0.0);
set_filter();
}
//Quadrotor Parameter
float Quad_MASS;
//Limitation
Eigen::Vector3f pos_error_max;
Eigen::Vector3f vel_error_max;
Eigen::Vector3f int_max;
float tilt_max;
float int_start_error;
//NE control parameter
Eigen::Vector3f Kp;
Eigen::Vector3f Kd;
Eigen::Vector3f T_ude;
float T_ne;
prometheus_msgs::ControlOutput _ControlOutput;
//Filter for NE
LowPassFilter LPF_x;
LowPassFilter LPF_y;
LowPassFilter LPF_z;
HighPassFilter HPF_x;
HighPassFilter HPF_y;
HighPassFilter HPF_z;
LeadLagFilter LLF_x;
LeadLagFilter LLF_y;
LeadLagFilter LLF_z;
//u_l for nominal contorol(PD), u_d for NE control(disturbance estimator)
Eigen::Vector3f u_l,u_d;
Eigen::Vector3f integral;
Eigen::Vector3f integral_LLF;
Eigen::Vector3f output_LLF;
Eigen::Vector3d pos_initial;
Eigen::Vector3f NoiseEstimator;
//Printf the NE parameter
void printf_param();
//Printf the control result
void printf_result();
// Position control main function
// [Input: Current state, Reference state, sub_mode, dt; Output: AttitudeReference;]
prometheus_msgs::ControlOutput pos_controller(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, float dt);
void set_initial_pos(const Eigen::Vector3d& pos);
void set_filter();
private:
ros::NodeHandle pos_NE_nh;
};
void pos_controller_NE::set_filter()
{
LPF_x.set_Time_constant(T_ne);
LPF_y.set_Time_constant(T_ne);
LPF_z.set_Time_constant(T_ne);
HPF_x.set_Time_constant(T_ne);
HPF_y.set_Time_constant(T_ne);
HPF_z.set_Time_constant(T_ne);
LLF_x.set_Time_constant(T_ne, Kd[0]);
LLF_y.set_Time_constant(T_ne, Kd[1]);
LLF_z.set_Time_constant(T_ne, Kd[2]);
}
void pos_controller_NE::set_initial_pos(const Eigen::Vector3d& pos)
{
pos_initial = pos;
}
prometheus_msgs::ControlOutput pos_controller_NE::pos_controller(
const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State, float dt)
{
Eigen::Vector3d accel_sp;
// 计算误差项
Eigen::Vector3f pos_error;
Eigen::Vector3f vel_error;
pos_error = prometheus_control_utils::cal_pos_error(_DroneState, _Reference_State);
vel_error = prometheus_control_utils::cal_vel_error(_DroneState, _Reference_State);
// 误差项限幅
for (int i=0; i<3; i++)
{
pos_error[i] = constrain_function(pos_error[i], pos_error_max[i]);
vel_error[i] = constrain_function(vel_error[i], vel_error_max[i]);
}
//Noise estimator
NoiseEstimator[0] = LPF_x.apply(_DroneState.velocity[0], dt) + HPF_x.apply(pos_initial[0] - _DroneState.position[0], dt);
NoiseEstimator[1] = LPF_y.apply(_DroneState.velocity[1], dt) + HPF_y.apply(pos_initial[1] - _DroneState.position[1], dt);
NoiseEstimator[2] = LPF_z.apply(_DroneState.velocity[2], dt) + HPF_z.apply(pos_initial[2] - _DroneState.position[2], dt);
//u_l
for (int i = 0; i < 3; i++)
{
u_l[i] = _Reference_State.acceleration_ref[i] + Kp[i] * pos_error[i] + Kd[i] * ( vel_error[i] + NoiseEstimator[i]);
}
//UDE term
Eigen::Vector3f input_LLF;
for (int i = 0; i < 3; i++)
{
integral_LLF[i] = integral_LLF[i] + _DroneState.velocity[i] * dt;
input_LLF[i] = integral_LLF[i] - _DroneState.position[i] + pos_initial[i];
}
output_LLF[0] = LLF_x.apply(input_LLF[0], dt);
output_LLF[1] = LLF_y.apply(input_LLF[1], dt);
output_LLF[2] = LLF_z.apply(input_LLF[2], dt);
for (int i = 0; i < 3; i++)
{
u_d[i] = 1.0 / T_ude[i] * ( _DroneState.velocity[i] - output_LLF[i] - integral[i] );
}
// 更新积分项
for (int i=0; i<3; i++)
{
integral[i] = integral[i] + ( _Reference_State.acceleration_ref[i] + Kp[i] * pos_error[i] + Kd[i] * vel_error[i]) * dt;
// If not in OFFBOARD mode, set all intergral to zero.
if(_DroneState.mode != "OFFBOARD")
{
integral[i] = 0;
}
if(abs(u_d[i]) > int_max[i])
{
cout << "u_d saturation! " << " [0-1-2] "<< i <<endl;
cout << "[u_d]: "<< u_d[i]<<" [u_d_max]: "<<int_max[i]<<" [m/s] "<<endl;
}
u_d[i] = constrain_function(u_d[i], int_max[i]);
}
// 期望加速度
accel_sp[0] = u_l[0] - u_d[0];
accel_sp[1] = u_l[1] - u_d[1];
accel_sp[2] = u_l[2] - u_d[2] + 9.8;
// 期望推力 = 期望加速度 × 质量
// 归一化推力 根据电机模型,反解出归一化推力
Eigen::Vector3d thrust_sp;
Eigen::Vector3d throttle_sp;
thrust_sp = prometheus_control_utils::accelToThrust(accel_sp, Quad_MASS, tilt_max);
throttle_sp = prometheus_control_utils::thrustToThrottle(thrust_sp);
for (int i=0; i<3; i++)
{
_ControlOutput.u_l[i] = u_l[i];
_ControlOutput.u_d[i] = u_d[i];
_ControlOutput.Thrust[i] = thrust_sp[i];
_ControlOutput.Throttle[i] = throttle_sp[i];
_ControlOutput.NE[i] = NoiseEstimator[i];
}
return _ControlOutput;
}
void pos_controller_NE::printf_result()
{
cout <<">>>>>>>>>>>>>>>>>>>>>> NE Position Controller <<<<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
cout << "NoiseEstimator [X Y Z] : " << Quad_MASS *Kd[0] * NoiseEstimator[0] << " [N] "<<Quad_MASS *Kd[1] * NoiseEstimator[1]<<" [N] "<<Quad_MASS *Kd[2] *NoiseEstimator[2]<<" [N] "<<endl;
cout << "output_LLF [X Y Z] : " << output_LLF[0] << " [N] "<< output_LLF[1]<<" [N] "<<output_LLF[2]<<" [N] "<<endl;
cout << "u_l [X Y Z] : " << u_l[0] << " [N] "<< u_l[1]<<" [N] "<<u_l[2]<<" [N] "<<endl;
cout << "u_d [X Y Z] : " << u_d[0] << " [N] "<< u_d[1]<<" [N] "<<u_d[2]<<" [N] "<<endl;
}
// 【打印参数函数】
void pos_controller_NE::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>NE Parameter <<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"Quad_MASS : "<< Quad_MASS << endl;
cout <<"Kp_X : "<< Kp[0] << endl;
cout <<"Kp_Y : "<< Kp[1] << endl;
cout <<"Kp_Z : "<< Kp[2] << endl;
cout <<"Kd_X : "<< Kd[0] << endl;
cout <<"Kd_Y : "<< Kd[1] << endl;
cout <<"Kd_Z : "<< Kd[2] << endl;
cout <<"NE_T_X : "<< T_ude[0] << endl;
cout <<"NE_T_Y : "<< T_ude[1] << endl;
cout <<"NE_T_Z : "<< T_ude[2] << endl;
cout <<"T_ne : "<< T_ne << endl;
cout <<"Limit: " <<endl;
cout <<"pxy_error_max : "<< pos_error_max[0] << endl;
cout <<"pz_error_max : "<< pos_error_max[2] << endl;
cout <<"vxy_error_max : "<< vel_error_max[0] << endl;
cout <<"vz_error_max : "<< vel_error_max[2] << endl;
cout <<"pxy_int_max : "<< int_max[0] << endl;
cout <<"pz_int_max : "<< int_max[2] << endl;
cout <<"tilt_max : "<< tilt_max << endl;
cout <<"int_start_error : "<< int_start_error << endl;
cout <<"Filter_LPFx : "<< LPF_x.get_Time_constant()<<" Filter_LPFy : "<< LPF_y.get_Time_constant()<<" Filter_LPFz : "<< LPF_z.get_Time_constant() << endl;
cout <<"Filter_HPFx : "<< HPF_x.get_Time_constant()<<" Filter_HPFy : "<< HPF_y.get_Time_constant()<<" Filter_HPFz : "<< HPF_z.get_Time_constant() << endl;
cout <<"Filter_LLFx : "<< LLF_x.get_Time_constant()<<" Filter_LLFy : "<< LLF_y.get_Time_constant()<<" Filter_LLFz : "<< LLF_z.get_Time_constant() << endl;
cout <<"kd_LLFx : "<< LLF_x.get_Kd() <<" kd_LLFy : "<< LLF_y.get_Kd() <<" kd_LLFz : "<< LLF_z.get_Kd() << endl;
}
#endif

@ -0,0 +1,215 @@
/***************************************************************************************************************************
* pos_controller_PID.h
*
* Author: Qyp
*
* Update Time: 2019.6.29
*
* Introduction: Position Controller using normal PID
* output = a_ff + K_p * pos_error + K_d * vel_error + K_i * pos_error * dt;
***************************************************************************************************************************/
#ifndef POS_CONTROLLER_PID_H
#define POS_CONTROLLER_PID_H
#include <math.h>
#include <command_to_mavros.h>
#include <prometheus_control_utils.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
using namespace std;
class pos_controller_PID
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
pos_controller_PID(void):
pos_pid_nh("~")
{
pos_pid_nh.param<float>("Quad/mass", Quad_MASS, 1.5);
pos_pid_nh.param<float>("Pos_pid/Kp_xy", Kp[0], 2.5);
pos_pid_nh.param<float>("Pos_pid/Kp_xy", Kp[1], 2.5);
pos_pid_nh.param<float>("Pos_pid/Kp_z" , Kp[2], 2.5);
pos_pid_nh.param<float>("Pos_pid/Kd_xy", Kd[0], 3.0);
pos_pid_nh.param<float>("Pos_pid/Kd_xy", Kd[1], 3.0);
pos_pid_nh.param<float>("Pos_pid/Kd_z" , Kd[2], 3.0);
pos_pid_nh.param<float>("Pos_pid/Ki_xy", Ki[0], 0.5);
pos_pid_nh.param<float>("Pos_pid/Ki_xy", Ki[1], 0.5);
pos_pid_nh.param<float>("Pos_pid/Ki_z" , Ki[2], 0.5);
pos_pid_nh.param<float>("Limit/pxy_error_max", pos_error_max[0], 10.0);
pos_pid_nh.param<float>("Limit/pxy_error_max", pos_error_max[1], 10.0);
pos_pid_nh.param<float>("Limit/pz_error_max" , pos_error_max[2], 10.0);
pos_pid_nh.param<float>("Limit/vxy_error_max", vel_error_max[0], 10.0);
pos_pid_nh.param<float>("Limit/vxy_error_max", vel_error_max[1], 10.0);
pos_pid_nh.param<float>("Limit/vz_error_max" , vel_error_max[2], 10.0);
pos_pid_nh.param<float>("Limit/pxy_int_max" , int_max[0], 10.0);
pos_pid_nh.param<float>("Limit/pxy_int_max" , int_max[1], 10.0);
pos_pid_nh.param<float>("Limit/pz_int_max" , int_max[2], 10.0);
pos_pid_nh.param<float>("Limit/tilt_max", tilt_max, 20.0);
pos_pid_nh.param<float>("Limit/int_start_error" , int_start_error, 10.0);
integral = Eigen::Vector3f(0.0,0.0,0.0);
}
//Quadrotor Parameter
float Quad_MASS;
//PID parameter for the control law
Eigen::Vector3f Kp;
Eigen::Vector3f Kd;
Eigen::Vector3f Ki;
//Limitation
Eigen::Vector3f pos_error_max;
Eigen::Vector3f vel_error_max;
Eigen::Vector3f int_max;
float tilt_max;
float int_start_error;
//积分项
Eigen::Vector3f integral;
//输出
prometheus_msgs::ControlOutput _ControlOutput;
//Printf the PID parameter
void printf_param();
void printf_result();
// Position control main function
// [Input: Current state, Reference state, sub_mode, dt; Output: AttitudeReference;]
prometheus_msgs::ControlOutput pos_controller(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, float dt);
private:
ros::NodeHandle pos_pid_nh;
};
prometheus_msgs::ControlOutput pos_controller_PID::pos_controller(
const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State, float dt)
{
Eigen::Vector3d accel_sp;
// 计算误差项
Eigen::Vector3f pos_error;
Eigen::Vector3f vel_error;
pos_error = prometheus_control_utils::cal_pos_error(_DroneState, _Reference_State);
vel_error = prometheus_control_utils::cal_vel_error(_DroneState, _Reference_State);
// 误差项限幅
for (int i=0; i<3; i++)
{
pos_error[i] = constrain_function(pos_error[i], pos_error_max[i]);
vel_error[i] = constrain_function(vel_error[i], vel_error_max[i]);
}
// 期望加速度 = 加速度前馈 + PID
for (int i=0; i<3; i++)
{
accel_sp[i] = _Reference_State.acceleration_ref[i] + Kp[i] * pos_error[i] + Kd[i] * vel_error[i] + Ki[i] * integral[i];
}
accel_sp[2] = accel_sp[2] + 9.8;
// 更新积分项
for (int i=0; i<3; i++)
{
if(abs(pos_error[i]) < int_start_error)
{
integral[i] += pos_error[i] * dt;
if(abs(integral[i]) > int_max[i])
{
cout << "Integral saturation! " << " [0-1-2] "<< i <<endl;
cout << "[integral]: "<< integral[i]<<" [int_max]: "<<int_max[i]<<" [m/s] "<<endl;
}
integral[i] = constrain_function(integral[i], int_max[i]);
}else
{
integral[i] = 0;
}
// If not in OFFBOARD mode, set all intergral to zero.
if(_DroneState.mode != "OFFBOARD")
{
integral[i] = 0;
}
}
// 期望推力 = 期望加速度 × 质量
// 归一化推力 根据电机模型,反解出归一化推力
Eigen::Vector3d thrust_sp;
Eigen::Vector3d throttle_sp;
thrust_sp = prometheus_control_utils::accelToThrust(accel_sp, Quad_MASS, tilt_max);
throttle_sp = prometheus_control_utils::thrustToThrottle(thrust_sp);
for (int i=0; i<3; i++)
{
_ControlOutput.Thrust[i] = thrust_sp[i];
_ControlOutput.Throttle[i] = throttle_sp[i];
}
return _ControlOutput;
}
void pos_controller_PID::printf_result()
{
cout <<">>>>>>>>>>>>>>>>>>>>>> PID Position Controller <<<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
}
// 【打印参数函数】
void pos_controller_PID::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>PID Parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"Quad_MASS : "<< Quad_MASS << endl;
cout <<"Kp_x : "<< Kp[0] << endl;
cout <<"Kp_y : "<< Kp[1] << endl;
cout <<"Kp_z : "<< Kp[2] << endl;
cout <<"Kd_x : "<< Kd[0] << endl;
cout <<"Kd_y : "<< Kd[1] << endl;
cout <<"Kd_z : "<< Kd[2] << endl;
cout <<"Ki_x : "<< Ki[0] << endl;
cout <<"Ki_y : "<< Ki[1] << endl;
cout <<"Ki_z : "<< Ki[2] << endl;
cout <<"Limit: " <<endl;
cout <<"pxy_error_max : "<< pos_error_max[0] << endl;
cout <<"pz_error_max : "<< pos_error_max[2] << endl;
cout <<"vxy_error_max : "<< vel_error_max[0] << endl;
cout <<"vz_error_max : "<< vel_error_max[2] << endl;
cout <<"pxy_int_max : "<< int_max[0] << endl;
cout <<"pz_int_max : "<< int_max[2] << endl;
cout <<"tilt_max : "<< tilt_max << endl;
cout <<"int_start_error : "<< int_start_error << endl;
}
#endif

@ -0,0 +1,308 @@
/***************************************************************************************************************************
* pos_controller_passivity.h
*
* Author: Qyp
*
* Update Time: 2019.5.1
*
* Introduction: Position Controller using passivity+UDE method
***************************************************************************************************************************/
#ifndef POS_CONTROLLER_PASSIVITY_H
#define POS_CONTROLLER_PASSIVITY_H
#include <Eigen/Eigen>
#include <math.h>
#include <command_to_mavros.h>
#include <prometheus_control_utils.h>
#include <math_utils.h>
#include <Filter/LowPassFilter.h>
#include <Filter/HighPassFilter.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
using namespace std;
class pos_controller_passivity
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
pos_controller_passivity(void):
pos_passivity_nh("~")
{
pos_passivity_nh.param<float>("Quad/mass", Quad_MASS, 1.0);
pos_passivity_nh.param<float>("Pos_passivity/Kp_xy", Kp[0], 1.0);
pos_passivity_nh.param<float>("Pos_passivity/Kp_xy", Kp[1], 1.0);
pos_passivity_nh.param<float>("Pos_passivity/Kp_z", Kp[2], 1.0);
pos_passivity_nh.param<float>("Pos_passivity/Kd_xy", Kd[0], 2.0);
pos_passivity_nh.param<float>("Pos_passivity/Kd_xy", Kd[1], 2.0);
pos_passivity_nh.param<float>("Pos_passivity/Kd_z", Kd[2], 2.0);
pos_passivity_nh.param<float>("Pos_passivity/T_ude_xy", T_ude[0], 1.0);
pos_passivity_nh.param<float>("Pos_passivity/T_ude_xy", T_ude[1], 1.0);
pos_passivity_nh.param<float>("Pos_passivity/T_ude_z", T_ude[2], 1.0);
pos_passivity_nh.param<float>("Pos_passivity/T_ps", T_ps, 1.0);
pos_passivity_nh.param<float>("Limit/pxy_error_max", pos_error_max[0], 0.6);
pos_passivity_nh.param<float>("Limit/pxy_error_max", pos_error_max[1], 0.6);
pos_passivity_nh.param<float>("Limit/pz_error_max" , pos_error_max[2], 1.0);
pos_passivity_nh.param<float>("Limit/vxy_error_max", vel_error_max[0], 0.3);
pos_passivity_nh.param<float>("Limit/vxy_error_max", vel_error_max[1], 0.3);
pos_passivity_nh.param<float>("Limit/vz_error_max" , vel_error_max[2], 1.0);
pos_passivity_nh.param<float>("Limit/pxy_int_max" , int_max[0], 0.5);
pos_passivity_nh.param<float>("Limit/pxy_int_max" , int_max[1], 0.5);
pos_passivity_nh.param<float>("Limit/pz_int_max" , int_max[2], 0.5);
pos_passivity_nh.param<float>("Limit/tilt_max", tilt_max, 20.0);
pos_passivity_nh.param<float>("Limit/int_start_error" , int_start_error, 0.3);
u_l = Eigen::Vector3f(0.0,0.0,0.0);
u_d = Eigen::Vector3f(0.0,0.0,0.0);
integral = Eigen::Vector3f(0.0,0.0,0.0);
y1_k = Eigen::Vector3f(0.0,0.0,0.0);
y2_k = Eigen::Vector3f(0.0,0.0,0.0);
y3_k = Eigen::Vector3f(0.0,0.0,0.0);
z_k = Eigen::Vector3f(0.0,0.0,0.0);
set_filter();
}
//Quadrotor Parameter
float Quad_MASS;
//passivity control parameter
Eigen::Vector3f Kp;
Eigen::Vector3f Kd;
Eigen::Vector3f T_ude;
float T_ps;
//Limitation
Eigen::Vector3f pos_error_max;
Eigen::Vector3f vel_error_max;
Eigen::Vector3f int_max;
float tilt_max;
float int_start_error;
//u_l for nominal contorol(PD), u_d for passivity control(disturbance estimator)
Eigen::Vector3f u_l,u_d;
Eigen::Vector3f integral;
prometheus_msgs::ControlOutput _ControlOutput;
HighPassFilter HPF_pos_error_x;
HighPassFilter HPF_pos_error_y;
HighPassFilter HPF_pos_error_z;
HighPassFilter HPF_pos_x;
HighPassFilter HPF_pos_y;
HighPassFilter HPF_pos_z;
LowPassFilter LPF_pos_error_x;
LowPassFilter LPF_pos_error_y;
LowPassFilter LPF_pos_error_z;
LowPassFilter LPF_int_x;
LowPassFilter LPF_int_y;
LowPassFilter LPF_int_z;
Eigen::Vector3f z_k;
Eigen::Vector3f y1_k,y2_k,y3_k;
//Printf the passivity parameter
void printf_param();
//Printf the control result
void printf_result();
void set_filter();
// Position control main function
// [Input: Current state, Reference state, sub_mode, dt; Output: AttitudeReference;]
prometheus_msgs::ControlOutput pos_controller(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, float dt);
private:
ros::NodeHandle pos_passivity_nh;
};
void pos_controller_passivity::set_filter()
{
HPF_pos_error_x.set_Time_constant(T_ps);
HPF_pos_error_y.set_Time_constant(T_ps);
HPF_pos_error_z.set_Time_constant(T_ps);
HPF_pos_x.set_Time_constant(T_ude[0]);
HPF_pos_y.set_Time_constant(T_ude[1]);
HPF_pos_z.set_Time_constant(T_ude[2]);
LPF_pos_error_x.set_Time_constant(T_ps);
LPF_pos_error_y.set_Time_constant(T_ps);
LPF_pos_error_z.set_Time_constant(T_ps);
LPF_int_x.set_Time_constant(T_ude[0]);
LPF_int_x.set_Time_constant(T_ude[1]);
LPF_int_x.set_Time_constant(T_ude[2]);
}
prometheus_msgs::ControlOutput pos_controller_passivity::pos_controller(
const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State, float dt)
{
Eigen::Vector3d accel_sp;
// 计算误差项
Eigen::Vector3f pos_error;
pos_error = prometheus_control_utils::cal_pos_error(_DroneState, _Reference_State);
// 误差项限幅
for (int i=0; i<3; i++)
{
pos_error[i] = constrain_function(pos_error[i], pos_error_max[i]);
}
//z_k
z_k[0] = HPF_pos_error_x.apply(pos_error[0], dt);
z_k[1] = HPF_pos_error_y.apply(pos_error[1], dt);
z_k[2] = HPF_pos_error_z.apply(pos_error[2], dt);
//u_l
for (int i = 0; i < 3; i++)
{
u_l[i] = _Reference_State.acceleration_ref[i] + (Kp[i] * pos_error[i] + Kd[i] * z_k[i]);
}
//UDE term y1 y2 y3
y1_k[0] = HPF_pos_x.apply(_DroneState.position[0], dt);
y1_k[1] = HPF_pos_y.apply(_DroneState.position[1], dt);
y1_k[2] = HPF_pos_z.apply(_DroneState.position[2], dt);
y2_k[0] = LPF_pos_error_x.apply(pos_error[0], dt);
y2_k[1] = LPF_pos_error_y.apply(pos_error[1], dt);
y2_k[2] = LPF_pos_error_z.apply(pos_error[2], dt);
y3_k[0] = LPF_int_x.apply(_Reference_State.acceleration_ref[0] + Kp[0] * integral[0] + Kd[0] * y2_k[0], dt);
y3_k[1] = LPF_int_y.apply(_Reference_State.acceleration_ref[1] + Kp[1] * integral[1] + Kd[1] * y2_k[1], dt);
y3_k[2] = LPF_int_z.apply(_Reference_State.acceleration_ref[2] + Kp[2] * integral[2] + Kd[2] * y2_k[2], dt);
for (int i = 0; i < 3; i++)
{
u_d[i] = y1_k[i] - y3_k[i];
}
// 更新积分项
for (int i=0; i<3; i++)
{
integral[i] += pos_error[i] * dt;
// If not in OFFBOARD mode, set all intergral to zero.
if(_DroneState.mode != "OFFBOARD")
{
integral[i] = 0;
}
if(abs(u_d[i]) > int_max[i])
{
cout << "u_d saturation! " << " [0-1-2] "<< i <<endl;
cout << "[u_d]: "<< u_d[i]<<" [u_d_max]: "<<int_max[i]<<" [m/s] "<<endl;
}
u_d[i] = constrain_function(u_d[i], int_max[i]);
}
// 期望加速度
accel_sp[0] = u_l[0] - u_d[0];
accel_sp[1] = u_l[1] - u_d[1];
accel_sp[2] = u_l[2] - u_d[2] + 9.8;
// 期望推力 = 期望加速度 × 质量
// 归一化推力 根据电机模型,反解出归一化推力
Eigen::Vector3d thrust_sp;
Eigen::Vector3d throttle_sp;
thrust_sp = prometheus_control_utils::accelToThrust(accel_sp, Quad_MASS, tilt_max);
throttle_sp = prometheus_control_utils::thrustToThrottle(thrust_sp);
for (int i=0; i<3; i++)
{
_ControlOutput.u_l[i] = u_l[i];
_ControlOutput.u_d[i] = u_d[i];
_ControlOutput.Thrust[i] = thrust_sp[i];
_ControlOutput.Throttle[i] = throttle_sp[i];
}
return _ControlOutput;
}
// 【打印参数函数】
void pos_controller_passivity::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>passivity Parameter <<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"Quad_MASS : "<< Quad_MASS << endl;
cout <<"Kp_X : "<< Kp[0] << endl;
cout <<"Kp_Y : "<< Kp[1] << endl;
cout <<"Kp_Z : "<< Kp[2] << endl;
cout <<"Kd_X : "<< Kd[0] << endl;
cout <<"Kd_Y : "<< Kd[1] << endl;
cout <<"Kd_Z : "<< Kd[2] << endl;
cout <<"passivity_T_X : "<< T_ude[0] << endl;
cout <<"passivity_T_Y : "<< T_ude[1] << endl;
cout <<"passivity_T_Z : "<< T_ude[2] << endl;
cout <<"T_ps : "<< T_ps << endl;
cout <<"Limit: " <<endl;
cout <<"pxy_error_max : "<< pos_error_max[0] << endl;
cout <<"pz_error_max : "<< pos_error_max[2] << endl;
cout <<"vxy_error_max : "<< vel_error_max[0] << endl;
cout <<"vz_error_max : "<< vel_error_max[2] << endl;
cout <<"pxy_int_max : "<< int_max[0] << endl;
cout <<"pz_int_max : "<< int_max[2] << endl;
cout <<"tilt_max : "<< tilt_max << endl;
cout <<"int_start_error : "<< int_start_error << endl;
}
void pos_controller_passivity::printf_result()
{
cout <<">>>>>>>>>>>>>>>>>>>> Passivity Position Controller <<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
cout << "z_k [X Y Z] : " << z_k[0] << " [N] "<< z_k[1]<<" [N] "<<z_k[2]<<" [N] "<<endl;
cout << "y1 [X Y Z] : " << y1_k[0] << " [N] "<< y1_k[1]<<" [N] "<<y1_k[2]<<" [N] "<<endl;
cout << "y2 [X Y Z] : " << y2_k[0] << " [N] "<< y2_k[1]<<" [N] "<<y2_k[2]<<" [N] "<<endl;
cout << "y3 [X Y Z] : " << y3_k[0] << " [N] "<< y3_k[1]<<" [N] "<<y3_k[2]<<" [N] "<<endl;
cout << "u_l [X Y Z] : " << u_l[0] << " [N] "<< u_l[1]<<" [N] "<<u_l[2]<<" [N] "<<endl;
cout << "u_d [X Y Z] : " << u_d[0] << " [N] "<< u_d[1]<<" [N] "<<u_d[2]<<" [N] "<<endl;
}
#endif

@ -0,0 +1,241 @@
/***************************************************************************************************************************
* pos_controller_UDE.h
*
* Author: Qyp
*
* Update Time: 2019.4.12
*
* Introduction: Position Controller using UDE method
* 1. Ref to Zhongqingchang's paper:
* Uncertainty and Disturbance Estimator-Based Robust Trajectory Tracking Control for a Quadrotor in a Global Positioning System-Denied Environment
* 2. Ref to : https://github.com/PX4/Firmware/blob/master/src/modules/mc_pos_control/PositionControl.cpp
* 3. ThrottleToAttitude ref to https://github.com/PX4/Firmware/blob/master/src/modules/mc_pos_control/Utility/ControlMath.cpp
* 4. 0
* 5. PX4z-100
***************************************************************************************************************************/
#ifndef POS_CONTROLLER_UDE_H
#define POS_CONTROLLER_UDE_H
#include <Eigen/Eigen>
#include <math.h>
#include <command_to_mavros.h>
#include <prometheus_control_utils.h>
#include <math_utils.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
using namespace std;
class pos_controller_UDE
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
pos_controller_UDE(void):
pos_UDE_nh("~")
{
pos_UDE_nh.param<float>("Quad/mass", Quad_MASS, 1.0);
pos_UDE_nh.param<float>("Pos_ude/Kp_xy", Kp[0], 1.0);
pos_UDE_nh.param<float>("Pos_ude/Kp_xy", Kp[1], 1.0);
pos_UDE_nh.param<float>("Pos_ude/Kp_z", Kp[2], 1.0);
pos_UDE_nh.param<float>("Pos_ude/Kd_xy", Kd[0], 2.0);
pos_UDE_nh.param<float>("Pos_ude/Kd_xy", Kd[1], 2.0);
pos_UDE_nh.param<float>("Pos_ude/Kd_z", Kd[2], 2.0);
pos_UDE_nh.param<float>("Pos_ude/T_ude_xy", T_ude[0], 1.0);
pos_UDE_nh.param<float>("Pos_ude/T_ude_xy", T_ude[1], 1.0);
pos_UDE_nh.param<float>("Pos_ude/T_ude_z", T_ude[2], 1.0);
pos_UDE_nh.param<float>("Limit/pxy_error_max", pos_error_max[0], 0.6);
pos_UDE_nh.param<float>("Limit/pxy_error_max", pos_error_max[1], 0.6);
pos_UDE_nh.param<float>("Limit/pz_error_max" , pos_error_max[2], 1.0);
pos_UDE_nh.param<float>("Limit/vxy_error_max", vel_error_max[0], 0.3);
pos_UDE_nh.param<float>("Limit/vxy_error_max", vel_error_max[1], 0.3);
pos_UDE_nh.param<float>("Limit/vz_error_max" , vel_error_max[2], 1.0);
pos_UDE_nh.param<float>("Limit/pxy_int_max" , int_max[0], 0.5);
pos_UDE_nh.param<float>("Limit/pxy_int_max" , int_max[1], 0.5);
pos_UDE_nh.param<float>("Limit/pz_int_max" , int_max[2], 0.5);
pos_UDE_nh.param<float>("Limit/tilt_max", tilt_max, 20.0);
pos_UDE_nh.param<float>("Limit/int_start_error" , int_start_error, 0.3);
u_l = Eigen::Vector3f(0.0,0.0,0.0);
u_d = Eigen::Vector3f(0.0,0.0,0.0);
integral = Eigen::Vector3f(0.0,0.0,0.0);
}
//Quadrotor Parameter
float Quad_MASS;
//UDE control parameter
Eigen::Vector3f Kp;
Eigen::Vector3f Kd;
Eigen::Vector3f T_ude;
//Limitation
Eigen::Vector3f pos_error_max;
Eigen::Vector3f vel_error_max;
Eigen::Vector3f int_max;
float tilt_max;
float int_start_error;
//u_l for nominal contorol(PD), u_d for ude control(disturbance estimator)
Eigen::Vector3f u_l,u_d;
Eigen::Vector3f integral;
prometheus_msgs::ControlOutput _ControlOutput;
//Printf the UDE parameter
void printf_param();
//Printf the control result
void printf_result();
// Position control main function
// [Input: Current state, Reference state, sub_mode, dt; Output: AttitudeReference;]
prometheus_msgs::ControlOutput pos_controller(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, float dt);
private:
ros::NodeHandle pos_UDE_nh;
};
prometheus_msgs::ControlOutput pos_controller_UDE::pos_controller(
const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State, float dt)
{
Eigen::Vector3d accel_sp;
// 计算误差项
Eigen::Vector3f pos_error;
Eigen::Vector3f vel_error;
pos_error = prometheus_control_utils::cal_pos_error(_DroneState, _Reference_State);
vel_error = prometheus_control_utils::cal_vel_error(_DroneState, _Reference_State);
// 误差项限幅
for (int i=0; i<3; i++)
{
pos_error[i] = constrain_function(pos_error[i], pos_error_max[i]);
vel_error[i] = constrain_function(vel_error[i], vel_error_max[i]);
}
// UDE算法
for (int i = 0; i < 3; i++)
{
u_l[i] = _Reference_State.acceleration_ref[i] + Kp[i] * pos_error[i] + Kd[i] * vel_error[i];
u_d[i] = - 1.0 / T_ude[i] * (Kd[i] * pos_error[i] + vel_error[i] + Kp[i] * integral[i]);
}
// 更新积分项
for (int i=0; i<3; i++)
{
if(abs(pos_error[i]) < int_start_error)
{
integral[i] += pos_error[i] * dt;
}else
{
integral[i] = 0;
}
if(_DroneState.mode != "OFFBOARD")
{
integral[i] = 0;
}
if(abs(u_d[i]) > int_max[i])
{
cout << "u_d saturation! " << " [0-1-2] "<< i <<endl;
cout << "[u_d]: "<< u_d[i]<<" [u_d_max]: "<<int_max[i]<<" [m/s] "<<endl;
}
u_d[i] = constrain_function(u_d[i], int_max[i]);
}
// 期望加速度
accel_sp[0] = u_l[0] - u_d[0];
accel_sp[1] = u_l[1] - u_d[1];
accel_sp[2] = u_l[2] - u_d[2] + 9.8;
// 期望推力 = 期望加速度 × 质量
// 归一化推力 根据电机模型,反解出归一化推力
Eigen::Vector3d thrust_sp;
Eigen::Vector3d throttle_sp;
thrust_sp = prometheus_control_utils::accelToThrust(accel_sp, Quad_MASS, tilt_max);
throttle_sp = prometheus_control_utils::thrustToThrottle(thrust_sp);
for (int i=0; i<3; i++)
{
_ControlOutput.u_l[i] = u_l[i];
_ControlOutput.u_d[i] = u_d[i];
_ControlOutput.Thrust[i] = thrust_sp[i];
_ControlOutput.Throttle[i] = throttle_sp[i];
}
return _ControlOutput;
}
void pos_controller_UDE::printf_result()
{
cout <<">>>>>>>>>>>>>>>>>>>> PD+UDE Position Controller <<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
cout << "u_l [X Y Z] : " << u_l[0] << " [N] "<< u_l[1]<<" [N] "<<u_l[2]<<" [N] "<<endl;
cout << "int [X Y Z] : " << integral[0] << " [N] "<< integral[1]<<" [N] "<<integral[2]<<" [N] "<<endl;
cout << "u_d [X Y Z] : " << u_d[0] << " [N] "<< u_d[1]<<" [N] "<<u_d[2]<<" [N] "<<endl;
}
// 【打印参数函数】
void pos_controller_UDE::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>UDE Parameter <<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"Quad_MASS : "<< Quad_MASS << endl;
cout <<"Kp_x : "<< Kp[0] << endl;
cout <<"Kp_y : "<< Kp[1] << endl;
cout <<"Kp_z : "<< Kp[2] << endl;
cout <<"Kd_x : "<< Kd[0] << endl;
cout <<"Kd_y : "<< Kd[1] << endl;
cout <<"Kd_z : "<< Kd[2] << endl;
cout <<"T_ude_x : "<< T_ude[0] << endl;
cout <<"T_ude_y : "<< T_ude[1] << endl;
cout <<"T_ude_z : "<< T_ude[2] << endl;
cout <<"Limit: " <<endl;
cout <<"pxy_error_max : "<< pos_error_max[0] << endl;
cout <<"pz_error_max : "<< pos_error_max[2] << endl;
cout <<"vxy_error_max : "<< vel_error_max[0] << endl;
cout <<"vz_error_max : "<< vel_error_max[2] << endl;
cout <<"pxy_int_max : "<< int_max[0] << endl;
cout <<"pz_int_max : "<< int_max[2] << endl;
cout <<"tilt_max : "<< tilt_max << endl;
cout <<"int_start_error : "<< int_start_error << endl;
}
#endif

@ -0,0 +1,390 @@
/***************************************************************************************************************************
* pos_controller_cascade_PID.h
*
* Author: Qyp
*
* Update Time: 2019.5.1
*
* Introduction: Position Controller using PID (P for pos loop, pid for vel loop)
* 1. Similiar to the position controller in PX4 (1.8.2)
* 2. Ref to : https://github.com/PX4/Firmware/blob/master/src/modules/mc_pos_control/PositionControl.cpp
* 3. Here we didn't consider the mass of the drone, we treat accel_sp is the thrust_sp.
* 4. ThrottleToAttitude ref to https://github.com/PX4/Firmware/blob/master/src/modules/mc_pos_control/Utility/ControlMath.cpp
* 5. For the derrive of the velocity error, we use a low-pass filter as same in PX4.
* Ref to: https://github.com/PX4/Firmware/blob/master/src/lib/controllib/BlockDerivative.cpp
* https://github.com/PX4/Firmware/blob/master/src/lib/controllib/BlockLowPass.cpp
* 6. 0
* 7. PX4z-100
***************************************************************************************************************************/
#ifndef POS_CONTROLLER_CASCADE_PID_H
#define POS_CONTROLLER_CASCADE_PID_H
#include <Eigen/Eigen>
#include <math.h>
#include <math_utils.h>
#include <prometheus_control_utils.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
using namespace std;
class pos_controller_cascade_PID
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
pos_controller_cascade_PID(void):
pos_cascade_pid_nh("~")
{
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Kp_xy", Kp_xy, 0.8);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Kp_z", Kp_z, 1.0);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Kp_vxvy", Kp_vxvy, 0.2);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Kp_vz", Kp_vz, 0.4);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Ki_vxvy", Ki_vxvy, 0.02);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Ki_vz", Ki_vz, 0.15);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Kd_vxvy", Kd_vxvy, 0.016);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Kd_vz", Kd_vz, 0.00);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/Hover_throttle", Hover_throttle, 0.43);
pos_cascade_pid_nh.param<float>("Pos_cascade_pid/MPC_VELD_LP", MPC_VELD_LP, 5.0);
pos_cascade_pid_nh.param<float>("Limit/XY_VEL_MAX", MPC_XY_VEL_MAX, 1.0);
pos_cascade_pid_nh.param<float>("Limit/Z_VEL_MAX", MPC_Z_VEL_MAX, 0.5);
pos_cascade_pid_nh.param<float>("Limit/THR_MIN", MPC_THR_MIN, 0.1);
pos_cascade_pid_nh.param<float>("Limit/THR_MAX", MPC_THR_MAX, 0.9);
pos_cascade_pid_nh.param<float>("Limit/THR_INT_MAX", MPC_THR_INT_MAX, 0.2);
pos_cascade_pid_nh.param<float>("Limit/tilt_max", tilt_max, 20.0);
vel_setpoint = Eigen::Vector3d(0.0,0.0,0.0);
thrust_sp = Eigen::Vector3d(0.0,0.0,0.0);
vel_P_output = Eigen::Vector3d(0.0,0.0,0.0);
thurst_int = Eigen::Vector3d(0.0,0.0,0.0);
vel_D_output = Eigen::Vector3d(0.0,0.0,0.0);
error_vel_dot_last = Eigen::Vector3d(0.0,0.0,0.0);
error_vel_last = Eigen::Vector3d(0.0,0.0,0.0);
delta_time = 0.02;
}
//PID parameter for the control law
float Kp_xy;
float Kp_z;
float Kp_vxvy;
float Kp_vz;
float Ki_vxvy;
float Ki_vz;
float Kd_vxvy;
float Kd_vz;
//Limitation of the velocity
float MPC_XY_VEL_MAX;
float MPC_Z_VEL_MAX;
//Hover thrust of drone (decided by the mass of the drone)
float Hover_throttle;
//Limitation of the thrust
float MPC_THR_MIN;
float MPC_THR_MAX;
float MPC_THR_INT_MAX;
//Limitation of the tilt angle (roll and pitch) [degree]
float tilt_max;
//输出
//Desired position and velocity of the drone
Eigen::Vector3d vel_setpoint;
//Desired thurst of the drone[the output of this class]
Eigen::Vector3d thrust_sp;
//Output of the vel loop in PID [thurst_int is the I]
Eigen::Vector3d vel_P_output;
Eigen::Vector3d thurst_int;
Eigen::Vector3d vel_D_output;
float MPC_VELD_LP;
//The delta time between now and the last step
float delta_time;
//Derriv of the velocity error in last step [used for the D-output in vel loop]
Eigen::Vector3d error_vel_dot_last;
Eigen::Vector3d error_vel_last;
//Current state of the drone
mavros_msgs::State current_state;
prometheus_msgs::ControlOutput _ControlOutput;
//Printf the PID parameter
void printf_param();
//Printf the control result
void printf_result();
// Position control main function
// [Input: Current state, Reference state, _Move_mode, dt; Output: AttitudeReference;]
prometheus_msgs::ControlOutput pos_controller(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, float dt);
//Position control loop [Input: current pos, desired pos; Output: desired vel]
void _positionController(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, Eigen::Vector3d& vel_setpoint);
//Velocity control loop [Input: current vel, desired vel; Output: desired thrust]
void _velocityController(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State, float dt, Eigen::Vector3d& thrust_sp);
void cal_vel_error_deriv(const Eigen::Vector3d& error_now, Eigen::Vector3d& vel_error_deriv);
private:
ros::NodeHandle pos_cascade_pid_nh;
};
prometheus_msgs::ControlOutput pos_controller_cascade_PID::pos_controller
(const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State,
float dt)
{
delta_time = dt;
_positionController(_DroneState, _Reference_State, vel_setpoint);
Eigen::Vector3d thrust_sp;
_velocityController(_DroneState, _Reference_State, delta_time, thrust_sp);
_ControlOutput.Throttle[0] = thrust_sp[0];
_ControlOutput.Throttle[1] = thrust_sp[1];
_ControlOutput.Throttle[2] = thrust_sp[2];
return _ControlOutput;
}
void pos_controller_cascade_PID::_positionController
(const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State,
Eigen::Vector3d& vel_setpoint)
{
//# Reference_State.Move_mode 2-bit value:
//# 0 for position, 1 for vel, 1st for xy, 2nd for z.
//# xy position xy velocity
//# z position 0b00[0] 0b10[2]
//# z velocity 0b01[1] 0b11(3)
if((_Reference_State.Move_mode & 0b10) == 0) //xy channel
{
vel_setpoint[0] = _Reference_State.velocity_ref[0] + Kp_xy * (_Reference_State.position_ref[0] - _DroneState.position[0]);
vel_setpoint[1] = _Reference_State.velocity_ref[1] + Kp_xy * (_Reference_State.position_ref[1] - _DroneState.position[1]);
}
else
{
vel_setpoint[0] = _Reference_State.velocity_ref[0];
vel_setpoint[1] = _Reference_State.velocity_ref[1];
}
if((_Reference_State.Move_mode & 0b01) == 0) //z channel
{
vel_setpoint[2] = _Reference_State.velocity_ref[2] + Kp_z * (_Reference_State.position_ref[2] - _DroneState.position[2]);
}
else
{
vel_setpoint[2] = _Reference_State.velocity_ref[2];
}
// Only for controller test
if(_Reference_State.Move_mode == prometheus_msgs::PositionReference::TRAJECTORY)
{
vel_setpoint[0] = Kp_xy * (_Reference_State.position_ref[0] - _DroneState.position[0]);
vel_setpoint[1] = Kp_xy * (_Reference_State.position_ref[1] - _DroneState.position[1]);
vel_setpoint[2] = Kp_z * (_Reference_State.position_ref[2] - _DroneState.position[2]);
}
// Limit the velocity setpoint
vel_setpoint[0] = constrain_function(vel_setpoint[0], MPC_XY_VEL_MAX);
vel_setpoint[1] = constrain_function(vel_setpoint[1], MPC_XY_VEL_MAX);
vel_setpoint[2] = constrain_function(vel_setpoint[2], MPC_Z_VEL_MAX);
}
void pos_controller_cascade_PID::_velocityController
(const prometheus_msgs::DroneState& _DroneState,
const prometheus_msgs::PositionReference& _Reference_State, float dt,
Eigen::Vector3d& thrust_sp)
{
// Generate desired thrust setpoint.
// PID
// u_des = P(error_vel) + D(error_vel_dot) + I(vel_integral)
// Umin <= u_des <= Umax
//
// Anti-Windup:
// u_des = _thrust_sp; y = vel_sp; r = _vel
// u_des >= Umax and r - y >= 0 => Saturation = true
// u_des >= Umax and r - y <= 0 => Saturation = false
// u_des <= Umin and r - y <= 0 => Saturation = true
// u_des <= Umin and r - y >= 0 => Saturation = false
//
// Notes:
// - control output in Z-direction has priority over XY-direction
// - the equilibrium point for the PID is at hover-thrust
// - the desired thrust in Z-direction is limited by the thrust limits
// - the desired thrust in XY-direction is limited by the thrust excess after
// consideration of the desired thrust in Z-direction. In addition, the thrust in
// XY-direction is also limited by the maximum tilt.
Eigen::Vector3d error_vel;
error_vel[0] = vel_setpoint[0] - _DroneState.velocity[0];
error_vel[1] = vel_setpoint[1] - _DroneState.velocity[1];
error_vel[2] = vel_setpoint[2] - _DroneState.velocity[2];
vel_P_output[0] = Kp_vxvy * error_vel[0];
vel_P_output[1] = Kp_vxvy * error_vel[1];
vel_P_output[2] = Kp_vz * error_vel[2];
Eigen::Vector3d vel_error_deriv;
cal_vel_error_deriv(error_vel, vel_error_deriv);
vel_D_output[0] = Kd_vxvy * vel_error_deriv[0];
vel_D_output[1] = Kd_vxvy * vel_error_deriv[1];
vel_D_output[2] = Kd_vz * vel_error_deriv[2];
// Consider thrust in Z-direction. [Here Hover_throttle is added]
float thrust_desired_Z = _Reference_State.acceleration_ref[2] + vel_P_output[2] + thurst_int[2] + vel_D_output[2] + Hover_throttle;
// Apply Anti-Windup in Z-direction.
// 两种情况:期望推力大于最大推力,且速度误差朝上;期望推力小于最小推力,且速度误差朝下
bool stop_integral_Z = ( thrust_desired_Z >= MPC_THR_MAX && error_vel[2] >= 0.0f) ||
( thrust_desired_Z <= MPC_THR_MIN && error_vel[2] <= 0.0f);
if (!stop_integral_Z) {
thurst_int[2] += Ki_vz * error_vel[2] * delta_time;
// limit thrust integral
thurst_int[2] = min(fabs(thurst_int[2]), MPC_THR_INT_MAX ) * sign_function(thurst_int[2]);
}else
{
// 发生Windup则积分项清零
thurst_int[2] = 0;
cout<<"Anti-Windup!"<<endl;
}
// Saturate thrust setpoint in Z-direction.
thrust_sp[2] = constrain_function2( thrust_desired_Z , MPC_THR_MIN, MPC_THR_MAX);
// PID-velocity controller for XY-direction.
float thrust_desired_X;
float thrust_desired_Y;
thrust_desired_X = _Reference_State.acceleration_ref[0] + vel_P_output[0] + thurst_int[0] + vel_D_output[0];
thrust_desired_Y = _Reference_State.acceleration_ref[1] + vel_P_output[1] + thurst_int[1] + vel_D_output[1];
// Get maximum allowed thrust in XY based on tilt angle and excess thrust.
float thrust_max_XY_tilt = fabs(thrust_sp[2]) * tanf(tilt_max/180.0*M_PI);
float thrust_max_XY = sqrtf(MPC_THR_MAX * MPC_THR_MAX - thrust_sp[2] * thrust_sp[2]);
thrust_max_XY = min(thrust_max_XY_tilt, thrust_max_XY);
// Saturate thrust in XY-direction.
thrust_sp[0] = thrust_desired_X;
thrust_sp[1] = thrust_desired_Y;
if ((thrust_desired_X * thrust_desired_X + thrust_desired_Y * thrust_desired_Y) > thrust_max_XY * thrust_max_XY) {
float mag = sqrtf((thrust_desired_X * thrust_desired_X + thrust_desired_Y * thrust_desired_Y));
thrust_sp[0] = thrust_desired_X / mag * thrust_max_XY;
thrust_sp[1] = thrust_desired_Y / mag * thrust_max_XY;
}
// Use tracking Anti-Windup for XY-direction: during saturation, the integrator is used to unsaturate the output
// see Anti-Reset Windup for PID controllers, L.Rundqwist, 1990
// Actually, I dont understand here.
float arw_gain = 2.f / Kp_vxvy;
float vel_err_lim_x,vel_err_lim_y;
vel_err_lim_x = error_vel[0] - (thrust_desired_X - thrust_sp[0]) * arw_gain;
vel_err_lim_y = error_vel[1] - (thrust_desired_Y - thrust_sp[1]) * arw_gain;
// cout << "vel_err_lim_x : " << vel_err_lim_x << " [deg] " <<endl;
// Update integral
thurst_int[0] += Ki_vxvy * vel_err_lim_x * delta_time;
thurst_int[1] += Ki_vxvy * vel_err_lim_y * delta_time;
//If not in OFFBOARD mode, set all intergral to zero.
if(_DroneState.mode != "OFFBOARD")
{
thurst_int = Eigen::Vector3d(0.0,0.0,0.0);
}
}
void pos_controller_cascade_PID::cal_vel_error_deriv(const Eigen::Vector3d& error_now, Eigen::Vector3d& vel_error_deriv)
{
Eigen::Vector3d error_vel_dot_now;
error_vel_dot_now = (error_now - error_vel_last)/delta_time;
error_vel_last = error_now;
float a,b;
b = 2 * M_PI * MPC_VELD_LP * delta_time;
a = b / (1 + b);
vel_error_deriv = a * error_vel_dot_now + (1 - a) * error_vel_dot_last ;
error_vel_dot_last = vel_error_deriv;
}
void pos_controller_cascade_PID::printf_result()
{
cout <<">>>>>>>>>>>>>>>>>>> cascade PID Position Controller <<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
// cout << "delta_time : " << delta_time<< " [s] " <<endl;
// cout << "Velocity_sp [X Y Z] : " << vel_setpoint[0] << " [m/s] "<< vel_setpoint[1]<<" [m/s] "<<vel_setpoint[2]<<" [m/s] "<<endl;
// cout << "Vel_P_output [X Y Z] : " << vel_P_output[0] << " [m/s] "<< vel_P_output[1]<<" [m/s] "<<vel_P_output[2]<<" [m/s] "<<endl;
// cout << "Vel_I_output [X Y Z] : " << thurst_int[0] << " [m/s] "<< thurst_int[1]<<" [m/s] "<<thurst_int[2]<<" [m/s] "<<endl;
// cout << "Vel_D_output [X Y Z] : " << vel_D_output[0] << " [m/s] "<< vel_D_output[1]<<" [m/s] "<<vel_D_output[2]<<" [m/s] "<<endl;
cout << "thrust_sp [X Y Z] : " << thrust_sp[0] << " [m/s^2] "<< thrust_sp[1]<<" [m/s^2] "<<thrust_sp[2]<<" [m/s^2] "<<endl;
}
// 【打印参数函数】
void pos_controller_cascade_PID::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>PID Parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"Position Loop: " <<endl;
cout <<"Kp_xy : "<< Kp_xy << endl;
cout <<"Kp_z : "<< Kp_z << endl;
cout <<"Velocity Loop: " <<endl;
cout <<"Kp_vxvy : "<< Kp_vxvy << endl;
cout <<"Kp_vz : "<< Kp_vz << endl;
cout <<"Ki_vxvy : "<< Ki_vxvy << endl;
cout <<"Ki_vz : "<< Ki_vz << endl;
cout <<"Kd_vxvy : "<< Kd_vxvy << endl;
cout <<"Kd_vz : "<< Kd_vz << endl;
cout <<"Limit: " <<endl;
cout <<"MPC_XY_VEL_MAX : "<< MPC_XY_VEL_MAX << endl;
cout <<"MPC_Z_VEL_MAX : "<< MPC_Z_VEL_MAX << endl;
cout <<"tilt_max : "<< tilt_max << endl;
cout <<"MPC_THR_MIN : "<< MPC_THR_MIN << endl;
cout <<"MPC_THR_MAX : "<< MPC_THR_MAX << endl;
cout <<"Hover_throttle : "<< Hover_throttle << endl;
}
#endif

@ -0,0 +1,177 @@
#include <ros/ros.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <termios.h>
#include <errno.h>
#include <string>
#include <sensor_msgs/Range.h>
namespace benewake
{
class TFmini
{
public:
TFmini(std::string _name, int _baudRate);
~TFmini(){};
float getDist();
void closePort();
unsigned char dataBuf[7];
private:
std::string portName_;
int baudRate_;
int serial_;
bool readData(unsigned char *_buf, int _nRead);
};
TFmini::TFmini(std::string _name, int _baudRate) :
portName_(_name), baudRate_(_baudRate)
{
serial_ = open(_name.c_str(), O_RDWR);
if(serial_ == -1)
{
ROS_ERROR_STREAM("Failed to open serial port!");
exit(0);
}
struct termios options;
if(tcgetattr(serial_, &options) != 0){
ROS_ERROR_STREAM("Can't get serial port sets!");
exit(0);
}
tcflush(serial_, TCIFLUSH);
switch(_baudRate)
{
case 921600:
cfsetispeed(&options, B921600);
cfsetospeed(&options, B921600);
break;
case 576000:
cfsetispeed(&options, B576000);
cfsetospeed(&options, B576000);
break;
case 500000:
cfsetispeed(&options, B500000);
cfsetospeed(&options, B500000);
break;
case 460800:
cfsetispeed(&options, B460800);
cfsetospeed(&options, B460800);
break;
case 230400:
cfsetispeed(&options, B230400);
cfsetospeed(&options, B230400);
break;
case 115200:
cfsetispeed(&options, B115200);
cfsetospeed(&options, B115200);
break;
case 57600:
cfsetispeed(&options, B57600);
cfsetospeed(&options, B57600);
break;
case 38400:
cfsetispeed(&options, B38400);
cfsetospeed(&options, B38400);
break;
case 19200:
cfsetispeed(&options, B19200);
cfsetospeed(&options, B19200);
break;
case 9600:
cfsetispeed(&options, B9600);
cfsetospeed(&options, B9600);
break;
case 4800:
cfsetispeed(&options, B4800);
cfsetospeed(&options, B4800);
break;
default:
ROS_ERROR_STREAM("Unsupported baud rate!");
exit(0);
}
options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
options.c_oflag &= ~OPOST;
options.c_iflag &= ~(IXON | IXOFF | IXANY);
options.c_iflag &= ~(INLCR | ICRNL | IGNCR);
options.c_oflag &= ~(ONLCR | OCRNL);
if(tcsetattr(serial_, TCSANOW, &options) != 0){
ROS_ERROR_STREAM("Can't set serial port options!");
exit(0);
}
}
bool TFmini::readData(unsigned char* _buf, int _nRead)
{
int total = 0, ret = 0;
while(total != _nRead)
{
ret = read(serial_, _buf + total, (_nRead - total));
if(ret < 0)
{
return false;
}
total += ret;
}
#ifdef DEBUG
for(int i = 0; i < _nRead; i++)
{
printf("%02x ", _buf[i]);
}
printf("\n");
#endif // DEBUG
return true;
}
float TFmini::getDist()
{
while(true)
{
if(readData(dataBuf, 2))
{
if(dataBuf[0] == 0x59 && dataBuf[1] == 0x59)
break;
}
else
{
return -1.0;
}
}
if(readData(dataBuf, 7))
{
int sumCheck = (0x59 + 0x59) % 256;
for(int i = 0; i < 6; i++)
{
sumCheck = (sumCheck + dataBuf[i]) % 256;
}
if(sumCheck == dataBuf[6])
{
return ((float)(dataBuf[1] << 8 | dataBuf[0]) / 100.0);
}
else
{
return 0.0;
}
}
else
{
return -1.0;
}
}
void TFmini::closePort()
{
close(serial_);
}
}

@ -0,0 +1,624 @@
/***************************************************************************************************************************
* command_to_mavros.h
*
* Author: Qyp
*
* Update Time: 2020.08.12
*
* Introduction: Drone control command send class using Mavros package
* 1. Ref to the Mavros plugins (setpoint_raw, loca_position, imu and etc..)
* 2. Ref to the Offboard Flight task in PX4 code: https://github.com/PX4/Firmware/blob/master/src/lib/FlightTasks/tasks/Offboard/FlightTaskOffboard.cpp
* 3. Ref to the Mavlink module in PX4 code: https://github.com/PX4/Firmware/blob/master/src/modules/mavlink/mavlink_receiver.cpp
* 4. Ref to the position control module in PX4: https://github.com/PX4/Firmware/blob/master/src/modules/mc_pos_control
* 5. Ref to the attitude control module in PX4: https://github.com/PX4/Firmware/blob/master/src/modules/mc_att_control
* 6.
*
* prometheus_controlmavros
* 1prometheus_controlmavros
* 2mavrosPX4
* 3
***************************************************************************************************************************/
#ifndef COMMAND_TO_MAVROS_H
#define COMMAND_TO_MAVROS_H
#include <ros/ros.h>
#include <math_utils.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <mavros_msgs/AttitudeTarget.h>
#include <mavros_msgs/PositionTarget.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/TwistStamped.h>
#include <mavros_msgs/ActuatorControl.h>
#include <mavros_msgs/MountControl.h>
#include <sensor_msgs/Imu.h>
#include <prometheus_msgs/DroneState.h>
#include <bitset>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/DroneState.h>
using namespace std;
class command_to_mavros
{
public:
//constructed function 1
command_to_mavros(void):
command_nh("~")
{
command_nh.param<string>("uav_name", uav_name, "/uav0");
if (uav_name == "/uav0")
{
uav_name = "";
}
pos_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
vel_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
accel_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
q_fcu_target = Eigen::Quaterniond(0.0,0.0,0.0,0.0);
euler_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
rates_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
Thrust_target = 0.0;
// 【订阅】无人机期望位置/速度/加速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为POSITION_TARGET_LOCAL_NED, 对应的飞控中的uORB消息为vehicle_local_position_setpoint.msg
position_target_sub = command_nh.subscribe<mavros_msgs::PositionTarget>(uav_name + "/mavros/setpoint_raw/target_local", 10, &command_to_mavros::pos_target_cb,this);
// 【订阅】无人机期望角度/角速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为ATTITUDE_TARGET (#83), 对应的飞控中的uORB消息为vehicle_attitude_setpoint.msg
attitude_target_sub = command_nh.subscribe<mavros_msgs::AttitudeTarget>(uav_name + "/mavros/setpoint_raw/target_attitude", 10, &command_to_mavros::att_target_cb,this);
// 【订阅】无人机底层控制量Mx My Mz 及 F [0][1][2][3]分别对应 roll pitch yaw控制量 及 油门推力
// 本话题来自飞控(通过Mavros功能包 /plugins/actuator_control.cpp读取), 对应Mavlink消息为ACTUATOR_CONTROL_TARGET, 对应的飞控中的uORB消息为actuator_controls.msg
actuator_target_sub = command_nh.subscribe<mavros_msgs::ActuatorControl>(uav_name + "/mavros/target_actuator_control", 10, &command_to_mavros::actuator_target_cb,this);
// 【发布】位置/速度/加速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_POSITION_TARGET_LOCAL_NED (#84), 对应的飞控中的uORB消息为position_setpoint_triplet.msg
setpoint_raw_local_pub = command_nh.advertise<mavros_msgs::PositionTarget>(uav_name + "/mavros/setpoint_raw/local", 10);
// 【发布】角度/角速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_ATTITUDE_TARGET (#82), 对应的飞控中的uORB消息为vehicle_attitude_setpoint.msg角度 或vehicle_rates_setpoint.msg角速度
setpoint_raw_attitude_pub = command_nh.advertise<mavros_msgs::AttitudeTarget>(uav_name + "/mavros/setpoint_raw/attitude", 10);
// 【发布】底层控制量Mx My Mz 及 F [0][1][2][3]分别对应 roll pitch yaw控制量 及 油门推力 注意 这里是NED系的
// 本话题要发送至飞控(通过Mavros功能包 /plugins/actuator_control.cpp发送), 对应Mavlink消息为SET_ACTUATOR_CONTROL_TARGET, 对应的飞控中的uORB消息为actuator_controls.msg
actuator_setpoint_pub = command_nh.advertise<mavros_msgs::ActuatorControl>(uav_name + "/mavros/actuator_control", 10);
// 本话题要发送至飞控(通过Mavros_extra功能包 /plugins/mount_control.cpp发送)
mount_control_pub = command_nh.advertise<mavros_msgs::MountControl>(uav_name + "/mavros/mount_control/command", 1);
// 【服务】解锁/上锁
// 本服务通过Mavros功能包 /plugins/command.cpp 实现
arming_client = command_nh.serviceClient<mavros_msgs::CommandBool>(uav_name + "/mavros/cmd/arming");
// 【服务】修改系统模式
// 本服务通过Mavros功能包 /plugins/command.cpp 实现
set_mode_client = command_nh.serviceClient<mavros_msgs::SetMode>(uav_name + "/mavros/set_mode");
}
//constructed function 2
command_to_mavros(string Uav_name):
command_nh("")
{
uav_name = Uav_name;
pos_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
vel_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
accel_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
q_fcu_target = Eigen::Quaterniond(0.0,0.0,0.0,0.0);
euler_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
rates_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
Thrust_target = 0.0;
// 【订阅】无人机期望位置/速度/加速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为POSITION_TARGET_LOCAL_NED, 对应的飞控中的uORB消息为vehicle_local_position_setpoint.msg
position_target_sub = command_nh.subscribe<mavros_msgs::PositionTarget>(uav_name + "/mavros/setpoint_raw/target_local", 10, &command_to_mavros::pos_target_cb,this);
// 【订阅】无人机期望角度/角速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为ATTITUDE_TARGET (#83), 对应的飞控中的uORB消息为vehicle_attitude_setpoint.msg
attitude_target_sub = command_nh.subscribe<mavros_msgs::AttitudeTarget>(uav_name + "/mavros/setpoint_raw/target_attitude", 10, &command_to_mavros::att_target_cb,this);
// 【订阅】无人机底层控制量Mx My Mz 及 F [0][1][2][3]分别对应 roll pitch yaw控制量 及 油门推力
// 本话题来自飞控(通过Mavros功能包 /plugins/actuator_control.cpp读取), 对应Mavlink消息为ACTUATOR_CONTROL_TARGET, 对应的飞控中的uORB消息为actuator_controls.msg
actuator_target_sub = command_nh.subscribe<mavros_msgs::ActuatorControl>(uav_name + "/mavros/target_actuator_control", 10, &command_to_mavros::actuator_target_cb,this);
// 【发布】位置/速度/加速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_POSITION_TARGET_LOCAL_NED (#84), 对应的飞控中的uORB消息为position_setpoint_triplet.msg
setpoint_raw_local_pub = command_nh.advertise<mavros_msgs::PositionTarget>(uav_name + "/mavros/setpoint_raw/local", 10);
// 【发布】角度/角速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_ATTITUDE_TARGET (#82), 对应的飞控中的uORB消息为vehicle_attitude_setpoint.msg角度 或vehicle_rates_setpoint.msg角速度
setpoint_raw_attitude_pub = command_nh.advertise<mavros_msgs::AttitudeTarget>(uav_name + "/mavros/setpoint_raw/attitude", 10);
// 【发布】底层控制量Mx My Mz 及 F [0][1][2][3]分别对应 roll pitch yaw控制量 及 油门推力 注意 这里是NED系的
// 本话题要发送至飞控(通过Mavros功能包 /plugins/actuator_control.cpp发送), 对应Mavlink消息为SET_ACTUATOR_CONTROL_TARGET, 对应的飞控中的uORB消息为actuator_controls.msg
actuator_setpoint_pub = command_nh.advertise<mavros_msgs::ActuatorControl>(uav_name + "/mavros/actuator_control", 10);
// 本话题要发送至飞控(通过Mavros_extra功能包 /plugins/mount_control.cpp发送)
mount_control_pub = command_nh.advertise<mavros_msgs::MountControl>(uav_name + "/mavros/mount_control/command", 1);
// 【服务】解锁/上锁
// 本服务通过Mavros功能包 /plugins/command.cpp 实现
arming_client = command_nh.serviceClient<mavros_msgs::CommandBool>(uav_name + "/mavros/cmd/arming");
// 【服务】修改系统模式
// 本服务通过Mavros功能包 /plugins/command.cpp 实现
set_mode_client = command_nh.serviceClient<mavros_msgs::SetMode>(uav_name + "/mavros/set_mode");
}
string uav_name;
//Target pos of the drone [from fcu]
Eigen::Vector3d pos_drone_fcu_target;
//Target vel of the drone [from fcu]
Eigen::Vector3d vel_drone_fcu_target;
//Target accel of the drone [from fcu]
Eigen::Vector3d accel_drone_fcu_target;
//Target att of the drone [from fcu]
Eigen::Quaterniond q_fcu_target;
Eigen::Vector3d euler_fcu_target;
Eigen::Vector3d rates_fcu_target;
//Target thrust of the drone [from fcu]
float Thrust_target;
mavros_msgs::ActuatorControl actuator_target;
//变量声明 - 服务
mavros_msgs::SetMode mode_cmd;
mavros_msgs::CommandBool arm_cmd;
ros::ServiceClient arming_client;
ros::ServiceClient set_mode_client;
//Idle. Do nothing.
void idle();
//px4 takeoff
void takeoff();
//px4 loiter
void loiter();
// px4 land
void land();
//发送位置期望值至飞控输入期望xyz,期望yaw
void send_pos_setpoint(const Eigen::Vector3d& pos_sp, float yaw_sp);
//发送速度期望值至飞控输入期望vxvyvz,期望yaw
void send_vel_setpoint(const Eigen::Vector3d& vel_sp, float yaw_sp);
//发送速度期望值至飞控输入期望vxvy z,期望yaw
void send_vel_xy_pos_z_setpoint(const Eigen::Vector3d& state_sp, float yaw_sp);
void send_vel_xy_pos_z_setpoint_yawrate(const Eigen::Vector3d& state_sp, float yaw_rate_sp);
//发送速度期望值至飞控机体系输入期望vxvyvz,期望yaw
void send_vel_setpoint_body(const Eigen::Vector3d& vel_sp, float yaw_sp);
void send_vel_setpoint_yaw_rate(const Eigen::Vector3d& vel_sp, float yaw_rate_sp);
// 发送位置+速度期望值至飞控机体系输入期望xyz + vxvyvz,期望yaw
void send_pos_vel_xyz_setpoint(const Eigen::Vector3d& pos_sp, const Eigen::Vector3d& vel_sp, float yaw_sp);
//发送加速度期望值至飞控输入期望axayaz,期望yaw
void send_acc_xyz_setpoint(const Eigen::Vector3d& accel_sp, float yaw_sp);
//发送角度期望值至飞控(输入:期望角度-四元数,期望推力)
//这是px4_pos_controller.cpp中目前使用的控制方式
void send_attitude_setpoint(const prometheus_msgs::AttitudeReference& _AttitudeReference);
//发送角度期望值至飞控(输入:期望角速度,期望推力)
void send_attitude_rate_setpoint(const Eigen::Vector3d& attitude_rate_sp, float thrust_sp);
void send_attitude_setpoint_yawrate(const prometheus_msgs::AttitudeReference& _AttitudeReference, float yaw_rate_sp);
//发送底层至飞控输入MxMyMz,期望推力)[Not recommanded. Because the high delay between the onboard computer and Pixhawk]
void send_actuator_setpoint(const Eigen::Vector4d& actuator_sp);
//发送云台控制指令
void send_mount_control_command(const Eigen::Vector3d& gimbal_att_sp);
private:
ros::NodeHandle command_nh;
ros::Subscriber position_target_sub;
ros::Subscriber attitude_target_sub;
ros::Subscriber actuator_target_sub;
ros::Publisher setpoint_raw_local_pub;
ros::Publisher setpoint_raw_attitude_pub;
ros::Publisher actuator_setpoint_pub;
ros::Publisher mount_control_pub;
void pos_target_cb(const mavros_msgs::PositionTarget::ConstPtr& msg)
{
pos_drone_fcu_target = Eigen::Vector3d(msg->position.x, msg->position.y, msg->position.z);
vel_drone_fcu_target = Eigen::Vector3d(msg->velocity.x, msg->velocity.y, msg->velocity.z);
accel_drone_fcu_target = Eigen::Vector3d(msg->acceleration_or_force.x, msg->acceleration_or_force.y, msg->acceleration_or_force.z);
}
void att_target_cb(const mavros_msgs::AttitudeTarget::ConstPtr& msg)
{
q_fcu_target = Eigen::Quaterniond(msg->orientation.w, msg->orientation.x, msg->orientation.y, msg->orientation.z);
//Transform the Quaternion to euler Angles
euler_fcu_target = quaternion_to_euler(q_fcu_target);
rates_fcu_target = Eigen::Vector3d(msg->body_rate.x, msg->body_rate.y, msg->body_rate.z);
Thrust_target = msg->thrust;
}
void actuator_target_cb(const mavros_msgs::ActuatorControl::ConstPtr& msg)
{
actuator_target = *msg;
}
};
void command_to_mavros::send_mount_control_command(const Eigen::Vector3d& gimbal_att_sp)
{
mavros_msgs::MountControl mount_setpoint;
//
mount_setpoint.mode = 2;
mount_setpoint.pitch = gimbal_att_sp[0]; // Gimbal Pitch
mount_setpoint.roll = gimbal_att_sp[1]; // Gimbal Yaw
mount_setpoint.yaw = gimbal_att_sp[2]; // Gimbal Yaw
mount_control_pub.publish(mount_setpoint);
}
void command_to_mavros::takeoff()
{
mavros_msgs::PositionTarget pos_setpoint;
//飞控如何接收该信号请见mavlink_receiver.cpp
//飞控如何执行该指令请见FlightTaskOffboard.cpp
//需要在QGC设置起飞高度
pos_setpoint.type_mask = 0x1000;
setpoint_raw_local_pub.publish(pos_setpoint);
}
void command_to_mavros::land()
{
mavros_msgs::PositionTarget pos_setpoint;
//飞控如何接收该信号请见mavlink_receiver.cpp
//飞控如何执行该指令请见FlightTaskOffboard.cpp
//需要在QGC设置降落速度
pos_setpoint.type_mask = 0x2000;
setpoint_raw_local_pub.publish(pos_setpoint);
}
void command_to_mavros::loiter()
{
mavros_msgs::PositionTarget pos_setpoint;
//飞控如何接收该信号请见mavlink_receiver.cpp
//飞控如何执行该指令请见FlightTaskOffboard.cpp
pos_setpoint.type_mask = 0x3000;
setpoint_raw_local_pub.publish(pos_setpoint);
}
void command_to_mavros::idle()
{
mavros_msgs::PositionTarget pos_setpoint;
//飞控如何接收该信号请见mavlink_receiver.cpp
//飞控如何执行该指令请见FlightTaskOffboard.cpp
pos_setpoint.type_mask = 0x4000;
setpoint_raw_local_pub.publish(pos_setpoint);
}
//发送位置期望值至飞控输入期望xyz,期望yaw
void command_to_mavros::send_pos_setpoint(const Eigen::Vector3d& pos_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
//Bitmask toindicate which dimensions should be ignored (1 means ignore,0 means not ignore; Bit 10 must set to 0)
//Bit 1:x, bit 2:y, bit 3:z, bit 4:vx, bit 5:vy, bit 6:vz, bit 7:ax, bit 8:ay, bit 9:az, bit 10:is_force_sp, bit 11:yaw, bit 12:yaw_rate
//Bit 10 should set to 0, means is not force sp
pos_setpoint.type_mask = 0b100111111000; // 100 111 111 000 xyz + yaw
pos_setpoint.coordinate_frame = 1;
pos_setpoint.position.x = pos_sp[0];
pos_setpoint.position.y = pos_sp[1];
pos_setpoint.position.z = pos_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Pos_target [X Y Z] : " << pos_drone_fcu_target[0] << " [ m ] "<< pos_drone_fcu_target[1]<<" [ m ] "<<pos_drone_fcu_target[2]<<" [ m ] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送速度期望值至飞控输入期望vxvyvz,期望yaw
void command_to_mavros::send_vel_setpoint(const Eigen::Vector3d& vel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
pos_setpoint.type_mask = 0b100111000111;
pos_setpoint.coordinate_frame = 1;
pos_setpoint.velocity.x = vel_sp[0];
pos_setpoint.velocity.y = vel_sp[1];
pos_setpoint.velocity.z = vel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送速度期望值至飞控输入期望vxvyvz,期望yaw
void command_to_mavros::send_vel_setpoint_yaw_rate(const Eigen::Vector3d& vel_sp, float yaw_rate_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
//Bitmask toindicate which dimensions should be ignored (1 means ignore,0 means not ignore; Bit 10 must set to 0)
//Bit 1:x, bit 2:y, bit 3:z, bit 4:vx, bit 5:vy, bit 6:vz, bit 7:ax, bit 8:ay, bit 9:az, bit 10:is_force_sp, bit 11:yaw, bit 12:yaw_rate
//Bit 10 should set to 0, means is not force sp
pos_setpoint.type_mask = 0b010111000111;
pos_setpoint.coordinate_frame = 1;
pos_setpoint.velocity.x = vel_sp[0];
pos_setpoint.velocity.y = vel_sp[1];
pos_setpoint.velocity.z = vel_sp[2];
pos_setpoint.yaw_rate = yaw_rate_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送速度期望值至飞控机体系输入期望vxvyvz,期望yaw
void command_to_mavros::send_vel_setpoint_body(const Eigen::Vector3d& vel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
pos_setpoint.type_mask = 0b100111000111;
//uint8 FRAME_LOCAL_NED = 1
//uint8 FRAME_BODY_NED = 8
pos_setpoint.coordinate_frame = 8;
pos_setpoint.position.x = vel_sp[0];
pos_setpoint.position.y = vel_sp[1];
pos_setpoint.position.z = vel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// // 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
void command_to_mavros::send_vel_xy_pos_z_setpoint(const Eigen::Vector3d& state_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
// 此处由于飞控暂不支持位置速度追踪的复合模式因此type_mask设定如下
pos_setpoint.type_mask = 0b100111000011; // 100 111 000 011 vx vy vz z + yaw
pos_setpoint.coordinate_frame = 1;
pos_setpoint.velocity.x = state_sp[0];
pos_setpoint.velocity.y = state_sp[1];
pos_setpoint.velocity.z = 0.0;
pos_setpoint.position.z = state_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
void command_to_mavros::send_vel_xy_pos_z_setpoint_yawrate(const Eigen::Vector3d& state_sp, float yaw_rate_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
// 此处由于飞控暂不支持位置速度追踪的复合模式因此type_mask设定如下
pos_setpoint.type_mask = 0b010111000011; // 100 111 000 011 vx vy vz z + yawrate
pos_setpoint.coordinate_frame = 1;
pos_setpoint.velocity.x = state_sp[0];
pos_setpoint.velocity.y = state_sp[1];
pos_setpoint.velocity.z = 0.0;
pos_setpoint.position.z = state_sp[2];
pos_setpoint.yaw_rate = yaw_rate_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
void command_to_mavros::send_pos_vel_xyz_setpoint(const Eigen::Vector3d& pos_sp, const Eigen::Vector3d& vel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
// 速度作为前馈项, 参见FlightTaskOffboard.cpp
// 2. position setpoint + velocity setpoint (velocity used as feedforward)
// 控制方法请见 PositionControl.cpp
pos_setpoint.type_mask = 0b100111000000; // 100 111 000 000 vx vy vz x y z+ yaw
pos_setpoint.coordinate_frame = 1;
pos_setpoint.position.x = pos_sp[0];
pos_setpoint.position.y = pos_sp[1];
pos_setpoint.position.z = pos_sp[2];
pos_setpoint.velocity.x = vel_sp[0];
pos_setpoint.velocity.y = vel_sp[1];
pos_setpoint.velocity.z = vel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
}
//发送加速度期望值至飞控输入期望axayaz,期望yaw
void command_to_mavros::send_acc_xyz_setpoint(const Eigen::Vector3d& accel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
pos_setpoint.type_mask = 0b100000111111;
pos_setpoint.coordinate_frame = 1;
pos_setpoint.acceleration_or_force.x = accel_sp[0];
pos_setpoint.acceleration_or_force.y = accel_sp[1];
pos_setpoint.acceleration_or_force.z = accel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Acc_target [X Y Z] : " << accel_drone_fcu_target[0] << " [m/s^2] "<< accel_drone_fcu_target[1]<<" [m/s^2] "<<accel_drone_fcu_target[2]<<" [m/s^2] "<<endl;
// cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送角度期望值至飞控(输入:期望角度-四元数,期望推力)
void command_to_mavros::send_attitude_setpoint(const prometheus_msgs::AttitudeReference& _AttitudeReference)
{
mavros_msgs::AttitudeTarget att_setpoint;
//Mappings: If any of these bits are set, the corresponding input should be ignored:
//bit 1: body roll rate, bit 2: body pitch rate, bit 3: body yaw rate. bit 4-bit 6: reserved, bit 7: throttle, bit 8: attitude
att_setpoint.type_mask = 0b00000111;
att_setpoint.orientation.x = _AttitudeReference.desired_att_q.x;
att_setpoint.orientation.y = _AttitudeReference.desired_att_q.y;
att_setpoint.orientation.z = _AttitudeReference.desired_att_q.z;
att_setpoint.orientation.w = _AttitudeReference.desired_att_q.w;
att_setpoint.thrust = _AttitudeReference.desired_throttle;
setpoint_raw_attitude_pub.publish(att_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Att_target [R P Y] : " << euler_fcu_target[0] * 180/M_PI <<" [deg] "<<euler_fcu_target[1] * 180/M_PI << " [deg] "<< euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
// cout << "Thr_target [0 - 1] : " << Thrust_target <<endl;
}
//发送角度期望值至飞控(输入:期望角度-四元数,期望推力)
void command_to_mavros::send_attitude_setpoint_yawrate(const prometheus_msgs::AttitudeReference& _AttitudeReference, float yaw_rate_sp)
{
mavros_msgs::AttitudeTarget att_setpoint;
//Mappings: If any of these bits are set, the corresponding input should be ignored:
//bit 1: body roll rate, bit 2: body pitch rate, bit 3: body yaw rate. bit 4-bit 6: reserved, bit 7: throttle, bit 8: attitude
att_setpoint.type_mask = 0b00000011;
att_setpoint.orientation.x = _AttitudeReference.desired_att_q.x;
att_setpoint.orientation.y = _AttitudeReference.desired_att_q.y;
att_setpoint.orientation.z = _AttitudeReference.desired_att_q.z;
att_setpoint.orientation.w = _AttitudeReference.desired_att_q.w;
att_setpoint.thrust = _AttitudeReference.desired_throttle;
att_setpoint.body_rate.x = 0.0;
att_setpoint.body_rate.y = 0.0;
att_setpoint.body_rate.z = yaw_rate_sp;
setpoint_raw_attitude_pub.publish(att_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Att_target [R P Y] : " << euler_fcu_target[0] * 180/M_PI <<" [deg] "<<euler_fcu_target[1] * 180/M_PI << " [deg] "<< euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
// cout << "Thr_target [0 - 1] : " << Thrust_target <<endl;
}
//发送角度期望值至飞控(输入:期望角速度,期望推力)
void command_to_mavros::send_attitude_rate_setpoint(const Eigen::Vector3d& attitude_rate_sp, float thrust_sp)
{
mavros_msgs::AttitudeTarget att_setpoint;
//Mappings: If any of these bits are set, the corresponding input should be ignored:
//bit 1: body roll rate, bit 2: body pitch rate, bit 3: body yaw rate. bit 4-bit 6: reserved, bit 7: throttle, bit 8: attitude
// msg.type_mask = 128; // Ignore orientation messages
att_setpoint.type_mask = 0b10000000;
att_setpoint.body_rate.x = attitude_rate_sp[0];
att_setpoint.body_rate.y = attitude_rate_sp[1];
att_setpoint.body_rate.z = attitude_rate_sp[2];
att_setpoint.thrust = thrust_sp;
setpoint_raw_attitude_pub.publish(att_setpoint);
// 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// cout << "Att_rate_target [R P Y] : " << rates_fcu_target[0] * 180/M_PI <<" [deg/s] "<<rates_fcu_target[1] * 180/M_PI << " [deg/s] "<< rates_fcu_target[2] * 180/M_PI<<" [deg/s] "<<endl;
// cout << "Thr_target [0 - 1] : " << Thrust_target <<endl;
}
//发送底层至飞控输入MxMyMz,期望推力)
void command_to_mavros::send_actuator_setpoint(const Eigen::Vector4d& actuator_sp)
{
mavros_msgs::ActuatorControl actuator_setpoint;
actuator_setpoint.group_mix = 0;
actuator_setpoint.controls[0] = actuator_sp(0);
actuator_setpoint.controls[1] = actuator_sp(1);
actuator_setpoint.controls[2] = actuator_sp(2);
actuator_setpoint.controls[3] = actuator_sp(3);
actuator_setpoint.controls[4] = 0.0;
actuator_setpoint.controls[5] = 0.0;
actuator_setpoint.controls[6] = 0.0;
actuator_setpoint.controls[7] = 0.0;
actuator_setpoint_pub.publish(actuator_setpoint);
// // 检查飞控是否收到控制量
// cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// //ned to enu
// cout << "actuator_target [0 1 2 3] : " << actuator_target.controls[0] << " [ ] "<< -actuator_target.controls[1] <<" [ ] "<<-actuator_target.controls[2]<<" [ ] "<<actuator_target.controls[3] <<" [ ] "<<endl;
// cout << "actuator_target [4 5 6 7] : " << actuator_target.controls[4] << " [ ] "<< actuator_target.controls[5] <<" [ ] "<<actuator_target.controls[6]<<" [ ] "<<actuator_target.controls[7] <<" [ ] "<<endl;
}
#endif

@ -0,0 +1,290 @@
/***************************************************************************************************************************
* controller_test.h
*
* Author: Qyp
*
* Update Time: 2020.1.10
* Controller_Test8
* 1线
* 28
* 3
***************************************************************************************************************************/
#ifndef CONTROLLER_TEST_H
#define CONTROLLER_TEST_H
#include <Eigen/Eigen>
#include <math.h>
#include <math_utils.h>
#include <prometheus_control_utils.h>
#include <prometheus_msgs/PositionReference.h>
#include <geometry_msgs/PoseStamped.h>
#include <nav_msgs/Path.h>
using namespace std;
class Controller_Test
{
public:
//构造函数
Controller_Test(void):
Controller_Test_nh("~")
{
Controller_Test_nh.param<float>("Controller_Test/Circle/Center_x", circle_center[0], 0.0);
Controller_Test_nh.param<float>("Controller_Test/Circle/Center_y", circle_center[1], 0.0);
Controller_Test_nh.param<float>("Controller_Test/Circle/Center_z", circle_center[2], 1.0);
Controller_Test_nh.param<float>("Controller_Test/Circle/circle_radius", circle_radius, 2.0);
Controller_Test_nh.param<float>("Controller_Test/Circle/linear_vel", linear_vel, 0.5);
Controller_Test_nh.param<float>("Controller_Test/Circle/direction", direction, 1.0);
Controller_Test_nh.param<float>("Controller_Test/Eight/Center_x", eight_origin_[0], 0.0);
Controller_Test_nh.param<float>("Controller_Test/Eight/Center_y", eight_origin_[1], 0.0);
Controller_Test_nh.param<float>("Controller_Test/Eight/Center_z", eight_origin_[2], 1.0);
Controller_Test_nh.param<float>("Controller_Test/Eight/omega", eight_omega_, 0.5);
Controller_Test_nh.param<float>("Controller_Test/Eight/radial", radial, 2.0);
Controller_Test_nh.param<float>("Controller_Test/Step/step_length", step_length, 0.0);
Controller_Test_nh.param<float>("Controller_Test/Step/step_interval", step_interval, 0.0);
}
//Printf the Controller_Test parameter
void printf_param();
//Controller_Test Calculation [Input: time_from_start; Output: Circle_trajectory;]
prometheus_msgs::PositionReference Circle_trajectory_generation(float time_from_start);
prometheus_msgs::PositionReference Eight_trajectory_generation(float time_from_start);
prometheus_msgs::PositionReference Step_trajectory_generation(float time_from_start);
prometheus_msgs::PositionReference Line_trajectory_generation(float time_from_start);
private:
ros::NodeHandle Controller_Test_nh;
// Circle Parameter
Eigen::Vector3f circle_center;
float circle_radius;
float linear_vel;
float direction; //direction = 1 for CCW 逆时针, direction = -1 for CW 顺时针
// Eight Shape Parameter
Eigen::Vector3f eight_origin_;
float radial;
float eight_omega_;
// Step
float step_length;
float step_interval;
};
prometheus_msgs::PositionReference Controller_Test::Circle_trajectory_generation(float time_from_start)
{
prometheus_msgs::PositionReference Circle_trajectory;
float omega;
if( circle_radius != 0)
{
omega = direction * fabs(linear_vel / circle_radius);
}else
{
omega = 0.0;
}
const float angle = time_from_start * omega;
const float cos_angle = cos(angle);
const float sin_angle = sin(angle);
// cout << "omega : " << omega * 180/M_PI <<" [deg/s] " <<endl;
// cout << "angle : " << angle * 180/M_PI <<" [deg] " <<endl;
Circle_trajectory.header.stamp = ros::Time::now();
Circle_trajectory.time_from_start = time_from_start;
Circle_trajectory.Move_mode = prometheus_msgs::PositionReference::TRAJECTORY;
Circle_trajectory.position_ref[0] = circle_radius * cos_angle + circle_center[0];
Circle_trajectory.position_ref[1] = circle_radius * sin_angle + circle_center[1];
Circle_trajectory.position_ref[2] = circle_center[2];
Circle_trajectory.velocity_ref[0] = - circle_radius * omega * sin_angle;
Circle_trajectory.velocity_ref[1] = circle_radius * omega * cos_angle;
Circle_trajectory.velocity_ref[2] = 0;
Circle_trajectory.acceleration_ref[0] = - circle_radius * pow(omega, 2.0) * cos_angle;
Circle_trajectory.acceleration_ref[1] = - circle_radius * pow(omega, 2.0) * sin_angle;
Circle_trajectory.acceleration_ref[2] = 0;
// Circle_trajectory.jerk_ref[0] = circle_radius * pow(omega, 3.0) * sin_angle;
// Circle_trajectory.jerk_ref[1] = - circle_radius * pow(omega, 3.0) * cos_angle;
// Circle_trajectory.jerk_ref[2] = 0;
// Circle_trajectory.snap_ref[0] = circle_radius * pow(omega, 4.0) * cos_angle;
// Circle_trajectory.snap_ref[1] = circle_radius * pow(omega, 4.0) * sin_angle;
// Circle_trajectory.snap_ref[2] = 0;
Circle_trajectory.yaw_ref = 0;
// Circle_trajectory.yaw_rate_ref = 0;
// Circle_trajectory.yaw_acceleration_ref = 0;
return Circle_trajectory;
}
prometheus_msgs::PositionReference Controller_Test::Line_trajectory_generation(float time_from_start)
{
prometheus_msgs::PositionReference Line_trajectory;
float omega;
if( circle_radius != 0)
{
omega = direction * fabs(linear_vel / circle_radius);
}else
{
omega = 0.0;
}
const float angle = time_from_start * omega;
const float cos_angle = cos(angle);
const float sin_angle = sin(angle);
Line_trajectory.header.stamp = ros::Time::now();
Line_trajectory.time_from_start = time_from_start;
Line_trajectory.Move_mode = prometheus_msgs::PositionReference::TRAJECTORY;
Line_trajectory.position_ref[0] = 0.0;
Line_trajectory.position_ref[1] = circle_radius * sin_angle + circle_center[1];
Line_trajectory.position_ref[2] = circle_center[2];
Line_trajectory.velocity_ref[0] = 0.0;
Line_trajectory.velocity_ref[1] = circle_radius * omega * cos_angle;
Line_trajectory.velocity_ref[2] = 0;
Line_trajectory.acceleration_ref[0] = 0.0;
Line_trajectory.acceleration_ref[1] = - circle_radius * pow(omega, 2.0) * sin_angle;
Line_trajectory.acceleration_ref[2] = 0;
// Line_trajectory.jerk_ref[0] = circle_radius * pow(omega, 3.0) * sin_angle;
// Line_trajectory.jerk_ref[1] = - circle_radius * pow(omega, 3.0) * cos_angle;
// Line_trajectory.jerk_ref[2] = 0;
// Line_trajectory.snap_ref[0] = circle_radius * pow(omega, 4.0) * cos_angle;
// Line_trajectory.snap_ref[1] = circle_radius * pow(omega, 4.0) * sin_angle;
// Line_trajectory.snap_ref[2] = 0;
Line_trajectory.yaw_ref = 0;
// Line_trajectory.yaw_rate_ref = 0;
// Line_trajectory.yaw_acceleration_ref = 0;
return Line_trajectory;
}
prometheus_msgs::PositionReference Controller_Test::Eight_trajectory_generation(float time_from_start)
{
Eigen::Vector3f position;
Eigen::Vector3f velocity;
Eigen::Vector3f acceleration;
float angle = eight_omega_* time_from_start;
const float cos_angle = cos(angle);
const float sin_angle = sin(angle);
Eigen::Vector3f eight_radial_ ;
Eigen::Vector3f eight_axis_ ;
eight_radial_ << radial, 0.0, 0.0;
eight_axis_ << 0.0, 0.0, 2.0;
position = cos_angle * eight_radial_ + sin_angle * cos_angle * eight_axis_.cross(eight_radial_)
+ (1 - cos_angle) * eight_axis_.dot(eight_radial_) * eight_axis_ + eight_origin_;
velocity = eight_omega_ * (-sin_angle * eight_radial_ + (pow(cos_angle, 2) - pow(sin_angle, 2)) * eight_axis_.cross(eight_radial_)
+ (sin_angle) * eight_axis_.dot(eight_radial_) * eight_axis_);
acceleration << 0.0, 0.0, 0.0;
prometheus_msgs::PositionReference Eight_trajectory;
Eight_trajectory.header.stamp = ros::Time::now();
Eight_trajectory.time_from_start = time_from_start;
Eight_trajectory.Move_mode = prometheus_msgs::PositionReference::TRAJECTORY;
Eight_trajectory.position_ref[0] = position[0];
Eight_trajectory.position_ref[1] = position[1];
Eight_trajectory.position_ref[2] = position[2];
Eight_trajectory.velocity_ref[0] = velocity[0];
Eight_trajectory.velocity_ref[1] = velocity[1];
Eight_trajectory.velocity_ref[2] = velocity[2];
Eight_trajectory.acceleration_ref[0] = 0;
Eight_trajectory.acceleration_ref[1] = 0;
Eight_trajectory.acceleration_ref[2] = 0;
Eight_trajectory.yaw_ref = 0;
// to be continued...
return Eight_trajectory;
}
prometheus_msgs::PositionReference Controller_Test::Step_trajectory_generation(float time_from_start)
{
prometheus_msgs::PositionReference Step_trajectory;
Step_trajectory.header.stamp = ros::Time::now();
Step_trajectory.time_from_start = time_from_start;
Step_trajectory.Move_mode = prometheus_msgs::PositionReference::TRAJECTORY;
int i = time_from_start / step_interval;
if( i%2 == 0)
{
Step_trajectory.position_ref[0] = step_length;
}else
{
Step_trajectory.position_ref[0] = - step_length;
}
Step_trajectory.position_ref[1] = 0;
Step_trajectory.position_ref[2] = 1.0;
Step_trajectory.velocity_ref[0] = 0;
Step_trajectory.velocity_ref[1] = 0;
Step_trajectory.velocity_ref[2] = 0;
Step_trajectory.acceleration_ref[0] = 0;
Step_trajectory.acceleration_ref[1] = 0;
Step_trajectory.acceleration_ref[2] = 0;
Step_trajectory.yaw_ref = 0;
return Step_trajectory;
}
// 【打印参数函数】
void Controller_Test::printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>Controller_Test Parameter <<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"Circle Shape: " <<endl;
cout <<"circle_center : " << circle_center[0] <<" [m] "<< circle_center[1] <<" [m] "<< circle_center[2] <<" [m] "<<endl;
cout <<"circle_radius : "<< circle_radius <<" [m] " <<"linear_vel : "<< linear_vel <<" [m/s] "<<"direction : "<< direction << endl;
cout <<"Eight Shape: " <<endl;
cout <<"eight_origin_ : "<< eight_origin_[0] <<" [m] "<< eight_origin_[1] <<" [m] "<< eight_origin_[2] <<" [m] "<<endl;
cout <<"eight_omega_ : "<< eight_omega_ <<" [rad/s] " << "radial : "<< radial << endl;
cout <<"Step: " <<endl;
cout <<"step_length : "<< step_length << " [m] step_interval : "<< step_interval << " [s] "<<endl;
}
#endif

@ -0,0 +1,202 @@
/***************************************************************************************************************************
* math_utils.h
*
* Author: Qyp
*
* Update Time: 2019.3.16
*
* Introduction: math utils functions
*
* 1 ref to https://github.com/PX4/Matrix/blob/56b069956da141da244926ed7000e89b2ba6c731/matrix/Euler.hpp
***************************************************************************************************************************/
#ifndef MATH_UTILS_H
#define MATH_UTILS_H
#include <Eigen/Eigen>
#include <math.h>
using namespace std;
// 四元数转欧拉角
Eigen::Vector3d quaternion_to_rpy2(const Eigen::Quaterniond &q)
{
// YPR - ZYX
return q.toRotationMatrix().eulerAngles(2, 1, 0).reverse();
}
// 从(roll,pitch,yaw)创建四元数 by a 3-2-1 intrinsic Tait-Bryan rotation sequence
Eigen::Quaterniond quaternion_from_rpy(const Eigen::Vector3d &rpy)
{
// YPR - ZYX
return Eigen::Quaterniond(
Eigen::AngleAxisd(rpy.z(), Eigen::Vector3d::UnitZ()) *
Eigen::AngleAxisd(rpy.y(), Eigen::Vector3d::UnitY()) *
Eigen::AngleAxisd(rpy.x(), Eigen::Vector3d::UnitX())
);
}
// 将四元数转换至(roll,pitch,yaw) by a 3-2-1 intrinsic Tait-Bryan rotation sequence
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
// q0 q1 q2 q3
// w x y z
Eigen::Vector3d quaternion_to_euler(const Eigen::Quaterniond &q)
{
float quat[4];
quat[0] = q.w();
quat[1] = q.x();
quat[2] = q.y();
quat[3] = q.z();
Eigen::Vector3d ans;
ans[0] = atan2(2.0 * (quat[3] * quat[2] + quat[0] * quat[1]), 1.0 - 2.0 * (quat[1] * quat[1] + quat[2] * quat[2]));
ans[1] = asin(2.0 * (quat[2] * quat[0] - quat[3] * quat[1]));
ans[2] = atan2(2.0 * (quat[3] * quat[0] + quat[1] * quat[2]), 1.0 - 2.0 * (quat[2] * quat[2] + quat[3] * quat[3]));
return ans;
}
//旋转矩阵转欧拉角
void rotation_to_euler(const Eigen::Matrix3d& dcm, Eigen::Vector3d& euler_angle)
{
double phi_val = atan2(dcm(2, 1), dcm(2, 2));
double theta_val = asin(-dcm(2, 0));
double psi_val = atan2(dcm(1, 0), dcm(0, 0));
double pi = M_PI;
if (fabs(theta_val - pi / 2.0) < 1.0e-3) {
phi_val = 0.0;
psi_val = atan2(dcm(1, 2), dcm(0, 2));
} else if (fabs(theta_val + pi / 2.0) < 1.0e-3) {
phi_val = 0.0;
psi_val = atan2(-dcm(1, 2), -dcm(0, 2));
}
euler_angle(0) = phi_val;
euler_angle(1) = theta_val;
euler_angle(2) = psi_val;
}
Eigen::Vector4d rot2Quaternion(const Eigen::Matrix3d &R)
{
Eigen::Vector4d quat;
double tr = R.trace();
if (tr > 0.0) {
double S = sqrt(tr + 1.0) * 2.0; // S=4*qw
quat(0) = 0.25 * S;
quat(1) = (R(2, 1) - R(1, 2)) / S;
quat(2) = (R(0, 2) - R(2, 0)) / S;
quat(3) = (R(1, 0) - R(0, 1)) / S;
} else if ((R(0, 0) > R(1, 1)) & (R(0, 0) > R(2, 2))) {
double S = sqrt(1.0 + R(0, 0) - R(1, 1) - R(2, 2)) * 2.0; // S=4*qx
quat(0) = (R(2, 1) - R(1, 2)) / S;
quat(1) = 0.25 * S;
quat(2) = (R(0, 1) + R(1, 0)) / S;
quat(3) = (R(0, 2) + R(2, 0)) / S;
} else if (R(1, 1) > R(2, 2)) {
double S = sqrt(1.0 + R(1, 1) - R(0, 0) - R(2, 2)) * 2.0; // S=4*qy
quat(0) = (R(0, 2) - R(2, 0)) / S;
quat(1) = (R(0, 1) + R(1, 0)) / S;
quat(2) = 0.25 * S;
quat(3) = (R(1, 2) + R(2, 1)) / S;
} else {
double S = sqrt(1.0 + R(2, 2) - R(0, 0) - R(1, 1)) * 2.0; // S=4*qz
quat(0) = (R(1, 0) - R(0, 1)) / S;
quat(1) = (R(0, 2) + R(2, 0)) / S;
quat(2) = (R(1, 2) + R(2, 1)) / S;
quat(3) = 0.25 * S;
}
return quat;
}
static Eigen::Vector3d matrix_hat_inv(const Eigen::Matrix3d &m)
{
Eigen::Vector3d v;
// TODO: Sanity checks if m is skew symmetric
v << m(7), m(2), m(3);
return v;
}
Eigen::Vector4d quatMultiplication(const Eigen::Vector4d &q, const Eigen::Vector4d &p)
{
Eigen::Vector4d quat;
quat << p(0) * q(0) - p(1) * q(1) - p(2) * q(2) - p(3) * q(3), p(0) * q(1) + p(1) * q(0) - p(2) * q(3) + p(3) * q(2),
p(0) * q(2) + p(1) * q(3) + p(2) * q(0) - p(3) * q(1), p(0) * q(3) - p(1) * q(2) + p(2) * q(1) + p(3) * q(0);
return quat;
}
Eigen::Matrix3d quat2RotMatrix(const Eigen::Vector4d &q)
{
Eigen::Matrix3d rotmat;
rotmat << q(0) * q(0) + q(1) * q(1) - q(2) * q(2) - q(3) * q(3), 2 * q(1) * q(2) - 2 * q(0) * q(3),
2 * q(0) * q(2) + 2 * q(1) * q(3),
2 * q(0) * q(3) + 2 * q(1) * q(2), q(0) * q(0) - q(1) * q(1) + q(2) * q(2) - q(3) * q(3),
2 * q(2) * q(3) - 2 * q(0) * q(1),
2 * q(1) * q(3) - 2 * q(0) * q(2), 2 * q(0) * q(1) + 2 * q(2) * q(3),
q(0) * q(0) - q(1) * q(1) - q(2) * q(2) + q(3) * q(3);
return rotmat;
}
//constrain_function
float constrain_function(float data, float Max)
{
if(abs(data)>Max)
{
return (data > 0) ? Max : -Max;
}
else
{
return data;
}
}
//constrain_function2
float constrain_function2(float data, float Min,float Max)
{
if(data > Max)
{
return Max;
}
else if (data < Min)
{
return Min;
}else
{
return data;
}
}
//sign_function
float sign_function(float data)
{
if(data>0)
{
return 1.0;
}
else if(data<0)
{
return -1.0;
}
else if(data == 0)
{
return 0.0;
}
}
// min function
float min(float data1,float data2)
{
if(data1>=data2)
{
return data2;
}
else
{
return data1;
}
}
#endif

@ -0,0 +1,416 @@
/***************************************************************************************************************************
* prometheus_control_utils.h
*
* Author: Qyp
*
* Update Time: 2019.7.6
***************************************************************************************************************************/
#ifndef PROMETHEUS_CONTORL_UTILS_H
#define PROMETHEUS_CONTORL_UTILS_H
#include <Eigen/Eigen>
#include <math.h>
#include <math_utils.h>
#include <command_to_mavros.h>
#include <prometheus_msgs/Message.h>
#include <prometheus_msgs/ControlCommand.h>
#include <prometheus_msgs/SwarmCommand.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
#include <prometheus_msgs/LogMessage.h>
#include <prometheus_msgs/LogMessageControl.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
using namespace std;
#define NUM_POINT 2
#define NUM_MOTOR 4
#define MOTOR_P1 -0.00069
#define MOTOR_P2 0.01271
#define MOTOR_P3 -0.07948
#define MOTOR_P4 0.3052
#define MOTOR_P5 0.008775
#define thrust_max_single_motor 6.0
namespace prometheus_control_utils
{
// 打印上层控制指令
void printf_command_control(const prometheus_msgs::ControlCommand& _ControlCommand)
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>> Control Command <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << "Source: [ "<< _ControlCommand.source << " ] Command_ID: "<< _ControlCommand.Command_ID <<endl;
switch(_ControlCommand.Mode)
{
case prometheus_msgs::ControlCommand::Idle:
if(_ControlCommand.Reference_State.yaw_ref == 999)
{
cout << "Command: [ Idle + Arming + Switching to OFFBOARD mode ] " <<endl;
}else
{
cout << "Command: [ Idle ] " <<endl;
}
break;
case prometheus_msgs::ControlCommand::Takeoff:
cout << "Command: [ Takeoff ] " <<endl;
break;
case prometheus_msgs::ControlCommand::Hold:
cout << "Command: [ Hold ] " <<endl;
break;
case prometheus_msgs::ControlCommand::Land:
cout << "Command: [ Land ] " <<endl;
break;
case prometheus_msgs::ControlCommand::Move:
if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_POS)
{
cout << "Command: [ Move ] " << "Move_mode: [ XYZ_POS ] " <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_POS_Z_VEL)
{
cout << "Command: [ Move ] " << "Move_mode: [ XY_POS_Z_VEL ] " <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_VEL_Z_POS)
{
cout << "Command: [ Move ] " << "Move_mode: [ XY_VEL_Z_POS ] " <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_VEL)
{
cout << "Command: [ Move ] " << "Move_mode: [ XYZ_VEL ] " <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::TRAJECTORY)
{
cout << "Command: [ Move ] " << "Move_mode: [ TRAJECTORY ] " <<endl;
}
if(_ControlCommand.Reference_State.Move_frame == prometheus_msgs::PositionReference::ENU_FRAME)
{
cout << "Move_frame: [ ENU_FRAME ] " <<endl;
}else if(_ControlCommand.Reference_State.Move_frame == prometheus_msgs::PositionReference::BODY_FRAME)
{
cout << "Move_frame: [ BODY_FRAME ] " <<endl;
}
cout << "Position [X Y Z] : " << _ControlCommand.Reference_State.position_ref[0] << " [ m ] "<< _ControlCommand.Reference_State.position_ref[1]<<" [ m ] "<< _ControlCommand.Reference_State.position_ref[2]<<" [ m ] "<<endl;
cout << "Velocity [X Y Z] : " << _ControlCommand.Reference_State.velocity_ref[0] << " [m/s] "<< _ControlCommand.Reference_State.velocity_ref[1]<<" [m/s] "<< _ControlCommand.Reference_State.velocity_ref[2]<<" [m/s] "<<endl;
cout << "Acceleration [X Y Z] : " << _ControlCommand.Reference_State.acceleration_ref[0] << " [m/s^2] "<< _ControlCommand.Reference_State.acceleration_ref[1]<<" [m/s^2] "<< _ControlCommand.Reference_State.acceleration_ref[2]<<" [m/s^2] "<<endl;
cout << "Yaw : " << _ControlCommand.Reference_State.yaw_ref* 180/M_PI << " [deg] " <<endl;
break;
case prometheus_msgs::ControlCommand::Disarm:
cout << "Command: [ Disarm ] " <<endl;
break;
case prometheus_msgs::ControlCommand::User_Mode1:
cout << "Command: [ User_Mode1 ] " <<endl;
break;
case prometheus_msgs::ControlCommand::User_Mode2:
cout << "Command: [ User_Mode2 ] " <<endl;
break;
}
}
// 打印无人机状态
void prinft_drone_state(const prometheus_msgs::DroneState& _Drone_state)
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>> Drone State <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << "Time: " << _Drone_state.time_from_start <<" [s] ";
//是否和飞控建立起连接
if (_Drone_state.connected == true)
{
cout << " [ Connected ]";
}
else
{
cout << " [ Unconnected ]";
}
//是否上锁
if (_Drone_state.armed == true)
{
cout << " [ Armed ]";
}
else
{
cout << " [ DisArmed ]";
}
//是否在地面
if (_Drone_state.landed == true)
{
cout << " [ Ground ] ";
}
else
{
cout << " [ Air ] ";
}
cout << "[ " << _Drone_state.mode<<" ] " <<endl;
cout << "Position [X Y Z] : " << _Drone_state.position[0] << " [ m ] "<< _Drone_state.position[1]<<" [ m ] "<<_Drone_state.position[2]<<" [ m ] "<<endl;
cout << "Velocity [X Y Z] : " << _Drone_state.velocity[0] << " [m/s] "<< _Drone_state.velocity[1]<<" [m/s] "<<_Drone_state.velocity[2]<<" [m/s] "<<endl;
cout << "Attitude [R P Y] : " << _Drone_state.attitude[0] * 180/M_PI <<" [deg] "<<_Drone_state.attitude[1] * 180/M_PI << " [deg] "<< _Drone_state.attitude[2] * 180/M_PI<<" [deg] "<<endl;
cout << "Att_rate [R P Y] : " << _Drone_state.attitude_rate[0] * 180/M_PI <<" [deg/s] "<<_Drone_state.attitude_rate[1] * 180/M_PI << " [deg/s] "<< _Drone_state.attitude_rate[2] * 180/M_PI<<" [deg/s] "<<endl;
}
// 打印位置控制器输出结果
void prinft_attitude_reference(const prometheus_msgs::AttitudeReference& _AttitudeReference)
{
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << "Attitude_sp [R P Y] : " << _AttitudeReference.desired_attitude[0] * 180/M_PI <<" [deg] "<<_AttitudeReference.desired_attitude[1] * 180/M_PI << " [deg] "<< _AttitudeReference.desired_attitude[2] * 180/M_PI<<" [deg] "<<endl;
cout << "Throttle_sp [ 0-1 ] : " << _AttitudeReference.desired_throttle <<endl;
}
void prinft_ref_pose(const geometry_msgs::PoseStamped& ref_pose)
{
cout <<">>>>>>>>>>>>>>>>>>>>>>> Ref Pose <<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << "Ref_position [X Y Z] : " << ref_pose.pose.position.x <<" [m] "<< ref_pose.pose.position.y <<" [m] " << ref_pose.pose.position.z <<" [m] "<<endl;
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 其 他 函 数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 【获取当前时间函数】 单位:秒
float get_time_in_sec(const ros::Time& begin_time)
{
ros::Time time_now = ros::Time::now();
float currTimeSec = time_now.sec - begin_time.sec;
float currTimenSec = time_now.nsec / 1e9 - begin_time.nsec / 1e9;
return (currTimeSec + currTimenSec);
}
// 【坐标系旋转函数】- 机体系到enu系
// body_frame是机体系,enu_frame是惯性系yaw_angle是当前偏航角[rad]
void rotation_yaw(float yaw_angle, float body_frame[2], float enu_frame[2])
{
enu_frame[0] = body_frame[0] * cos(yaw_angle) - body_frame[1] * sin(yaw_angle);
enu_frame[1] = body_frame[0] * sin(yaw_angle) + body_frame[1] * cos(yaw_angle);
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 控 制 辅 助 函 数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
//计算位置误差
Eigen::Vector3f cal_pos_error(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State)
{
Eigen::Vector3f pos_error;
for (int i=0; i<3; i++)
{
pos_error[i] = _Reference_State.position_ref[i] - _DroneState.position[i];
}
return pos_error;
}
//计算速度误差
Eigen::Vector3f cal_vel_error(const prometheus_msgs::DroneState& _DroneState, const prometheus_msgs::PositionReference& _Reference_State)
{
Eigen::Vector3f vel_error;
for (int i=0; i<3; i++)
{
vel_error[i] = _Reference_State.velocity_ref[i] - _DroneState.velocity[i];
}
return vel_error;
}
Eigen::Vector3d accelToThrust(const Eigen::Vector3d& accel_sp, float mass, float tilt_max)
{
Eigen::Vector3d thrust_sp;
//除以电机个数得到单个电机的期望推力
thrust_sp = mass * accel_sp / NUM_MOTOR;
// 推力限幅,根据最大倾斜角及最大油门
float thrust_max_XY_tilt = fabs(thrust_sp[2]) * tanf(tilt_max/180.0*M_PI);
float thrust_max_XY = sqrtf(thrust_max_single_motor * thrust_max_single_motor - pow(thrust_sp[2],2));
thrust_max_XY = min(thrust_max_XY_tilt, thrust_max_XY);
if ((pow(thrust_sp[0],2) + pow(thrust_sp[1],2)) > pow(thrust_max_XY,2))
{
float mag = sqrtf((pow(thrust_sp[0],2) + pow(thrust_sp[1],2)));
thrust_sp[0] = thrust_sp[0] / mag * thrust_max_XY;
thrust_sp[1] = thrust_sp[1] / mag * thrust_max_XY;
}
return thrust_sp;
}
Eigen::Vector3d thrustToThrottle(const Eigen::Vector3d& thrust_sp)
{
Eigen::Vector3d throttle_sp;
//电机模型,可通过辨识得到,推力-油门曲线
for (int i=0; i<3; i++)
{
throttle_sp[i] = MOTOR_P1 * pow(thrust_sp[i],4) + MOTOR_P2 * pow(thrust_sp[i],3) + MOTOR_P3 * pow(thrust_sp[i],2) + MOTOR_P4 * thrust_sp[i] + MOTOR_P5;
// PX4内部默认假设 0.5油门为悬停推力 在无人机重量为1kg时直接除20得到0.5
// throttle_sp[i] = thrust_sp[i]/20
}
return throttle_sp;
}
//Throttle to Attitude
//Thrust to Attitude
//Input: desired thrust (desired throttle [0,1]) and yaw_sp(rad)
//Output: desired attitude (quaternion)
prometheus_msgs::AttitudeReference ThrottleToAttitude(const Eigen::Vector3d& thr_sp, float yaw_sp)
{
prometheus_msgs::AttitudeReference _AttitudeReference;
Eigen::Vector3d att_sp;
att_sp[2] = yaw_sp;
// desired body_z axis = -normalize(thrust_vector)
Eigen::Vector3d body_x, body_y, body_z;
double thr_sp_length = thr_sp.norm();
//cout << "thr_sp_length : "<< thr_sp_length << endl;
if (thr_sp_length > 0.00001f) {
body_z = thr_sp.normalized();
} else {
// no thrust, set Z axis to safe value
body_z = Eigen::Vector3d(0.0f, 0.0f, 1.0f);
}
// vector of desired yaw direction in XY plane, rotated by PI/2
Eigen::Vector3d y_C = Eigen::Vector3d(-sinf(yaw_sp),cosf(yaw_sp),0.0);
if (fabsf(body_z(2)) > 0.000001f) {
// desired body_x axis, orthogonal to body_z
body_x = y_C.cross(body_z);
// keep nose to front while inverted upside down
if (body_z(2) < 0.0f) {
body_x = -body_x;
}
body_x.normalize();
} else {
// desired thrust is in XY plane, set X downside to construct correct matrix,
// but yaw component will not be used actually
body_x = Eigen::Vector3d(0.0f, 0.0f, 0.0f);
body_x(2) = 1.0f;
}
// desired body_y axis
body_y = body_z.cross(body_x);
Eigen::Matrix3d R_sp;
// fill rotation matrix
for (int i = 0; i < 3; i++) {
R_sp(i, 0) = body_x(i);
R_sp(i, 1) = body_y(i);
R_sp(i, 2) = body_z(i);
}
Eigen::Quaterniond q_sp(R_sp);
rotation_to_euler(R_sp, att_sp);
//cout << "Desired euler [R P Y]: "<< att_sp[0]* 180/M_PI <<" [deg] " << att_sp[1]* 180/M_PI <<" [deg] "<< att_sp[2]* 180/M_PI <<" [deg] "<< endl;
//cout << "Desired Thrust: "<< thr_sp_length<< endl;
// cout << "q_sp [x y z w]: "<< q_sp.x() <<" [ ] " << q_sp.y() <<" [ ] "<<q_sp.z() <<" [ ] "<<q_sp.w() <<" [ ] "<<endl;
// cout << "R_sp : "<< R_sp(0, 0) <<" " << R_sp(0, 1) <<" "<< R_sp(0, 2) << endl;
// cout << " : "<< R_sp(1, 0) <<" " << R_sp(1, 1) <<" "<< R_sp(1, 2) << endl;
// cout << " : "<< R_sp(2, 0) <<" " << R_sp(2, 1) <<" "<< R_sp(2, 2) << endl;
_AttitudeReference.throttle_sp[0] = thr_sp[0];
_AttitudeReference.throttle_sp[1] = thr_sp[1];
_AttitudeReference.throttle_sp[2] = thr_sp[2];
//期望油门
_AttitudeReference.desired_throttle = thr_sp_length;
_AttitudeReference.desired_att_q.w = q_sp.w();
_AttitudeReference.desired_att_q.x = q_sp.x();
_AttitudeReference.desired_att_q.y = q_sp.y();
_AttitudeReference.desired_att_q.z = q_sp.z();
_AttitudeReference.desired_attitude[0] = att_sp[0];
_AttitudeReference.desired_attitude[1] = att_sp[1];
_AttitudeReference.desired_attitude[2] = att_sp[2];
return _AttitudeReference;
}
//random number Generation
//if a = 0 b =0, random_num = [-1,1]
//rand函数C语言中用来产生一个随机数的函数
float random_num(float a, float b)
{
float random_num;
random_num = a * 2 * (((float)(rand() % 100))/100 - 0.5) + b;
return random_num;
}
}
#endif

@ -0,0 +1,285 @@
/***************************************************************************************************************************
* prometheus_station_utils.h
*
* Author: Qyp
*
* Update Time: 2019.7.6
***************************************************************************************************************************/
#ifndef PROMETHEUS_STATION_UTILS_H
#define PROMETHEUS_STATION_UTILS_H
#include <Eigen/Eigen>
#include <math.h>
#include <prometheus_msgs/Message.h>
#include <prometheus_msgs/ControlCommand.h>
#include <prometheus_msgs/SwarmCommand.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/ControlOutput.h>
#include <prometheus_msgs/LogMessageControl.h>
#include <prometheus_msgs/LogMessageDetection.h>
#include <prometheus_msgs/LogMessagePlanning.h>
#include <prometheus_msgs/DetectionInfo.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include "printf_utils.h"
using namespace std;
#define NUM_POINT 2
namespace prometheus_station_utils
{
// 五种状态机
enum MISSION_TYPE
{
CONTROL,
LAND,
PLAN,
TRACK,
};
// 打印上层控制指令
void printf_command_control(const prometheus_msgs::ControlCommand& _ControlCommand)
{
cout << GREEN <<">>>>>>>>>>>>>>>>>>>>>>>> Control Command <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << TAIL <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << GREEN << "Source: [ "<< _ControlCommand.source << " ] Command_ID: "<< _ControlCommand.Command_ID << TAIL <<endl;
switch(_ControlCommand.Mode)
{
case prometheus_msgs::ControlCommand::Idle:
if(_ControlCommand.Reference_State.yaw_ref == 999)
{
cout << GREEN << "Command: [ Idle + Arming + Switching to OFFBOARD mode ] " << TAIL <<endl;
}else
{
cout << GREEN << "Command: [ Idle ] " << TAIL <<endl;
}
break;
case prometheus_msgs::ControlCommand::Takeoff:
cout << GREEN << "Command: [ Takeoff ] " << TAIL <<endl;
break;
case prometheus_msgs::ControlCommand::Hold:
cout << GREEN << "Command: [ Hold ] " << TAIL <<endl;
break;
case prometheus_msgs::ControlCommand::Land:
cout << GREEN << "Command: [ Land ] " << TAIL <<endl;
break;
case prometheus_msgs::ControlCommand::Move:
if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_POS)
{
cout << GREEN << "Command: [ Move ] " << "Move_mode: [ XYZ_POS ] " << TAIL <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_POS_Z_VEL)
{
cout << GREEN << "Command: [ Move ] " << "Move_mode: [ XY_POS_Z_VEL ] " << TAIL <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_VEL_Z_POS)
{
cout << GREEN << "Command: [ Move ] " << "Move_mode: [ XY_VEL_Z_POS ] " << TAIL <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_VEL)
{
cout << GREEN << "Command: [ Move ] " << "Move_mode: [ XYZ_VEL ] " << TAIL <<endl;
}else if(_ControlCommand.Reference_State.Move_mode == prometheus_msgs::PositionReference::TRAJECTORY)
{
cout << GREEN << "Command: [ Move ] " << "Move_mode: [ TRAJECTORY ] " << TAIL <<endl;
}
if(_ControlCommand.Reference_State.Move_frame == prometheus_msgs::PositionReference::ENU_FRAME)
{
cout << GREEN << "Move_frame: [ ENU_FRAME ] " << TAIL <<endl;
}else if(_ControlCommand.Reference_State.Move_frame == prometheus_msgs::PositionReference::BODY_FRAME)
{
cout << GREEN << "Move_frame: [ BODY_FRAME ] " << TAIL <<endl;
}
cout << GREEN << "Position [X Y Z] : " << _ControlCommand.Reference_State.position_ref[0] << " [ m ] "<< _ControlCommand.Reference_State.position_ref[1]<<" [ m ] "<< _ControlCommand.Reference_State.position_ref[2]<<" [ m ] "<< TAIL <<endl;
cout << GREEN << "Velocity [X Y Z] : " << _ControlCommand.Reference_State.velocity_ref[0] << " [m/s] "<< _ControlCommand.Reference_State.velocity_ref[1]<<" [m/s] "<< _ControlCommand.Reference_State.velocity_ref[2]<<" [m/s] "<< TAIL <<endl;
cout << GREEN << "Acceleration [X Y Z] : " << _ControlCommand.Reference_State.acceleration_ref[0] << " [m/s^2] "<< _ControlCommand.Reference_State.acceleration_ref[1]<<" [m/s^2] "<< _ControlCommand.Reference_State.acceleration_ref[2]<<" [m/s^2] "<< TAIL <<endl;
cout << GREEN << "Yaw : " << _ControlCommand.Reference_State.yaw_ref* 180/M_PI << " [deg] " << TAIL <<endl;
break;
case prometheus_msgs::ControlCommand::Disarm:
cout << GREEN << "Command: [ Disarm ] " << TAIL <<endl;
break;
case prometheus_msgs::ControlCommand::User_Mode1:
cout << GREEN << "Command: [ User_Mode1 ] " << TAIL <<endl;
break;
case prometheus_msgs::ControlCommand::User_Mode2:
cout << GREEN << "Command: [ User_Mode2 ] " << TAIL <<endl;
break;
}
}
// 打印无人机状态
void prinft_drone_state(const prometheus_msgs::DroneState& _Drone_state)
{
cout << GREEN <<">>>>>>>>>>>>>>>>>>>>>>>> Drone State <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << TAIL <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << GREEN << "Time: " << _Drone_state.time_from_start <<" [s] ";
//是否和飞控建立起连接
if (_Drone_state.connected == true)
{
cout << GREEN << " [ Connected ]";
}
else
{
cout << GREEN << " [ Unconnected ]";
}
//是否上锁
if (_Drone_state.armed == true)
{
cout << GREEN << " [ Armed ]";
}
else
{
cout << GREEN << " [ DisArmed ]";
}
//是否在地面
if (_Drone_state.landed == true)
{
cout << GREEN << " [ Ground ] ";
}
else
{
cout << GREEN << " [ Air ] ";
}
cout << GREEN << "[ " << _Drone_state.mode<<" ] " << TAIL <<endl;
cout << GREEN << "Position [X Y Z] : " << _Drone_state.position[0] << " [ m ] "<< _Drone_state.position[1]<<" [ m ] "<<_Drone_state.position[2]<<" [ m ] "<< TAIL <<endl;
cout << GREEN << "Velocity [X Y Z] : " << _Drone_state.velocity[0] << " [m/s] "<< _Drone_state.velocity[1]<<" [m/s] "<<_Drone_state.velocity[2]<<" [m/s] "<< TAIL <<endl;
cout << GREEN << "Attitude [R P Y] : " << _Drone_state.attitude[0] * 180/M_PI <<" [deg] "<<_Drone_state.attitude[1] * 180/M_PI << " [deg] "<< _Drone_state.attitude[2] * 180/M_PI<<" [deg] "<< TAIL <<endl;
cout << GREEN << "Att_rate [R P Y] : " << _Drone_state.attitude_rate[0] * 180/M_PI <<" [deg/s] "<<_Drone_state.attitude_rate[1] * 180/M_PI << " [deg/s] "<< _Drone_state.attitude_rate[2] * 180/M_PI<<" [deg/s] "<< TAIL <<endl;
}
// 打印位置控制器输出结果
void prinft_attitude_reference(const prometheus_msgs::AttitudeReference& _AttitudeReference)
{
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << GREEN << "Attitude_sp [R P Y] : " << _AttitudeReference.desired_attitude[0] * 180/M_PI <<" [deg] "<<_AttitudeReference.desired_attitude[1] * 180/M_PI << " [deg] "<< _AttitudeReference.desired_attitude[2] * 180/M_PI<<" [deg] "<< TAIL <<endl;
cout << GREEN << "Throttle_sp [ 0-1 ] : " << _AttitudeReference.desired_throttle << TAIL <<endl;
}
// tracking error
Eigen::Vector3d tracking_error(const prometheus_msgs::DroneState& _Drone_state, const prometheus_msgs::ControlCommand& _ControlCommand)
{
Eigen::Vector3d error;
error[0] = sqrt(pow(_Drone_state.position[0] - _ControlCommand.Reference_State.position_ref[0],2)+
pow(_Drone_state.position[1] - _ControlCommand.Reference_State.position_ref[1],2)+
pow(_Drone_state.position[2] - _ControlCommand.Reference_State.position_ref[2],2));
error[1] = sqrt(pow(_Drone_state.velocity[0] - _ControlCommand.Reference_State.velocity_ref[0],2)+
pow(_Drone_state.velocity[1] - _ControlCommand.Reference_State.velocity_ref[1],2)+
pow(_Drone_state.velocity[2] - _ControlCommand.Reference_State.velocity_ref[2],2));
error[2] = 0;
return error;
}
void prinft_ref_pose(const geometry_msgs::PoseStamped& ref_pose)
{
cout << GREEN <<">>>>>>>>>>>>>>>>>>>>>>> Ref Pose <<<<<<<<<<<<<<<<<<<<<<<<<<<<" << TAIL <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(NUM_POINT);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout << GREEN << "Ref_position [X Y Z] : " << ref_pose.pose.position.x <<" [m] "<< ref_pose.pose.position.y <<" [m] " << ref_pose.pose.position.z <<" [m] "<< TAIL <<endl;
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 其 他 函 数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 【获取当前时间函数】 单位:秒
float get_time_in_sec(const ros::Time& begin_time)
{
ros::Time time_now = ros::Time::now();
float currTimeSec = time_now.sec - begin_time.sec;
float currTimenSec = time_now.nsec / 1e9 - begin_time.nsec / 1e9;
return (currTimeSec + currTimenSec);
}
// 将四元数转换至(roll,pitch,yaw) by a 3-2-1 intrinsic Tait-Bryan rotation sequence
// https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
// q0 q1 q2 q3
// w x y z
Eigen::Vector3d quaternion_to_euler(const Eigen::Quaterniond &q)
{
float quat[4];
quat[0] = q.w();
quat[1] = q.x();
quat[2] = q.y();
quat[3] = q.z();
Eigen::Vector3d ans;
ans[0] = atan2(2.0 * (quat[3] * quat[2] + quat[0] * quat[1]), 1.0 - 2.0 * (quat[1] * quat[1] + quat[2] * quat[2]));
ans[1] = asin(2.0 * (quat[2] * quat[0] - quat[3] * quat[1]));
ans[2] = atan2(2.0 * (quat[3] * quat[0] + quat[1] * quat[2]), 1.0 - 2.0 * (quat[2] * quat[2] + quat[3] * quat[3]));
return ans;
}
}
#endif

@ -0,0 +1,160 @@
/***************************************************************************************************************************
* state_from_mavros.h
*
* Author: Qyp
*
* Update Time: 2020.1.18
*
*
* prometheus_controlmavros
* 1mavros
* 2/prometheus/drone_trajectorypos_estimator/state_fromposehistory_window
* 1 mavros
* 2raddeg
*
***************************************************************************************************************************/
#ifndef STATE_FROM_MAVROS_H
#define STATE_FROM_MAVROS_H
#include <ros/ros.h>
#include <bitset>
#include <math_utils.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <mavros_msgs/ExtendedState.h>
#include <mavros_msgs/AttitudeTarget.h>
#include <mavros_msgs/PositionTarget.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/TwistStamped.h>
#include <mavros_msgs/ActuatorControl.h>
#include <sensor_msgs/Imu.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <nav_msgs/Odometry.h>
#include <nav_msgs/Path.h>
#include <std_msgs/Float64.h>
#include <tf2_msgs/TFMessage.h>
#include <geometry_msgs/TransformStamped.h>
#include <tf/transform_listener.h>
using namespace std;
class state_from_mavros
{
public:
//constructed function
state_from_mavros(void):
state_nh("~")
{
state_nh.param<string>("uav_name", uav_name, "/uav0");
if (uav_name == "/uav0")
{
uav_name = "";
}
// 【订阅】无人机当前状态 - 来自飞控
// 本话题来自飞控(通过Mavros功能包 /plugins/sys_status.cpp)
state_sub = state_nh.subscribe<mavros_msgs::State>(uav_name + "/mavros/state", 10, &state_from_mavros::state_cb,this);
// 【订阅】无人机当前状态 - 来自飞控
extended_state_sub = state_nh.subscribe<mavros_msgs::ExtendedState>(uav_name + "/mavros/extended_state", 10, &state_from_mavros::extended_state_cb,this);
// 【订阅】无人机当前位置 坐标系:ENU系 此处注意所有状态量在飞控中均为NED系但在ros中mavros将其转换为ENU系处理。所以在ROS中所有和mavros交互的量都为ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/local_position.cpp读取), 对应Mavlink消息为LOCAL_POSITION_NED (#32), 对应的飞控中的uORB消息为vehicle_local_position.msg
position_sub = state_nh.subscribe<geometry_msgs::PoseStamped>(uav_name + "/mavros/local_position/pose", 10, &state_from_mavros::pos_cb,this);
// 【订阅】无人机当前速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/local_position.cpp读取), 对应Mavlink消息为LOCAL_POSITION_NED (#32), 对应的飞控中的uORB消息为vehicle_local_position.msg
velocity_sub = state_nh.subscribe<geometry_msgs::TwistStamped>(uav_name + "/mavros/local_position/velocity_local", 10, &state_from_mavros::vel_cb,this);
// 【订阅】无人机当前欧拉角 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/imu.cpp读取), 对应Mavlink消息为ATTITUDE (#30), 对应的飞控中的uORB消息为vehicle_attitude.msg
attitude_sub = state_nh.subscribe<sensor_msgs::Imu>(uav_name + "/mavros/imu/data", 10, &state_from_mavros::att_cb,this);
// 【订阅】无人机相对高度 此订阅仅针对户外实验
alt_sub = state_nh.subscribe<std_msgs::Float64>(uav_name + "/mavros/global_position/rel_alt", 10, &state_from_mavros::alt_cb,this);
_DroneState.odom_valid = false;
}
//变量声明
prometheus_msgs::DroneState _DroneState;
string uav_name;
private:
ros::NodeHandle state_nh;
ros::Subscriber state_sub;
ros::Subscriber position_sub;
ros::Subscriber velocity_sub;
ros::Subscriber attitude_sub, alt_sub;
ros::Subscriber extended_state_sub;
ros::Publisher trajectory_pub;
void state_cb(const mavros_msgs::State::ConstPtr &msg)
{
_DroneState.connected = msg->connected;
_DroneState.armed = msg->armed;
_DroneState.mode = msg->mode;
}
void extended_state_cb(const mavros_msgs::ExtendedState::ConstPtr &msg)
{
if(msg->landed_state == msg->LANDED_STATE_ON_GROUND)
{
_DroneState.landed = true;
}else
{
_DroneState.landed = false;
}
}
void pos_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
_DroneState.position[0] = msg->pose.position.x;
_DroneState.position[1] = msg->pose.position.y;
_DroneState.position[2] = msg->pose.position.z;
// 如何判断T265失效呢 或者无人机当前有危险
// _DroneState.odom_valid = false;
}
void vel_cb(const geometry_msgs::TwistStamped::ConstPtr &msg)
{
_DroneState.velocity[0] = msg->twist.linear.x;
_DroneState.velocity[1] = msg->twist.linear.y;
_DroneState.velocity[2] = msg->twist.linear.z;
}
void att_cb(const sensor_msgs::Imu::ConstPtr& msg)
{
Eigen::Quaterniond q_fcu = Eigen::Quaterniond(msg->orientation.w, msg->orientation.x, msg->orientation.y, msg->orientation.z);
//Transform the Quaternion to euler Angles
Eigen::Vector3d euler_fcu = quaternion_to_euler(q_fcu);
_DroneState.attitude_q.w = q_fcu.w();
_DroneState.attitude_q.x = q_fcu.x();
_DroneState.attitude_q.y = q_fcu.y();
_DroneState.attitude_q.z = q_fcu.z();
_DroneState.attitude[0] = euler_fcu[0];
_DroneState.attitude[1] = euler_fcu[1];
_DroneState.attitude[2] = euler_fcu[2];
_DroneState.attitude_rate[0] = msg->angular_velocity.x;
_DroneState.attitude_rate[1] = msg->angular_velocity.x;
_DroneState.attitude_rate[2] = msg->angular_velocity.x;
}
void alt_cb(const std_msgs::Float64::ConstPtr &msg)
{
_DroneState.rel_alt = msg->data;
}
};
#endif

@ -0,0 +1,418 @@
/***************************************************************************************************************************
* att_controller_PID.h
*
* Author: Qyp
*
* Update Time: 2019.3.23
*
* Introduction: attition Controller using PID (P for att loop, pid for rates loop)
* 1. Similiar to the attition controller in PX4 (1.8.2)
* 2. Ref to : https://github.com/PX4/Firmware/blob/master/src/modules/mc_att_control/mc_att_control_main.cpp
* https://github.com/PX4/Firmware/blob/master/src/modules/mc_att_control/AttitudeControl/AttitudeControl.cpp
* 3. Here we didn't consider the mass of the drone, we treat accel_sp is the thrust_sp.
* 4. We didn't use filter to get the derivation of the ratesocity [It must be considered.]
* 5. ThrottleToAttitude ref to https://github.com/PX4/Firmware/blob/master/src/modules/mc_att_control/Utility/ControlMath.cpp
***************************************************************************************************************************/
#ifndef ATT_CONTROLLER_PID_H
#define ATT_CONTROLLER_PID_H
#include <Eigen/Eigen>
#include <math.h>
#include <math_utils.h>
#include <mavros_msgs/State.h>
#include <mavros_msgs/ActuatorControl.h>
#include <sensor_msgs/Imu.h>
using namespace std;
namespace namespace_PID {
class att_controller_PID
{
//public表明该数据成员、成员函数是对全部用户开放的。全部用户都能够直接进行调用在程序的不论什么其他地方訪问。
public:
//构造函数
att_controller_PID(void):
att_pid_nh("~")
{
att_pid_nh.param<float>("MC_ROLL_P", MC_ROLL_P, 6.5);
att_pid_nh.param<float>("MC_ROLLRATE_P", MC_ROLLRATE_P, 0.15);
att_pid_nh.param<float>("MC_ROLLRATE_I", MC_ROLLRATE_I, 0.05);
att_pid_nh.param<float>("MC_ROLLRATE_D", MC_ROLLRATE_D, 0.003);
att_pid_nh.param<float>("MC_RR_INT_LIM", MC_RR_INT_LIM, 0.3);
att_pid_nh.param<float>("MC_PITCH_P", MC_PITCH_P, 6.5);
att_pid_nh.param<float>("MC_PITCHRATE_P", MC_PITCHRATE_P, 0.15);
att_pid_nh.param<float>("MC_PITCHRATE_I", MC_PITCHRATE_I, 0.05);
att_pid_nh.param<float>("MC_PITCHRATE_D", MC_PITCHRATE_D, 0.003);
att_pid_nh.param<float>("MC_PR_INT_LIM", MC_PR_INT_LIM, 0.3);
att_pid_nh.param<float>("MC_YAW_P", MC_YAW_P, 2.8);
att_pid_nh.param<float>("MC_YAWRATE_P", MC_YAWRATE_P, 0.2);
att_pid_nh.param<float>("MC_YAWRATE_I", MC_YAWRATE_I, 0.1);
att_pid_nh.param<float>("MC_YAWRATE_D", MC_YAWRATE_D, 0.00);
att_pid_nh.param<float>("MC_YR_INT_LIM", MC_YR_INT_LIM, 0.3);
att_pid_nh.param<float>("MC_YAW_FF", MC_YAW_FF, 0.5);
att_pid_nh.param<float>("MC_ROLLRATE_MAX", MC_ROLLRATE_MAX, 220.0);
att_pid_nh.param<float>("MC_PITCHRATE_MAX", MC_PITCHRATE_MAX, 220.0);
att_pid_nh.param<float>("MC_YAWRATE_MAX", MC_YAWRATE_MAX, 200.0);
att_pid_nh.param<float>("MC_DTERM_CUTOFF", MC_DTERM_CUTOFF, 30.0);
Euler_fcu = Eigen::Vector3d(0.0,0.0,0.0);
q_fcu = Eigen::Quaterniond(0.0,0.0,0.0,0.0);
rates_fcu = Eigen::Vector3d(0.0,0.0,0.0);
rates_P_output = Eigen::Vector3d(0.0,0.0,0.0);
rates_int = Eigen::Vector3d(0.0,0.0,0.0);
rates_D_output = Eigen::Vector3d(0.0,0.0,0.0);
error_rates_last = Eigen::Vector3d(0.0,0.0,0.0);
euler_setpoint = Eigen::Vector3d(0.0,0.0,0.0);
rates_setpoint = Eigen::Vector3d(0.0,0.0,0.0);
actuator_setpoint = Eigen::Vector4d(0.0,0.0,0.0,0.0);
thrust_sp = Eigen::Vector3d(0.0,0.0,0.0);
flag_offboard = 0;
state_sub = att_pid_nh.subscribe<mavros_msgs::State>("/mavros/state", 10, &att_controller_PID::state_cb,this);
}
//PID parameter for the control law
float MC_ROLL_P;
float MC_ROLLRATE_P;
float MC_ROLLRATE_I;
float MC_ROLLRATE_D;
float MC_RR_INT_LIM;
float MC_PITCH_P;
float MC_PITCHRATE_P;
float MC_PITCHRATE_I;
float MC_PITCHRATE_D;
float MC_PR_INT_LIM;
float MC_YAW_P;
float MC_YAWRATE_P;
float MC_YAWRATE_I;
float MC_YAWRATE_D;
float MC_YR_INT_LIM;
float MC_YAW_FF;
float MC_ROLLRATE_MAX;
float MC_PITCHRATE_MAX;
float MC_YAWRATE_MAX;
float MC_DTERM_CUTOFF;
//Current att of the drone
Eigen::Quaterniond q_fcu;
Eigen::Vector3d Euler_fcu;
Eigen::Vector3d rates_fcu;
//Output of the rates loop in PID [rates_int is the I]
Eigen::Vector3d rates_P_output;
Eigen::Vector3d rates_int;
Eigen::Vector3d rates_D_output;
//Error of the rates in last step [used for the D-output in rates loop]
Eigen::Vector3d error_rates_last;
Eigen::Vector3d error_rates_dot_last;
\
//
Eigen::Vector3d euler_setpoint;
Eigen::Vector3d rates_setpoint;
Eigen::Vector4d actuator_setpoint;
//The delta time between now and the last step
float delta_time;
//Time of the last step
float last_time;
Eigen::Vector3d thrust_sp;
float thrust_body_sp;
//Current state of the drone
mavros_msgs::State current_state;
//Flag of the offboard mode [1 for OFFBOARD mode , 0 for non-OFFBOARD mode]
int flag_offboard;
//Printf the PID parameter
void printf_pid_param();
//Printf the control result
void printf_result();
//attition control main function [Input: desired state, time_now; Output: actuator_setpoint;]
Eigen::Vector4d att_controller(Eigen::Vector3d att, Eigen::Vector3d rates, Eigen::Vector3d accel_sp, float yaw_sp, float curtime);
//ThrottleToAttitude [Input: desired thrust,desired yaw angle; Output: desired euler angle]
void ThrottleToAttitude(float yaw_sp);
//attition control loop [Input: desired state; Output: desired rates]
void _attController();
//ratesocity control loop [Input: rates_setpoint; Output: actuator_setpoint]
void _attrateController();
Eigen::Vector3d cal_rates_error_deriv(Eigen::Vector3d error_now);
private:
ros::NodeHandle att_pid_nh;
ros::Subscriber state_sub;
void state_cb(const mavros_msgs::State::ConstPtr &msg)
{
current_state = *msg;
if(current_state.mode == "OFFBOARD")
{
flag_offboard = 1;
}else
{
flag_offboard = 0;
}
}
};
//attition control main function [Input: desired state, time_now; Output: actuator_setpoint;]
Eigen::Vector4d att_controller_PID::att_controller(Eigen::Vector3d att, Eigen::Vector3d rates, Eigen::Vector3d accel_sp, float yaw_sp, float curtime)
{
delta_time = curtime - last_time;
thrust_sp = accel_sp;
Euler_fcu = att;
rates_fcu = rates;
ThrottleToAttitude(yaw_sp);
_attController();
_attrateController();
last_time = curtime;
return actuator_setpoint;
}
void att_controller_PID::ThrottleToAttitude(float yaw_sp)
{
Eigen::Vector3d body_x,body_y,body_z;
euler_setpoint(2) = yaw_sp;
float thrust_sp_length = thrust_sp.norm();
if (thrust_sp_length > 0.00001f) {
//ENU or NED is different
//body_z = -thrust_sp.normalized();
body_z = thrust_sp.normalized();
} else {
// no thrust, set Z axis to safe value
body_z(0) = 0.0f;
body_z(1) = 0.0f;
body_z(2) = 1.0f;
}
// vector of desired yaw direction in XY plane, rotated by PI/2
Eigen::Vector3d y_C(-sin(euler_setpoint(2)), cos(euler_setpoint(2)), 0.0f);
if (fabs(body_z(2)) > 0.000001f) {
// desired body_x axis, orthogonal to body_z
body_x = y_C.cross( body_z);
// keep nose to front while inverted upside down
if (body_z(2) < 0.0f) {
body_x = -body_x;
}
body_x.normalize();
} else {
// desired thrust is in XY plane, set X downside to construct correct matrix,
// but yaw component will not be used actually
body_x(0) = 0.0f;
body_x(1) = 0.0f;
body_x(2) = 1.0f;
}
// desired body_y axis
body_y = body_z .cross( body_x );
Eigen::Matrix3d R_sp;
// fill rotation matrix
for (int i = 0; i < 3; i++) {
R_sp(i, 0) = body_x(i);
R_sp(i, 1) = body_y(i);
R_sp(i, 2) = body_z(i);
}
//这里由于NED与ENU的关系 ,导致结算出来的欧拉角度有相差
euler_setpoint = rotation_to_euler(R_sp);
thrust_body_sp = thrust_sp_length;
}
void att_controller_PID::_attController()
{
rates_setpoint(0) = MC_ROLL_P * (euler_setpoint(0) - Euler_fcu(0));
rates_setpoint(1) = MC_PITCH_P * (euler_setpoint(1) - Euler_fcu(1));
rates_setpoint(2) = MC_YAW_P * (euler_setpoint(2) - Euler_fcu(2));
// Limit the ratesocity setpoint
rates_setpoint(0) = constrain_function2(rates_setpoint(0), -MC_ROLLRATE_MAX, MC_ROLLRATE_MAX);
rates_setpoint(1) = constrain_function2(rates_setpoint(1), -MC_PITCHRATE_MAX, MC_PITCHRATE_MAX);
rates_setpoint(2) = constrain_function2(rates_setpoint(2), -MC_YAWRATE_MAX, MC_YAWRATE_MAX);
}
void att_controller_PID::_attrateController()
{
Eigen::Vector3d error_rates = rates_setpoint - rates_fcu;
rates_P_output(0) = MC_ROLLRATE_P * error_rates(0);
rates_P_output(1) = MC_PITCHRATE_P * error_rates(1);
rates_P_output(2) = MC_YAWRATE_P * error_rates(2);
Eigen::Vector3d rates_error_deriv = cal_rates_error_deriv(error_rates);
rates_D_output(0) = MC_ROLLRATE_D * rates_error_deriv(0);
rates_D_output(1) = MC_PITCHRATE_D * rates_error_deriv(1);
rates_D_output(2) = MC_YAWRATE_D * rates_error_deriv(2);
// Update integral
rates_int(0) += MC_ROLLRATE_I * error_rates(0) * delta_time;
rates_int(1) += MC_PITCHRATE_I * error_rates(1) * delta_time;
rates_int(2) += MC_YAWRATE_I * error_rates(2) * delta_time;
rates_int(0) = constrain_function2(rates_int(0), -MC_RR_INT_LIM, MC_RR_INT_LIM);
rates_int(1) = constrain_function2(rates_int(1), -MC_PR_INT_LIM, MC_PR_INT_LIM);
rates_int(2) = constrain_function2(rates_int(2), -MC_YR_INT_LIM, MC_YR_INT_LIM);
//
actuator_setpoint(0) = rates_P_output(0) + rates_int(0) + rates_D_output(0);
actuator_setpoint(1) = rates_P_output(1) + rates_int(1) + rates_D_output(1);
actuator_setpoint(2) = rates_P_output(2) + rates_int(2) + rates_D_output(2);
actuator_setpoint(3) = thrust_body_sp;
//If not in OFFBOARD mode, set all intergral to zero.
if(flag_offboard == 0)
{
rates_int = Eigen::Vector3d(0.0,0.0,0.0);
}
}
Eigen::Vector3d att_controller_PID::cal_rates_error_deriv(Eigen::Vector3d error_now)
{
Eigen::Vector3d error_rates_dot_now;
error_rates_dot_now = (error_now - error_rates_last)/delta_time;
error_rates_last = error_now;
float a,b;
b = 2 * M_PI * MC_DTERM_CUTOFF * delta_time;
a = b / (1 + b);
Eigen::Vector3d output;
output = a * error_rates_dot_now + (1 - a) * error_rates_dot_last ;
error_rates_dot_last = output;
return output;
}
void att_controller_PID::printf_result()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>attition Controller<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
cout<<setprecision(2);
cout << "delta_time : " << delta_time<< " [s] " <<endl;
cout << "euler_setpoint [X Y Z] : " << euler_setpoint[0] / M_PI *180 << " [deg] "<< euler_setpoint[1] / M_PI *180 <<" [deg] "<<euler_setpoint[2]/ M_PI *180 <<" [deg] "<<endl;
cout << "rates_setpoint [X Y Z] : " << rates_setpoint[0] / M_PI *180 << " [deg/s] "<< rates_setpoint[1] / M_PI *180 <<" [deg/s] "<<rates_setpoint[2]/ M_PI *180 <<" [deg/s] "<<endl;
cout << "rates_P_output [X Y Z] : " << rates_P_output[0] << " [m/s] "<< rates_P_output[1]<<" [m/s] "<<rates_P_output[2]<<" [m/s] "<<endl;
cout << "rates_I_output [X Y Z] : " << rates_int[0] << " [m/s] "<< rates_int[1]<<" [m/s] "<<rates_int[2]<<" [m/s] "<<endl;
cout << "rates_D_output [X Y Z] : " << rates_D_output[0] << " [m/s] "<< rates_D_output[1]<<" [m/s] "<<rates_D_output[2]<<" [m/s] "<<endl;
cout << "actuator_setpoint [0 1 2 3] : " << actuator_setpoint(0) << " [ ] "<< actuator_setpoint(1) <<" [ ] "<< actuator_setpoint(2) <<" [ ] "<< actuator_setpoint(3)<<" [ ] "<<endl;
}
// 【打印参数函数】
void att_controller_PID::printf_pid_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>> PID Parameter for Attitude Control <<<<<<<<<<<<<<<<<<<" <<endl;
cout <<"MC_ROLL_P : "<< MC_ROLL_P << endl;
cout <<"MC_ROLLRATE_P : "<< MC_ROLLRATE_P << endl;
cout <<"MC_ROLLRATE_I : "<< MC_ROLLRATE_I << endl;
cout <<"MC_ROLLRATE_D : "<< MC_ROLLRATE_D << endl;
cout <<"MC_PITCH_P : "<< MC_PITCH_P << endl;
cout <<"MC_PITCHRATE_P : "<< MC_PITCHRATE_P << endl;
cout <<"MC_PITCHRATE_I : "<< MC_PITCHRATE_I << endl;
cout <<"MC_PITCHRATE_D : "<< MC_PITCHRATE_D << endl;
cout <<"MC_YAW_P : "<< MC_YAW_P << endl;
cout <<"MC_YAWRATE_P : "<< MC_YAWRATE_P << endl;
cout <<"MC_YAWRATE_I : "<< MC_YAWRATE_I << endl;
cout <<"MC_YAWRATE_D : "<< MC_YAWRATE_D << endl;
cout <<"MC_ROLLRATE_MAX : "<< MC_ROLLRATE_MAX << endl;
cout <<"MC_PITCHRATE_MAX : "<< MC_PITCHRATE_MAX << endl;
cout <<"MC_YAWRATE_MAX : "<< MC_YAWRATE_MAX << endl;
cout <<"MC_RR_INT_LIM : "<< MC_RR_INT_LIM << endl;
cout <<"MC_PR_INT_LIM : "<< MC_PR_INT_LIM << endl;
cout <<"MC_YR_INT_LIM : "<< MC_YR_INT_LIM << endl;
}
}
#endif

@ -0,0 +1,387 @@
/***************************************************************************************************************************
* command_to_mavros.h
*
* Author: Qyp
*
* Update Time: 2019.6.28
*
* Introduction: Drone control command send class using Mavros package
* 1. Ref to the Mavros plugins (setpoint_raw, loca_position, imu and etc..)
* 2. Ref to the Offboard Flight task in PX4 code: https://github.com/PX4/Firmware/blob/master/src/lib/FlightTasks/tasks/Offboard/FlightTaskOffboard.cpp
* 3. Ref to the Mavlink module in PX4 code: https://github.com/PX4/Firmware/blob/master/src/modules/mavlink/mavlink_receiver.cpp
* 4. Ref to the position control module in PX4: https://github.com/PX4/Firmware/blob/master/src/modules/mc_pos_control
* 5. Ref to the attitude control module in PX4: https://github.com/PX4/Firmware/blob/master/src/modules/mc_att_control
* 6.
*
* prometheus_controlmavros
* 1prometheus_controlmavros
* 2mavrosPX4
* 3
***************************************************************************************************************************/
#ifndef COMMAND_TO_MAVROS_H
#define COMMAND_TO_MAVROS_H
#include <ros/ros.h>
#include <math_utils.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <mavros_msgs/AttitudeTarget.h>
#include <mavros_msgs/PositionTarget.h>
#include <geometry_msgs/PoseStamped.h>
#include <geometry_msgs/TwistStamped.h>
#include <mavros_msgs/ActuatorControl.h>
#include <sensor_msgs/Imu.h>
#include <prometheus_msgs/DroneState.h>
#include <bitset>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_msgs/DroneState.h>
using namespace std;
class command_to_mavros
{
public:
//constructed function
command_to_mavros(void):
command_nh("~")
{
pos_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
vel_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
accel_drone_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
q_fcu_target = Eigen::Quaterniond(0.0,0.0,0.0,0.0);
euler_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
rates_fcu_target = Eigen::Vector3d(0.0,0.0,0.0);
Thrust_target = 0.0;
// 【订阅】无人机期望位置/速度/加速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为POSITION_TARGET_LOCAL_NED, 对应的飞控中的uORB消息为vehicle_local_position_setpoint.msg
position_target_sub = command_nh.subscribe<mavros_msgs::PositionTarget>("/mavros/setpoint_raw/target_local", 10, &command_to_mavros::pos_target_cb,this);
// 【订阅】无人机期望角度/角速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为ATTITUDE_TARGET (#83), 对应的飞控中的uORB消息为vehicle_attitude_setpoint.msg
attitude_target_sub = command_nh.subscribe<mavros_msgs::AttitudeTarget>("/mavros/setpoint_raw/target_attitude", 10, &command_to_mavros::att_target_cb,this);
// 【订阅】无人机底层控制量Mx My Mz 及 F [0][1][2][3]分别对应 roll pitch yaw控制量 及 油门推力
// 本话题来自飞控(通过Mavros功能包 /plugins/actuator_control.cpp读取), 对应Mavlink消息为ACTUATOR_CONTROL_TARGET, 对应的飞控中的uORB消息为actuator_controls.msg
actuator_target_sub = command_nh.subscribe<mavros_msgs::ActuatorControl>("/mavros/target_actuator_control", 10, &command_to_mavros::actuator_target_cb,this);
// 【发布】位置/速度/加速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_POSITION_TARGET_LOCAL_NED (#84), 对应的飞控中的uORB消息为position_setpoint_triplet.msg
setpoint_raw_local_pub = command_nh.advertise<mavros_msgs::PositionTarget>("/mavros/setpoint_raw/local", 10);
// 【发布】角度/角速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_ATTITUDE_TARGET (#82), 对应的飞控中的uORB消息为vehicle_attitude_setpoint.msg角度 或vehicle_rates_setpoint.msg角速度
setpoint_raw_attitude_pub = command_nh.advertise<mavros_msgs::AttitudeTarget>("/mavros/setpoint_raw/attitude", 10);
// 【发布】底层控制量Mx My Mz 及 F [0][1][2][3]分别对应 roll pitch yaw控制量 及 油门推力 注意 这里是NED系的
// 本话题要发送至飞控(通过Mavros功能包 /plugins/actuator_control.cpp发送), 对应Mavlink消息为SET_ACTUATOR_CONTROL_TARGET, 对应的飞控中的uORB消息为actuator_controls.msg
actuator_setpoint_pub = command_nh.advertise<mavros_msgs::ActuatorControl>("/mavros/actuator_control", 10);
// 【服务】解锁/上锁
// 本服务通过Mavros功能包 /plugins/command.cpp 实现
arming_client = command_nh.serviceClient<mavros_msgs::CommandBool>("/mavros/cmd/arming");
// 【服务】修改系统模式
// 本服务通过Mavros功能包 /plugins/command.cpp 实现
set_mode_client = command_nh.serviceClient<mavros_msgs::SetMode>("/mavros/set_mode");
}
// 相应的命令分别为 待机,起飞,移动(惯性系ENU),移动(机体系),悬停,降落,上锁,紧急降落
enum Command_Type
{
Idle,
Takeoff,
Move_ENU,
Move_Body,
Hold,
Land,
Disarm,
PPN_land,
Trajectory_Tracking,
};
enum Submode_Type
{
XYZ_POS,
XY_POS_Z_VEL,
XY_VEL_Z_POS,
XYZ_VEL,
};
//Target pos of the drone [from fcu]
Eigen::Vector3d pos_drone_fcu_target;
//Target vel of the drone [from fcu]
Eigen::Vector3d vel_drone_fcu_target;
//Target accel of the drone [from fcu]
Eigen::Vector3d accel_drone_fcu_target;
//Target att of the drone [from fcu]
Eigen::Quaterniond q_fcu_target;
Eigen::Vector3d euler_fcu_target;
Eigen::Vector3d rates_fcu_target;
//Target thrust of the drone [from fcu]
float Thrust_target;
mavros_msgs::ActuatorControl actuator_target;
//变量声明 - 服务
mavros_msgs::SetMode mode_cmd;
mavros_msgs::CommandBool arm_cmd;
ros::ServiceClient arming_client;
ros::ServiceClient set_mode_client;
//Idle. Do nothing.
void idle();
//发送位置期望值至飞控输入期望xyz,期望yaw
void send_pos_setpoint(Eigen::Vector3d pos_sp, float yaw_sp);
//发送速度期望值至飞控输入期望vxvyvz,期望yaw
void send_vel_setpoint(Eigen::Vector3d vel_sp, float yaw_sp);
//发送速度期望值至飞控机体系输入期望vxvyvz,期望yaw
void send_vel_setpoint_body(Eigen::Vector3d vel_sp, float yaw_sp);
//发送加速度期望值至飞控输入期望axayaz,期望yaw
//这是px4_pos_controller.cpp中目前使用的控制方式
void send_accel_setpoint(Eigen::Vector3d accel_sp, float yaw_sp);
//发送角度期望值至飞控(输入:期望角度-四元数,期望推力)
void send_attitude_setpoint(prometheus_msgs::AttitudeReference _AttitudeReference);
//发送角度期望值至飞控(输入:期望角速度,期望推力)
void send_attitude_rate_setpoint(Eigen::Vector3d attitude_rate_sp, float thrust_sp);
//发送底层至飞控输入MxMyMz,期望推力)[Not recommanded. Because the high delay between the onboard computer and Pixhawk]
void send_actuator_setpoint(Eigen::Vector4d actuator_sp);
private:
ros::NodeHandle command_nh;
ros::Subscriber position_target_sub;
ros::Subscriber attitude_target_sub;
ros::Subscriber actuator_target_sub;
ros::Publisher setpoint_raw_local_pub;
ros::Publisher setpoint_raw_attitude_pub;
ros::Publisher actuator_setpoint_pub;
void pos_target_cb(const mavros_msgs::PositionTarget::ConstPtr& msg)
{
pos_drone_fcu_target = Eigen::Vector3d(msg->position.x, msg->position.y, msg->position.z);
vel_drone_fcu_target = Eigen::Vector3d(msg->velocity.x, msg->velocity.y, msg->velocity.z);
accel_drone_fcu_target = Eigen::Vector3d(msg->acceleration_or_force.x, msg->acceleration_or_force.y, msg->acceleration_or_force.z);
}
void att_target_cb(const mavros_msgs::AttitudeTarget::ConstPtr& msg)
{
q_fcu_target = Eigen::Quaterniond(msg->orientation.w, msg->orientation.x, msg->orientation.y, msg->orientation.z);
//Transform the Quaternion to euler Angles
euler_fcu_target = quaternion_to_euler(q_fcu_target);
rates_fcu_target = Eigen::Vector3d(msg->body_rate.x, msg->body_rate.y, msg->body_rate.z);
Thrust_target = msg->thrust;
}
void actuator_target_cb(const mavros_msgs::ActuatorControl::ConstPtr& msg)
{
actuator_target = *msg;
}
};
void command_to_mavros::idle()
{
mavros_msgs::PositionTarget pos_setpoint;
//Here pls ref to mavlink_receiver.cpp
pos_setpoint.type_mask = 0x4000;
setpoint_raw_local_pub.publish(pos_setpoint);
}
//发送位置期望值至飞控输入期望xyz,期望yaw
void command_to_mavros::send_pos_setpoint(Eigen::Vector3d pos_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
//Bitmask toindicate which dimensions should be ignored (1 means ignore,0 means not ignore; Bit 10 must set to 0)
//Bit 1:x, bit 2:y, bit 3:z, bit 4:vx, bit 5:vy, bit 6:vz, bit 7:ax, bit 8:ay, bit 9:az, bit 10:is_force_sp, bit 11:yaw, bit 12:yaw_rate
//Bit 10 should set to 0, means is not force sp
pos_setpoint.type_mask = 0b100111111000; // 100 111 111 000 xyz + yaw
pos_setpoint.coordinate_frame = 1;
pos_setpoint.position.x = pos_sp[0];
pos_setpoint.position.y = pos_sp[1];
pos_setpoint.position.z = pos_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Pos_target [X Y Z] : " << pos_drone_fcu_target[0] << " [ m ] "<< pos_drone_fcu_target[1]<<" [ m ] "<<pos_drone_fcu_target[2]<<" [ m ] "<<endl;
cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送速度期望值至飞控输入期望vxvyvz,期望yaw
void command_to_mavros::send_vel_setpoint(Eigen::Vector3d vel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
pos_setpoint.type_mask = 0b100111000111;
pos_setpoint.coordinate_frame = 1;
pos_setpoint.velocity.x = vel_sp[0];
pos_setpoint.velocity.y = vel_sp[1];
pos_setpoint.velocity.z = vel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送速度期望值至飞控机体系输入期望vxvyvz,期望yaw
void command_to_mavros::send_vel_setpoint_body(Eigen::Vector3d vel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
pos_setpoint.type_mask = 0b100111000111;
//uint8 FRAME_LOCAL_NED = 1
//uint8 FRAME_BODY_NED = 8
pos_setpoint.coordinate_frame = 8;
pos_setpoint.position.x = vel_sp[0];
pos_setpoint.position.y = vel_sp[1];
pos_setpoint.position.z = vel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送加速度期望值至飞控输入期望axayaz,期望yaw
void command_to_mavros::send_accel_setpoint(Eigen::Vector3d accel_sp, float yaw_sp)
{
mavros_msgs::PositionTarget pos_setpoint;
pos_setpoint.type_mask = 0b100000111111;
pos_setpoint.coordinate_frame = 1;
pos_setpoint.acceleration_or_force.x = accel_sp[0];
pos_setpoint.acceleration_or_force.y = accel_sp[1];
pos_setpoint.acceleration_or_force.z = accel_sp[2];
pos_setpoint.yaw = yaw_sp;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Acc_target [X Y Z] : " << accel_drone_fcu_target[0] << " [m/s^2] "<< accel_drone_fcu_target[1]<<" [m/s^2] "<<accel_drone_fcu_target[2]<<" [m/s^2] "<<endl;
cout << "Yaw_target : " << euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
}
//发送角度期望值至飞控(输入:期望角度-四元数,期望推力)
void command_to_mavros::send_attitude_setpoint(prometheus_msgs::AttitudeReference _AttitudeReference)
{
mavros_msgs::AttitudeTarget att_setpoint;
//Mappings: If any of these bits are set, the corresponding input should be ignored:
//bit 1: body roll rate, bit 2: body pitch rate, bit 3: body yaw rate. bit 4-bit 6: reserved, bit 7: throttle, bit 8: attitude
att_setpoint.type_mask = 0b00000111;
att_setpoint.orientation.x = _AttitudeReference.desired_att_q.x;
att_setpoint.orientation.y = _AttitudeReference.desired_att_q.y;
att_setpoint.orientation.z = _AttitudeReference.desired_att_q.z;
att_setpoint.orientation.w = _AttitudeReference.desired_att_q.w;
att_setpoint.thrust = _AttitudeReference.desired_throttle;
setpoint_raw_attitude_pub.publish(att_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Att_target [R P Y] : " << euler_fcu_target[0] * 180/M_PI <<" [deg] "<<euler_fcu_target[1] * 180/M_PI << " [deg] "<< euler_fcu_target[2] * 180/M_PI<<" [deg] "<<endl;
cout << "Thr_target [0 - 1] : " << Thrust_target <<endl;
}
//发送角度期望值至飞控(输入:期望角速度,期望推力)
void command_to_mavros::send_attitude_rate_setpoint(Eigen::Vector3d attitude_rate_sp, float thrust_sp)
{
mavros_msgs::AttitudeTarget att_setpoint;
//Mappings: If any of these bits are set, the corresponding input should be ignored:
//bit 1: body roll rate, bit 2: body pitch rate, bit 3: body yaw rate. bit 4-bit 6: reserved, bit 7: throttle, bit 8: attitude
att_setpoint.type_mask = 0b10000000;
att_setpoint.body_rate.x = attitude_rate_sp[0];
att_setpoint.body_rate.y = attitude_rate_sp[1];
att_setpoint.body_rate.z = attitude_rate_sp[2];
att_setpoint.thrust = thrust_sp;
setpoint_raw_attitude_pub.publish(att_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Att_rate_target [R P Y] : " << rates_fcu_target[0] * 180/M_PI <<" [deg/s] "<<rates_fcu_target[1] * 180/M_PI << " [deg/s] "<< rates_fcu_target[2] * 180/M_PI<<" [deg/s] "<<endl;
cout << "Thr_target [0 - 1] : " << Thrust_target <<endl;
}
//发送底层至飞控输入MxMyMz,期望推力)
void command_to_mavros::send_actuator_setpoint(Eigen::Vector4d actuator_sp)
{
mavros_msgs::ActuatorControl actuator_setpoint;
actuator_setpoint.group_mix = 0;
actuator_setpoint.controls[0] = actuator_sp(0);
actuator_setpoint.controls[1] = actuator_sp(1);
actuator_setpoint.controls[2] = actuator_sp(2);
actuator_setpoint.controls[3] = actuator_sp(3);
actuator_setpoint.controls[4] = 0.0;
actuator_setpoint.controls[5] = 0.0;
actuator_setpoint.controls[6] = 0.0;
actuator_setpoint.controls[7] = 0.0;
actuator_setpoint_pub.publish(actuator_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
//ned to enu
cout << "actuator_target [0 1 2 3] : " << actuator_target.controls[0] << " [ ] "<< -actuator_target.controls[1] <<" [ ] "<<-actuator_target.controls[2]<<" [ ] "<<actuator_target.controls[3] <<" [ ] "<<endl;
cout << "actuator_target [4 5 6 7] : " << actuator_target.controls[4] << " [ ] "<< actuator_target.controls[5] <<" [ ] "<<actuator_target.controls[6]<<" [ ] "<<actuator_target.controls[7] <<" [ ] "<<endl;
}
#endif

@ -0,0 +1,161 @@
//串口读取库函数(用于读取超声波数据)
//主要功能:读取串口数据
//输入:需要先设置波特率、端口号等
//输出:串口数据
#ifndef _SERIAL_H
#define _SERIAL_H
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <stdlib.h>
#include <errno.h>
#include <iostream>
using namespace std;
class Serial{
public:
Serial();
~Serial();
public:
static int set_opt(int fd, int nSpeed, int nBits, char nEvent, int nStop);
static int open_portUSB(int comport);
static int open_port_ultrasonic();
static int nwrite(int serialfd, unsigned char *data, int datalength);
static int nread(int fd, unsigned char *data, int datalength);
};
Serial::Serial( ) {
}
Serial::~Serial() {
}
int Serial::set_opt(int fd,int nSpeed, int nBits, char nEvent, int nStop)
{
struct termios newtio,oldtio;
if ( tcgetattr( fd,&oldtio) != 0) {
perror("SetupSerial 1");
return -1;
}
bzero(&newtio, sizeof(newtio));
newtio.c_cflag |= CLOCAL | CREAD;
newtio.c_cflag &= ~CSIZE;
switch( nBits )
{
case 7:
newtio.c_cflag |= CS7;
break;
case 8:
newtio.c_cflag |= CS8;
break;
}
switch( nEvent )
{
case 'O':
newtio.c_cflag |= PARENB;
newtio.c_cflag |= PARODD;
newtio.c_iflag |= (INPCK | ISTRIP);
break;
case 'E':
newtio.c_iflag |= (INPCK | ISTRIP);
newtio.c_cflag |= PARENB;
newtio.c_cflag &= ~PARODD;
break;
case 'N':
newtio.c_cflag &= ~PARENB;
break;
}
switch( nSpeed )
{
case 2400:
cfsetispeed(&newtio, B2400);
cfsetospeed(&newtio, B2400);
break;
case 4800:
cfsetispeed(&newtio, B4800);
cfsetospeed(&newtio, B4800);
break;
case 9600:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
case 115200:
cfsetispeed(&newtio, B115200);
cfsetospeed(&newtio, B115200);
break;
default:
cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
break;
}
if( nStop == 1 )
newtio.c_cflag &= ~CSTOPB;
else if ( nStop == 2 )
newtio.c_cflag |= CSTOPB;
newtio.c_cc[VTIME] = 0;
newtio.c_cc[VMIN] = 0;
tcflush(fd,TCIFLUSH);
if((tcsetattr(fd,TCSANOW,&newtio))!=0)
{
perror("com set error");
return -1;
}
return 0;
}
int Serial::open_portUSB(int comport) //通过参数,打开相应的串口
{
string serial_port_adr("/dev/ttyUSB"+ to_string(comport));
cout << serial_port_adr << endl;
int fd = open( serial_port_adr.c_str() , O_RDWR|O_NOCTTY);
if (-1 == fd)
{
perror("Can't Open Serial Port!!");
}
return fd;
}
int Serial::open_port_ultrasonic() //通过参数,打开相应的串口
{
string serial_port_adr("/dev/ultrasonic");
cout << serial_port_adr << endl;
int fd = open( serial_port_adr.c_str() , O_RDWR|O_NOCTTY);
if (-1 == fd)
{
perror("Can't Open Serial Port!!");
}
return fd;
}
int Serial::nwrite (int serialfd,unsigned char *data, int datalength )
{
return write(serialfd, data, datalength);
}
int Serial::nread(int fd, unsigned char *data,int datalength) {
int readlen = read(fd,data,datalength);
cout << "readlen: " << readlen<<endl;
if( readlen <= 0 )
{
printf("read error!!");
}
return readlen;
}
#endif

@ -0,0 +1,462 @@
/***************************************************************************************************************************
* keyboard_control.cpp
*
* Author: Qyp
*
* Update Time: 2019.01.10
*
* : ,仿,使.
* 1.
* 2.
* 3.
* 4.
* 5.
*
***************************************************************************************************************************/
#include <ros/ros.h>
#include <KeyboardEvent.h>
#include <Eigen/Eigen>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <prometheus_msgs/ControlCommand.h>
#include <controller_test.h>
#include <nav_msgs/Path.h>
#define VEL_XY_STEP_SIZE 0.1
#define VEL_Z_STEP_SIZE 0.1
#define YAW_STEP_SIZE 0.08
#define TRA_WINDOW 2000
#define NODE_NAME "keyboard_control"
float time_trajectory = 0.0;
float trajectory_total_time = 50.0;
using namespace std;
std::vector<geometry_msgs::PoseStamped> posehistory_vector_;
ros::Publisher ref_trajectory_pub;
prometheus_msgs::ControlCommand Command_Now;
mavros_msgs::State current_state; //无人机当前状态[包含上锁状态 模式] (从飞控中读取)
void Draw_in_rviz(const prometheus_msgs::PositionReference& pos_ref, bool draw_trajectory);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void state_cb(const mavros_msgs::State::ConstPtr& msg)
{
current_state = *msg;
}
void timerCallback(const ros::TimerEvent& e)
{
cout << ">>>>>>>>>>>>>>>>>>>>>>>> Welcome to Prometheus <<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "ENTER key to control the drone: 1 for switch offboard and arm, Space for Takeoff, L for Land, H for Hold" <<endl;
cout << "Move mode (XYZ_VEL,BODY_FRAME): w/s for body_x, a/d for body_y, k/m for z, q/e for body_yaw" <<endl;
cout << "CTRL-C to quit." <<endl;
}
int main(int argc, char **argv)
{
ros::init(argc, argv, "keyboard_control");
ros::NodeHandle nh;
ros::Rate rate(20.0);
ros::Publisher move_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
//【发布】参考轨迹
ref_trajectory_pub = nh.advertise<nav_msgs::Path>("/prometheus/reference_trajectory", 10);
ros::Timer timer = nh.createTimer(ros::Duration(30.0), timerCallback);
// 圆形轨迹追踪类
Controller_Test Controller_Test;
Controller_Test.printf_param();
KeyboardEvent keyboardcontrol;
char key_now;
char key_last;
// 初始化命令-
// 默认设置Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = 0;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = 0;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(1);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
while (ros::ok())
{
keyboardcontrol.RosWhileLoopRun();
key_now = keyboardcontrol.GetPressedKey();
switch (key_now)
{
//悬停, 应当只发送一次, 不需要循环发送
case U_KEY_NONE:
if (key_last != U_KEY_NONE)
{
//to be continued.
}
sleep(0.5);
break;
// 数字1非小键盘数字解锁及切换到OFFBOARD模式
case U_KEY_1:
cout << " " <<endl;
cout << "Arm and Switch to OFFBOARD." <<endl;
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.yaw_ref = 999;
move_pub.publish(Command_Now);
sleep(1.0);
break;
// 空格:起飞
case U_KEY_SPACE:
cout << " " <<endl;
cout << "Switch to Takeoff Mode." <<endl;
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.Reference_State.yaw_ref = 0.0;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
sleep(1.0);
break;
// 键盘L降落
case U_KEY_L:
cout << " " <<endl;
cout << "Switch to Land Mode." <<endl;
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Land;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
// 键盘0非小键盘数字紧急停止
case U_KEY_0:
cout << " " <<endl;
cout << "Switch to Disarm Mode." <<endl;
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Disarm;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
//起飞要维持起飞的模式?
case U_KEY_T:
cout << " " <<endl;
cout << "Switch to Takeoff Mode." <<endl;
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
sleep(2.0);
break;
//起飞要维持起飞的模式?
case U_KEY_H:
cout << " " <<endl;
cout << "Switch to Hold Mode." <<endl;
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Hold;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
move_pub.publish(Command_Now);
sleep(1.0);
break;
// 向前匀速运动
case U_KEY_W:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.velocity_ref[0] += VEL_XY_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_Now.Reference_State.velocity_ref[0] << " [m/s] " << Command_Now.Reference_State.velocity_ref[1] << " [m/s] " << Command_Now.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向后匀速运动
case U_KEY_S:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.velocity_ref[0] -= VEL_XY_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_Now.Reference_State.velocity_ref[0] << " [m/s] " << Command_Now.Reference_State.velocity_ref[1] << " [m/s] " << Command_Now.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向左匀速运动
case U_KEY_A:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.velocity_ref[1] += VEL_XY_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_Now.Reference_State.velocity_ref[0] << " [m/s] " << Command_Now.Reference_State.velocity_ref[1] << " [m/s] " << Command_Now.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向右匀速运动
case U_KEY_D:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.velocity_ref[1] -= VEL_XY_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_Now.Reference_State.velocity_ref[0] << " [m/s] " << Command_Now.Reference_State.velocity_ref[1] << " [m/s] " << Command_Now.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向上运动
case U_KEY_K:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.velocity_ref[2] += VEL_Z_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_Now.Reference_State.velocity_ref[0] << " [m/s] " << Command_Now.Reference_State.velocity_ref[1] << " [m/s] " << Command_Now.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向下运动
case U_KEY_M:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.velocity_ref[2] -= VEL_Z_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_Now.Reference_State.velocity_ref[0] << " [m/s] " << Command_Now.Reference_State.velocity_ref[1] << " [m/s] " << Command_Now.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 偏航运动,左转 (这个里偏航控制的是位置 不是速度)
case U_KEY_Q:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.yaw_ref = YAW_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Increase the Yaw angle." <<endl;
sleep(0.1);
break;
// 偏航运动,右转
case U_KEY_E:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_Now.Reference_State.yaw_ref = YAW_STEP_SIZE;
move_pub.publish(Command_Now);
cout << " " <<endl;
cout << "Decrease the Yaw angle." <<endl;
sleep(0.1);
break;
// 圆形追踪
case U_KEY_9:
time_trajectory = 0.0;
trajectory_total_time = 50.0;
// 需要设置
while(time_trajectory < trajectory_total_time)
{
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State = Controller_Test.Circle_trajectory_generation(time_trajectory);
move_pub.publish(Command_Now);
time_trajectory = time_trajectory + 0.01;
cout << "Trajectory tracking: "<< time_trajectory << " / " << trajectory_total_time << " [ s ]" <<endl;
Draw_in_rviz(Command_Now.Reference_State, true);
ros::Duration(0.01).sleep();
}
break;
// 8字追踪
case U_KEY_8:
time_trajectory = 0.0;
trajectory_total_time = 50.0;
// 需要设置
while(time_trajectory < trajectory_total_time)
{
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State = Controller_Test.Eight_trajectory_generation(time_trajectory);
move_pub.publish(Command_Now);
time_trajectory = time_trajectory + 0.01;
cout << "Trajectory tracking: "<< time_trajectory << " / " << trajectory_total_time << " [ s ]" <<endl;
Draw_in_rviz(Command_Now.Reference_State, true);
ros::Duration(0.01).sleep();
}
break;
}
key_last = key_now;
ros::spinOnce();
rate.sleep();
}
return 0;
}
void Draw_in_rviz(const prometheus_msgs::PositionReference& pos_ref, bool draw_trajectory)
{
geometry_msgs::PoseStamped reference_pose;
reference_pose.header.stamp = ros::Time::now();
reference_pose.header.frame_id = "world";
reference_pose.pose.position.x = pos_ref.position_ref[0];
reference_pose.pose.position.y = pos_ref.position_ref[1];
reference_pose.pose.position.z = pos_ref.position_ref[2];
if(draw_trajectory)
{
posehistory_vector_.insert(posehistory_vector_.begin(), reference_pose);
if(posehistory_vector_.size() > TRA_WINDOW){
posehistory_vector_.pop_back();
}
nav_msgs::Path reference_trajectory;
reference_trajectory.header.stamp = ros::Time::now();
reference_trajectory.header.frame_id = "world";
reference_trajectory.poses = posehistory_vector_;
ref_trajectory_pub.publish(reference_trajectory);
}else
{
posehistory_vector_.clear();
nav_msgs::Path reference_trajectory;
reference_trajectory.header.stamp = ros::Time::now();
reference_trajectory.header.frame_id = "world";
reference_trajectory.poses = posehistory_vector_;
ref_trajectory_pub.publish(reference_trajectory);
}
}

@ -0,0 +1,178 @@
//ROS 头文件
#include <ros/ros.h>
#include <iostream>
#include <quadrotor_msgs/PositionCommand.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/ControlCommand.h>
using namespace std;
#define NODE_NAME "planner_server"
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>全 局 变 量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
bool sim_mode; // 选择Gazebo仿真模式 或 真实实验模式
bool drone_ok;
int controller_flag;
prometheus_msgs::DroneState _DroneState; // 无人机状态
quadrotor_msgs::PositionCommand cmd_from_planning;
prometheus_msgs::ControlCommand Command_Now; //发送给控制模块 [px4_pos_controller.cpp]的命令
ros::Publisher command_pub;
void planning_cmd_cb(const quadrotor_msgs::PositionCommand::ConstPtr& msg)
{
cmd_from_planning = *msg;
if(cmd_from_planning.trajectory_flag == 1)
{
//flag为1代表轨迹可用
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
if(controller_flag == 0)
{
// pos_controller
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::TRAJECTORY;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
}
else if (controller_flag ==1)
{
// px4_sender
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
}
Command_Now.Reference_State.position_ref[0] = cmd_from_planning.position.x;
Command_Now.Reference_State.position_ref[1] = cmd_from_planning.position.y;
Command_Now.Reference_State.position_ref[2] = cmd_from_planning.position.z;
Command_Now.Reference_State.velocity_ref[0] = cmd_from_planning.velocity.x;
Command_Now.Reference_State.velocity_ref[1] = cmd_from_planning.velocity.y;
Command_Now.Reference_State.velocity_ref[2] = cmd_from_planning.velocity.z;
Command_Now.Reference_State.acceleration_ref[0] = cmd_from_planning.acceleration.x;
Command_Now.Reference_State.acceleration_ref[1] = cmd_from_planning.acceleration.y;
Command_Now.Reference_State.acceleration_ref[2] = cmd_from_planning.acceleration.z;
Command_Now.Reference_State.yaw_ref = cmd_from_planning.yaw;
Command_Now.Reference_State.yaw_rate_ref = cmd_from_planning.yaw_dot;
if(drone_ok)
{
command_pub.publish(Command_Now);
}
}else
{
cout << "wrong trajectory_flag"<<endl;
}
}
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
{
_DroneState = *msg;
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "planner_server");
ros::NodeHandle nh("~");
ros::Rate rate(100.0);
//【订阅】规划器 traj_server发布的控制指令
ros::Subscriber landpad_det_sub = nh.subscribe<quadrotor_msgs::PositionCommand>("/planning/pos_cmd", 10, planning_cmd_cb);
//【订阅】无人机状态
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
//【发布】转化为prometheus可用的控制指令
command_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>参数读取<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
// 仿真模式 - 区别在于是否自动切换offboard模式
nh.param<bool>("sim_mode", sim_mode, true);
nh.param<int>("controller_flag", controller_flag, 0);
drone_ok = false;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(2);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
Command_Now.Command_ID = 1;
Command_Now.source = NODE_NAME;
if(sim_mode)
{
// Waiting for input
int start_flag = 0;
while(start_flag == 0)
{
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>Planner Server Mission<<<<<<<<<<<<<<<<<<<<<< "<< endl;
cout << "Please check the parameter and settingenter 1 to continue else for quit: "<<endl;
cin >> start_flag;
}
while(ros::ok() && _DroneState.mode != "OFFBOARD")
{
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.yaw_ref = 999;
command_pub.publish(Command_Now);
cout << "Switch to OFFBOARD and arm ..."<<endl;
ros::Duration(2.0).sleep();
ros::spinOnce();
}
}else
{
while(ros::ok() && _DroneState.mode != "OFFBOARD")
{
cout << "Waiting for the offboard mode"<<endl;
ros::Duration(1.0).sleep();
ros::spinOnce();
}
}
// 起飞
cout<<"[planner_server]: "<<"Takeoff to predefined position."<<endl;
while( _DroneState.position[2] < 0.5)
{
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
command_pub.publish(Command_Now);
cout << "Takeoff ..."<<endl;
ros::Duration(3.0).sleep();
ros::spinOnce();
}
drone_ok = true;
// 等待
ros::Duration(3.0).sleep();
while (ros::ok())
{
//回调
ros::spinOnce();
rate.sleep();
}
return 0;
}

@ -0,0 +1,199 @@
#include <ros/ros.h>
#include <state_from_mavros.h>
#include <command_to_mavros.h>
#include <pos_controller_PID.h>
#include <prometheus_msgs/ControlCommand.h>
#include <prometheus_msgs/DroneState.h>
#include <prometheus_msgs/PositionReference.h>
#include <prometheus_msgs/AttitudeReference.h>
#include <prometheus_control_utils.h>
#include <prometheus_msgs/Trajectory.h>
#include <Eigen/Eigen>
using namespace std;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>变量声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
prometheus_msgs::ControlCommand Command_Now; //无人机当前执行命令
prometheus_msgs::ControlCommand Command_Last; //无人机上一条执行命令
prometheus_msgs::DroneState _DroneState; //无人机状态量
float cur_time;
Eigen::Vector3d pos_sp(0,0,0);
Eigen::Vector3d vel_sp(0,0,0);
double yaw_sp;
//Target pos of the drone [from fcu]
Eigen::Vector3d pos_drone_fcu_target;
//Target vel of the drone [from fcu]
Eigen::Vector3d vel_drone_fcu_target;
void Command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
Command_Now = *msg;
}
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
{
_DroneState = *msg;
_DroneState.time_from_start = cur_time;
}
void pos_target_cb(const mavros_msgs::PositionTarget::ConstPtr& msg)
{
pos_drone_fcu_target = Eigen::Vector3d(msg->position.x, msg->position.y, msg->position.z);
vel_drone_fcu_target = Eigen::Vector3d(msg->velocity.x, msg->velocity.y, msg->velocity.z);
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_fw_controller");
ros::NodeHandle nh("~");
ros::Subscriber Command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10, Command_cb);
//【订阅】无人机当前状态
// 本话题来自根据需求自定px4_pos_estimator.cpp
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus_msgs/drone_state", 10, drone_state_cb);
// 【订阅】无人机期望位置/速度/加速度 坐标系:ENU系
// 本话题来自飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp读取), 对应Mavlink消息为POSITION_TARGET_LOCAL_NED, 对应的飞控中的uORB消息为vehicle_local_position_setpoint.msg
ros::Subscriber position_target_sub = nh.subscribe<mavros_msgs::PositionTarget>("/mavros/setpoint_raw/target_local", 10, pos_target_cb);
// 【发布】位置/速度/加速度期望值 坐标系 ENU系
// 本话题要发送至飞控(通过Mavros功能包 /plugins/setpoint_raw.cpp发送), 对应Mavlink消息为SET_POSITION_TARGET_LOCAL_NED (#84), 对应的飞控中的uORB消息为position_setpoint_triplet.msg
ros::Publisher setpoint_raw_local_pub = nh.advertise<mavros_msgs::PositionTarget>("/mavros/setpoint_raw/local", 10);
// 频率 [50Hz]
ros::Rate rate(50.0);
// 先读取一些飞控的数据
for(int i=0;i<50;i++)
{
ros::spinOnce();
rate.sleep();
}
// 初始化命令-
// 默认设置Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_Now.Mode = command_to_mavros::Idle;
Command_Now.Command_ID = 0;
Command_Now.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = 0;
// 记录启控时间
ros::Time begin_time = ros::Time::now();
float last_time = prometheus_control_utils::get_time_in_sec(begin_time);
float dt = 0;
mavros_msgs::PositionTarget pos_setpoint;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
// 当前时间
cur_time = prometheus_control_utils::get_time_in_sec(begin_time);
dt = cur_time - last_time;
dt = constrain_function2(dt, 0.01, 0.03);
last_time = cur_time;
//执行回调函数
ros::spinOnce();
cout <<">>>>>>>>>>>>>>>>>>>>>> px4_fw_controller <<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
// 打印无人机状态
prometheus_control_utils::prinft_drone_state(_DroneState);
// 打印上层控制指令
prometheus_control_utils::printf_command_control(Command_Now);
switch (Command_Now.Mode)
{
case command_to_mavros::Idle:
break;
case command_to_mavros::Takeoff:
break;
// 不支持复合模式
case prometheus_msgs::ControlCommand::Move:
//Bitmask toindicate which dimensions should be ignored (1 means ignore,0 means not ignore; Bit 10 must set to 0)
//Bit 1:x, bit 2:y, bit 3:z, bit 4:vx, bit 5:vy, bit 6:vz, bit 7:ax, bit 8:ay, bit 9:az, bit 10:is_force_sp, bit 11:yaw, bit 12:yaw_rate
//Bit 10 should set to 0, means is not force sp
pos_setpoint.type_mask = 0b110111000000; // 110 111 000 000 vxvyvz + xyz
pos_setpoint.coordinate_frame = 1;
pos_setpoint.position.x = Command_Now.Reference_State.position_ref[0];
pos_setpoint.position.y = Command_Now.Reference_State.position_ref[1];
pos_setpoint.position.z = Command_Now.Reference_State.position_ref[2];
pos_setpoint.velocity.x = 0.0;
pos_setpoint.velocity.y = 0.0;
pos_setpoint.velocity.z = Command_Now.Reference_State.yaw_ref /3.14 * 180;
setpoint_raw_local_pub.publish(pos_setpoint);
// 检查飞控是否收到控制量
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>command_to_mavros<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Pos_target [X Y Z] : " << pos_drone_fcu_target[0] << " [ m ] "<< pos_drone_fcu_target[1]<<" [ m ] "<<pos_drone_fcu_target[2]<<" [ m ] "<<endl;
cout << "Vel_target [X Y Z] : " << vel_drone_fcu_target[0] << " [m/s] "<< vel_drone_fcu_target[1]<<" [m/s] "<<vel_drone_fcu_target[2]<<" [m/s] "<<endl;
break;
// 不支持复合模式
case command_to_mavros::Move_Body:
break;
case command_to_mavros::Hold:
break;
case prometheus_msgs::ControlCommand::Land:
break;
case command_to_mavros::Disarm:
break;
case command_to_mavros::PPN_land:
break;
}
Command_Last = Command_Now;
rate.sleep();
}
return 0;
}

@ -0,0 +1,402 @@
/***************************************************************************************************************************
* px4_pos_att_controller.cpp
*
* Author: Qyp
*
* Update Time: 2019.3.16
*
* Introduction: PX4 Position & Attitude Controller using own control mehthod (but it is pid now)
* 1. Subscribe command.msg from upper nodes
* 2. Calculate the accel_sp using pos_controller_PID.h
* 3. Send command using command_to_mavros.h
***************************************************************************************************************************/
#include <ros/ros.h>
#include <command_to_mavros.h>
#include <pos_controller_PID.h>
#include <att_controller_PID.h>
#include <prometheus_msgs/ControlCommand.h>
#include <Eigen/Eigen>
using namespace std;
using namespace namespace_PID;
//自定义的Command变量
//相应的命令分别为 待机 起飞 悬停 降落 移动(惯性系ENU) 上锁 移动(机体系)
//但目前 起飞和待机 并没有正式使用
enum Command
{
Move_ENU,
Move_Body,
Hold,
Land,
Disarm,
PPN_land,
Idle
};
//Command Now [from upper node]
prometheus_msgs::ControlCommand Command_Now; //无人机当前执行命令
//Command Last [from upper node]
prometheus_msgs::ControlCommand Command_Last; //无人机上一条执行命令
int flag_using_pid;
float get_time_in_sec(ros::Time begin);
void prinft_command_state();
void rotation_yaw(float yaw_angle, float input[2], float output[2]);
void Command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
Command_Now = *msg;
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_pos_att_controller");
ros::NodeHandle nh("~");
//flag of using our own pid control law or not: 0 for not use, 1 for use
nh.param<int>("flag_using_pid", flag_using_pid, 0);
ros::Subscriber Command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10, Command_cb);
ros::Rate rate(250.0);
Eigen::Vector3d pos_sp(0,0,0);
Eigen::Vector3d vel_sp(0,0,0);
Eigen::Vector3d accel_sp(0,0,0);
Eigen::Vector4d actuator_sp(0,0,0,0);
command_to_mavros command_fsc;
pos_controller_PID pos_controller_fsc;
att_controller_PID att_controller_fsc;
command_fsc.printf_param();
pos_controller_fsc.printf_pid_param();
att_controller_fsc.printf_pid_param();
command_fsc.show_geo_fence();
int check_flag;
// 这一步是为了程序运行前检查一下参数是否正确
// 输入1,继续,其他,退出程序
cout << "Please check the parameter and settingenter 1 to continue else for quit: "<<endl;
cin >> check_flag;
if(check_flag != 1)
{
return -1;
}
// 等待和飞控的连接
while(ros::ok() && command_fsc.current_state.connected)
{
ros::spinOnce();
rate.sleep();
ROS_INFO("Not Connected");
}
// 连接成功
ROS_INFO("Connected!!");
// 先读取一些飞控的数据
int i =0;
for(i=0;i<50;i++)
{
ros::spinOnce();
rate.sleep();
}
command_fsc.set_takeoff_position();
//初始化命令-
// 默认设置move模式 子模式:位置控制 起飞到当前位置点上方
Command_Now.Command_ID = 0;
Command_Now.Mode = Move_ENU;
Command_Now.Move_mode = 0;
Command_Now.Reference_State.position_ref[0] = command_fsc.Takeoff_position[0]; //ENU Frame
Command_Now.Reference_State.position_ref[1] = command_fsc.Takeoff_position[1]; //ENU Frame
Command_Now.Reference_State.position_ref[2] = command_fsc.Takeoff_position[2] + command_fsc.Takeoff_height; //ENU Frame
Command_Now.Reference_State.velocity_ref[0] = 0; //ENU Frame
Command_Now.Reference_State.velocity_ref[1] = 0; //ENU Frame
Command_Now.Reference_State.velocity_ref[2] = 0; //ENU Frame
Command_Now.Reference_State.yaw_ref = 0;
Command_Now.yaw_rate_sp = 0;
// 记录启控时间
ros::Time begin_time = ros::Time::now();
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
//执行回调函数
ros::spinOnce();
// 当前时间
float cur_time = get_time_in_sec(begin_time);
//Printf the drone state
command_fsc.prinft_drone_state2(cur_time);
//Printf the command state
prinft_command_state();
command_fsc.failsafe();
//Printf the pid controller result
//pos_controller_fsc.printf_result();
att_controller_fsc.printf_result();
//无人机一旦接受到Land指令则会屏蔽其他指令
if(Command_Last.Mode == Land)
{
Command_Now.Mode = Land;
}
switch (Command_Now.Mode)
{
case Move_ENU:
pos_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
vel_sp = Eigen::Vector3d(Command_Now.Reference_State.velocity_ref[0],Command_Now.Reference_State.velocity_ref[1],Command_Now.Reference_State.velocity_ref[2]);
accel_sp = pos_controller_fsc.pos_controller(command_fsc.pos_drone_fcu, command_fsc.vel_drone_fcu, pos_sp, vel_sp, Command_Now.Move_mode , cur_time);
actuator_sp = att_controller_fsc.att_controller(command_fsc.Euler_fcu, command_fsc.rates_fcu, accel_sp, Command_Now.Reference_State.yaw_ref, cur_time);
//for test
//command_fsc.send_accel_setpoint(accel_sp, Command_Now.Reference_State.yaw_ref );
command_fsc.send_actuator_setpoint(actuator_sp);
break;
case Move_Body:
//只有在comid增加时才会进入解算
if( Command_Now.Command_ID > Command_Last.comid )
{
//xy velocity mode
if( Command_Now.Move_mode & 0b10 )
{
float d_vel_body[2] = {Command_Now.Reference_State.velocity_ref[0], Command_Now.Reference_State.velocity_ref[1]}; //the desired xy velocity in Body Frame
float d_vel_enu[2]; //the desired xy velocity in NED Frame
rotation_yaw(command_fsc.Euler_fcu[2], d_vel_body, d_vel_enu);
vel_sp[0] = d_vel_enu[0];
vel_sp[1] = d_vel_enu[1];
}
//xy position mode
else
{
float d_pos_body[2] = {Command_Now.Reference_State.position_ref[0], Command_Now.Reference_State.position_ref[1]}; //the desired xy position in Body Frame
float d_pos_enu[2]; //the desired xy position in enu Frame (The origin point is the drone)
rotation_yaw(command_fsc.Euler_fcu[2], d_pos_body, d_pos_enu);
pos_sp[0] = command_fsc.pos_drone_fcu[0] + d_pos_enu[0];
pos_sp[1] = command_fsc.pos_drone_fcu[1] + d_pos_enu[1];
}
//z velocity mode
if( Command_Now.Move_mode & 0b01 )
{
vel_sp[2] = Command_Now.Reference_State.velocity_ref[2];
}
//z posiiton mode
{
pos_sp[2] = command_fsc.pos_drone_fcu[2] + Command_Now.Reference_State.position_ref[2];
}
}
accel_sp = pos_controller_fsc.pos_controller(command_fsc.pos_drone_fcu, command_fsc.vel_drone_fcu, pos_sp, vel_sp, Command_Now.Move_mode , cur_time);
actuator_sp = att_controller_fsc.att_controller(command_fsc.Euler_fcu, command_fsc.rates_fcu, accel_sp, Command_Now.Reference_State.yaw_ref, cur_time);
command_fsc.send_actuator_setpoint(actuator_sp);
break;
case Hold:
if (Command_Last.Mode != Hold)
{
command_fsc.Hold_position = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
}
accel_sp = pos_controller_fsc.pos_controller(command_fsc.pos_drone_fcu, command_fsc.vel_drone_fcu, pos_sp, vel_sp, Command_Now.Move_mode , cur_time);
actuator_sp = att_controller_fsc.att_controller(command_fsc.Euler_fcu, command_fsc.rates_fcu, accel_sp, Command_Now.Reference_State.yaw_ref, cur_time);
command_fsc.send_actuator_setpoint(actuator_sp);
break;
case Land:
if (Command_Last.Mode != Land)
{
pos_sp = Eigen::Vector3d(command_fsc.pos_drone_fcu[0],command_fsc.pos_drone_fcu[1],command_fsc.Takeoff_position[2]);
}
//如果距离起飞高度小于20厘米则直接上锁并切换为手动模式
if(abs(command_fsc.pos_drone_fcu[2] - command_fsc.Takeoff_position[2]) < ( 0.2))
{
if(command_fsc.current_state.mode == "OFFBOARD")
{
command_fsc.mode_cmd.request.custom_mode = "MANUAL";
command_fsc.set_mode_client.call(command_fsc.mode_cmd);
}
if(command_fsc.current_state.armed)
{
command_fsc.arm_cmd.request.value = false;
command_fsc.arming_client.call(command_fsc.arm_cmd);
}
if (command_fsc.arm_cmd.response.success)
{
cout<<"Disarm successfully!"<<endl;
}
}else
{
accel_sp = pos_controller_fsc.pos_controller(command_fsc.pos_drone_fcu, command_fsc.vel_drone_fcu, pos_sp, vel_sp, Command_Now.Move_mode , cur_time);
actuator_sp = att_controller_fsc.att_controller(command_fsc.Euler_fcu, command_fsc.rates_fcu, accel_sp, Command_Now.Reference_State.yaw_ref, cur_time);
command_fsc.send_actuator_setpoint(actuator_sp);
}
break;
case Disarm:
if(command_fsc.current_state.mode == "OFFBOARD")
{
command_fsc.mode_cmd.request.custom_mode = "MANUAL";
command_fsc.set_mode_client.call(command_fsc.mode_cmd);
}
if(command_fsc.current_state.armed)
{
command_fsc.arm_cmd.request.value = false;
command_fsc.arming_client.call(command_fsc.arm_cmd);
}
if (command_fsc.arm_cmd.response.success)
{
cout<<"Disarm successfully!"<<endl;
}
break;
// 【】
case PPN_land:
break;
// 【】
case Idle:
break;
}
Command_Last = Command_Now;
rate.sleep();
}
return 0;
}
// 【获取当前时间函数】 单位:秒
float get_time_in_sec(ros::Time begin)
{
ros::Time time_now = ros::Time::now();
float currTimeSec = time_now.sec-begin.sec;
float currTimenSec = time_now.nsec / 1e9 - begin.nsec / 1e9;
return (currTimeSec + currTimenSec);
}
// 【打印控制指令函数】
void prinft_command_state()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Command State<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
switch(Command_Now.Mode)
{
case Move_ENU:
cout << "Command: [ Move_ENU ] " <<endl;
break;
case Move_Body:
cout << "Command: [ Move_Body ] " <<endl;
break;
case Hold:
cout << "Command: [ Hold ] " <<endl;
break;
case Land:
cout << "Command: [ Land ] " <<endl;
break;
case Disarm:
cout << "Command: [ Disarm ] " <<endl;
break;
case PPN_land:
cout << "Command: [ PPN_land ] " <<endl;
break;
case Idle:
cout << "Command: [ Idle ] " <<endl;
break;
}
int sub_mode;
sub_mode = Command_Now.Move_mode ;
if((sub_mode & 0b10) == 0) //xy channel
{
cout << "Submode: xy position control "<<endl;
cout << "X_setpoint : " << Command_Now.Reference_State.position_ref[0] << " [ m ]" << " Y_setpoint : "<< Command_Now.Reference_State.position_ref[1] << " [ m ]"<<endl;
}
else{
cout << "Submode: xy velocity control "<<endl;
cout << "X_setpoint : " << Command_Now.Reference_State.velocity_ref[0] << " [m/s]" << " Y_setpoint : "<< Command_Now.Reference_State.velocity_ref[1] << " [m/s]" <<endl;
}
if((sub_mode & 0b01) == 0) //z channel
{
cout << "Submode: z position control "<<endl;
cout << "Z_setpoint : "<< Command_Now.Reference_State.position_ref[2] << " [ m ]" << endl;
}
else
{
cout << "Submode: z velocity control "<<endl;
cout << "Z_setpoint : "<< Command_Now.Reference_State.velocity_ref[2] << " [m/s]" <<endl;
}
cout << "Yaw_setpoint : " << Command_Now.Reference_State.yaw_ref << " [deg] " <<endl;
}
// 【坐标系旋转函数】- 机体系到enu系
// input是机体系,output是惯性系yaw_angle是当前偏航角
void rotation_yaw(float yaw_angle, float input[2], float output[2])
{
output[0] = input[0] * cos(yaw_angle) - input[1] * sin(yaw_angle);
output[1] = input[0] * sin(yaw_angle) + input[1] * cos(yaw_angle);
}

@ -0,0 +1,72 @@
#include "ros/ros.h"
#include "OptiTrackFeedBackRigidBody.h"
#include "KeyboardEvent.h"
#include <Eigen/Eigen>
using namespace std;
using namespace Eigen;
int main(int argc, char **argv)
{
double Control_Rate = 40;// Hz the rate
// Initialize ros node
ros::init(argc, argv, "OptiTrackTest");
ros::NodeHandle n;
// Initialize Data Recorder
//DataRecorder Rigidbody1_recorder("OptiTestRigidbody1.txt",31,Control_Rate);
double Rigidbody1state[16];
/* 0 OptTrack Flag
1 - 3 Rigidbody1 positition from OpTiFeedback (hx,hy,Altitude)
4 - 6 Rigidbody1 filtered velocity from OpTiFeedback
7 - 9 Rigidbody1 raw velocity from Optifeedback
10 - 12 Rigidbody1 raw angular velocity from Optifeedback
13 - 15 Rigidbody1 filtered angular velocity from Optifeedback
16 - 18 Rigidbody1 euler angle from OpTiFeedback
19 - 22 Rigidbody1 quaterion from OpTiFeedback
23 - 31 Rigidbody1 Rotation matrix R_IB from OptiFeedback
*/
// Initialize OptiTrack System
OptiTrackFeedBackRigidBody Opti_RigidBody1("/vrpn_client_node/UAV/pose",n,3,3);
OptiTrackFeedBackRigidBody Opti_RigidBody2("/vrpn_client_node/RigidBody2/pose",n,3,3);
KeyboardEvent keyboardcontrol;
rigidbody_state RigidBody1state;
ros::Rate loop_rate(Control_Rate);
while (ros::ok())
{
Opti_RigidBody1.RosWhileLoopRun();
Opti_RigidBody2.RosWhileLoopRun();
keyboardcontrol.RosWhileLoopRun();
switch (keyboardcontrol.GetPressedKey())
{
case U_KEY_E:
{
//Rigidbody1_recorder.StartRecording();
}
case U_KEY_Q:
{
Opti_RigidBody1.GetOptiTrackState();
Opti_RigidBody2.GetOptiTrackState();
Opti_RigidBody1.GetState(RigidBody1state);
cout<< "Rigid 1 Position: \n" << RigidBody1state.Position << endl;
cout<< "Rigid 1 Velocity: \n" << RigidBody1state.V_I << endl;
cout<< "Rigid 1 AngularVelocity: \n" << RigidBody1state.Omega_BI << endl;
cout<< "Rigid 1 R_IB: \n" << RigidBody1state.R_IB << endl;
cout<< "Rigid 1 R_BI: \n" << RigidBody1state.R_BI << endl;
cout<< "Rigid 1 Rotation Test: \n" << RigidBody1state.R_IB * RigidBody1state.R_BI<< endl;
cout<< "Rigid 1 Euler: \n" <<RigidBody1state.Euler*57.3<<endl;
cout<< "Rigid 1 quaterion: \n" <<RigidBody1state.quaterion<<endl;
//Rigidbody1_recorder.StopRecording();
break;
}
case U_KEY_NONE:
{
break;
}
}
//Rigidbody1_recorder.RecorderUpdate(Rigidbody1state);
ros::spinOnce();// do the loop once
loop_rate.sleep();
}
return 0;
}

@ -0,0 +1,52 @@
#include <TFmini.h>
using namespace std;
int main(int argc, char **argv)
{
ros::init(argc, argv, "TFmini");
ros::NodeHandle nh("~");
std::string id = "TFmini";
std::string portName;
int baud_rate;
benewake::TFmini *tfmini_obj;
nh.param("serial_port", portName, std::string("/dev/ttyUSB0"));
nh.param("baud_rate", baud_rate, 115200);
tfmini_obj = new benewake::TFmini(portName, baud_rate);
ros::Publisher pub_range = nh.advertise<sensor_msgs::Range>("/prometheus/tfmini_range", 1000, true);
sensor_msgs::Range TFmini_range;
TFmini_range.radiation_type = sensor_msgs::Range::INFRARED;
TFmini_range.field_of_view = 0.04;
TFmini_range.min_range = 0.3;
TFmini_range.max_range = 12;
TFmini_range.header.frame_id = id;
float dist = 0;
ROS_INFO_STREAM("Start processing ...");
while(ros::master::check() && ros::ok())
{
ros::spinOnce();
dist = tfmini_obj->getDist();
if(dist > 0 && dist < TFmini_range.max_range)
{
TFmini_range.range = dist;
TFmini_range.header.stamp = ros::Time::now();
pub_range.publish(TFmini_range);
cout << "get" << dist<<endl;
}
else if(dist == -1.0)
{
ROS_ERROR_STREAM("Failed to read data. TFmini ros node stopped!");
break;
}
else if(dist == 0.0)
{
ROS_ERROR_STREAM("Data validation error!");
}
}
tfmini_obj->closePort();
}

@ -0,0 +1,59 @@
//头文件
#include <ros/ros.h>
#include <iostream>
//话题头文件
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <mavros_msgs/State.h>
#include <Eigen/Eigen>
#include <math.h>
#include <math_utils.h>
using namespace std;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "test");
ros::NodeHandle nh("~");
ros::Rate rate(20.0);
Eigen::Vector3d vector;
vector = Eigen::Vector3d(0.0,0.0,0.0);
//float a;
Eigen::Vector3d thr_sp;
float yaw_sp;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
cout << "Please input the thrust_x: "<<endl;
cin >> thr_sp(0);
cout << "Please input the thrust_y: "<<endl;
cin >> thr_sp(1);
cout << "Please input the thrust_z: "<<endl;
cin >> thr_sp(2);
cout << "Please input the yaw_sp: "<<endl;
cin >> yaw_sp;
//Eigen::Quaterniond q_sp = ThrottleToAttitude(thr_sp, yaw_sp);
//周期休眠
rate.sleep();
}
return 0;
}

@ -0,0 +1,69 @@
/***************************************************************************************************************************
* fake_vicon.cpp
*
* Author: Qyp
*
* Update Time: 2019.3.16
*
* Introduction: test function for fake publish vicon topic
***************************************************************************************************************************/
//头文件
#include <ros/ros.h>
#include <iostream>
#include <math_utils.h>
#include <geometry_msgs/PoseStamped.h>
using namespace std;
geometry_msgs::PoseStamped mocap; //发送给飞控的mocap(来源mocap或laser)
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "fake_vicon");
ros::NodeHandle nh("~");
// 【订阅】optitrack估计位置
ros::Publisher optitrack_pub = nh.advertise<geometry_msgs::PoseStamped>("/vrpn_client_node/UAV/pose", 1000);
// 频率
ros::Rate rate(100.0);
Eigen::Vector3d pos_vicon_enu(0,0,0);
Eigen::Vector3d Euler_vicon(0,10.0/180*M_PI,10.0/180*M_PI);
Eigen::Quaterniond q_vicon = quaternion_from_rpy(Euler_vicon);
// Transform the Quaternion from NED to ENU
//Eigen::Quaterniond q_vicon_enu = transform_orientation_aircraft_to_baselink( transform_orientation_ned_to_enu(q_vicon) );
mocap.pose.orientation.x = q_vicon.x();
mocap.pose.orientation.y = q_vicon.y();
mocap.pose.orientation.z = q_vicon.z();
mocap.pose.orientation.w = q_vicon.w();
mocap.pose.position.x = pos_vicon_enu[0];
mocap.pose.position.y = pos_vicon_enu[1];
mocap.pose.position.z = pos_vicon_enu[2];
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Main Loop<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>[Fake Vicon]<<<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout.setf(ios::fixed);
cout << "Position: " << " " << fixed <<setprecision(5)<< pos_vicon_enu[0] << " [ m ] "<< pos_vicon_enu[1]<<" [ m ] "<<pos_vicon_enu[2]<<" [ m ] "<<endl;
cout << "Attitude: " << " " << Euler_vicon[2]/M_PI*180<<" [deg] "<<endl;
optitrack_pub.publish(mocap);
rate.sleep();
}
return 0;
}

@ -0,0 +1,87 @@
#include <ros/ros.h>
#include <iostream>
#include <Filter/LowPassFilter.h>
#include <prometheus_control_utils.h>
#include <geometry_msgs/Point.h>
using namespace std;
int main(int argc, char **argv)
{
ros::init(argc, argv, "filter_tester");
ros::NodeHandle nh;
geometry_msgs::Point random;
ros::Publisher log_pub = nh.advertise<geometry_msgs::Point>("/prometheus/test", 10);
ros::Rate rate(50.0);
float T1 = 0.1;
float T2 = 1;
LowPassFilter LPF1;
LowPassFilter LPF2;
LowPassFilter LPF3;
LPF1.set_Time_constant(T2);
LPF2.set_Time_constant(T2);
LPF3.set_Time_constant(T2);
float dt = 1;
float input1,input2;
float output1,output2;
while(ros::ok())
{
// cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--------<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
// cout << "Input the input of the LPF1"<<endl;
// cin >> input1;
// cout << "Input the input of the LPF2"<<endl;
// cin >> input2;
// output1 = LPF1.apply(input1,dt);
// output2 = LPF2.apply(input2,dt);
// float _T1 = LPF1.get_Time_constant();
// float _T2 = LPF2.get_Time_constant();
// cout << "T for LPF1: "<< _T1 <<endl;
// cout << "T for LPF2: "<< _T2 <<endl;
// cout << "ouput for LPF1: "<< output1 <<endl;
// cout << "ouput for LPF2: "<< output2 <<endl;
// 先生成随机数
random.x = prometheus_control_utils::random_num(0.2, 0.1);
random.y = prometheus_control_utils::random_num(2, 0.0);
random.z = prometheus_control_utils::random_num(0.1, 0.05);
// 低通滤波
random.x = LPF1.apply(random.x , 0.02);
random.y = LPF2.apply(random.y , 0.02);
random.z = LPF3.apply(random.z , 0.02);
ROS_INFO("random.x: [%f]", random.x);
ROS_INFO("random.y: [%f]", random.y);
ROS_INFO("random.z: [%f]", random.z);
log_pub.publish(random);
rate.sleep();
}
return 0;
}

@ -0,0 +1,432 @@
//头文件
#include <ros/ros.h>
#include <iostream>
#include <Eigen/Eigen>
#include "state_from_mavros.h"
#include "math_utils.h"
#include "prometheus_control_utils.h"
#include "Filter/LowPassFilter.h"
#include "message_utils.h"
using namespace std;
#define TRA_WINDOW 1000
#define TIMEOUT_MAX 0.05
#define NODE_NAME "pos_estimator"
//---------------------------------------相关参数-----------------------------------------------
int input_source;
float rate_hz;
Eigen::Vector3f pos_offset;
float yaw_offset;
string object_name;
ros::Time last_timestamp;
//---------------------------------------vicon定位相关------------------------------------------
Eigen::Vector3d pos_drone_mocap; //无人机当前位置 (vicon)
Eigen::Quaterniond q_mocap;
Eigen::Vector3d Euler_mocap; //无人机当前姿态 (vicon)
//---------------------------------------laser定位相关------------------------------------------
Eigen::Vector3d pos_drone_laser; //无人机当前位置 (laser)
Eigen::Quaterniond q_laser;
Eigen::Vector3d Euler_laser; //无人机当前姿态(laser)
geometry_msgs::TransformStamped laser; //当前时刻cartorgrapher发布的数据
//---------------------------------------T265------------------------------------------
Eigen::Vector3d pos_drone_t265;
Eigen::Quaterniond q_t265;
Eigen::Vector3d Euler_t265;
//---------------------------------------gazebo真值相关------------------------------------------
Eigen::Vector3d pos_drone_gazebo;
Eigen::Quaterniond q_gazebo;
Eigen::Vector3d Euler_gazebo;
//---------------------------------------SLAM相关------------------------------------------
Eigen::Vector3d pos_drone_slam;
Eigen::Quaterniond q_slam;
Eigen::Vector3d Euler_slam;
//---------------------------------------发布相关变量--------------------------------------------
ros::Publisher vision_pub;
ros::Publisher drone_state_pub;
ros::Publisher message_pub;
prometheus_msgs::Message message;
ros::Publisher odom_pub;
ros::Publisher trajectory_pub;
prometheus_msgs::DroneState Drone_State;
nav_msgs::Odometry Drone_odom;
std::vector<geometry_msgs::PoseStamped> posehistory_vector_;
//噪声
float noise_a,noise_b;
float noise_T;
float dt;
bool apply_noise;
LowPassFilter LPF_x;
LowPassFilter LPF_y;
LowPassFilter LPF_z;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>函数声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void send_to_fcu();
void pub_to_nodes(prometheus_msgs::DroneState State_from_fcu);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void laser_cb(const tf2_msgs::TFMessage::ConstPtr &msg)
{
//确定是cartographer发出来的/tf信息
//有的时候/tf这个消息的发布者不止一个
//可改成TF监听
if (msg->transforms[0].header.frame_id == "map" && msg->transforms[0].child_frame_id == "base_link" && input_source == 1)
{
laser = msg->transforms[0];
//位置 xy [将解算的位置从map坐标系转换至world坐标系]
pos_drone_laser[0] = laser.transform.translation.x + pos_offset[0];
pos_drone_laser[1] = laser.transform.translation.y + pos_offset[1];
pos_drone_laser[2] = laser.transform.translation.z + pos_offset[2];
// Read the Quaternion from the Carto Package [Frame: Laser[ENU]]
Eigen::Quaterniond q_laser_enu(laser.transform.rotation.w, laser.transform.rotation.x, laser.transform.rotation.y, laser.transform.rotation.z);
q_laser = q_laser_enu;
// Transform the Quaternion to Euler Angles
Euler_laser = quaternion_to_euler(q_laser);
// pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "test.");
//cout << "Position [X Y Z] : " << pos_drone_laser[0] << " [ m ] "<< pos_drone_laser[1]<<" [ m ] "<< pos_drone_laser[2]<<" [ m ] "<<endl;
//cout << "Euler [X Y Z] : " << Euler_laser[0] << " [m/s] "<< Euler_laser[1]<<" [m/s] "<< Euler_laser[2]<<" [m/s] "<<endl;
}
}
void mocap_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
//位置 -- optitrack系 到 ENU系
//Frame convention 0: Z-up -- 1: Y-up (See the configuration in the motive software)
int optitrack_frame = 0;
if (optitrack_frame == 0)
{
// Read the Drone Position from the Vrpn Package [Frame: Vicon] (Vicon to ENU frame)
pos_drone_mocap = Eigen::Vector3d(msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);
pos_drone_mocap[0] = pos_drone_mocap[0] - pos_offset[0];
pos_drone_mocap[1] = pos_drone_mocap[1] - pos_offset[1];
pos_drone_mocap[2] = pos_drone_mocap[2] - pos_offset[2];
// Read the Quaternion from the Vrpn Package [Frame: Vicon[ENU]]
q_mocap = Eigen::Quaterniond(msg->pose.orientation.w, msg->pose.orientation.x, msg->pose.orientation.y, msg->pose.orientation.z);
}
else
{
// Read the Drone Position from the Vrpn Package [Frame: Vicon] (Vicon to ENU frame)
pos_drone_mocap = Eigen::Vector3d(-msg->pose.position.x, msg->pose.position.z, msg->pose.position.y);
// Read the Quaternion from the Vrpn Package [Frame: Vicon[ENU]]
q_mocap = Eigen::Quaterniond(msg->pose.orientation.w, msg->pose.orientation.x, msg->pose.orientation.z, msg->pose.orientation.y); //Y-up convention, switch the q2 & q3
pos_drone_mocap[0] = pos_drone_mocap[0] - pos_offset[0];
pos_drone_mocap[1] = pos_drone_mocap[1] - pos_offset[1];
pos_drone_mocap[2] = pos_drone_mocap[2] - pos_offset[2];
}
// Transform the Quaternion to Euler Angles
Euler_mocap = quaternion_to_euler(q_mocap);
last_timestamp = msg->header.stamp;
}
void gazebo_cb(const nav_msgs::Odometry::ConstPtr &msg)
{
if (msg->header.frame_id == "world")
{
pos_drone_gazebo = Eigen::Vector3d(msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z);
q_gazebo = Eigen::Quaterniond(msg->pose.pose.orientation.w, msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z);
Euler_gazebo = quaternion_to_euler(q_gazebo);
// Euler_gazebo[2] = Euler_gazebo[2] + yaw_offset;
// q_gazebo = quaternion_from_rpy(Euler_gazebo);
}
else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "wrong gazebo ground truth frame id.");
}
}
void slam_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
if (msg->header.frame_id == "map_slam")
{
pos_drone_slam = Eigen::Vector3d(msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);
// pos_drone_gazebo[0] = msg->pose.pose.position.x + pos_offset[0];
// pos_drone_gazebo[1] = msg->pose.pose.position.y + pos_offset[1];
// pos_drone_gazebo[2] = msg->pose.pose.position.z + pos_offset[2];
q_slam = Eigen::Quaterniond(msg->pose.orientation.w, msg->pose.orientation.x, msg->pose.orientation.y, msg->pose.orientation.z);
Euler_slam = quaternion_to_euler(q_slam);
// Euler_gazebo[2] = Euler_gazebo[2] + yaw_offset;
// q_gazebo = quaternion_from_rpy(Euler_gazebo);
}
else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "wrong slam frame id.");
}
}
void t265_cb(const nav_msgs::Odometry::ConstPtr &msg)
{
if (msg->header.frame_id == "t265_odom_frame")
{
pos_drone_t265 = Eigen::Vector3d(msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z);
// pos_drone_t265[0] = msg->pose.pose.position.x + pos_offset[0];
// pos_drone_t265[1] = msg->pose.pose.position.y + pos_offset[1];
// pos_drone_t265[2] = msg->pose.pose.position.z + pos_offset[2];
q_t265 = Eigen::Quaterniond(msg->pose.pose.orientation.w, msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z);
Euler_t265 = quaternion_to_euler(q_gazebo);
// Euler_t265[2] = Euler_t265[2] + yaw_offset;
// q_t265 = quaternion_from_rpy(Euler_t265);
}
else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "wrong t265 frame id.");
}
}
void timerCallback(const ros::TimerEvent &e)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Program is running.");
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_pos_estimator_with_noise");
ros::NodeHandle nh("~");
//读取参数表中的参数
// 定位数据输入源 0 for vicon 1 for 激光SLAM, 2 for gazebo ground truth, 3 for T265 , 9 for outdoor
nh.param<int>("input_source", input_source, 0);
// 动作捕捉设备中设定的刚体名字
nh.param<string>("object_name", object_name, "UAV");
// 程序执行频率
nh.param<float>("rate_hz", rate_hz, 20);
// 定位设备偏移量
nh.param<float>("offset_x", pos_offset[0], 0);
nh.param<float>("offset_y", pos_offset[1], 0);
nh.param<float>("offset_z", pos_offset[2], 0);
nh.param<float>("offset_yaw", yaw_offset, 0);
nh.param<bool>("apply_noise", apply_noise, false);
nh.param<float>("noise_a", noise_a, 0.0);
nh.param<float>("noise_b", noise_b, 0.0);
nh.param<float>("noise_T", noise_T, 0.5);
LPF_x.set_Time_constant(noise_T);
LPF_y.set_Time_constant(noise_T);
LPF_z.set_Time_constant(noise_T);
// 【订阅】cartographer估计位置
ros::Subscriber laser_sub = nh.subscribe<tf2_msgs::TFMessage>("/tf", 100, laser_cb);
// 【订阅】t265估计位置
ros::Subscriber t265_sub = nh.subscribe<nav_msgs::Odometry>("/t265/odom/sample", 100, t265_cb);
// 【订阅】optitrack估计位置
ros::Subscriber optitrack_sub = nh.subscribe<geometry_msgs::PoseStamped>("/vrpn_client_node/"+ object_name + "/pose", 100, mocap_cb);
// 【订阅】gazebo仿真真值
ros::Subscriber gazebo_sub = nh.subscribe<nav_msgs::Odometry>("/prometheus/ground_truth/p300_basic", 100, gazebo_cb);
// 【订阅】SLAM估计位姿
ros::Subscriber slam_sub = nh.subscribe<geometry_msgs::PoseStamped>("/slam/pose", 100, slam_cb);
// 【发布】无人机位置和偏航角 坐标系 ENU系
// 本话题要发送飞控(通过mavros_extras/src/plugins/vision_pose_estimate.cpp发送), 对应Mavlink消息为VISION_POSITION_ESTIMATE(#102), 对应的飞控中的uORB消息为vehicle_vision_position.msg 及 vehicle_vision_attitude.msg
vision_pub = nh.advertise<geometry_msgs::PoseStamped>("/mavros/vision_pose/pose", 10);
// 【发布】无人机状态量
drone_state_pub = nh.advertise<prometheus_msgs::DroneState>("/prometheus/drone_state", 10);
// 【发布】无人机odometry用于RVIZ显示
odom_pub = nh.advertise<nav_msgs::Odometry>("/prometheus/drone_odom", 10);
// 【发布】无人机移动轨迹用于RVIZ显示
trajectory_pub = nh.advertise<nav_msgs::Path>("/prometheus/drone_trajectory", 10);
// 【发布】提示消息
message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
// 10秒定时打印以确保程序在正确运行
ros::Timer timer = nh.createTimer(ros::Duration(10.0), timerCallback);
// 用于与mavros通讯的类通过mavros接收来至飞控的消息【飞控->mavros->本程序】
state_from_mavros _state_from_mavros;
// 频率
ros::Rate rate(rate_hz);
dt = 1.0/rate_hz;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Main Loop<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while (ros::ok())
{
//回调一次 更新传感器状态
ros::spinOnce();
// 将采集的机载设备的定位信息及偏航角信息发送至飞控根据参数input_source选择定位信息来源
send_to_fcu();
// 发布无人机状态至其他节点如px4_pos_controller.cpp节点
pub_to_nodes(_state_from_mavros._DroneState);
rate.sleep();
}
return 0;
}
void send_to_fcu()
{
geometry_msgs::PoseStamped vision;
//vicon
if (input_source == 0)
{
vision.pose.position.x = pos_drone_mocap[0];
vision.pose.position.y = pos_drone_mocap[1];
vision.pose.position.z = pos_drone_mocap[2];
vision.pose.orientation.x = q_mocap.x();
vision.pose.orientation.y = q_mocap.y();
vision.pose.orientation.z = q_mocap.z();
vision.pose.orientation.w = q_mocap.w();
// 此处时间主要用于监测动捕T265设备是否正常工作
if( prometheus_control_utils::get_time_in_sec(last_timestamp) > TIMEOUT_MAX)
{
pub_message(message_pub, prometheus_msgs::Message::ERROR, NODE_NAME, "Mocap Timeout.");
}
} //laser
else if (input_source == 1)
{
vision.pose.position.x = pos_drone_laser[0];
vision.pose.position.y = pos_drone_laser[1];
vision.pose.position.z = pos_drone_laser[2];
//目前为二维雷达仿真情况故z轴使用其他来源
vision.pose.position.z = pos_drone_gazebo[2];
vision.pose.orientation.x = q_laser.x();
vision.pose.orientation.y = q_laser.y();
vision.pose.orientation.z = q_laser.z();
vision.pose.orientation.w = q_laser.w();
}
else if (input_source == 2)
{
vision.pose.position.x = pos_drone_gazebo[0];
vision.pose.position.y = pos_drone_gazebo[1];
vision.pose.position.z = pos_drone_gazebo[2];
vision.pose.orientation.x = q_gazebo.x();
vision.pose.orientation.y = q_gazebo.y();
vision.pose.orientation.z = q_gazebo.z();
vision.pose.orientation.w = q_gazebo.w();
}
else if (input_source == 3)
{
vision.pose.position.x = pos_drone_t265[0];
vision.pose.position.y = pos_drone_t265[1];
vision.pose.position.z = pos_drone_t265[2];
vision.pose.orientation.x = q_t265.x();
vision.pose.orientation.y = q_t265.y();
vision.pose.orientation.z = q_t265.z();
vision.pose.orientation.w = q_t265.w();
}
else if (input_source == 4)
{
vision.pose.position.x = pos_drone_slam[0];
vision.pose.position.y = pos_drone_slam[1];
vision.pose.position.z = pos_drone_slam[2];
vision.pose.orientation.x = q_slam.x();
vision.pose.orientation.y = q_slam.y();
vision.pose.orientation.z = q_slam.z();
vision.pose.orientation.w = q_slam.w();
}
vision.header.stamp = ros::Time::now();
vision_pub.publish(vision);
}
void pub_to_nodes(prometheus_msgs::DroneState State_from_fcu)
{
// 发布无人机状态,具体内容参见 prometheus_msgs::DroneState
Drone_State = State_from_fcu;
Drone_State.header.stamp = ros::Time::now();
// 户外情况,使用相对高度
if(input_source == 9 )
{
Drone_State.position[2] = Drone_State.rel_alt;
}
if(apply_noise)
{
Eigen::Vector3d random;
// 先生成随机数
random[0] = prometheus_control_utils::random_num(noise_a, noise_b);
random[1] = prometheus_control_utils::random_num(noise_a, noise_b);
random[2] = prometheus_control_utils::random_num(noise_a, noise_b);
// 低通滤波
random[0] = LPF_x.apply(random[0], dt);
random[1] = LPF_y.apply(random[1], dt);
random[2] = LPF_z.apply(random[2], dt);
for (int i=0;i<3;i++)
{
Drone_State.velocity[i] = Drone_State.velocity[i] + random[i];
}
}
drone_state_pub.publish(Drone_State);
// 发布无人机当前odometry,用于导航及rviz显示
nav_msgs::Odometry Drone_odom;
Drone_odom.header.stamp = ros::Time::now();
Drone_odom.header.frame_id = "world";
Drone_odom.child_frame_id = "base_link";
Drone_odom.pose.pose.position.x = Drone_State.position[0];
Drone_odom.pose.pose.position.y = Drone_State.position[1];
Drone_odom.pose.pose.position.z = Drone_State.position[2];
// 导航算法规定 高度不能小于0
if (Drone_odom.pose.pose.position.z <= 0)
{
Drone_odom.pose.pose.position.z = 0.01;
}
Drone_odom.pose.pose.orientation = Drone_State.attitude_q;
Drone_odom.twist.twist.linear.x = Drone_State.velocity[0];
Drone_odom.twist.twist.linear.y = Drone_State.velocity[1];
Drone_odom.twist.twist.linear.z = Drone_State.velocity[2];
odom_pub.publish(Drone_odom);
// 发布无人机运动轨迹用于rviz显示
geometry_msgs::PoseStamped drone_pos;
drone_pos.header.stamp = ros::Time::now();
drone_pos.header.frame_id = "world";
drone_pos.pose.position.x = Drone_State.position[0];
drone_pos.pose.position.y = Drone_State.position[1];
drone_pos.pose.position.z = Drone_State.position[2];
drone_pos.pose.orientation = Drone_State.attitude_q;
//发布无人机的位姿 和 轨迹 用作rviz中显示
posehistory_vector_.insert(posehistory_vector_.begin(), drone_pos);
if (posehistory_vector_.size() > TRA_WINDOW)
{
posehistory_vector_.pop_back();
}
nav_msgs::Path drone_trajectory;
drone_trajectory.header.stamp = ros::Time::now();
drone_trajectory.header.frame_id = "world";
drone_trajectory.poses = posehistory_vector_;
trajectory_pub.publish(drone_trajectory);
}

@ -0,0 +1,98 @@
#include <ros/ros.h>
#include <iostream>
#include <prometheus_msgs/ControlCommand.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <nav_msgs/Path.h>
#define VEL_XY_STEP_SIZE 0.1
#define VEL_Z_STEP_SIZE 0.1
#define YAW_STEP_SIZE 0.08
#define TRA_WINDOW 2000
#define NODE_NAME "ros_info_color_test"
using namespace std;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 主函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "ros_info_color_test");
ros::NodeHandle nh;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(2);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
//cout.setf(ios::showpos);
ros::Rate rate(10);
while(ros::ok())
{
cout << ">>>>>>>>>>>>>>>> Welcome to use ros_info_color_test <<<<<<<<<<<<<<<<"<< endl;
// 基本
ROS_INFO("---->ROS_INFO");
ROS_WARN("---->ROS_WARN");
ROS_ERROR("---->ROS_ERROR");
// 仅打印一次
ROS_INFO_STREAM_ONCE ("---->This message only printf once.");
// 按频率打印
float interval = 1.0;
ROS_INFO_STREAM_THROTTLE(interval, "---->This message printf in 1 Hz.");
// printf(“\033[0;30;41m color!!! \033[0m Hello \n”);
// 其中41的位置代表字的背景色, 30的位置是代表字的颜色0 是字的一些特殊属性0代表默认关闭一些其他属性如闪烁、下划线等。
// 参考网页https://blog.csdn.net/u014470361/article/details/81512330
// 字背景颜色范围:40--49 字颜色: 30--39
// 40: 黑 30: 黑
// 41:红 31: 红
// 42:绿 32: 绿
// 43:黄 33: 黄
// 44:蓝 34: 蓝
// 45:紫 35: 紫
// 46:深绿 36: 深绿
// 47:白色 37: 白色
// 绿色字体
ROS_INFO("\033[1;31m----> Red color.\033[0m");
ROS_INFO("\033[1;32m----> Green color.\033[0m");
ROS_INFO("\033[1;33m----> Yellow color.\033[0m");
ROS_INFO("\033[1;33;41m----> Hightlight color.\033[0m");
// 打印数值
float a = 10.0;
ROS_INFO("---->The value of a is %f.", a);
cout << "\033[1;31m" << "Hello World, Red color!" << "\033[0m" << endl;
cout << "\033[1;32m" << "Hello World, Green color!" << "\033[0m" << endl;
cout << "\033[1;33m" << "Hello World, Yellow color!" << "\033[0m" << endl;
string yellow, tail;
yellow = "\033[0;1;33m";
tail = "\033[0m";
cout << yellow << "hello world" << tail << endl;
rate.sleep();
}
return 0;
}

@ -0,0 +1,180 @@
/***************************************************************************************************************************
* set_mode.cpp
*
* Author: Qyp
*
* Update Time: 2019.3.16
*
* Introduction: Change mode
***************************************************************************************************************************/
//头文件
#include <ros/ros.h>
#include <iostream>
//话题头文件
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
using namespace std;
mavros_msgs::State current_state; //无人机当前状态[包含上锁状态 模式] (从飞控中读取)
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void state_cb(const mavros_msgs::State::ConstPtr& msg)
{
current_state = *msg;
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "set_mode");
ros::NodeHandle nh("~");
// 【订阅】无人机当前状态 - 来自飞控
// 本话题来自飞控(通过/plugins/sys_status.cpp)
ros::Subscriber state_sub = nh.subscribe<mavros_msgs::State>("/mavros/state", 10, state_cb);
// 【服务】修改系统模式
ros::ServiceClient set_mode_client = nh.serviceClient<mavros_msgs::SetMode>("/mavros/set_mode");
ros::ServiceClient arming_client = nh.serviceClient<mavros_msgs::CommandBool>("/mavros/cmd/arming");
mavros_msgs::SetMode mode_cmd;
mavros_msgs::CommandBool arm_cmd;
arm_cmd.request.value = true;
ros::Rate rate(10.0);
int Num_StateMachine = 0;
int flag_1;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
switch (Num_StateMachine)
{
// input
case 0:
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--------<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
cout << "Input the mode: 0 for OFFBOARD,1 for STABILIZED, 2 for POSCTL,3 for ALTCTL, 4 for arm "<<endl;
cin >> flag_1;
//1000 降落 也可以指向其他任务
if (flag_1 == 0)
{
Num_StateMachine = 1;
break;
}
else if (flag_1 == 1)
{
Num_StateMachine = 2;
break;
}
else if(flag_1 == 2)
{
Num_StateMachine = 3;
}//惯性系移动
else if(flag_1 == 3)
{
Num_StateMachine = 4;
}
else if(flag_1 == 4)
{
Num_StateMachine = 5;
}
break;
//OFFBOARD
case 1:
if(current_state.mode != "OFFBOARD")
{
mode_cmd.request.custom_mode = "OFFBOARD";
set_mode_client.call(mode_cmd);
cout << "Setting to OFFBOARD Mode..." <<endl;
}else
{
Num_StateMachine = 0;
cout << "Set to OFFBOARD Mode Susscess!!!" <<endl;
}
break;
//STABILIZED
case 2:
if(current_state.mode != "STABILIZED")
{
mode_cmd.request.custom_mode = "STABILIZED";
set_mode_client.call(mode_cmd);
cout << "Setting to STABILIZED Mode..." <<endl;
}else
{
Num_StateMachine = 0;
cout << "Set to STABILIZED Mode Susscess!!!" <<endl;
}
break;
//POSCTL
case 3:
if(current_state.mode != "POSCTL")
{
mode_cmd.request.custom_mode = "POSCTL";
set_mode_client.call(mode_cmd);
cout << "Setting to POSCTL Mode..." <<endl;
}else
{
Num_StateMachine = 0;
cout << "Set to POSCTL Mode Susscess!!!" <<endl;
}
break;
//ALTCTL
case 4:
if(current_state.mode != "ALTCTL")
{
mode_cmd.request.custom_mode = "ALTCTL";
set_mode_client.call(mode_cmd);
cout << "Setting to ALTCTL Mode..." <<endl;
}else
{
Num_StateMachine = 0;
cout << "Set to ALTCTL Mode Susscess!!!" <<endl;
}
break;
//arm
case 5:
if(!current_state.armed)
{
arm_cmd.request.value = true;
arming_client.call(arm_cmd);
cout << "Arming..." <<endl;
}else
{
Num_StateMachine = 0;
cout << "Arm Susscess!!!" <<endl;
}
break;
}
//执行回调函数
ros::spinOnce();
//周期休眠
rate.sleep();
}
return 0;
}

@ -0,0 +1,712 @@
/***************************************************************************************************************************
* terminal_control.cpp
*
* Author: Qyp
*
* Update Time: 2020.11.4
*
* Introduction: test function for sending ControlCommand.msg
***************************************************************************************************************************/
#include <ros/ros.h>
#include <iostream>
#include <prometheus_msgs/ControlCommand.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <nav_msgs/Path.h>
#include "controller_test.h"
#include "KeyboardEvent.h"
#define VEL_XY_STEP_SIZE 0.1
#define VEL_Z_STEP_SIZE 0.1
#define YAW_STEP_SIZE 0.08
#define TRA_WINDOW 2000
#define NODE_NAME "terminal_control"
using namespace std;
//即将发布的command
prometheus_msgs::ControlCommand Command_to_pub;
//轨迹容器
std::vector<geometry_msgs::PoseStamped> posehistory_vector_;
float time_trajectory = 0.0;
// 轨迹追踪总时长,键盘控制时固定时长,指令输入控制可调
float trajectory_total_time = 50.0;
//发布
ros::Publisher move_pub;
ros::Publisher ref_trajectory_pub;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 函数声明 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void mainloop1();
void mainloop2();
void generate_com(int Move_mode, float state_desired[4]);
void Draw_in_rviz(const prometheus_msgs::PositionReference& pos_ref, bool draw_trajectory);
void timerCallback(const ros::TimerEvent& e)
{
cout << ">>>>>>>>>>>>>>>> Welcome to use Prometheus Terminal Control <<<<<<<<<<<<<<<<"<< endl;
cout << "ENTER key to control the drone: " <<endl;
cout << "1 for Arm, Space for Takeoff, L for Land, H for Hold, 0 for Disarm, 8/9 for Trajectory tracking" <<endl;
cout << "Move mode is fixed (XYZ_VEL,BODY_FRAME): w/s for body_x, a/d for body_y, k/m for z, q/e for body_yaw" <<endl;
cout << "CTRL-C to quit." <<endl;
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 主函数 <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "terminal_control");
ros::NodeHandle nh;
// 【发布】 控制指令
move_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
// 【发布】 参考轨迹
ref_trajectory_pub = nh.advertise<nav_msgs::Path>("/prometheus/reference_trajectory", 10);
//用于控制器测试的类,功能例如:生成圆形轨迹,8字轨迹等
Controller_Test Controller_Test; // 打印参数
Controller_Test.printf_param();
// 初始化命令 - Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Idle;
Command_to_pub.Command_ID = 0;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_to_pub.Reference_State.position_ref[0] = 0;
Command_to_pub.Reference_State.position_ref[1] = 0;
Command_to_pub.Reference_State.position_ref[2] = 0;
Command_to_pub.Reference_State.velocity_ref[0] = 0;
Command_to_pub.Reference_State.velocity_ref[1] = 0;
Command_to_pub.Reference_State.velocity_ref[2] = 0;
Command_to_pub.Reference_State.acceleration_ref[0] = 0;
Command_to_pub.Reference_State.acceleration_ref[1] = 0;
Command_to_pub.Reference_State.acceleration_ref[2] = 0;
Command_to_pub.Reference_State.yaw_ref = 0;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(2);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
//cout.setf(ios::showpos);
// 选择通过终端输入控制或键盘控制
int Remote_Mode;
cout << ">>>>>>>>>>>>>>>> Welcome to use Prometheus Terminal Control <<<<<<<<<<<<<<<<"<< endl;
cout << "Please choose the Remote Mode: 0 for command input control, 1 for keyboard input control"<<endl;
cin >> Remote_Mode;
if (Remote_Mode == 0)
{
cout << "Command input control mode"<<endl;
mainloop1();
}else if(Remote_Mode == 1)
{
ros::Timer timer = nh.createTimer(ros::Duration(30.0), timerCallback);
cout << "Keyboard input control mode"<<endl;
mainloop2();
}
return 0;
}
void mainloop1()
{
int Control_Mode = 0;
int Move_mode = 0;
int Move_frame = 0;
int Trjectory_mode = 0;
float state_desired[4];
Controller_Test Controller_Test;
while(ros::ok())
{
// Waiting for input
cout << ">>>>>>>>>>>>>>>> Welcome to use Prometheus Terminal Control <<<<<<<<<<<<<<<<"<< endl;
cout << "Please choose the Command.Mode: 0 for Idle, 1 for Takeoff, 2 for Hold, 3 for Land, 4 for Move, 5 for Disarm, 6 for User_Mode1, 7 for User_Mode2"<<endl;
cout << "Input 999 to switch to offboard mode and arm the drone (ONLY for simulation, please use RC in experiment!!!)"<<endl;
cin >> Control_Mode;
if(Control_Mode == prometheus_msgs::ControlCommand::Move)
{
cout << "Please choose the Command.Reference_State.Move_mode: 0 for XYZ_POS, 1 for XY_POS_Z_VEL, 2 for XY_VEL_Z_POS, 3 for XYZ_VEL, 5 for TRAJECTORY"<<endl;
cin >> Move_mode;
if(Move_mode == prometheus_msgs::PositionReference::TRAJECTORY)
{
cout << "For safety, please move the drone near to the trajectory start point firstly!!!"<<endl;
cout << "Please choose the trajectory type: 0 for Circle, 1 for Eight Shape, 2 for Step, 3 for Line"<<endl;
cin >> Trjectory_mode;
cout << "Input the trajectory_total_time:"<<endl;
cin >> trajectory_total_time;
}else
{
cout << "Please choose the Command.Reference_State.Move_frame: 0 for ENU_FRAME, 1 for BODY_FRAME"<<endl;
cin >> Move_frame;
cout << "Please input the reference state [x y z yaw]: "<< endl;
cout << "setpoint_t[0] --- x [m] : "<< endl;
cin >> state_desired[0];
cout << "setpoint_t[1] --- y [m] : "<< endl;
cin >> state_desired[1];
cout << "setpoint_t[2] --- z [m] : "<< endl;
cin >> state_desired[2];
cout << "setpoint_t[3] --- yaw [du] : "<< endl;
cin >> state_desired[3];
}
}else if(Control_Mode == 999)
{
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Idle;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.yaw_ref = 999;
move_pub.publish(Command_to_pub);
Command_to_pub.Reference_State.yaw_ref = 0.0;
}
switch (Control_Mode)
{
case prometheus_msgs::ControlCommand::Idle:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Idle;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
case prometheus_msgs::ControlCommand::Takeoff:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
case prometheus_msgs::ControlCommand::Hold:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Hold;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
case prometheus_msgs::ControlCommand::Land:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Land;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
case prometheus_msgs::ControlCommand::Move:
if(Move_mode == prometheus_msgs::PositionReference::TRAJECTORY)
{
time_trajectory = 0.0;
while(time_trajectory < trajectory_total_time)
{
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
if(Trjectory_mode == 0)
{
Command_to_pub.Reference_State = Controller_Test.Circle_trajectory_generation(time_trajectory);
}else if(Trjectory_mode == 1)
{
Command_to_pub.Reference_State = Controller_Test.Eight_trajectory_generation(time_trajectory);
}else if(Trjectory_mode == 2)
{
Command_to_pub.Reference_State = Controller_Test.Step_trajectory_generation(time_trajectory);
}else if(Trjectory_mode == 3)
{
Command_to_pub.Reference_State = Controller_Test.Line_trajectory_generation(time_trajectory);
}
move_pub.publish(Command_to_pub);
time_trajectory = time_trajectory + 0.01;
cout << "Trajectory tracking: "<< time_trajectory << " / " << trajectory_total_time << " [ s ]" <<endl;
Draw_in_rviz(Command_to_pub.Reference_State, true);
ros::Duration(0.01).sleep();
}
}else
{
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = Move_mode;
Command_to_pub.Reference_State.Move_frame = Move_frame;
Command_to_pub.Reference_State.time_from_start = -1;
generate_com(Move_mode, state_desired);
move_pub.publish(Command_to_pub);
}
break;
case prometheus_msgs::ControlCommand::Disarm:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Disarm;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
case prometheus_msgs::ControlCommand::User_Mode1:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::User_Mode1;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
case prometheus_msgs::ControlCommand::User_Mode2:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::User_Mode2;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
}
cout << "....................................................." <<endl;
sleep(1.0);
}
}
void mainloop2()
{
KeyboardEvent keyboardcontrol;
Controller_Test Controller_Test;
char key_now;
char key_last;
cout << ">>>>>>>>>>>>>>>> Welcome to use Prometheus Terminal Control <<<<<<<<<<<<<<<<"<< endl;
cout << "ENTER key to control the drone: " <<endl;
cout << "1 for Arm, Space for Takeoff, L for Land, H for Hold, 0 for Disarm, 8/9 for Trajectory tracking" <<endl;
cout << "Move mode is fixed (XYZ_VEL,BODY_FRAME): w/s for body_x, a/d for body_y, k/m for z, q/e for body_yaw" <<endl;
cout << "CTRL-C to quit." <<endl;
while (ros::ok())
{
keyboardcontrol.RosWhileLoopRun();
key_now = keyboardcontrol.GetPressedKey();
switch (key_now)
{
//悬停, 应当只发送一次, 不需要循环发送
case U_KEY_NONE:
if (key_last != U_KEY_NONE)
{
//to be continued.
}
sleep(0.5);
break;
// 数字1非小键盘数字解锁及切换到OFFBOARD模式
case U_KEY_1:
cout << " " <<endl;
cout << "Arm and Switch to OFFBOARD." <<endl;
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Idle;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.yaw_ref = 999;
move_pub.publish(Command_to_pub);
sleep(1.0);
break;
// 空格:起飞
case U_KEY_SPACE:
cout << " " <<endl;
cout << "Switch to Takeoff Mode." <<endl;
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.Reference_State.yaw_ref = 0.0;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
sleep(1.0);
break;
// 键盘L降落
case U_KEY_L:
cout << " " <<endl;
cout << "Switch to Land Mode." <<endl;
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Land;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
// 键盘0非小键盘数字紧急停止
case U_KEY_0:
cout << " " <<endl;
cout << "Switch to Disarm Mode." <<endl;
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Disarm;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
break;
//起飞要维持起飞的模式?
case U_KEY_T:
cout << " " <<endl;
cout << "Switch to Takeoff Mode." <<endl;
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
move_pub.publish(Command_to_pub);
sleep(2.0);
break;
//起飞要维持起飞的模式?
case U_KEY_H:
cout << " " <<endl;
cout << "Switch to Hold Mode." <<endl;
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Hold;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.position_ref[0] = 0;
Command_to_pub.Reference_State.position_ref[1] = 0;
Command_to_pub.Reference_State.position_ref[2] = 0;
Command_to_pub.Reference_State.velocity_ref[0] = 0;
Command_to_pub.Reference_State.velocity_ref[1] = 0;
Command_to_pub.Reference_State.velocity_ref[2] = 0;
Command_to_pub.Reference_State.acceleration_ref[0] = 0;
Command_to_pub.Reference_State.acceleration_ref[1] = 0;
Command_to_pub.Reference_State.acceleration_ref[2] = 0;
move_pub.publish(Command_to_pub);
sleep(1.0);
break;
// 向前匀速运动
case U_KEY_W:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.velocity_ref[0] += VEL_XY_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_to_pub.Reference_State.velocity_ref[0] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[1] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向后匀速运动
case U_KEY_S:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.velocity_ref[0] -= VEL_XY_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_to_pub.Reference_State.velocity_ref[0] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[1] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向左匀速运动
case U_KEY_A:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.velocity_ref[1] += VEL_XY_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_to_pub.Reference_State.velocity_ref[0] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[1] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向右匀速运动
case U_KEY_D:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.velocity_ref[1] -= VEL_XY_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_to_pub.Reference_State.velocity_ref[0] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[1] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向上运动
case U_KEY_K:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.velocity_ref[2] += VEL_Z_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_to_pub.Reference_State.velocity_ref[0] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[1] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 向下运动
case U_KEY_M:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.velocity_ref[2] -= VEL_Z_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Current Velocity [X Y Z]: " << Command_to_pub.Reference_State.velocity_ref[0] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[1] << " [m/s] " << Command_to_pub.Reference_State.velocity_ref[2] << " [m/s] "<<endl;
sleep(0.1);
break;
// 偏航运动,左转 (这个里偏航控制的是位置 不是速度)
case U_KEY_Q:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.yaw_ref = YAW_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Increase the Yaw angle." <<endl;
sleep(0.1);
break;
// 偏航运动,右转
case U_KEY_E:
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_to_pub.Reference_State.Move_frame = prometheus_msgs::PositionReference::BODY_FRAME;
Command_to_pub.Reference_State.yaw_ref = YAW_STEP_SIZE;
move_pub.publish(Command_to_pub);
cout << " " <<endl;
cout << "Decrease the Yaw angle." <<endl;
sleep(0.1);
break;
// 圆形追踪
case U_KEY_9:
time_trajectory = 0.0;
trajectory_total_time = 50.0;
// 需要设置
while(time_trajectory < trajectory_total_time)
{
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State = Controller_Test.Circle_trajectory_generation(time_trajectory);
move_pub.publish(Command_to_pub);
time_trajectory = time_trajectory + 0.01;
cout << "Trajectory tracking: "<< time_trajectory << " / " << trajectory_total_time << " [ s ]" <<endl;
Draw_in_rviz(Command_to_pub.Reference_State, true);
ros::Duration(0.01).sleep();
}
break;
// 8字追踪
case U_KEY_8:
time_trajectory = 0.0;
trajectory_total_time = 50.0;
// 需要设置
while(time_trajectory < trajectory_total_time)
{
Command_to_pub.header.stamp = ros::Time::now();
Command_to_pub.Mode = prometheus_msgs::ControlCommand::Move;
Command_to_pub.Command_ID = Command_to_pub.Command_ID + 1;
Command_to_pub.source = NODE_NAME;
Command_to_pub.Reference_State = Controller_Test.Eight_trajectory_generation(time_trajectory);
move_pub.publish(Command_to_pub);
time_trajectory = time_trajectory + 0.01;
cout << "Trajectory tracking: "<< time_trajectory << " / " << trajectory_total_time << " [ s ]" <<endl;
Draw_in_rviz(Command_to_pub.Reference_State, true);
ros::Duration(0.01).sleep();
}
break;
}
key_last = key_now;
ros::spinOnce();
sleep(0.1);
}
}
void generate_com(int Move_mode, float state_desired[4])
{
//# Move_mode 2-bit value:
//# 0 for position, 1 for vel, 1st for xy, 2nd for z.
//# xy position xy velocity
//# z position 0b00(0) 0b10(2)
//# z velocity 0b01(1) 0b11(3)
if(Move_mode == prometheus_msgs::PositionReference::XYZ_ACC)
{
cout << "ACC control not support yet." <<endl;
}
if((Move_mode & 0b10) == 0) //xy channel
{
Command_to_pub.Reference_State.position_ref[0] = state_desired[0];
Command_to_pub.Reference_State.position_ref[1] = state_desired[1];
Command_to_pub.Reference_State.velocity_ref[0] = 0;
Command_to_pub.Reference_State.velocity_ref[1] = 0;
}
else
{
Command_to_pub.Reference_State.position_ref[0] = 0;
Command_to_pub.Reference_State.position_ref[1] = 0;
Command_to_pub.Reference_State.velocity_ref[0] = state_desired[0];
Command_to_pub.Reference_State.velocity_ref[1] = state_desired[1];
}
if((Move_mode & 0b01) == 0) //z channel
{
Command_to_pub.Reference_State.position_ref[2] = state_desired[2];
Command_to_pub.Reference_State.velocity_ref[2] = 0;
}
else
{
Command_to_pub.Reference_State.position_ref[2] = 0;
Command_to_pub.Reference_State.velocity_ref[2] = state_desired[2];
}
Command_to_pub.Reference_State.acceleration_ref[0] = 0;
Command_to_pub.Reference_State.acceleration_ref[1] = 0;
Command_to_pub.Reference_State.acceleration_ref[2] = 0;
Command_to_pub.Reference_State.yaw_ref = state_desired[3]/180.0*M_PI;
}
void Draw_in_rviz(const prometheus_msgs::PositionReference& pos_ref, bool draw_trajectory)
{
geometry_msgs::PoseStamped reference_pose;
reference_pose.header.stamp = ros::Time::now();
reference_pose.header.frame_id = "world";
reference_pose.pose.position.x = pos_ref.position_ref[0];
reference_pose.pose.position.y = pos_ref.position_ref[1];
reference_pose.pose.position.z = pos_ref.position_ref[2];
if(draw_trajectory)
{
posehistory_vector_.insert(posehistory_vector_.begin(), reference_pose);
if(posehistory_vector_.size() > TRA_WINDOW){
posehistory_vector_.pop_back();
}
nav_msgs::Path reference_trajectory;
reference_trajectory.header.stamp = ros::Time::now();
reference_trajectory.header.frame_id = "world";
reference_trajectory.poses = posehistory_vector_;
ref_trajectory_pub.publish(reference_trajectory);
}else
{
posehistory_vector_.clear();
nav_msgs::Path reference_trajectory;
reference_trajectory.header.stamp = ros::Time::now();
reference_trajectory.header.frame_id = "world";
reference_trajectory.poses = posehistory_vector_;
ref_trajectory_pub.publish(reference_trajectory);
}
}

@ -0,0 +1,261 @@
/***************************************************************************************************************************
* terminal_control_rover.cpp
*
* Author: Qyp
*
* Update Time: 2020.1.10
*
* Introduction: test function for sending ControlCommand.msg
***************************************************************************************************************************/
#include <ros/ros.h>
#include <controller_test.h>
#include <iostream>
#include <prometheus_msgs/ControlCommand.h>
#include <mavros_msgs/CommandBool.h>
#include <mavros_msgs/SetMode.h>
#include <mavros_msgs/State.h>
#include <nav_msgs/Path.h>
#define TRA_WINDOW 2000
#define NODE_NAME "terminal_control_rover"
using namespace std;
prometheus_msgs::ControlCommand Command_Now;
std::vector<geometry_msgs::PoseStamped> posehistory_vector_;
ros::Publisher move_pub;
ros::Publisher ref_trajectory_pub;
void generate_com(int Move_mode, float state_desired[4]);
void Draw_in_rviz(const prometheus_msgs::PositionReference& pos_ref, bool draw_trajectory);
int main(int argc, char **argv)
{
ros::init(argc, argv, "terminal_control_rover");
ros::NodeHandle nh;
move_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
//【发布】参考轨迹
ref_trajectory_pub = nh.advertise<nav_msgs::Path>("/prometheus/reference_trajectory", 10);
int Control_Mode = 0;
int Move_mode = 0;
int Move_frame = 0;
int Trjectory_mode = 0;
float trajectory_total_time = 0;
float state_desired[4];
// 圆形轨迹追踪类
Controller_Test Controller_Test;
Controller_Test.printf_param();
// 初始化命令-
// 默认设置Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = 0;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = 0;
while(ros::ok())
{
// Waiting for input
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Control Test<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
cout << "Input the Mode: 0 for Idle, 1 for Takeoff, 2 for Hold, 3 for Land, 4 for Move, 5 for Disarm, 6 for User_Mode1, 7 for User_Mode2"<<endl;
cout << "Input 999 to switch to offboard mode and arm the drone"<<endl;
cin >> Control_Mode;
if(Control_Mode == prometheus_msgs::ControlCommand::Move)
{
cout << "Input the Move_mode: 0 for position control, 3 for velocity control, 4 for att control"<<endl;
cin >> Move_mode;
cout << "Please input reference state [x y z yaw]: "<< endl;
cout << "setpoint_t[0] --- x [m] : "<< endl;
cin >> state_desired[0];
cout << "setpoint_t[1] --- y [m] : "<< endl;
cin >> state_desired[1];
cout << "setpoint_t[3] --- yaw [du] : "<< endl;
cin >> state_desired[3];
}else if(Control_Mode == 999)
{
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.yaw_ref = 999;
move_pub.publish(Command_Now);
}
switch (Control_Mode)
{
case prometheus_msgs::ControlCommand::Idle:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::Takeoff:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Takeoff;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::Hold:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Hold;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::Land:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Land;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::Move:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
Command_Now.Reference_State.Move_mode = Move_mode;
Command_Now.Reference_State.Move_frame = Move_frame;
Command_Now.Reference_State.time_from_start = -1;
generate_com(Move_mode, state_desired);
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::Disarm:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::Disarm;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::User_Mode1:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::User_Mode1;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
case prometheus_msgs::ControlCommand::User_Mode2:
Command_Now.header.stamp = ros::Time::now();
Command_Now.Mode = prometheus_msgs::ControlCommand::User_Mode2;
Command_Now.Command_ID = Command_Now.Command_ID + 1;
Command_Now.source = NODE_NAME;
move_pub.publish(Command_Now);
break;
}
ROS_INFO("..................................");
sleep(1.0);
}
return 0;
}
void generate_com(int Move_mode, float state_desired[4])
{
//# Move_mode 2-bit value:
//# 0 for position, 1 for vel, 1st for xy, 2nd for z.
//# xy position xy velocity
//# z position 0b00(0) 0b10(2)
//# z velocity 0b01(1) 0b11(3)
if(Move_mode == 0) //xy channel
{
Command_Now.Reference_State.position_ref[0] = state_desired[0];
Command_Now.Reference_State.position_ref[1] = state_desired[1];
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
}
else if(Move_mode == 3)
{
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[0] = state_desired[0];
Command_Now.Reference_State.velocity_ref[1] = state_desired[1];
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
}
else if(Move_mode == 4)
{
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[0] = state_desired[0];
Command_Now.Reference_State.acceleration_ref[1] = state_desired[1];
}
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = state_desired[3]/180.0*M_PI;
}
void Draw_in_rviz(const prometheus_msgs::PositionReference& pos_ref, bool draw_trajectory)
{
geometry_msgs::PoseStamped reference_pose;
reference_pose.header.stamp = ros::Time::now();
reference_pose.header.frame_id = "map";
reference_pose.pose.position.x = pos_ref.position_ref[0];
reference_pose.pose.position.y = pos_ref.position_ref[1];
reference_pose.pose.position.z = pos_ref.position_ref[2];
//ref_pose_pub.publish(reference_pose);
if(draw_trajectory)
{
posehistory_vector_.insert(posehistory_vector_.begin(), reference_pose);
if(posehistory_vector_.size() > TRA_WINDOW){
posehistory_vector_.pop_back();
}
nav_msgs::Path reference_trajectory;
reference_trajectory.header.stamp = ros::Time::now();
reference_trajectory.header.frame_id = "map";
reference_trajectory.poses = posehistory_vector_;
ref_trajectory_pub.publish(reference_trajectory);
}else
{
posehistory_vector_.clear();
nav_msgs::Path reference_trajectory;
reference_trajectory.header.stamp = ros::Time::now();
reference_trajectory.header.frame_id = "map";
reference_trajectory.poses = posehistory_vector_;
ref_trajectory_pub.publish(reference_trajectory);
}
}

@ -0,0 +1,68 @@
#include "KeyboardEvent.h"
KeyboardEvent::KeyboardEvent()
{
input_flag = -1;
buff = 0;
}
void KeyboardEvent::getch()
{
input_flag = -1; //if not key is pressed, then return -1 for the keyboard_input. reset this flag every time
fd_set set;
struct timeval timeout;
int rv;
buff = 0;
int len = 1;
int filedesc = 0;
FD_ZERO(&set);
FD_SET(filedesc, &set);
timeout.tv_sec = 0;
//timeout.tv_usec = 1000;//
timeout.tv_usec = 1000;
rv = select(filedesc + 1, &set, NULL, NULL, &timeout);
struct termios old = {0};
if (tcgetattr(filedesc, &old) < 0)
ROS_ERROR("tcsetattr()");
old.c_lflag &= ~ICANON;
old.c_lflag &= ~ECHO;
old.c_cc[VMIN] = 1;
old.c_cc[VTIME] = 0;
if (tcsetattr(filedesc, TCSANOW, &old) < 0)
ROS_ERROR("tcsetattr ICANON");
if(rv == -1){
ROS_ERROR("select");
}
else if(rv == 0)
{
//{ROS_INFO("-----");
}
else
{read(filedesc, &buff, len);
input_flag = 1;}
old.c_lflag |= ICANON;
old.c_lflag |= ECHO;
if (tcsetattr(filedesc, TCSADRAIN, &old) < 0)
ROS_ERROR ("tcsetattr ~ICANON");
}
char KeyboardEvent::GetPressedKey()
{
char key;
if(input_flag>-1)//if keyboard is pressed, then perform the callbacks
{
key = buff;
}else{
key = U_KEY_NONE;
}
return key;
}
void KeyboardEvent::RosWhileLoopRun()
{
getch();
}
int KeyboardEvent::input_flag;
char KeyboardEvent::buff;

@ -0,0 +1,385 @@
#include "OptiTrackFeedBackRigidBody.h"
OptiTrackFeedBackRigidBody::OptiTrackFeedBackRigidBody(const char* name,ros::NodeHandle& n,unsigned int linear_window, unsigned int angular_window)
{
// load filter window size
linear_velocity_window = linear_window;
angular_velocity_window = angular_window;
if(linear_velocity_window>max_windowsize)
{
ROS_INFO("Linear Velocity Window Size Overlimit, Max Value is [%d]",max_windowsize);
ROS_INFO("Input Valude is [%d]",linear_velocity_window);
linear_velocity_window = max_windowsize;
}
if(angular_velocity_window>max_windowsize)
{
ROS_INFO("Angular Velocity Window Size Overlimit, Max Value is [%d]",max_windowsize);
ROS_INFO("Input Valude is [%d]",angular_velocity_window);
angular_velocity_window = max_windowsize;
}
// set up subscriber to vrpn optitrack beedback
subOptiTrack = n.subscribe(name, 1, &OptiTrackFeedBackRigidBody::OptiTrackCallback,this);
//Initialize all velocity
for(int i =0;i<max_windowsize;i++)
{
velocity_raw[i](0)=0;
velocity_raw[i](1)=0;
velocity_raw[i](2)=0;
angular_velocity_raw[i](0)=0;
angular_velocity_raw[i](1)=0;
angular_velocity_raw[i](2)=0;
}
velocity_filtered(0)=0;
velocity_filtered(1)=0;
velocity_filtered(2)=0;
angular_velocity_filtered(0)=0;
angular_velocity_filtered(1)=0;
angular_velocity_filtered(2)=0;
//Initialize all pose
for(int i = 0;i<2;i++)
{
pose[i].q0 = 1;
pose[i].q1 = 0;
pose[i].q2 = 0;
pose[i].q3 = 0;
pose[i].t = 0;
pose[i].Position(0) = 0;
pose[i].Position(1) = 0;
pose[i].Position(2) = 0;
pose[i].L<< 0,1,0,0,
0,0,1,0,
0,0,0,1;
pose[i].R<< 0,1,0,0,
0,0,1,0,
0,0,0,1;
pose[1].R_IB<< 1,0,0,
0,1,0,
0,0,1;
pose[1].R_BI<< 1,0,0,
0,1,0,
0,0,1;
}
// Initialize flag
OptiTrackFlag = 0;
FeedbackState = 0;
}
void OptiTrackFeedBackRigidBody::CalculateVelocityFromPose()
{
/* Logic:
* 1) push the current pose into buffer
* 2) determine whether the buffer has a valid time value (pose[0].t >0); if so calculate velocity
* 3) if not just set the velocity_onestep as zero
* 4) push current time, and velocity_onestep into the velocity buffer
* 5) update the filtered velocity
*/
// perform the Logic:
// step (1): push the current pose into buffer
PushPose();
// step (2): determine whether the buffer has a valid time value (pose[0].t >0); if so calculate velocity
double dt = 0.0;
Vector3d velocity_onestep;
Vector3d angular_velocity_onestep;
if (pose[0].t >0)// calculate only when last time stamp has been recorded.
{
// step (2)
dt = pose[1].t - pose[0].t;// time step
// calculate linear velocity
velocity_onestep = (pose[1].Position- pose[0].Position)/dt;
// calculate angular velocity
Matrix3d RotationDifference = - pose[1].R_BI*pose[0].R_IB/dt;
Veemap(RotationDifference,angular_velocity_onestep);
}else// step (3): if not set velocity to zero
{
velocity_onestep(0) = 0.0;
velocity_onestep(1) = 0.0;
velocity_onestep(2) = 0.0;
angular_velocity_onestep(0) = 0.0;
angular_velocity_onestep(1) = 0.0;
angular_velocity_onestep(2) = 0.0;
}
// step (4): push current time, and velocity_onestep into the velocity buffer
PushRawVelocity(velocity_onestep,angular_velocity_onestep);
// step (5): update filtered velocity
MovingWindowAveraging();
}
void OptiTrackFeedBackRigidBody::PushPose()
{
pose[0] = pose[1];// straightforward push the pose into buffer
// update the latest pose
double t_current = (double)OptiTrackdata.header.stamp.sec + (double)OptiTrackdata.header.stamp.nsec*0.000000001;
pose[1].t = t_current;
// take a special note at the order of the quaterion
pose[1].q0 = OptiTrackdata.pose.orientation.w;
pose[1].q1 = OptiTrackdata.pose.orientation.x;
pose[1].q2 = OptiTrackdata.pose.orientation.y;
pose[1].q3 = OptiTrackdata.pose.orientation.z;
// update the auxiliary matrix
/*
L = [-q1 q0 q3 -q2;
-q2 -q3 q0 q1;
-q3 q2 -q1 q0]
R = [-q1 q0 -q3 q2;
-q2 q3 q0 -q1;
-q3 -q2 q1 q0]
R_IB = RL^T
*/
pose[1].L(0,0) = - pose[1].q1;
pose[1].L(1,0) = - pose[1].q2;
pose[1].L(2,0) = - pose[1].q3;
pose[1].L(0,1) = pose[1].q0;
pose[1].L(1,2) = pose[1].q0;
pose[1].L(2,3) = pose[1].q0;
pose[1].L(0,2) = pose[1].q3;
pose[1].L(0,3) = - pose[1].q2;
pose[1].L(1,1) = - pose[1].q3;
pose[1].L(1,3) = pose[1].q1;
pose[1].L(2,1) = pose[1].q2;
pose[1].L(2,2) = - pose[1].q1;
pose[1].R(0,0) = - pose[1].q1;
pose[1].R(1,0) = - pose[1].q2;
pose[1].R(2,0) = - pose[1].q3;
pose[1].R(0,1) = pose[1].q0;
pose[1].R(1,2) = pose[1].q0;
pose[1].R(2,3) = pose[1].q0;
pose[1].R(0,2) = -pose[1].q3;
pose[1].R(0,3) = pose[1].q2;
pose[1].R(1,1) = pose[1].q3;
pose[1].R(1,3) = -pose[1].q1;
pose[1].R(2,1) = -pose[1].q2;
pose[1].R(2,2) = pose[1].q1;
pose[1].R_IB = pose[1].R * pose[1].L.transpose();
pose[1].R_BI = pose[1].R_IB.transpose();
// position is straight forward
pose[1].Position(0) = OptiTrackdata.pose.position.x;
pose[1].Position(1) = OptiTrackdata.pose.position.y;
pose[1].Position(2) = OptiTrackdata.pose.position.z;
}
void OptiTrackFeedBackRigidBody::PushRawVelocity(Vector3d& new_linear_velocity, Vector3d& new_angular_velocity)
{
/* Logic:
* a(i-1) = a(i), i = 2...windowsize
* should fristly start from i = 2. a(1) = a(2); a(2) = a(3);....; a(N-1) = a(N)
* secondly a(N) = a_new
*/
// linear velocity
for(int i = 1;i<linear_velocity_window;i++)//first step
{
velocity_raw[i-1] = velocity_raw[i];
}
velocity_raw[linear_velocity_window-1] = new_linear_velocity;// second step update the last variable in the velocity buffer
// angular velocity
for(int i = 1;i<angular_velocity_window;i++)//first step
{
angular_velocity_raw[i-1] = angular_velocity_raw[i];
}
angular_velocity_raw[angular_velocity_window-1] = new_angular_velocity;// second step update the last variable in the velocity buffer
}
void OptiTrackFeedBackRigidBody::MovingWindowAveraging()
{
/* Logic: Average the raw velocity measurement in the
*/
double weight_linear = (double)1/linear_velocity_window;// the weight on each velocity to be summed up.
double weight_angular = (double)1/angular_velocity_window;// the weight on each velocity to be summed up.
// create a temporary variable to store the summed velocity and initialize it witht the 1st buffer value
Vector3d velocitytemp;
Vector3d angular_velocitytemp;
velocitytemp = weight_linear*velocity_raw[0];
angular_velocitytemp = weight_angular*angular_velocity_raw[0];
for(int i = 1;i<linear_velocity_window;i++)// sum starts from the second buffer value
{
velocitytemp += weight_linear*velocity_raw[i];
}
for(int i = 1;i<angular_velocity_window;i++)// sum starts from the second buffer value
{
angular_velocitytemp += weight_angular*angular_velocity_raw[i];
}
// the filtered vlocity is just the weighted summed result
velocity_filtered = velocitytemp;
angular_velocity_filtered = angular_velocitytemp;
}
void OptiTrackFeedBackRigidBody::GetState(rigidbody_state& state)
{
state.time_stamp = pose[1].t;
state.Position = pose[1].Position;
state.V_I = velocity_filtered;
state.Omega_BI = angular_velocity_filtered;
Hatmap(state.Omega_BI,state.Omega_Cross);
state.R_IB = pose[1].R_IB;
state.R_BI = pose[1].R_BI;
double euler_temp[3];
GetEulerAngleFromQuaterion_NormalConvention(euler_temp);
state.Euler(0) = euler_temp[0];// euler angle
state.Euler(1) = euler_temp[1];// euler angle
state.Euler(2) = euler_temp[2];// euler angle
state.quaterion(0) = pose[1].q0;
state.quaterion(1) = pose[1].q1;
state.quaterion(2) = pose[1].q2;
state.quaterion(3) = pose[1].q3;
}
void OptiTrackFeedBackRigidBody::GetRaWVelocity(Vector3d& linear_velocity,Vector3d& angular_velocity)
{
linear_velocity = velocity_raw[linear_velocity_window-1];// return the filtered velocity
angular_velocity = angular_velocity_raw[angular_velocity_window-1];// return the filtered velocity
}
void OptiTrackFeedBackRigidBody::SetZeroVelocity()
{
for(int i =0;i<linear_velocity_window;i++)
{
velocity_raw[i](0)=0;
velocity_raw[i](1)=0;
velocity_raw[i](2)=0;
}
for(int i =0;i<angular_velocity_window;i++)
{
angular_velocity_raw[i](0)=0;
angular_velocity_raw[i](1)=0;
angular_velocity_raw[i](2)=0;
}
velocity_filtered(0)=0;
velocity_filtered(1)=0;
velocity_filtered(2)=0;
angular_velocity_filtered(0) =0;
angular_velocity_filtered(1) =0;
angular_velocity_filtered(2) =0;
}
void OptiTrackFeedBackRigidBody::RosWhileLoopRun()
{
if(OptiTrackFlag==1)
{// update the velocity only when there is OptiTrack feedback
CalculateVelocityFromPose();
FeedbackState=1;
}else{
// if the optitrack measurements no longer feedback, when the pose update will stop and we only return 0 velocity
SetZeroVelocity();
FeedbackState=0;
}
OptiTrackFlag = 0;// reset the feedback flag to 0
}
int OptiTrackFeedBackRigidBody::GetOptiTrackState()
{
if (FeedbackState==1) {
ROS_INFO("OptiTrack:Normal");
}else{
ROS_INFO("OptiTrack:No FeedBack");
}
ROS_INFO("Linear Velocity Filter Window Size is [%d]",linear_velocity_window);
ROS_INFO("Angular Velocity Filter Window Size is [%d]",angular_velocity_window);
return FeedbackState;
}
void OptiTrackFeedBackRigidBody::GetEulerAngleFromQuaterion_NormalConvention(double (&eulerangle)[3])
{
/* Normal means the following https://en.wikipedia.org/wiki/Conversion_between_quaternions_and_Euler_angles
*/
// eulerangle[0] = atan2(2.0 * (quat[3] * quat[2] + quat[0] * quat[1]), 1.0 - 2.0 * (quat[1] * quat[1] + quat[2] * quat[2]));
// eulerangle[1] = asin(2.0 * (quat[2] * quat[0] - quat[3] * quat[1]));
// eulerangle[2] = atan2(2.0 * (quat[3] * quat[0] + quat[1] * quat[2]), 1.0 - 2.0 * (quat[2] * quat[2] + quat[3] * quat[3]));
// roll (x-axis rotation)
double sinr_cosp = +2.0 * (pose[1].q0 * pose[1].q1 + pose[1].q2 * pose[1].q3);
double cosr_cosp = +1.0 - 2.0 * (pose[1].q1 * pose[1].q1 +pose[1].q2 * pose[1].q2);
double roll = atan2(sinr_cosp, cosr_cosp);
// pitch (y-axis rotation)
double sinp = +2.0 * (pose[1].q0 * pose[1].q2 - pose[1].q3 * pose[1].q1);
double pitch;
if (fabs(sinp) >= 1)
pitch = copysign(M_PI / 2, sinp); // use 90 degrees if out of range
else
pitch = asin(sinp);
// yaw (z-axis rotation)
double siny_cosp = +2.0 * (pose[1].q0 * pose[1].q3 + pose[1].q1 * pose[1].q2);
double cosy_cosp = +1.0 - 2.0 * (pose[1].q2 * pose[1].q2 + pose[1].q3 * pose[1].q3);
double yaw = atan2(siny_cosp, cosy_cosp);
//double yaw = atan2(2.0 * (dronepose[1].q3 * dronepose[1].q0 + dronepose[1].q1 * dronepose[1].q2), -1.0 + 2.0 * (dronepose[1].q0 * dronepose[1].q0 + dronepose[1].q1 * dronepose[1].q1));
eulerangle[0] = roll;
eulerangle[1] = pitch;
eulerangle[2] = yaw;
}
void OptiTrackFeedBackRigidBody::GetEulerAngleFromQuaterion_OptiTrackYUpConvention(double (&eulerangle)[3])
{
// OptiTrack gives a quaternion with q2 and q3 flipped. (and sign flipped for q3)
// roll (x-axis rotation)
double sinr_cosp = +2.0 * (pose[1].q0 * pose[1].q1 + pose[1].q3 * pose[1].q2);
double cosr_cosp = +1.0 - 2.0 * (pose[1].q1 * pose[1].q1 +pose[1].q3 * pose[1].q3);
double roll = atan2(sinr_cosp, cosr_cosp);
// pitch (y-axis rotation)
double sinp = +2.0 * (pose[1].q0 * pose[1].q3 - pose[1].q2 * pose[1].q1);
double pitch;
if (fabs(sinp) >= 1)
pitch = copysign(M_PI / 2, sinp); // use 90 degrees if out of range
else
pitch = asin(sinp);
// yaw (z-axis rotation)
double siny_cosp = +2.0 * (pose[1].q0 * pose[1].q2 + pose[1].q1 * pose[1].q3);
double cosy_cosp = +1.0 - 2.0 * (pose[1].q2 * pose[1].q2 + pose[1].q3 * pose[1].q3);
double yaw = atan2(siny_cosp, cosy_cosp);
eulerangle[0] = roll;
eulerangle[1] = pitch;
eulerangle[2] = yaw;
}
void OptiTrackFeedBackRigidBody::OptiTrackCallback(const geometry_msgs::PoseStamped& msg)
{
// must use head information to distiguish the correct
OptiTrackdata = msg; // update optitrack data
OptiTrackFlag = 1;// signal a new measurement feed has been revcieved.
}
OptiTrackFeedBackRigidBody::~OptiTrackFeedBackRigidBody()
{
}
void OptiTrackFeedBackRigidBody::Veemap(Matrix3d& cross_matrix, Vector3d& vector)
{
vector(0) = -cross_matrix(1,2);
vector(1) = cross_matrix(0,2);
vector(2) = -cross_matrix(0,1);
}
void OptiTrackFeedBackRigidBody::Hatmap(Vector3d& vector, Matrix3d& cross_matrix)
{
/*
r^x = [0 -r3 r2;
r3 0 -r1;
-r2 r1 0]
*/
cross_matrix(0,0) = 0.0;
cross_matrix(0,1) = - vector(2);
cross_matrix(0,2) = vector(1);
cross_matrix(1,0) = vector(2);
cross_matrix(1,1) = 0.0;
cross_matrix(1,2) = - vector(0);
cross_matrix(2,0) = - vector(1);
cross_matrix(2,1) = vector(0);
cross_matrix(2,2) = 0.0;
}

@ -0,0 +1,564 @@
/***************************************************************************************************************************
* px4_geometry_controller.cpp
*
* Author: Qyp
*
* Update Time: 2021.03.05
*
* +
* 12+3++
***************************************************************************************************************************/
#include <ros/ros.h>
#include "state_from_mavros.h"
#include "command_to_mavros.h"
#include "prometheus_control_utils.h"
#include "message_utils.h"
#include "control_common.h"
#include "Position_Controller/pos_controller_cascade_PID.h"
#include "Position_Controller/pos_controller_PID.h"
#include "Position_Controller/pos_controller_Passivity.h"
#include "Position_Controller/geometry_controller.h"
#include "Filter/LowPassFilter.h"
#define NODE_NAME "geometry_controller"
using namespace std;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>变量声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
float cur_time; //程序运行时间
string controller_type; //控制器类型
float Takeoff_height; //默认起飞高度
float Disarm_height; //自动上锁高度
float Land_speed; //降落速度
//Geigraphical fence 地理围栏
Eigen::Vector2f geo_fence_x;
Eigen::Vector2f geo_fence_y;
Eigen::Vector2f geo_fence_z;
Eigen::Vector3d Takeoff_position; // 起飞位置
prometheus_msgs::DroneState _DroneState; //无人机状态量
prometheus_msgs::ControlCommand Command_Now; //无人机当前执行命令
prometheus_msgs::ControlCommand Command_Last; //无人机上一条执行命令
prometheus_msgs::ControlOutput _ControlOutput;
prometheus_msgs::AttitudeReference _AttitudeReference; //位置控制器输出,即姿态环参考量
prometheus_msgs::Message message;
prometheus_msgs::LogMessageControl LogMessage;
//RVIZ显示期望位置
geometry_msgs::PoseStamped ref_pose_rviz;
float dt = 0;
ros::Publisher att_ref_pub;
ros::Publisher rivz_ref_pose_pub;
ros::Publisher message_pub;
ros::Publisher log_message_pub;
Eigen::Vector3d throttle_sp;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>函数声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int check_failsafe();
void printf_param();
void Body_to_ENU();
void add_disturbance();
geometry_msgs::PoseStamped get_ref_pose_rviz(const prometheus_msgs::ControlCommand& cmd, const prometheus_msgs::AttitudeReference& att_ref);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void Command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
// CommandID必须递增才会被记录
if( msg->Command_ID > Command_Now.Command_ID )
{
Command_Now = *msg;
}else
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Wrong Command ID.");
}
// 无人机一旦接受到Disarm指令则会屏蔽其他指令
if(Command_Last.Mode == prometheus_msgs::ControlCommand::Disarm)
{
Command_Now = Command_Last;
}
}
void station_command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
Command_Now = *msg;
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Get a command from Prometheus Station.");
// 无人机一旦接受到Disarm指令则会屏蔽其他指令
if(Command_Last.Mode == prometheus_msgs::ControlCommand::Disarm)
{
Command_Now = Command_Last;
}
}
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
{
_DroneState = *msg;
_DroneState.time_from_start = cur_time;
}
void timerCallback(const ros::TimerEvent& e)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Program is running.");
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_geometry_controller");
ros::NodeHandle nh("~");
//【订阅】指令
// 本话题为任务模块生成的控制指令
ros::Subscriber Command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10, Command_cb);
//【订阅】指令
// 本话题为Prometheus地面站发送的控制指令
ros::Subscriber station_command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command_station", 10, station_command_cb);
//【订阅】无人机状态
// 本话题来自px4_pos_estimator.cpp
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
//【发布】位置控制器的输出量:期望姿态
att_ref_pub = nh.advertise<prometheus_msgs::AttitudeReference>("/prometheus/control/attitude_reference", 10);
//【发布】参考位姿 RVIZ显示用
rivz_ref_pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/prometheus/control/ref_pose_rviz", 10);
// 【发布】用于地面站显示的提示消息
message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
// 【发布】用于log的消息
log_message_pub = nh.advertise<prometheus_msgs::LogMessageControl>("/prometheus/log/control", 10);
// 10秒定时打印以确保程序在正确运行
ros::Timer timer = nh.createTimer(ros::Duration(10.0), timerCallback);
// 参数读取
nh.param<string>("controller_type", controller_type, "geometry");
nh.param<float>("Takeoff_height", Takeoff_height, 1.5);
nh.param<float>("Disarm_height", Disarm_height, 0.15);
nh.param<float>("Land_speed", Land_speed, 0.2);
nh.param<float>("geo_fence/x_min", geo_fence_x[0], -100.0);
nh.param<float>("geo_fence/x_max", geo_fence_x[1], 100.0);
nh.param<float>("geo_fence/y_min", geo_fence_y[0], -100.0);
nh.param<float>("geo_fence/y_max", geo_fence_y[1], 100.0);
nh.param<float>("geo_fence/z_min", geo_fence_z[0], -100.0);
nh.param<float>("geo_fence/z_max", geo_fence_z[1], 100.0);
// 加大频率
ros::Rate rate(100.0);
float time_trajectory = 0.0;
// 用于与mavros通讯的类通过mavros发送控制指令至飞控【本程序->mavros->飞控】
command_to_mavros _command_to_mavros;
geometry_controller geometry_controller;
printf_param();
geometry_controller.printf_param();
// 初始化命令-
// 默认设置Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = 0;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = 0;
// 记录启控时间
ros::Time begin_time = ros::Time::now();
float last_time = prometheus_control_utils::get_time_in_sec(begin_time);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
// 当前时间
cur_time = prometheus_control_utils::get_time_in_sec(begin_time);
dt = cur_time - last_time;
dt = constrain_function2(dt, 0.01, 0.03);
last_time = cur_time;
//执行回调函数
ros::spinOnce();
// Check for geo fence: If drone is out of the geo fence, it will land now.
if(check_failsafe() == 1)
{
Command_Now.Mode = prometheus_msgs::ControlCommand::Land;
}
switch (Command_Now.Mode)
{
// 【Idle】 怠速旋转此时可以切入offboard模式但不会起飞。
case prometheus_msgs::ControlCommand::Idle:
_command_to_mavros.idle();
// 设定yaw_ref=999时切换offboard模式并解锁
if(Command_Now.Reference_State.yaw_ref == 999)
{
if(_DroneState.mode != "OFFBOARD")
{
_command_to_mavros.mode_cmd.request.custom_mode = "OFFBOARD";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Setting to OFFBOARD Mode...");
}else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "The Drone is in OFFBOARD Mode already...");
}
if(!_DroneState.armed)
{
_command_to_mavros.arm_cmd.request.value = true;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Arming...");
}else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "The Drone is armd already...");
}
}
break;
// 【Takeoff】 从摆放初始位置原地起飞至指定高度,偏航角也保持当前角度
case prometheus_msgs::ControlCommand::Takeoff:
// 当无人机在空中时若受到起飞指令,则发出警告并悬停
if (_DroneState.landed == false)
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "The drone is in the air!");
}
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Takeoff)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Takeoff to the desired point.");
// 设定起飞位置
Takeoff_position[0] = _DroneState.position[0];
Takeoff_position[1] = _DroneState.position[1];
Takeoff_position[2] = _DroneState.position[2];
//
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = Takeoff_position[0];
Command_Now.Reference_State.position_ref[1] = Takeoff_position[1];
Command_Now.Reference_State.position_ref[2] = Takeoff_position[2] + Takeoff_height;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2];
}
break;
// 【Hold】 悬停。当前位置悬停
case prometheus_msgs::ControlCommand::Hold:
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Hold)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2];
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
}
break;
// 【Land】 降落。当前位置原地降落降落后会自动上锁且切换为mannual模式
case prometheus_msgs::ControlCommand::Land:
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Land)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
}
if(_DroneState.position[2] > Disarm_height)
{
Command_Now.Reference_State.position_ref[2] = _DroneState.attitude[2] - Land_speed*dt;
Command_Now.Reference_State.velocity_ref[0] = 0.0;
Command_Now.Reference_State.velocity_ref[1] = 0.0;
Command_Now.Reference_State.velocity_ref[2] = - Land_speed; //Land_speed
}else
{
if(_DroneState.mode != "AUTO.LAND")
{
//此处切换会manual模式是因为:PX4默认在offboard模式且有控制的情况下没法上锁,直接使用飞控中的land模式
_command_to_mavros.mode_cmd.request.custom_mode = "AUTO.LAND";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "LAND: inter AUTO LAND filght mode");
}
}
if(_DroneState.landed)
{
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
}
break;
// 【Move】 ENU系移动。只有PID算法中才有追踪速度的选项其他控制只能追踪位置
case prometheus_msgs::ControlCommand::Move:
//对于机体系的指令,需要转换成ENU坐标系执行,且同一ID号内,只执行一次.
if(Command_Now.Reference_State.Move_frame != prometheus_msgs::PositionReference::ENU_FRAME && Command_Now.Command_ID > Command_Last.Command_ID )
{
Body_to_ENU();
}
break;
// 【Disarm】 上锁
case prometheus_msgs::ControlCommand::Disarm:
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Disarm: switch to MANUAL flight mode");
if(_DroneState.mode == "OFFBOARD")
{
_command_to_mavros.mode_cmd.request.custom_mode = "MANUAL";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
}
if(_DroneState.armed)
{
_command_to_mavros.arm_cmd.request.value = false;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
}
break;
// 【User_Mode1】 暂空。可进行自定义
case prometheus_msgs::ControlCommand::User_Mode1:
break;
// 【User_Mode2】 暂空。可进行自定义
case prometheus_msgs::ControlCommand::User_Mode2:
break;
}
//执行控制
static Eigen::Vector4d cmd;
if(Command_Now.Mode != prometheus_msgs::ControlCommand::Idle)
{
//选择控制器
if(controller_type == "geometry")
{
cmd = geometry_controller.pos_controller(_DroneState, Command_Now.Reference_State);
}else
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Wrong controller type");
}
}
Eigen::Vector3d bodyrate_cmd;
float thrust_sp;
bodyrate_cmd = cmd.head(3);
thrust_sp = cmd(3);
//发送解算得到的期望姿态角速度至PX4
_command_to_mavros.send_attitude_rate_setpoint(bodyrate_cmd,thrust_sp);
//发布log消息可用rosbag记录
LogMessage.control_type = PX4_GEO_CONTROLLER;
LogMessage.time = cur_time;
LogMessage.Drone_State = _DroneState;
LogMessage.Control_Command = Command_Now;
log_message_pub.publish(LogMessage);
Command_Last = Command_Now;
rate.sleep();
}
return 0;
}
void printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>> px4_geometry_controller Parameter <<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "controller_type: "<< controller_type <<endl;
cout << "Takeoff_height : "<< Takeoff_height<<" [m] "<<endl;
cout << "Disarm_height : "<< Disarm_height <<" [m] "<<endl;
cout << "Land_speed : "<< Land_speed <<" [m/s] "<<endl;
cout << "geo_fence_x : "<< geo_fence_x[0] << " [m] to "<<geo_fence_x[1] << " [m]"<< endl;
cout << "geo_fence_y : "<< geo_fence_y[0] << " [m] to "<<geo_fence_y[1] << " [m]"<< endl;
cout << "geo_fence_z : "<< geo_fence_z[0] << " [m] to "<<geo_fence_z[1] << " [m]"<< endl;
}
int check_failsafe()
{
if (_DroneState.position[0] < geo_fence_x[0] || _DroneState.position[0] > geo_fence_x[1] ||
_DroneState.position[1] < geo_fence_y[0] || _DroneState.position[1] > geo_fence_y[1] ||
_DroneState.position[2] < geo_fence_z[0] || _DroneState.position[2] > geo_fence_z[1])
{
pub_message(message_pub, prometheus_msgs::Message::ERROR, NODE_NAME, "Out of the geo fence, the drone is landing...");
return 1;
}
else{
return 0;
}
}
//【Body_to_ENU】 机体系移动。
void Body_to_ENU()
{
if( Command_Now.Reference_State.Move_mode & 0b10 )
{
//xy velocity mode
float d_vel_body[2] = {Command_Now.Reference_State.velocity_ref[0], Command_Now.Reference_State.velocity_ref[1]}; //the desired xy velocity in Body Frame
float d_vel_enu[2]; //the desired xy velocity in NED Frame
//根据无人机当前偏航角进行坐标系转换
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_vel_body, d_vel_enu);
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[0] = d_vel_enu[0];
Command_Now.Reference_State.velocity_ref[1] = d_vel_enu[1];
}
else
{
//xy position mode
float d_pos_body[2] = {Command_Now.Reference_State.position_ref[0], Command_Now.Reference_State.position_ref[1]}; //the desired xy position in Body Frame
float d_pos_enu[2]; //the desired xy position in enu Frame (The origin point is the drone)
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_pos_body, d_pos_enu);
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0] + d_pos_enu[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1] + d_pos_enu[1];
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
}
if(Command_Now.Reference_State.Move_frame == prometheus_msgs::PositionReference::MIX_FRAME)
{
Command_Now.Reference_State.position_ref[2] = Command_Now.Reference_State.position_ref[2];
//Command_Now.Reference_State.yaw_ref = Command_Now.Reference_State.yaw_ref;
}else
{
if( Command_Now.Reference_State.Move_mode & 0b01 )
{
//z velocity mode
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[2] = Command_Now.Reference_State.velocity_ref[2];
}
else
{
//z posiiton mode
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] + Command_Now.Reference_State.position_ref[2];
Command_Now.Reference_State.velocity_ref[2] = 0;
}
}
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2] + Command_Now.Reference_State.yaw_ref;
float d_acc_body[2] = {Command_Now.Reference_State.acceleration_ref[0], Command_Now.Reference_State.acceleration_ref[1]};
float d_acc_enu[2];
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_acc_body, d_acc_enu);
Command_Now.Reference_State.acceleration_ref[0] = d_acc_enu[0];
Command_Now.Reference_State.acceleration_ref[1] = d_acc_enu[1];
Command_Now.Reference_State.acceleration_ref[2] = Command_Now.Reference_State.acceleration_ref[2];
}
void add_disturbance()
{
}
geometry_msgs::PoseStamped get_ref_pose_rviz(const prometheus_msgs::ControlCommand& cmd, const prometheus_msgs::AttitudeReference& att_ref)
{
geometry_msgs::PoseStamped ref_pose;
ref_pose.header.stamp = ros::Time::now();
// world: 世界系,即gazebo坐标系,参见tf_transform.launch
ref_pose.header.frame_id = "world";
if(cmd.Mode == prometheus_msgs::ControlCommand::Idle)
{
ref_pose.pose.position.x = _DroneState.position[0];
ref_pose.pose.position.y = _DroneState.position[1];
ref_pose.pose.position.z = _DroneState.position[2];
ref_pose.pose.orientation = _DroneState.attitude_q;
}else if(cmd.Mode == prometheus_msgs::ControlCommand::Takeoff || cmd.Mode == prometheus_msgs::ControlCommand::Hold)
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
ref_pose.pose.orientation = _DroneState.attitude_q;
}else if(cmd.Mode == prometheus_msgs::ControlCommand::Disarm || cmd.Mode == prometheus_msgs::ControlCommand::Land )
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = 0.0;
ref_pose.pose.orientation = _DroneState.attitude_q;
}
else if(cmd.Mode == prometheus_msgs::ControlCommand::Move)
{
//xy速度控制
if( Command_Now.Reference_State.Move_mode & 0b10 )
{
ref_pose.pose.position.x = _DroneState.position[0] + cmd.Reference_State.velocity_ref[0] * dt;
ref_pose.pose.position.y = _DroneState.position[1] + cmd.Reference_State.velocity_ref[1] * dt;
}else
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
}
if(Command_Now.Reference_State.Move_mode & 0b01 )
{
ref_pose.pose.position.z = _DroneState.position[2] + cmd.Reference_State.velocity_ref[2] * dt;
}else
{
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
}
ref_pose.pose.orientation = att_ref.desired_att_q;
}else
{
ref_pose.pose.position.x = 0.0;
ref_pose.pose.position.y = 0.0;
ref_pose.pose.position.z = 0.0;
ref_pose.pose.orientation = _DroneState.attitude_q;
}
return ref_pose;
}

@ -0,0 +1,649 @@
/***************************************************************************************************************************
* px4_pos_controller.cpp
*
* Author: Qyp
*
* Update Time: 2020.08.10
*
* Introduction: PX4 Position Controller
* 1. /prometheus/control_commandControlCommand.msg
* 2. px4_pos_estimator.cppDroneState.msg
* 3. cascade_PID, PID, UDE, passivity-UDE, NE+UDE
* 4. command_to_mavros.hmavrosmavlink
* 5. PX4mavlink_receiver.cppmavlink
***************************************************************************************************************************/
#include <ros/ros.h>
#include "state_from_mavros.h"
#include "command_to_mavros.h"
#include "prometheus_control_utils.h"
#include "message_utils.h"
#include "control_common.h"
#include "Position_Controller/pos_controller_cascade_PID.h"
#include "Position_Controller/pos_controller_PID.h"
#include "Position_Controller/pos_controller_UDE.h"
#include "Position_Controller/pos_controller_NE.h"
#include "Position_Controller/pos_controller_Passivity.h"
#include "Filter/LowPassFilter.h"
#define NODE_NAME "pos_controller"
using namespace std;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>变量声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
float cur_time; //程序运行时间
string controller_type; //控制器类型
float Takeoff_height; //默认起飞高度
float Disarm_height; //自动上锁高度
float Land_speed; //降落速度
//Geigraphical fence 地理围栏
Eigen::Vector2f geo_fence_x;
Eigen::Vector2f geo_fence_y;
Eigen::Vector2f geo_fence_z;
Eigen::Vector3d Takeoff_position; // 起飞位置
prometheus_msgs::DroneState _DroneState; //无人机状态量
prometheus_msgs::ControlCommand Command_Now; //无人机当前执行命令
prometheus_msgs::ControlCommand Command_Last; //无人机上一条执行命令
prometheus_msgs::ControlOutput _ControlOutput;
prometheus_msgs::AttitudeReference _AttitudeReference; //位置控制器输出,即姿态环参考量
prometheus_msgs::Message message;
prometheus_msgs::LogMessageControl LogMessage;
//RVIZ显示期望位置
geometry_msgs::PoseStamped ref_pose_rviz;
float dt = 0;
float disturbance_a_xy,disturbance_b_xy;
float disturbance_a_z,disturbance_b_z;
float disturbance_T;
float disturbance_start_time;
float disturbance_end_time;
ros::Publisher att_ref_pub;
ros::Publisher rivz_ref_pose_pub;
ros::Publisher message_pub;
ros::Publisher log_message_pub;
Eigen::Vector3d throttle_sp;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>函数声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int check_failsafe();
void printf_param();
void Body_to_ENU();
void add_disturbance();
geometry_msgs::PoseStamped get_ref_pose_rviz(const prometheus_msgs::ControlCommand& cmd, const prometheus_msgs::AttitudeReference& att_ref);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void Command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
// CommandID必须递增才会被记录
if( msg->Command_ID > Command_Now.Command_ID )
{
Command_Now = *msg;
}else
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Wrong Command ID.");
}
// 无人机一旦接受到Disarm指令则会屏蔽其他指令
if(Command_Last.Mode == prometheus_msgs::ControlCommand::Disarm)
{
Command_Now = Command_Last;
}
}
void station_command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
Command_Now = *msg;
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Get a command from Prometheus Station.");
// 无人机一旦接受到Disarm指令则会屏蔽其他指令
if(Command_Last.Mode == prometheus_msgs::ControlCommand::Disarm)
{
Command_Now = Command_Last;
}
}
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
{
_DroneState = *msg;
_DroneState.time_from_start = cur_time;
}
void timerCallback(const ros::TimerEvent& e)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Program is running.");
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_pos_controller");
ros::NodeHandle nh("~");
//【订阅】指令
// 本话题为任务模块生成的控制指令
ros::Subscriber Command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10, Command_cb);
//【订阅】指令
// 本话题为Prometheus地面站发送的控制指令
ros::Subscriber station_command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command_station", 10, station_command_cb);
//【订阅】无人机状态
// 本话题来自px4_pos_estimator.cpp
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
//【发布】位置控制器的输出量:期望姿态
att_ref_pub = nh.advertise<prometheus_msgs::AttitudeReference>("/prometheus/control/attitude_reference", 10);
//【发布】参考位姿 RVIZ显示用
rivz_ref_pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/prometheus/control/ref_pose_rviz", 10);
// 【发布】用于地面站显示的提示消息
message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
// 【发布】用于log的消息
log_message_pub = nh.advertise<prometheus_msgs::LogMessageControl>("/prometheus/log/control", 10);
// 10秒定时打印以确保程序在正确运行
ros::Timer timer = nh.createTimer(ros::Duration(10.0), timerCallback);
// 参数读取
nh.param<string>("controller_type", controller_type, "default");
nh.param<float>("Takeoff_height", Takeoff_height, 1.5);
nh.param<float>("Disarm_height", Disarm_height, 0.15);
nh.param<float>("Land_speed", Land_speed, 0.2);
nh.param<float>("geo_fence/x_min", geo_fence_x[0], -100.0);
nh.param<float>("geo_fence/x_max", geo_fence_x[1], 100.0);
nh.param<float>("geo_fence/y_min", geo_fence_y[0], -100.0);
nh.param<float>("geo_fence/y_max", geo_fence_y[1], 100.0);
nh.param<float>("geo_fence/z_min", geo_fence_z[0], -100.0);
nh.param<float>("geo_fence/z_max", geo_fence_z[1], 100.0);
nh.param<float>("disturbance_a_xy", disturbance_a_xy, 0.5);
nh.param<float>("disturbance_b_xy", disturbance_b_xy, 0.0);
nh.param<float>("disturbance_a_z", disturbance_a_z, 0.5);
nh.param<float>("disturbance_b_z", disturbance_b_z, 0.0);
nh.param<float>("disturbance_T", disturbance_T, 0.0);
nh.param<float>("disturbance_start_time", disturbance_start_time, 10.0);
nh.param<float>("disturbance_end_time", disturbance_end_time, -1.0);
LowPassFilter LPF_x;
LowPassFilter LPF_y;
LowPassFilter LPF_z;
LPF_x.set_Time_constant(disturbance_T);
LPF_y.set_Time_constant(disturbance_T);
LPF_z.set_Time_constant(disturbance_T);
// 位置控制一般选取为50Hz主要取决于位置状态的更新频率
ros::Rate rate(50.0);
float time_trajectory = 0.0;
// 用于与mavros通讯的类通过mavros发送控制指令至飞控【本程序->mavros->飞控】
command_to_mavros _command_to_mavros;
// 位置控制器声明
pos_controller_cascade_PID pos_controller_cascade_pid;
// 可以设置自定义位置环控制算法
pos_controller_PID pos_controller_pid;
pos_controller_passivity pos_controller_passivity;
pos_controller_UDE pos_controller_UDE;
pos_controller_NE pos_controller_NE;
printf_param();
if(controller_type == "default")
{
pos_controller_cascade_pid.printf_param();
}else if(controller_type == "pid")
{
pos_controller_pid.printf_param();
}else if(controller_type == "passivity")
{
pos_controller_passivity.printf_param();
}else if(controller_type == "ude")
{
pos_controller_UDE.printf_param();
}else if(controller_type == "ne")
{
pos_controller_NE.printf_param();
}
// 初始化命令-
// 默认设置Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = 0;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = 0;
// 记录启控时间
ros::Time begin_time = ros::Time::now();
float last_time = prometheus_control_utils::get_time_in_sec(begin_time);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
// 当前时间
cur_time = prometheus_control_utils::get_time_in_sec(begin_time);
dt = cur_time - last_time;
dt = constrain_function2(dt, 0.01, 0.03);
last_time = cur_time;
//执行回调函数
ros::spinOnce();
// Check for geo fence: If drone is out of the geo fence, it will land now.
if(check_failsafe() == 1)
{
Command_Now.Mode = prometheus_msgs::ControlCommand::Land;
}
switch (Command_Now.Mode)
{
// 【Idle】 怠速旋转此时可以切入offboard模式但不会起飞。
case prometheus_msgs::ControlCommand::Idle:
_command_to_mavros.idle();
// 设定yaw_ref=999时切换offboard模式并解锁
if(Command_Now.Reference_State.yaw_ref == 999)
{
if(_DroneState.mode != "OFFBOARD")
{
_command_to_mavros.mode_cmd.request.custom_mode = "OFFBOARD";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Setting to OFFBOARD Mode...");
}else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "The Drone is in OFFBOARD Mode already...");
}
if(!_DroneState.armed)
{
_command_to_mavros.arm_cmd.request.value = true;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Arming...");
}else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "The Drone is armd already...");
}
}
break;
// 【Takeoff】 从摆放初始位置原地起飞至指定高度,偏航角也保持当前角度
case prometheus_msgs::ControlCommand::Takeoff:
//当无人机在空中时若受到起飞指令,则发出警告并悬停
// if (_DroneState.landed == false)
// {
// Command_Now.Mode = prometheus_msgs::ControlCommand::Hold;
// pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "The drone is in the air!");
// }
if (_DroneState.landed == true && Command_Last.Mode != prometheus_msgs::ControlCommand::Takeoff)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Takeoff to the desired point.");
// 设定起飞位置
Takeoff_position[0] = _DroneState.position[0];
Takeoff_position[1] = _DroneState.position[1];
Takeoff_position[2] = _DroneState.position[2];
//
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = Takeoff_position[0];
Command_Now.Reference_State.position_ref[1] = Takeoff_position[1];
Command_Now.Reference_State.position_ref[2] = Takeoff_position[2] + Takeoff_height;
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2];
}
break;
// 【Hold】 悬停。当前位置悬停
case prometheus_msgs::ControlCommand::Hold:
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Hold)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2];
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
}
break;
// 【Land】 降落。当前位置原地降落降落后会自动上锁且切换为mannual模式
case prometheus_msgs::ControlCommand::Land:
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Land)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XY_POS_Z_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.velocity_ref[2] = - Land_speed; //Land_speed
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
}
//如果距离起飞高度小于10厘米则直接切换为land模式
if(abs(_DroneState.position[2] - Takeoff_position[2]) < Disarm_height)
{
if(_DroneState.mode != "AUTO.LAND")
{
//此处切换会manual模式是因为:PX4默认在offboard模式且有控制的情况下没法上锁,直接使用飞控中的land模式
_command_to_mavros.mode_cmd.request.custom_mode = "AUTO.LAND";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "LAND: inter AUTO LAND filght mode");
}
}
if(_DroneState.landed)
{
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
}
break;
// 【Move】 ENU系移动。只有PID算法中才有追踪速度的选项其他控制只能追踪位置
case prometheus_msgs::ControlCommand::Move:
//对于机体系的指令,需要转换成ENU坐标系执行,且同一ID号内,只执行一次.
if(Command_Now.Reference_State.Move_frame != prometheus_msgs::PositionReference::ENU_FRAME && Command_Now.Command_ID > Command_Last.Command_ID )
{
Body_to_ENU();
}
break;
// 【Disarm】 上锁
case prometheus_msgs::ControlCommand::Disarm:
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Disarm: switch to MANUAL flight mode");
if(_DroneState.mode == "OFFBOARD")
{
_command_to_mavros.mode_cmd.request.custom_mode = "MANUAL";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
}
if(_DroneState.armed)
{
_command_to_mavros.arm_cmd.request.value = false;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
}
break;
// 【User_Mode1】 暂空。可进行自定义
case prometheus_msgs::ControlCommand::User_Mode1:
break;
// 【User_Mode2】 暂空。可进行自定义
case prometheus_msgs::ControlCommand::User_Mode2:
break;
}
//执行控制
if(Command_Now.Mode != prometheus_msgs::ControlCommand::Idle)
{
//选择控制器
if(controller_type == "default")
{
//轨迹追踪控制,直接改为PID控制器
if(Command_Now.Reference_State.Move_mode != prometheus_msgs::PositionReference::TRAJECTORY)
{
_ControlOutput = pos_controller_cascade_pid.pos_controller(_DroneState, Command_Now.Reference_State, dt);
}else
{
_ControlOutput = pos_controller_cascade_pid.pos_controller(_DroneState, Command_Now.Reference_State, dt);
// _ControlOutput = pos_controller_pid.pos_controller(_DroneState, Command_Now.Reference_State, dt);
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "CPID NOT SUPPOORT TRAJECTORY TRACKING.");
}
}else if(controller_type == "pid")
{
_ControlOutput = pos_controller_pid.pos_controller(_DroneState, Command_Now.Reference_State, dt);
}else if(controller_type == "passivity")
{
_ControlOutput = pos_controller_passivity.pos_controller(_DroneState, Command_Now.Reference_State, dt);
}else if(controller_type == "ude")
{
_ControlOutput = pos_controller_UDE.pos_controller(_DroneState, Command_Now.Reference_State, dt);
}else if(controller_type == "ne")
{
_ControlOutput = pos_controller_NE.pos_controller(_DroneState, Command_Now.Reference_State, dt);
}
if(Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::TRAJECTORY)
{
// 输入干扰
Eigen::Vector3d random;
// 先生成随机数
random[0] = prometheus_control_utils::random_num(disturbance_a_xy, disturbance_b_xy);
random[1] = prometheus_control_utils::random_num(disturbance_a_xy, disturbance_b_xy);
random[2] = prometheus_control_utils::random_num(disturbance_a_z, disturbance_b_z);
// 低通滤波
random[0] = LPF_x.apply(random[0], dt);
random[1] = LPF_y.apply(random[1], dt);
random[2] = LPF_z.apply(random[2], dt);
if(Command_Now.Reference_State.time_from_start>disturbance_start_time && Command_Now.Reference_State.time_from_start<disturbance_end_time)
{
//应用输入干扰信号
_ControlOutput.Throttle[0] = _ControlOutput.Throttle[0] + random[0];
_ControlOutput.Throttle[1] = _ControlOutput.Throttle[1] + random[1];
_ControlOutput.Throttle[2] = _ControlOutput.Throttle[2] + random[2];
}
}
}
throttle_sp[0] = _ControlOutput.Throttle[0];
throttle_sp[1] = _ControlOutput.Throttle[1];
throttle_sp[2] = _ControlOutput.Throttle[2];
_AttitudeReference = prometheus_control_utils::ThrottleToAttitude(throttle_sp, Command_Now.Reference_State.yaw_ref);
//发送解算得到的期望姿态角至PX4
_command_to_mavros.send_attitude_setpoint(_AttitudeReference);
//发布期望姿态
att_ref_pub.publish(_AttitudeReference);
//发布用于RVIZ显示的位姿
ref_pose_rviz = get_ref_pose_rviz(Command_Now, _AttitudeReference);
rivz_ref_pose_pub.publish(ref_pose_rviz);
//发布log消息可用rosbag记录
LogMessage.control_type = 1;
LogMessage.time = cur_time;
LogMessage.Drone_State = _DroneState;
LogMessage.Control_Command = Command_Now;
LogMessage.Control_Output = _ControlOutput;
LogMessage.Attitude_Reference = _AttitudeReference;
LogMessage.ref_pose = ref_pose_rviz;
log_message_pub.publish(LogMessage);
Command_Last = Command_Now;
rate.sleep();
}
return 0;
}
void printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>> px4_pos_controller Parameter <<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "controller_type: "<< controller_type <<endl;
cout << "Takeoff_height : "<< Takeoff_height<<" [m] "<<endl;
cout << "Disarm_height : "<< Disarm_height <<" [m] "<<endl;
cout << "Land_speed : "<< Land_speed <<" [m/s] "<<endl;
cout << "geo_fence_x : "<< geo_fence_x[0] << " [m] to "<<geo_fence_x[1] << " [m]"<< endl;
cout << "geo_fence_y : "<< geo_fence_y[0] << " [m] to "<<geo_fence_y[1] << " [m]"<< endl;
cout << "geo_fence_z : "<< geo_fence_z[0] << " [m] to "<<geo_fence_z[1] << " [m]"<< endl;
}
int check_failsafe()
{
if (_DroneState.position[0] < geo_fence_x[0] || _DroneState.position[0] > geo_fence_x[1] ||
_DroneState.position[1] < geo_fence_y[0] || _DroneState.position[1] > geo_fence_y[1] ||
_DroneState.position[2] < geo_fence_z[0] || _DroneState.position[2] > geo_fence_z[1])
{
pub_message(message_pub, prometheus_msgs::Message::ERROR, NODE_NAME, "Out of the geo fence, the drone is landing...");
return 1;
}
else{
return 0;
}
}
//【Body_to_ENU】 机体系移动。
void Body_to_ENU()
{
if( Command_Now.Reference_State.Move_mode & 0b10 )
{
//xy velocity mode
float d_vel_body[2] = {Command_Now.Reference_State.velocity_ref[0], Command_Now.Reference_State.velocity_ref[1]}; //the desired xy velocity in Body Frame
float d_vel_enu[2]; //the desired xy velocity in NED Frame
//根据无人机当前偏航角进行坐标系转换
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_vel_body, d_vel_enu);
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[0] = d_vel_enu[0];
Command_Now.Reference_State.velocity_ref[1] = d_vel_enu[1];
}
else
{
//xy position mode
float d_pos_body[2] = {Command_Now.Reference_State.position_ref[0], Command_Now.Reference_State.position_ref[1]}; //the desired xy position in Body Frame
float d_pos_enu[2]; //the desired xy position in enu Frame (The origin point is the drone)
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_pos_body, d_pos_enu);
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0] + d_pos_enu[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1] + d_pos_enu[1];
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
}
if(Command_Now.Reference_State.Move_frame == prometheus_msgs::PositionReference::MIX_FRAME)
{
Command_Now.Reference_State.position_ref[2] = Command_Now.Reference_State.position_ref[2];
//Command_Now.Reference_State.yaw_ref = Command_Now.Reference_State.yaw_ref;
}else
{
if( Command_Now.Reference_State.Move_mode & 0b01 )
{
//z velocity mode
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[2] = Command_Now.Reference_State.velocity_ref[2];
}
else
{
//z posiiton mode
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] + Command_Now.Reference_State.position_ref[2];
Command_Now.Reference_State.velocity_ref[2] = 0;
}
}
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2] + Command_Now.Reference_State.yaw_ref;
float d_acc_body[2] = {Command_Now.Reference_State.acceleration_ref[0], Command_Now.Reference_State.acceleration_ref[1]};
float d_acc_enu[2];
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_acc_body, d_acc_enu);
Command_Now.Reference_State.acceleration_ref[0] = d_acc_enu[0];
Command_Now.Reference_State.acceleration_ref[1] = d_acc_enu[1];
Command_Now.Reference_State.acceleration_ref[2] = Command_Now.Reference_State.acceleration_ref[2];
}
void add_disturbance()
{
}
geometry_msgs::PoseStamped get_ref_pose_rviz(const prometheus_msgs::ControlCommand& cmd, const prometheus_msgs::AttitudeReference& att_ref)
{
geometry_msgs::PoseStamped ref_pose;
ref_pose.header.stamp = ros::Time::now();
// world: 世界系,即gazebo坐标系,参见tf_transform.launch
ref_pose.header.frame_id = "world";
if(cmd.Mode == prometheus_msgs::ControlCommand::Idle)
{
ref_pose.pose.position.x = _DroneState.position[0];
ref_pose.pose.position.y = _DroneState.position[1];
ref_pose.pose.position.z = _DroneState.position[2];
ref_pose.pose.orientation = _DroneState.attitude_q;
}else if(cmd.Mode == prometheus_msgs::ControlCommand::Takeoff || cmd.Mode == prometheus_msgs::ControlCommand::Hold)
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
ref_pose.pose.orientation = _DroneState.attitude_q;
}else if(cmd.Mode == prometheus_msgs::ControlCommand::Disarm || cmd.Mode == prometheus_msgs::ControlCommand::Land )
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = 0.0;
ref_pose.pose.orientation = _DroneState.attitude_q;
}
else if(cmd.Mode == prometheus_msgs::ControlCommand::Move)
{
//xy速度控制
if( Command_Now.Reference_State.Move_mode & 0b10 )
{
ref_pose.pose.position.x = _DroneState.position[0] + cmd.Reference_State.velocity_ref[0] * dt;
ref_pose.pose.position.y = _DroneState.position[1] + cmd.Reference_State.velocity_ref[1] * dt;
}else
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
}
if(Command_Now.Reference_State.Move_mode & 0b01 )
{
ref_pose.pose.position.z = _DroneState.position[2] + cmd.Reference_State.velocity_ref[2] * dt;
}else
{
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
}
ref_pose.pose.orientation = att_ref.desired_att_q;
}else
{
ref_pose.pose.position.x = 0.0;
ref_pose.pose.position.y = 0.0;
ref_pose.pose.position.z = 0.0;
ref_pose.pose.orientation = _DroneState.attitude_q;
}
return ref_pose;
}

@ -0,0 +1,419 @@
/***************************************************************************************************************************
* px4_pos_estimator.cpp
*
* Author: Qyp
*
* Update Time: 2020.10.29
*
* : mavros
* 1. SLAM (cartorgrapher_ros) ,laserNED
* 2. Mocap (vrpn-client-ros) mocapNED
* 3.
* 4. 使
* 5. SLAMMocap(xyz+yaw)
*
***************************************************************************************************************************/
//头文件
#include <ros/ros.h>
#include <iostream>
#include <Eigen/Eigen>
#include "state_from_mavros.h"
#include "math_utils.h"
#include "prometheus_control_utils.h"
#include "message_utils.h"
using namespace std;
#define TRA_WINDOW 1000
#define TIMEOUT_MAX 0.05
#define NODE_NAME "pos_estimator"
//---------------------------------------相关参数-----------------------------------------------
int input_source;
float rate_hz;
Eigen::Vector3f pos_offset;
float yaw_offset;
string object_name;
ros::Time last_timestamp;
//---------------------------------------vicon定位相关------------------------------------------
Eigen::Vector3d pos_drone_mocap; //无人机当前位置 (vicon)
Eigen::Quaterniond q_mocap;
Eigen::Vector3d Euler_mocap; //无人机当前姿态 (vicon)
//---------------------------------------laser定位相关------------------------------------------
Eigen::Vector3d pos_drone_laser; //无人机当前位置 (laser)
Eigen::Quaterniond q_laser;
Eigen::Vector3d Euler_laser; //无人机当前姿态(laser)
geometry_msgs::TransformStamped laser; //当前时刻cartorgrapher发布的数据
//---------------------------------------T265------------------------------------------
Eigen::Vector3d pos_drone_t265;
Eigen::Quaterniond q_t265;
Eigen::Vector3d Euler_t265;
//---------------------------------------gazebo真值相关------------------------------------------
Eigen::Vector3d pos_drone_gazebo;
Eigen::Quaterniond q_gazebo;
Eigen::Vector3d Euler_gazebo;
//---------------------------------------SLAM相关------------------------------------------
Eigen::Vector3d pos_drone_slam;
Eigen::Quaterniond q_slam;
Eigen::Vector3d Euler_slam;
//---------------------------------------发布相关变量--------------------------------------------
ros::Publisher vision_pub;
ros::Publisher drone_state_pub;
ros::Publisher message_pub;
prometheus_msgs::Message message;
ros::Publisher odom_pub;
ros::Publisher trajectory_pub;
prometheus_msgs::DroneState Drone_State;
bool _odom_valid = false;
nav_msgs::Odometry Drone_odom;
std::vector<geometry_msgs::PoseStamped> posehistory_vector_;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>函数声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void send_to_fcu();
void pub_to_nodes(prometheus_msgs::DroneState State_from_fcu);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void laser_cb(const tf2_msgs::TFMessage::ConstPtr &msg)
{
//确定是cartographer发出来的/tf信息
//有的时候/tf这个消息的发布者不止一个
//可改成TF监听
if (msg->transforms[0].header.frame_id == "map" && msg->transforms[0].child_frame_id == "base_link" && input_source == 1)
{
laser = msg->transforms[0];
//位置 xy [将解算的位置从map坐标系转换至world坐标系]
pos_drone_laser[0] = laser.transform.translation.x + pos_offset[0];
pos_drone_laser[1] = laser.transform.translation.y + pos_offset[1];
pos_drone_laser[2] = laser.transform.translation.z + pos_offset[2];
// Read the Quaternion from the Carto Package [Frame: Laser[ENU]]
Eigen::Quaterniond q_laser_enu(laser.transform.rotation.w, laser.transform.rotation.x, laser.transform.rotation.y, laser.transform.rotation.z);
q_laser = q_laser_enu;
// Transform the Quaternion to Euler Angles
Euler_laser = quaternion_to_euler(q_laser);
// pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "test.");
//cout << "Position [X Y Z] : " << pos_drone_laser[0] << " [ m ] "<< pos_drone_laser[1]<<" [ m ] "<< pos_drone_laser[2]<<" [ m ] "<<endl;
//cout << "Euler [X Y Z] : " << Euler_laser[0] << " [m/s] "<< Euler_laser[1]<<" [m/s] "<< Euler_laser[2]<<" [m/s] "<<endl;
}
_odom_valid= true;
}
void mocap_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
//位置 -- optitrack系 到 ENU系
//Frame convention 0: Z-up -- 1: Y-up (See the configuration in the motive software)
int optitrack_frame = 0;
if (optitrack_frame == 0)
{
// Read the Drone Position from the Vrpn Package [Frame: Vicon] (Vicon to ENU frame)
pos_drone_mocap = Eigen::Vector3d(msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);
pos_drone_mocap[0] = pos_drone_mocap[0] - pos_offset[0];
pos_drone_mocap[1] = pos_drone_mocap[1] - pos_offset[1];
pos_drone_mocap[2] = pos_drone_mocap[2] - pos_offset[2];
// Read the Quaternion from the Vrpn Package [Frame: Vicon[ENU]]
q_mocap = Eigen::Quaterniond(msg->pose.orientation.w, msg->pose.orientation.x, msg->pose.orientation.y, msg->pose.orientation.z);
}
else
{
// Read the Drone Position from the Vrpn Package [Frame: Vicon] (Vicon to ENU frame)
pos_drone_mocap = Eigen::Vector3d(-msg->pose.position.x, msg->pose.position.z, msg->pose.position.y);
// Read the Quaternion from the Vrpn Package [Frame: Vicon[ENU]]
q_mocap = Eigen::Quaterniond(msg->pose.orientation.w, msg->pose.orientation.x, msg->pose.orientation.z, msg->pose.orientation.y); //Y-up convention, switch the q2 & q3
pos_drone_mocap[0] = pos_drone_mocap[0] - pos_offset[0];
pos_drone_mocap[1] = pos_drone_mocap[1] - pos_offset[1];
pos_drone_mocap[2] = pos_drone_mocap[2] - pos_offset[2];
}
// Transform the Quaternion to Euler Angles
Euler_mocap = quaternion_to_euler(q_mocap);
_odom_valid= true;
last_timestamp = msg->header.stamp;
}
void gazebo_cb(const nav_msgs::Odometry::ConstPtr &msg)
{
if (msg->header.frame_id == "world")
{
pos_drone_gazebo = Eigen::Vector3d(msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z);
q_gazebo = Eigen::Quaterniond(msg->pose.pose.orientation.w, msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z);
Euler_gazebo = quaternion_to_euler(q_gazebo);
// Euler_gazebo[2] = Euler_gazebo[2] + yaw_offset;
// q_gazebo = quaternion_from_rpy(Euler_gazebo);
}
else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "wrong gazebo ground truth frame id.");
}
_odom_valid= true;
}
void slam_cb(const geometry_msgs::PoseStamped::ConstPtr &msg)
{
if (msg->header.frame_id == "map_slam")
{
pos_drone_slam = Eigen::Vector3d(msg->pose.position.x, msg->pose.position.y, msg->pose.position.z);
// pos_drone_gazebo[0] = msg->pose.pose.position.x + pos_offset[0];
// pos_drone_gazebo[1] = msg->pose.pose.position.y + pos_offset[1];
// pos_drone_gazebo[2] = msg->pose.pose.position.z + pos_offset[2];
q_slam = Eigen::Quaterniond(msg->pose.orientation.w, msg->pose.orientation.x, msg->pose.orientation.y, msg->pose.orientation.z);
Euler_slam = quaternion_to_euler(q_slam);
// Euler_gazebo[2] = Euler_gazebo[2] + yaw_offset;
// q_gazebo = quaternion_from_rpy(Euler_gazebo);
}
else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "wrong slam frame id.");
}
_odom_valid= true;
}
void t265_cb(const nav_msgs::Odometry::ConstPtr &msg)
{
if (msg->header.frame_id == "t265_odom_frame")
{
pos_drone_t265 = Eigen::Vector3d(msg->pose.pose.position.x, msg->pose.pose.position.y, msg->pose.pose.position.z);
// pos_drone_t265[0] = msg->pose.pose.position.x + pos_offset[0];
// pos_drone_t265[1] = msg->pose.pose.position.y + pos_offset[1];
// pos_drone_t265[2] = msg->pose.pose.position.z + pos_offset[2];
q_t265 = Eigen::Quaterniond(msg->pose.pose.orientation.w, msg->pose.pose.orientation.x, msg->pose.pose.orientation.y, msg->pose.pose.orientation.z);
Euler_t265 = quaternion_to_euler(q_gazebo);
// Euler_t265[2] = Euler_t265[2] + yaw_offset;
// q_t265 = quaternion_from_rpy(Euler_t265);
}
else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "wrong t265 frame id.");
}
_odom_valid= true;
}
void timerCallback(const ros::TimerEvent &e)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Program is running.");
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_pos_estimator");
ros::NodeHandle nh("~");
//读取参数表中的参数
// 定位数据输入源 0 for vicon 1 for 激光SLAM, 2 for gazebo ground truth, 3 for T265 , 9 for outdoor
nh.param<int>("input_source", input_source, 0);
// 动作捕捉设备中设定的刚体名字
nh.param<string>("object_name", object_name, "UAV");
// 程序执行频率
nh.param<float>("rate_hz", rate_hz, 20);
// 定位设备偏移量
nh.param<float>("offset_x", pos_offset[0], 0);
nh.param<float>("offset_y", pos_offset[1], 0);
nh.param<float>("offset_z", pos_offset[2], 0);
nh.param<float>("offset_yaw", yaw_offset, 0);
// 【订阅】cartographer估计位置
ros::Subscriber laser_sub = nh.subscribe<tf2_msgs::TFMessage>("/tf", 100, laser_cb);
// 【订阅】t265估计位置
ros::Subscriber t265_sub = nh.subscribe<nav_msgs::Odometry>("/t265/odom/sample", 100, t265_cb);
// 【订阅】optitrack估计位置
ros::Subscriber optitrack_sub = nh.subscribe<geometry_msgs::PoseStamped>("/vrpn_client_node/"+ object_name + "/pose", 100, mocap_cb);
// 【订阅】gazebo仿真真值
ros::Subscriber gazebo_sub = nh.subscribe<nav_msgs::Odometry>("/prometheus/ground_truth/p300_basic", 100, gazebo_cb);
// 【订阅】SLAM估计位姿
ros::Subscriber slam_sub = nh.subscribe<geometry_msgs::PoseStamped>("/slam/pose", 100, slam_cb);
// 【发布】无人机位置和偏航角 坐标系 ENU系
// 本话题要发送飞控(通过mavros_extras/src/plugins/vision_pose_estimate.cpp发送), 对应Mavlink消息为VISION_POSITION_ESTIMATE(#102), 对应的飞控中的uORB消息为vehicle_vision_position.msg 及 vehicle_vision_attitude.msg
vision_pub = nh.advertise<geometry_msgs::PoseStamped>("/mavros/vision_pose/pose", 10);
// 【发布】无人机状态量
drone_state_pub = nh.advertise<prometheus_msgs::DroneState>("/prometheus/drone_state", 10);
// 【发布】无人机odometry用于RVIZ显示
odom_pub = nh.advertise<nav_msgs::Odometry>("/prometheus/drone_odom", 10);
// 【发布】无人机移动轨迹用于RVIZ显示
trajectory_pub = nh.advertise<nav_msgs::Path>("/prometheus/drone_trajectory", 10);
// 【发布】提示消息
message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
// 10秒定时打印以确保程序在正确运行
ros::Timer timer = nh.createTimer(ros::Duration(10.0), timerCallback);
// 用于与mavros通讯的类通过mavros接收来至飞控的消息【飞控->mavros->本程序】
state_from_mavros _state_from_mavros;
// 频率
ros::Rate rate(rate_hz);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Main Loop<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while (ros::ok())
{
//回调一次 更新传感器状态
ros::spinOnce();
// 将采集的机载设备的定位信息及偏航角信息发送至飞控根据参数input_source选择定位信息来源
send_to_fcu();
// 发布无人机状态至其他节点如px4_pos_controller.cpp节点
pub_to_nodes(_state_from_mavros._DroneState);
rate.sleep();
}
return 0;
}
void send_to_fcu()
{
geometry_msgs::PoseStamped vision;
//vicon
if (input_source == 0)
{
vision.pose.position.x = pos_drone_mocap[0];
vision.pose.position.y = pos_drone_mocap[1];
vision.pose.position.z = pos_drone_mocap[2];
vision.pose.orientation.x = q_mocap.x();
vision.pose.orientation.y = q_mocap.y();
vision.pose.orientation.z = q_mocap.z();
vision.pose.orientation.w = q_mocap.w();
// 此处时间主要用于监测动捕T265设备是否正常工作
if( prometheus_control_utils::get_time_in_sec(last_timestamp) > TIMEOUT_MAX)
{
_odom_valid= false;
pub_message(message_pub, prometheus_msgs::Message::ERROR, NODE_NAME, "Mocap Timeout.");
}
} //laser
else if (input_source == 1)
{
vision.pose.position.x = pos_drone_laser[0];
vision.pose.position.y = pos_drone_laser[1];
vision.pose.position.z = pos_drone_laser[2];
//目前为二维雷达仿真情况故z轴使用其他来源
vision.pose.position.z = pos_drone_gazebo[2];
vision.pose.orientation.x = q_laser.x();
vision.pose.orientation.y = q_laser.y();
vision.pose.orientation.z = q_laser.z();
vision.pose.orientation.w = q_laser.w();
}
else if (input_source == 2)
{
vision.pose.position.x = pos_drone_gazebo[0];
vision.pose.position.y = pos_drone_gazebo[1];
vision.pose.position.z = pos_drone_gazebo[2];
vision.pose.orientation.x = q_gazebo.x();
vision.pose.orientation.y = q_gazebo.y();
vision.pose.orientation.z = q_gazebo.z();
vision.pose.orientation.w = q_gazebo.w();
}
else if (input_source == 3)
{
vision.pose.position.x = pos_drone_t265[0];
vision.pose.position.y = pos_drone_t265[1];
vision.pose.position.z = pos_drone_t265[2];
vision.pose.orientation.x = q_t265.x();
vision.pose.orientation.y = q_t265.y();
vision.pose.orientation.z = q_t265.z();
vision.pose.orientation.w = q_t265.w();
}
else if (input_source == 4)
{
vision.pose.position.x = pos_drone_slam[0];
vision.pose.position.y = pos_drone_slam[1];
vision.pose.position.z = pos_drone_slam[2];
vision.pose.orientation.x = q_slam.x();
vision.pose.orientation.y = q_slam.y();
vision.pose.orientation.z = q_slam.z();
vision.pose.orientation.w = q_slam.w();
}
vision.header.stamp = ros::Time::now();
vision_pub.publish(vision);
}
void pub_to_nodes(prometheus_msgs::DroneState State_from_fcu)
{
// 发布无人机状态,具体内容参见 prometheus_msgs::DroneState
Drone_State = State_from_fcu;
Drone_State.odom_valid= _odom_valid;
Drone_State.header.stamp = ros::Time::now();
// 户外情况,使用相对高度
if(input_source == 9 )
{
// FIXME rel_alt?
// Drone_State.position[2] = Drone_State.rel_alt;
_odom_valid= true;
}
drone_state_pub.publish(Drone_State);
// 发布无人机当前odometry,用于导航及rviz显示
nav_msgs::Odometry Drone_odom;
Drone_odom.header.stamp = ros::Time::now();
Drone_odom.header.frame_id = "world";
Drone_odom.child_frame_id = "base_link";
Drone_odom.pose.pose.position.x = Drone_State.position[0];
Drone_odom.pose.pose.position.y = Drone_State.position[1];
Drone_odom.pose.pose.position.z = Drone_State.position[2];
// 导航算法规定 高度不能小于0
if (Drone_odom.pose.pose.position.z <= 0)
{
Drone_odom.pose.pose.position.z = 0.01;
}
Drone_odom.pose.pose.orientation = Drone_State.attitude_q;
Drone_odom.twist.twist.linear.x = Drone_State.velocity[0];
Drone_odom.twist.twist.linear.y = Drone_State.velocity[1];
Drone_odom.twist.twist.linear.z = Drone_State.velocity[2];
odom_pub.publish(Drone_odom);
// 发布无人机运动轨迹用于rviz显示
geometry_msgs::PoseStamped drone_pos;
drone_pos.header.stamp = ros::Time::now();
drone_pos.header.frame_id = "world";
drone_pos.pose.position.x = Drone_State.position[0];
drone_pos.pose.position.y = Drone_State.position[1];
drone_pos.pose.position.z = Drone_State.position[2];
drone_pos.pose.orientation = Drone_State.attitude_q;
//发布无人机的位姿 和 轨迹 用作rviz中显示
posehistory_vector_.insert(posehistory_vector_.begin(), drone_pos);
if (posehistory_vector_.size() > TRA_WINDOW)
{
posehistory_vector_.pop_back();
}
nav_msgs::Path drone_trajectory;
drone_trajectory.header.stamp = ros::Time::now();
drone_trajectory.header.frame_id = "world";
drone_trajectory.poses = posehistory_vector_;
trajectory_pub.publish(drone_trajectory);
}

@ -0,0 +1,701 @@
/***************************************************************************************************************************
* px4_sender.cpp
*
* Author: Qyp
*
* Update Time: 2020.10.18
*
* Introduction: PX4 command sender using px4 default command
* 1. Subscribe command.msg from upper nodes
* 2. Subscribe drone_state msg from px4_pos_estimator.cpp
* 2. Send command using command_to_mavros.h
* 3. Command includes: (1)idle
* (2)takeoff
* (3)land
* (4)hold
* (5)disarm
* (6)move:
* 1. xyz_pos + yaw in ENU/Body frame
* 2. xyz_vel + yaw in ENU/Body frame
* 3. xy_vel_z_pos + yaw in ENU/Body frame
* 4. xyz_acc + yaw in ENU/Body frame
* 5. trajectory 使
***************************************************************************************************************************/
#include <ros/ros.h>
#include "state_from_mavros.h"
#include "command_to_mavros.h"
#include "prometheus_control_utils.h"
#include "message_utils.h"
#include "control_common.h"
#include "printf_utils.h"
#include "prometheus_station_utils.h"
#define NODE_NAME "px4_sender"
using namespace std;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>变量声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
float cur_time; //程序运行时间
float Takeoff_height; //默认起飞高度
float Disarm_height; //自动上锁高度
float Land_speed; //降落速度
int Land_mode; //降落策略选择
bool quick_land = false;
//Geigraphical fence 地理围栏
Eigen::Vector2f geo_fence_x;
Eigen::Vector2f geo_fence_y;
Eigen::Vector2f geo_fence_z;
Eigen::Vector3d Takeoff_position; // 起飞位置
prometheus_msgs::DroneState _DroneState; //无人机状态量
prometheus_msgs::ControlCommand Command_Now; //无人机当前执行命令
prometheus_msgs::ControlCommand Command_Last; //无人机上一条执行命令
Eigen::Vector3d state_sp(0,0,0);
Eigen::Vector3d state_sp_extra(0,0,0);
double yaw_sp;
double yaw_rate_sp;
prometheus_msgs::Message message;
prometheus_msgs::LogMessageControl LogMessage;
//RVIZ显示期望位置
geometry_msgs::PoseStamped ref_pose_rviz;
float dt = 0;
ros::Publisher rivz_ref_pose_pub;
ros::Publisher message_pub;
ros::Publisher log_message_pub;
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>函数声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void printf_param();
int check_failsafe();
geometry_msgs::PoseStamped get_rviz_ref_posistion(const prometheus_msgs::ControlCommand& cmd);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
void Command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
// CommandID必须递增才会被记录
if( msg->Command_ID > Command_Now.Command_ID )
{
Command_Now = *msg;
}else
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Wrong Command ID.");
}
// 无人机一旦接受到Disarm指令则会屏蔽其他指令
if(Command_Last.Mode == prometheus_msgs::ControlCommand::Disarm)
{
Command_Now = Command_Last;
}
}
void station_command_cb(const prometheus_msgs::ControlCommand::ConstPtr& msg)
{
Command_Now = *msg;
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Get a command from Prometheus Station.");
// 无人机一旦接受到Disarm指令则会屏蔽其他指令
if(Command_Last.Mode == prometheus_msgs::ControlCommand::Disarm)
{
Command_Now = Command_Last;
}
}
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
{
_DroneState = *msg;
_DroneState.time_from_start = cur_time;
}
void timerCallback(const ros::TimerEvent& e)
{
cout << GREEN <<">>>>>>>>>>>>>>>>>>>>>>>> PX4 SENDER <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << TAIL <<endl;
//固定的浮点显示
cout.setf(ios::fixed);
//setprecision(n) 设显示小数精度为n位
cout<<setprecision(2);
//左对齐
cout.setf(ios::left);
// 强制显示小数点
cout.setf(ios::showpoint);
// 强制显示符号
cout.setf(ios::showpos);
// 【打印】无人机状态,包括位置,速度等数据信息
prometheus_station_utils::prinft_drone_state(_DroneState);
// 【打印】来自上层的控制指令
prometheus_station_utils::printf_command_control(Command_Now);
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
int main(int argc, char **argv)
{
ros::init(argc, argv, "px4_sender");
ros::NodeHandle nh("~");
//【订阅】指令
// 本话题为任务模块生成的控制指令
ros::Subscriber Command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10, Command_cb);
//【订阅】指令
// 本话题为Prometheus地面站发送的控制指令
ros::Subscriber station_command_sub = nh.subscribe<prometheus_msgs::ControlCommand>("/prometheus/control_command_station", 10, station_command_cb);
//【订阅】无人机状态
// 本话题来自px4_pos_estimator.cpp
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
//【发布】参考位姿 RVIZ显示用
rivz_ref_pose_pub = nh.advertise<geometry_msgs::PoseStamped>("/prometheus/control/ref_pose_rviz", 10);
// 【发布】用于地面站显示的提示消息
message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
// 【发布】用于log的消息
log_message_pub = nh.advertise<prometheus_msgs::LogMessageControl>("/prometheus/log/control", 10);
// 10秒定时打印以确保程序在正确运行
ros::Timer timer = nh.createTimer(ros::Duration(10.0), timerCallback);
// 参数读取
nh.param<float>("Takeoff_height", Takeoff_height, 1.0);
nh.param<float>("Disarm_height", Disarm_height, 0.15);
nh.param<float>("Land_speed", Land_speed, 0.2);
nh.param<int>("Land_mode",Land_mode,0);
nh.param<float>("geo_fence/x_min", geo_fence_x[0], -100.0);
nh.param<float>("geo_fence/x_max", geo_fence_x[1], 100.0);
nh.param<float>("geo_fence/y_min", geo_fence_y[0], -100.0);
nh.param<float>("geo_fence/y_max", geo_fence_y[1], 100.0);
nh.param<float>("geo_fence/z_min", geo_fence_z[0], -100.0);
nh.param<float>("geo_fence/z_max", geo_fence_z[1], 100.0);
// 设定起飞位置
Takeoff_position[0] = 0.0;
Takeoff_position[1] = 0.0;
Takeoff_position[2] = 0.15;
// 建议控制频率 10 - 50Hz, 控制频率取决于控制形式,若控制方式为速度或加速度应适当提高频率
ros::Rate rate(20.0);
// 用于与mavros通讯的类通过mavros发送控制指令至飞控【本程序->mavros->飞控】
command_to_mavros _command_to_mavros;
printf_param();
// 初始化命令-
// 默认设置Idle模式 电机怠速旋转 等待来自上层的控制指令
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
Command_Now.Command_ID = 0;
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.position_ref[2] = 0;
Command_Now.Reference_State.velocity_ref[0] = 0;
Command_Now.Reference_State.velocity_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[2] = 0;
Command_Now.Reference_State.acceleration_ref[0] = 0;
Command_Now.Reference_State.acceleration_ref[1] = 0;
Command_Now.Reference_State.acceleration_ref[2] = 0;
Command_Now.Reference_State.yaw_ref = 0;
// 记录启控时间
ros::Time begin_time = ros::Time::now();
float last_time = prometheus_control_utils::get_time_in_sec(begin_time);
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 循 环<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
while(ros::ok())
{
// 当前时间
cur_time = prometheus_control_utils::get_time_in_sec(begin_time);
dt = cur_time - last_time;
dt = constrain_function2(dt, 0.02, 0.1);
last_time = cur_time;
// 执行回调函数
ros::spinOnce();
// Check for geo fence: If drone is out of the geo fence, it will land now.
if(Command_Now.Mode !=prometheus_msgs::ControlCommand::Idle )
{
int safety_flag = check_failsafe();
if(safety_flag == 1)
{
Command_Now.Mode = prometheus_msgs::ControlCommand::Land;
}else if(safety_flag == 2)
{
// 快速降落
Land_speed = 0.8;
quick_land = true;
Command_Now.Mode = prometheus_msgs::ControlCommand::Land;
}
}
switch (Command_Now.Mode)
{
// 【Idle】 怠速旋转此时可以切入offboard模式但不会起飞。
case prometheus_msgs::ControlCommand::Idle:
_command_to_mavros.idle();
// 设定yaw_ref=999时切换offboard模式并解锁
if(Command_Now.Reference_State.yaw_ref == 999)
{
if(_DroneState.mode != "OFFBOARD")
{
_command_to_mavros.mode_cmd.request.custom_mode = "OFFBOARD";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Setting to OFFBOARD Mode...");
}else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "The Drone is in OFFBOARD Mode already...");
}
if(!_DroneState.armed)
{
_command_to_mavros.arm_cmd.request.value = true;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Arming...");
}else
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "The Drone is armd already...");
}
}
break;
// 【Takeoff】 从摆放初始位置原地起飞至指定高度,偏航角也保持当前角度
case prometheus_msgs::ControlCommand::Takeoff:
// 不能多次起飞!
// 此处起飞有一个bug则是飞机起飞会有很严重的超调没发现具体导致的因素
// 设定起飞点
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Takeoff)
{
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Takeoff to the desired point.");
// 设定起飞位置
Takeoff_position[0] = _DroneState.position[0];
Takeoff_position[1] = _DroneState.position[1];
Takeoff_position[2] = _DroneState.position[2];
//
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = Takeoff_position[0];
Command_Now.Reference_State.position_ref[1] = Takeoff_position[1];
Command_Now.Reference_State.position_ref[2] = Takeoff_position[2] + Takeoff_height;
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2];
state_sp = Eigen::Vector3d(Takeoff_position[0],Takeoff_position[1],Takeoff_position[2] + Takeoff_height);
yaw_sp = _DroneState.attitude[2]; //rad
}
_command_to_mavros.send_pos_setpoint(state_sp, yaw_sp);
//_command_to_mavros.takeoff(); 无用,未知原因
break;
// 【Hold】 悬停。当前位置悬停
case prometheus_msgs::ControlCommand::Hold:
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Hold)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2];
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
state_sp = Eigen::Vector3d(_DroneState.position[0],_DroneState.position[1],_DroneState.position[2]);
yaw_sp = _DroneState.attitude[2]; //rad
}
_command_to_mavros.send_pos_setpoint(state_sp, yaw_sp);
//_command_to_mavros.loiter(); 可用,但不启用
break;
// 【Land】 降落。两种降落方式: 只有加载了参数Land_mode为1时启用第二种降落方式默认启用第一种降落方式。
// 第一种当前位置原地降落降落后会自动上锁且切换为mannual模式
// 第二种当前位置原地降落降落中到达Disarm_height后切换为飞控中land模式
case prometheus_msgs::ControlCommand::Land:
if(quick_land)
{
// 紧急降落
state_sp << 0.0, 0.0, -Land_speed;
yaw_sp = _DroneState.attitude[2]; //rad
_command_to_mavros.send_vel_setpoint(state_sp,yaw_sp);
}else if(Land_mode == 1)
{
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Land)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XY_POS_Z_VEL;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
}
//如果距离起飞高度小于30厘米则直接切换为land模式
if(_DroneState.position[2] <= Disarm_height)
{
if(_DroneState.mode != "AUTO.LAND") // 无效
{
//此处切换会manual模式是因为:PX4默认在offboard模式且有控制的情况下没法上锁,直接使用飞控中的land模式
_command_to_mavros.mode_cmd.request.custom_mode = "AUTO.LAND";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "LAND: inter AUTO LAND filght mode");
}
}
else if(_DroneState.position[2] > Disarm_height)
{
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] - Land_speed * dt ;
Command_Now.Reference_State.velocity_ref[0] = 0.0;
Command_Now.Reference_State.velocity_ref[1] = 0.0;
Command_Now.Reference_State.velocity_ref[2] = - Land_speed; //Land_speed
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
state_sp_extra = Eigen::Vector3d(0.0,0.0,Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = _DroneState.attitude[2];
_command_to_mavros.send_pos_vel_xyz_setpoint(state_sp,state_sp_extra,yaw_sp);
}
if(_DroneState.landed)
{
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
}
}else{
if (Command_Last.Mode != prometheus_msgs::ControlCommand::Land)
{
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS;
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1];
Command_Now.Reference_State.yaw_ref = _DroneState.attitude[2]; //rad
}
if(_DroneState.position[2] > Disarm_height)
{
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] - Land_speed * dt ;
Command_Now.Reference_State.velocity_ref[0] = 0.0;
Command_Now.Reference_State.velocity_ref[1] = 0.0;
Command_Now.Reference_State.velocity_ref[2] = - Land_speed; //Land_speed
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1], Command_Now.Reference_State.position_ref[2] );
state_sp_extra = Eigen::Vector3d(0.0, 0.0 , Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
_command_to_mavros.send_pos_vel_xyz_setpoint(state_sp, state_sp_extra, yaw_sp);
}else
{
//此处切换会manual模式是因为:PX4默认在offboard模式且有控制的情况下没法上锁,直接使用飞控中的land模式
_command_to_mavros.mode_cmd.request.custom_mode = "MANUAL";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
_command_to_mavros.arm_cmd.request.value = false;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Disarming...");
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "LAND: switch to MANUAL filght mode");
}
}
break;
case prometheus_msgs::ControlCommand::Move:
// PX4暂不支持轨迹模式
// PX4暂不支持位置速度复合模式详细见mavlink_receiver.cpp
if(Command_Now.Reference_State.Move_frame == prometheus_msgs::PositionReference::ENU_FRAME)
{
if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_POS )
{
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_VEL )
{
state_sp = Eigen::Vector3d(Command_Now.Reference_State.velocity_ref[0],Command_Now.Reference_State.velocity_ref[1],Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_VEL_Z_POS )
{
state_sp = Eigen::Vector3d(Command_Now.Reference_State.velocity_ref[0],Command_Now.Reference_State.velocity_ref[1],Command_Now.Reference_State.position_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_POS_Z_VEL )
{
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] + Command_Now.Reference_State.velocity_ref[2] * dt;
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
state_sp_extra = Eigen::Vector3d(0.0, 0.0 ,Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
}else if ( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_ACC )
{
state_sp = Eigen::Vector3d(Command_Now.Reference_State.acceleration_ref[0],Command_Now.Reference_State.acceleration_ref[1],Command_Now.Reference_State.acceleration_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
}
}else
{
if( Command_Now.Command_ID > Command_Last.Command_ID)
{
if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_POS )
{
float d_pos_body[2] = {Command_Now.Reference_State.position_ref[0], Command_Now.Reference_State.position_ref[1]}; //the desired xy position in Body Frame
float d_pos_enu[2]; //the desired xy position in enu Frame (The origin point is the drone)
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_pos_body, d_pos_enu);
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0] + d_pos_enu[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1] + d_pos_enu[1];
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] + Command_Now.Reference_State.position_ref[2];
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
yaw_sp = _DroneState.attitude[2] + Command_Now.Reference_State.yaw_ref;
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_VEL )
{
//xy velocity mode
float d_vel_body[2] = {Command_Now.Reference_State.velocity_ref[0], Command_Now.Reference_State.velocity_ref[1]}; //the desired xy velocity in Body Frame
float d_vel_enu[2]; //the desired xy velocity in NED Frame
//根据无人机当前偏航角进行坐标系转换
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_vel_body, d_vel_enu);
Command_Now.Reference_State.velocity_ref[0] = d_vel_enu[0];
Command_Now.Reference_State.velocity_ref[1] = d_vel_enu[1];
state_sp = Eigen::Vector3d(Command_Now.Reference_State.velocity_ref[0],Command_Now.Reference_State.velocity_ref[1],Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = _DroneState.attitude[2] + Command_Now.Reference_State.yaw_ref;
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_VEL_Z_POS )
{
//xy velocity mode
float d_vel_body[2] = {Command_Now.Reference_State.velocity_ref[0], Command_Now.Reference_State.velocity_ref[1]}; //the desired xy velocity in Body Frame
float d_vel_enu[2]; //the desired xy velocity in NED Frame
//根据无人机当前偏航角进行坐标系转换
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_vel_body, d_vel_enu);
Command_Now.Reference_State.position_ref[0] = 0;
Command_Now.Reference_State.position_ref[1] = 0;
Command_Now.Reference_State.velocity_ref[0] = d_vel_enu[0];
Command_Now.Reference_State.velocity_ref[1] = d_vel_enu[1];
Command_Now.Reference_State.velocity_ref[2] = 0.0;
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] + Command_Now.Reference_State.position_ref[2];
// 高度锁定为给定值 2021.3.24 云台追踪控制修改
state_sp = Eigen::Vector3d(Command_Now.Reference_State.velocity_ref[0],Command_Now.Reference_State.velocity_ref[1],Command_Now.Reference_State.position_ref[2]);
if(Command_Now.Reference_State.Move_frame == prometheus_msgs::PositionReference::MIX_FRAME)
{
// 2021.6.30 for color_line_following
yaw_sp = _DroneState.attitude[2] + Command_Now.Reference_State.yaw_ref;
}else
{
// 偏航角更新为锁定 2021.3.24 云台追踪控制修改
yaw_sp = Command_Now.Reference_State.yaw_ref + _DroneState.attitude[2] ;
}
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_POS_Z_VEL )
{
float d_pos_body[2] = {Command_Now.Reference_State.position_ref[0], Command_Now.Reference_State.position_ref[1]}; //the desired xy position in Body Frame
float d_pos_enu[2]; //the desired xy position in enu Frame (The origin point is the drone)
prometheus_control_utils::rotation_yaw(_DroneState.attitude[2], d_pos_body, d_pos_enu);
Command_Now.Reference_State.position_ref[0] = _DroneState.position[0] + d_pos_enu[0];
Command_Now.Reference_State.position_ref[1] = _DroneState.position[1] + d_pos_enu[1];
Command_Now.Reference_State.position_ref[2] = _DroneState.position[2] + Command_Now.Reference_State.velocity_ref[2] * dt;
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
state_sp_extra = Eigen::Vector3d(0.0, 0.0 ,Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = _DroneState.attitude[2] + Command_Now.Reference_State.yaw_ref;
}else if ( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_ACC )
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Not Defined. Change to ENU frame");
}
}
}
if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_POS )
{
_command_to_mavros.send_pos_setpoint(state_sp, yaw_sp);
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_VEL )
{
if(Command_Now.Reference_State.Yaw_Rate_Mode)
{
yaw_rate_sp = Command_Now.Reference_State.yaw_rate_ref;
_command_to_mavros.send_vel_setpoint_yaw_rate(state_sp, yaw_rate_sp);
}else
{
_command_to_mavros.send_vel_setpoint(state_sp, yaw_sp);
}
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_VEL_Z_POS )
{
if(Command_Now.Reference_State.Yaw_Rate_Mode)
{
yaw_rate_sp = Command_Now.Reference_State.yaw_rate_ref;
_command_to_mavros.send_vel_xy_pos_z_setpoint_yawrate(state_sp, yaw_rate_sp);
}else
{
_command_to_mavros.send_vel_xy_pos_z_setpoint(state_sp, yaw_sp);
}
}else if ( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_POS_Z_VEL )
{
// 特殊情况,一般也用不到
_command_to_mavros.send_pos_vel_xyz_setpoint(state_sp, state_sp_extra, yaw_sp);
}else if ( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_ACC )
{
_command_to_mavros.send_acc_xyz_setpoint(state_sp, yaw_sp);
}else if ( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::TRAJECTORY )
{
state_sp = Eigen::Vector3d(Command_Now.Reference_State.position_ref[0],Command_Now.Reference_State.position_ref[1],Command_Now.Reference_State.position_ref[2]);
state_sp_extra = Eigen::Vector3d(Command_Now.Reference_State.velocity_ref[0], Command_Now.Reference_State.velocity_ref[1] ,Command_Now.Reference_State.velocity_ref[2]);
yaw_sp = Command_Now.Reference_State.yaw_ref;
_command_to_mavros.send_pos_vel_xyz_setpoint(state_sp, state_sp_extra,yaw_sp);
}else
{
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Not Defined. Hold there");
_command_to_mavros.loiter();
}
break;
// 【Disarm】 上锁
case prometheus_msgs::ControlCommand::Disarm:
pub_message(message_pub, prometheus_msgs::Message::WARN, NODE_NAME, "Disarm: switch to MANUAL flight mode");
if(_DroneState.mode == "OFFBOARD")
{
_command_to_mavros.mode_cmd.request.custom_mode = "MANUAL";
_command_to_mavros.set_mode_client.call(_command_to_mavros.mode_cmd);
}
if(_DroneState.armed)
{
_command_to_mavros.arm_cmd.request.value = false;
_command_to_mavros.arming_client.call(_command_to_mavros.arm_cmd);
}
break;
// 【User_Mode1】 暂空。可进行自定义
case prometheus_msgs::ControlCommand::User_Mode1:
break;
// 【User_Mode2】 暂空。可进行自定义
case prometheus_msgs::ControlCommand::User_Mode2:
break;
}
//发布用于RVIZ显示的位姿
ref_pose_rviz = get_rviz_ref_posistion(Command_Now);
rivz_ref_pose_pub.publish(ref_pose_rviz);
//发布log消息可用rosbag记录
LogMessage.control_type = PX4_SENDER;
LogMessage.time = cur_time;
LogMessage.Drone_State = _DroneState;
LogMessage.Control_Command = Command_Now;
LogMessage.ref_pose = ref_pose_rviz;
log_message_pub.publish(LogMessage);
Command_Last = Command_Now;
rate.sleep();
}
return 0;
}
void printf_param()
{
cout <<">>>>>>>>>>>>>>>>>>>>>>>> px4_sender Parameter <<<<<<<<<<<<<<<<<<<<<<" <<endl;
cout << "Takeoff_height : "<< Takeoff_height<<" [m] "<<endl;
cout << "Disarm_height : "<< Disarm_height <<" [m] "<<endl;
cout << "Land_speed : "<< Land_speed <<" [m/s] "<<endl;
cout << "Land_mode : "<< Land_mode << endl;
cout << "geo_fence_x : "<< geo_fence_x[0] << " [m] to "<<geo_fence_x[1] << " [m]"<< endl;
cout << "geo_fence_y : "<< geo_fence_y[0] << " [m] to "<<geo_fence_y[1] << " [m]"<< endl;
cout << "geo_fence_z : "<< geo_fence_z[0] << " [m] to "<<geo_fence_z[1] << " [m]"<< endl;
}
int check_failsafe()
{
if (_DroneState.position[0] < geo_fence_x[0] || _DroneState.position[0] > geo_fence_x[1] ||
_DroneState.position[1] < geo_fence_y[0] || _DroneState.position[1] > geo_fence_y[1] ||
_DroneState.position[2] < geo_fence_z[0] || _DroneState.position[2] > geo_fence_z[1])
{
cout << RED <<":----> Out of the geo fence, the drone is landing..."<< TAIL << endl;
return 1;
}else if(!_DroneState.odom_valid)
{
cout << RED <<":----> Mocap valid..., land quickly!"<< TAIL << endl;
return 2;
}
else{
return 0;
}
}
geometry_msgs::PoseStamped get_rviz_ref_posistion(const prometheus_msgs::ControlCommand& cmd)
{
geometry_msgs::PoseStamped ref_pose;
ref_pose.header.stamp = ros::Time::now();
// world: 世界系,即gazebo坐标系,参见tf_transform.launch
ref_pose.header.frame_id = "world";
if(cmd.Mode == prometheus_msgs::ControlCommand::Idle)
{
ref_pose.pose.position.x = _DroneState.position[0];
ref_pose.pose.position.y = _DroneState.position[1];
ref_pose.pose.position.z = _DroneState.position[2];
ref_pose.pose.orientation = _DroneState.attitude_q;
}else if(cmd.Mode == prometheus_msgs::ControlCommand::Takeoff || cmd.Mode == prometheus_msgs::ControlCommand::Hold)
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
ref_pose.pose.orientation = _DroneState.attitude_q;
}else if(cmd.Mode == prometheus_msgs::ControlCommand::Disarm || cmd.Mode == prometheus_msgs::ControlCommand::Land )
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = 0.0;
ref_pose.pose.orientation = _DroneState.attitude_q;
}
else if(cmd.Mode == prometheus_msgs::ControlCommand::Move)
{
if( cmd.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_POS )
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_VEL )
{
ref_pose.pose.position.x = _DroneState.position[0] + cmd.Reference_State.velocity_ref[0] * dt;
ref_pose.pose.position.y = _DroneState.position[1] + cmd.Reference_State.velocity_ref[1] * dt;
ref_pose.pose.position.z = _DroneState.position[2] + cmd.Reference_State.velocity_ref[2] * dt;
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_VEL_Z_POS )
{
ref_pose.pose.position.x = _DroneState.position[0] + cmd.Reference_State.velocity_ref[0] * dt;
ref_pose.pose.position.y = _DroneState.position[1] + cmd.Reference_State.velocity_ref[1] * dt;
ref_pose.pose.position.z = cmd.Reference_State.position_ref[2];
}else if( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XY_POS_Z_VEL )
{
ref_pose.pose.position.x = cmd.Reference_State.position_ref[0];
ref_pose.pose.position.y = cmd.Reference_State.position_ref[1];
ref_pose.pose.position.z = _DroneState.position[2] + cmd.Reference_State.velocity_ref[2] * dt;
}else if ( Command_Now.Reference_State.Move_mode == prometheus_msgs::PositionReference::XYZ_ACC )
{
ref_pose.pose.position.x = _DroneState.position[0] + 0.5 * cmd.Reference_State.acceleration_ref[0] * dt * dt;
ref_pose.pose.position.y = _DroneState.position[1] + 0.5 * cmd.Reference_State.acceleration_ref[1] * dt * dt;
ref_pose.pose.position.z = _DroneState.position[2] + 0.5 * cmd.Reference_State.acceleration_ref[2] * dt * dt;
}
ref_pose.pose.orientation = _DroneState.attitude_q;
}else
{
ref_pose.pose.position.x = 0.0;
ref_pose.pose.position.y = 0.0;
ref_pose.pose.position.z = 0.0;
ref_pose.pose.orientation = _DroneState.attitude_q;
}
return ref_pose;
}

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save