parent
c29be1d4ff
commit
9b1df5d91c
@ -0,0 +1 @@
|
||||
Subproject commit 0968058b546193d2d2d0ce66de1b4bed36f369d1
|
@ -1,11 +0,0 @@
|
||||
#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
|
@ -1,208 +0,0 @@
|
||||
#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
|
@ -1,44 +0,0 @@
|
||||
/***************************************************************************************************************************
|
||||
* 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
|
@ -1,88 +0,0 @@
|
||||
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
|
||||
)
|
@ -1,13 +0,0 @@
|
||||
# Check if objects in image
|
||||
|
||||
# Goal definition
|
||||
int16 id
|
||||
sensor_msgs/Image image
|
||||
|
||||
---
|
||||
# Result definition
|
||||
int16 id
|
||||
prometheus_msgs/BoundingBoxes bounding_boxes
|
||||
|
||||
---
|
||||
# Feedback definition
|
@ -1,7 +0,0 @@
|
||||
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 ## 四元数
|
@ -1,7 +0,0 @@
|
||||
string Class
|
||||
float64 probability
|
||||
int64 xmin
|
||||
int64 ymin
|
||||
int64 xmax
|
||||
int64 ymax
|
||||
|
@ -1,3 +0,0 @@
|
||||
Header header
|
||||
Header image_header
|
||||
BoundingBox[] bounding_boxes
|
@ -1,4 +0,0 @@
|
||||
std_msgs/Header header
|
||||
uint8[59] received_data
|
||||
uint8[5] get_data_com
|
||||
uint8[20] gimbal_control # 控制
|
@ -1,23 +0,0 @@
|
||||
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
|
@ -1,11 +0,0 @@
|
||||
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]
|
||||
|
@ -1,6 +0,0 @@
|
||||
uint8 HORIZONTAL=0
|
||||
uint8 TRIANGEL=1
|
||||
uint8 DIAMOND=2
|
||||
uint8 DIAMOND_STAGE_1=3
|
||||
|
||||
uint8 type
|
@ -1,9 +0,0 @@
|
||||
float32 pitch
|
||||
float32 yaw
|
||||
float32 zoom
|
||||
float32 focus
|
||||
uint16 home
|
||||
uint16 TakePicture
|
||||
uint16 cameraModeChange
|
||||
uint16 yawfollow
|
||||
uint16 quadhome
|
@ -1,12 +0,0 @@
|
||||
## 是否检测到目标
|
||||
bool detected
|
||||
|
||||
# 坐标
|
||||
float64 x
|
||||
float64 y
|
||||
# 速度
|
||||
float64 velx
|
||||
float64 vely
|
||||
# 积分
|
||||
float64 Ix
|
||||
float64 Iy
|
@ -1,12 +0,0 @@
|
||||
|
||||
std_msgs/Header header
|
||||
|
||||
ArucoInfo Aruco1
|
||||
ArucoInfo Aruco2
|
||||
ArucoInfo Aruco3
|
||||
ArucoInfo Aruco4
|
||||
ArucoInfo Aruco5
|
||||
ArucoInfo Aruco6
|
||||
ArucoInfo Aruco7
|
||||
ArucoInfo Aruco8
|
||||
ArucoInfo Aruco9
|
@ -1,12 +0,0 @@
|
||||
std_msgs/Header header
|
||||
|
||||
## 节点回传地面站的消息
|
||||
uint8 message_type
|
||||
# enum message_type
|
||||
uint8 NORMAL = 0
|
||||
uint8 WARN = 1
|
||||
uint8 ERROR = 2
|
||||
|
||||
string source_node
|
||||
|
||||
string content
|
@ -1,7 +0,0 @@
|
||||
std_msgs/Header header
|
||||
|
||||
## 检测到的aruco码数量
|
||||
int32 num_arucos
|
||||
|
||||
## 每个aruco码的检测结果
|
||||
ArucoInfo[] aruco_infos
|
@ -1,10 +0,0 @@
|
||||
Header header
|
||||
|
||||
## 检测到的目标数量
|
||||
int32 num_objs
|
||||
|
||||
## Detecting or Tracking (0:detect, 1:track)
|
||||
int32 detect_or_track
|
||||
|
||||
## 每个目标的检测结果
|
||||
DetectionInfo[] detection_infos
|
@ -1,24 +0,0 @@
|
||||
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]
|
||||
|
||||
|
@ -1,15 +0,0 @@
|
||||
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
|
@ -1,38 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>prometheus_msgs</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The prometheus_msgs 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/amov-lab/Prometheus.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_depend>actionlib_msgs</build_depend>
|
||||
<build_export_depend>std_msgs</build_export_depend>
|
||||
<build_export_depend>actionlib_msgs</build_export_depend>
|
||||
<exec_depend>std_msgs</exec_depend>
|
||||
<exec_depend>actionlib_msgs</exec_depend>
|
||||
|
||||
<build_depend>geometry_msgs</build_depend>
|
||||
<build_export_depend>geometry_msgs</build_export_depend>
|
||||
<exec_depend>geometry_msgs</exec_depend>
|
||||
|
||||
<build_depend>sensor_msgs</build_depend>
|
||||
<build_export_depend>sensor_msgs</build_export_depend>
|
||||
<exec_depend>sensor_msgs</exec_depend>
|
||||
|
||||
|
||||
|
||||
<export>
|
||||
|
||||
</export>
|
||||
</package>
|
@ -1,230 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(prometheus_mission)
|
||||
|
||||
## 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
|
||||
sensor_msgs
|
||||
mavros
|
||||
nav_msgs
|
||||
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
|
||||
sensor_msgs
|
||||
std_msgs
|
||||
)
|
||||
|
||||
catkin_package(
|
||||
CATKIN_DEPENDS message_runtime
|
||||
)
|
||||
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
include_directories(
|
||||
include
|
||||
autonomous_landing
|
||||
${catkin_INCLUDE_DIRS}
|
||||
../common/include
|
||||
../control/include
|
||||
)
|
||||
|
||||
|
||||
###############################
|
||||
## 声明可执行cpp文件 ##
|
||||
###############################
|
||||
add_executable(gimbal_control_circle gimbal_control/gimbal_control_circle.cpp)
|
||||
add_dependencies(gimbal_control_circle prometheus_mission_gencpp)
|
||||
target_link_libraries(gimbal_control_circle ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(gimbal_control_demo gimbal_control/gimbal_control_demo.cpp)
|
||||
add_dependencies(gimbal_control_demo prometheus_mission_gencpp)
|
||||
target_link_libraries(gimbal_control_demo ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(gimbal_control gimbal_control/gimbal_control.cpp)
|
||||
add_dependencies(gimbal_control prometheus_mission_gencpp)
|
||||
target_link_libraries(gimbal_control ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(pad_tracking test/pad_tracking.cpp)
|
||||
add_dependencies(pad_tracking prometheus_mission_gencpp)
|
||||
target_link_libraries(pad_tracking ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(mission_cmd_pub test/mission_cmd_pub.cpp)
|
||||
add_dependencies(mission_cmd_pub prometheus_mission_gencpp)
|
||||
target_link_libraries(mission_cmd_pub ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(turtlebot_formation formation_flight/turtlebot_formation.cpp)
|
||||
add_dependencies(turtlebot_formation prometheus_mission_gencpp)
|
||||
target_link_libraries(turtlebot_formation ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(circle_crossing circle_crossing/circle_crossing.cpp)
|
||||
add_dependencies(circle_crossing prometheus_mission_gencpp)
|
||||
target_link_libraries(circle_crossing ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(number_detection number_detection/number_detection.cpp)
|
||||
add_dependencies(number_detection prometheus_mission_gencpp)
|
||||
target_link_libraries(number_detection ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(turtlebot_follow formation_flight/turtlebot_follow.cpp)
|
||||
add_dependencies(turtlebot_follow prometheus_mission_gencpp)
|
||||
target_link_libraries(turtlebot_follow ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(color_line_following color_line_following/color_line_following.cpp)
|
||||
add_dependencies(color_line_following prometheus_mission_gencpp)
|
||||
target_link_libraries(color_line_following ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(planning_mission planning_mission/planning_mission.cpp)
|
||||
add_dependencies(planning_mission prometheus_mission_gencpp)
|
||||
target_link_libraries(planning_mission ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(pub_goal planning_mission/pub_goal.cpp)
|
||||
add_dependencies(pub_goal prometheus_mission_gencpp)
|
||||
target_link_libraries(pub_goal ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(pub_goal_swarm planning_mission/pub_goal_swarm.cpp)
|
||||
add_dependencies(pub_goal_swarm prometheus_mission_gencpp)
|
||||
target_link_libraries(pub_goal_swarm ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(waypoint_tracking waypoint_tracking/waypoint_tracking.cpp)
|
||||
add_dependencies(waypoint_tracking prometheus_mission_gencpp)
|
||||
target_link_libraries(waypoint_tracking ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(autonomous_landing autonomous_landing/autonomous_landing.cpp)
|
||||
add_dependencies(autonomous_landing prometheus_mission_gencpp)
|
||||
target_link_libraries(autonomous_landing ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(autonomous_landing_aruco autonomous_landing/autonomous_landing_aruco.cpp)
|
||||
add_dependencies(autonomous_landing_aruco prometheus_mission_gencpp)
|
||||
target_link_libraries(autonomous_landing_aruco ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(object_tracking object_tracking/object_tracking.cpp)
|
||||
add_dependencies(object_tracking prometheus_mission_gencpp)
|
||||
target_link_libraries(object_tracking ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(indoor_competition indoor_competition/indoor_competition.cpp)
|
||||
add_dependencies(indoor_competition prometheus_mission_gencpp)
|
||||
target_link_libraries(indoor_competition ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(fake_detectioninfo test/fake_detectioninfo.cpp)
|
||||
add_dependencies(fake_detectioninfo prometheus_mission_gencpp)
|
||||
target_link_libraries(fake_detectioninfo ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_getpose formation/formation_getpose.cpp)
|
||||
add_dependencies(formation_getpose prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_getpose ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_state formation/formation_state.cpp)
|
||||
add_dependencies(formation_state prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_state ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_move formation/formation_move.cpp)
|
||||
add_dependencies(formation_move prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_move ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_change formation/formation_change.cpp)
|
||||
add_dependencies(formation_change prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_change ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_setmode formation/formation_setmode.cpp)
|
||||
add_dependencies(formation_setmode prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_setmode ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_control formation/formation_control.cpp)
|
||||
add_dependencies(formation_control prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_control ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(formation_square formation/formation_square.cpp)
|
||||
add_dependencies(formation_square prometheus_mission_gencpp)
|
||||
target_link_libraries(formation_square ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(pub_goal_from_qgc planning_mission/pub_goal_from_qgc.cpp)
|
||||
add_dependencies(pub_goal_from_qgc prometheus_mission_gencpp)
|
||||
target_link_libraries(pub_goal_from_qgc ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(circlex_landing_gimbal autonomous_landing/circlex_landing_gimbal.cpp)
|
||||
add_dependencies(circlex_landing_gimbal prometheus_msgs_generate_message_cpp)
|
||||
target_link_libraries(circlex_landing_gimbal ${catkin_LIBRARIES})
|
||||
|
||||
add_executable(circlex_landing_fixed_camera autonomous_landing/circlex_landing_fixed_camera.cpp)
|
||||
target_link_libraries(circlex_landing_fixed_camera ${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_mission.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,190 +0,0 @@
|
||||
/***************************************************************************************************************************
|
||||
* color_line_following.cpp
|
||||
*
|
||||
* Author: Qyp
|
||||
*
|
||||
* Update Time: 2020.4.6
|
||||
*
|
||||
***************************************************************************************************************************/
|
||||
//ROS 头文件
|
||||
#include <ros/ros.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
#include <tf/transform_datatypes.h>
|
||||
//topic 头文件
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
#include <geometry_msgs/Pose.h>
|
||||
#include <prometheus_msgs/ControlCommand.h>
|
||||
#include <nav_msgs/Odometry.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace Eigen;
|
||||
#define FOLLOWING_VEL 0.5
|
||||
#define FOLLOWING_KP 2.0
|
||||
# define NODE_NAME "color_line_following"
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>全 局 变 量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
//---------------------------------------Drone---------------------------------------------
|
||||
float drone_height;
|
||||
float drone_yaw;
|
||||
float start_point_x,start_point_y,start_point_z;
|
||||
//---------------------------------------Vision---------------------------------------------
|
||||
int flag_detection;
|
||||
float error_body_y;
|
||||
float yaw_sp;
|
||||
float next_desired_yaw;
|
||||
//---------------------------------------Output---------------------------------------------
|
||||
prometheus_msgs::ControlCommand Command_Now; //发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>函数声明<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
void printf_param(); //打印各项参数以供检查
|
||||
void printf_result();
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回调函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
void color_line_cb(const geometry_msgs::Pose::ConstPtr &msg)
|
||||
{
|
||||
error_body_y = - tan(msg->position.x) * start_point_z;
|
||||
flag_detection = msg->position.y;
|
||||
|
||||
float x1 = msg->orientation.w;
|
||||
float y1 = msg->orientation.x;
|
||||
float x2 = msg->orientation.y;
|
||||
float y2 = msg->orientation.z;
|
||||
|
||||
next_desired_yaw = - atan2(y2 - y1, x2 - x1);
|
||||
|
||||
yaw_sp = (0.7*yaw_sp + 0.3*next_desired_yaw);
|
||||
}
|
||||
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
drone_yaw = msg->attitude[2];
|
||||
drone_height = msg->position[2];
|
||||
}
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "color_line_following");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
//节点运行频率: 20hz 【视觉端解算频率大概为20HZ】
|
||||
ros::Rate rate(20.0);
|
||||
|
||||
//【订阅】所识别线与相机中心轴的偏移角度
|
||||
ros::Subscriber color_line_sub = nh.subscribe<geometry_msgs::Pose>("/prometheus/object_detection/color_line_angle", 10, color_line_cb);
|
||||
|
||||
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
|
||||
|
||||
//【发布】发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
ros::Publisher command_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
|
||||
|
||||
// 【发布】用于地面站显示的提示消息
|
||||
ros::Publisher message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
|
||||
|
||||
nh.param<float>("start_point_x", start_point_x, 0.0);
|
||||
nh.param<float>("start_point_y", start_point_y, 0.0);
|
||||
nh.param<float>("start_point_z", start_point_z, 2.0);
|
||||
|
||||
//固定的浮点显示
|
||||
cout.setf(ios::fixed);
|
||||
//setprecision(n) 设显示小数精度为n位
|
||||
cout<<setprecision(2);
|
||||
//左对齐
|
||||
cout.setf(ios::left);
|
||||
// 强制显示小数点
|
||||
cout.setf(ios::showpoint);
|
||||
// 强制显示符号
|
||||
cout.setf(ios::showpos);
|
||||
|
||||
printf_param();
|
||||
// Waiting for input
|
||||
int start_flag = 0;
|
||||
while(start_flag == 0)
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>Color Line Following Mission<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "Please enter 1 to start... "<<endl;
|
||||
cin >> start_flag;
|
||||
}
|
||||
|
||||
// 起飞
|
||||
cout<<"[color_line_following]: "<<"Takeoff to predefined position."<<endl;
|
||||
pub_message(message_pub, prometheus_msgs::Message::NORMAL, NODE_NAME, "Takeoff to predefined position.");
|
||||
Command_Now.Command_ID = 1;
|
||||
Command_Now.source = NODE_NAME;
|
||||
while( drone_height < 0.3)
|
||||
{
|
||||
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(3.0).sleep();
|
||||
|
||||
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::ENU_FRAME;
|
||||
Command_Now.Reference_State.position_ref[0] = start_point_x;
|
||||
Command_Now.Reference_State.position_ref[1] = start_point_y;
|
||||
Command_Now.Reference_State.position_ref[2] = start_point_z;
|
||||
Command_Now.Reference_State.yaw_ref = 0.0;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Takeoff ..."<<endl;
|
||||
ros::Duration(3.0).sleep();
|
||||
|
||||
ros::spinOnce();
|
||||
}
|
||||
|
||||
ros::Duration(5.0).sleep();
|
||||
|
||||
// 先读取一些飞控的数据
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
ros::spinOnce();
|
||||
rate.sleep();
|
||||
}
|
||||
|
||||
while (ros::ok())
|
||||
{
|
||||
//回调
|
||||
ros::spinOnce();
|
||||
|
||||
Command_Now.header.stamp = ros::Time::now();
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
Command_Now.source = NODE_NAME;
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
|
||||
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XY_VEL_Z_POS;
|
||||
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::MIX_FRAME;
|
||||
Command_Now.Reference_State.velocity_ref[0] = FOLLOWING_VEL;
|
||||
Command_Now.Reference_State.velocity_ref[1] = FOLLOWING_KP * error_body_y;
|
||||
Command_Now.Reference_State.position_ref[2] = start_point_z;
|
||||
Command_Now.Reference_State.yaw_ref = yaw_sp; // 增量yaw
|
||||
command_pub.publish(Command_Now);
|
||||
printf_result();
|
||||
rate.sleep();
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void printf_result()
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>Color Line Following Mission<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "error_body_y : " << error_body_y << " [ m ] "<<endl;
|
||||
cout << "yaw_from_vision: " << next_desired_yaw/3.1415926 *180 << " [deg] "<<endl;
|
||||
cout << "yaw_sp : " << yaw_sp/3.1415926 *180 << " [deg] "<<endl;
|
||||
}
|
||||
void printf_param()
|
||||
{
|
||||
cout <<">>>>>>>>>>>>>>>>>>>>>>>>>>>>>> Parameter <<<<<<<<<<<<<<<<<<<<<<<<<<<" <<endl;
|
||||
cout << "start_point_x : "<< start_point_x << endl;
|
||||
cout << "start_point_y : "<< start_point_y << endl;
|
||||
cout << "start_point_z : "<< start_point_z << endl;
|
||||
cout << "FOLLOWING_KP : "<< FOLLOWING_KP << endl;
|
||||
|
||||
}
|
||||
|
@ -1,140 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:formation_change.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.14
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中模式切换相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
#include "Formation.h"
|
||||
#include <iostream>
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
//创建队形变化数据发布者
|
||||
ros::param::param<int>("~DIAMOND_intervals", diamond_intervals, 5);
|
||||
ros::param::param<string>("Location_source", location_source, "gps");
|
||||
formation_type_pub = n.advertise<prometheus_msgs::Formation>("/prometheus/formation/change", 10);
|
||||
}
|
||||
|
||||
//是否等待函数
|
||||
void formation::is_wait(int time)
|
||||
{
|
||||
//判断是否需要等待,time变量不为0,则等待
|
||||
if(time != 0)
|
||||
{
|
||||
sleep(time);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//打印集群队形状态函数
|
||||
void formation::printf_formation_type(std::string type_name)
|
||||
{
|
||||
std::cout << std::endl;
|
||||
std::cout << ">>>>>>>>Formation Type<<<<<<<<" << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << " " << type_name << " " << std::endl;
|
||||
std::cout << std::endl;
|
||||
std::cout << "------------------------------" << std::endl;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
void formation::change()
|
||||
{
|
||||
//初始化,创建队形变换信息发布者
|
||||
init();
|
||||
//创建获取用户输入值的变量
|
||||
int type_last;
|
||||
int type_now;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
//打印提示信息
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--------<<<<<<<<<<<<<<<<<<<<<<<<<<< " << std::endl;
|
||||
std::cout << "Input the formation type: 0 for horizontal formation, 1 for triangle formation, 2 for diamond formation" << std::endl;
|
||||
//获取用户输入的值
|
||||
std::cin >> type_now;
|
||||
//判断值是否正确,正确则进入正常流程,错误则打印警告信息
|
||||
if((type_now >= 0) && (type_now <= 2))
|
||||
{
|
||||
switch(type_now)
|
||||
{
|
||||
//一字队形
|
||||
case 0:
|
||||
//判断当前队形是否为菱形队形,是菱形则先进入过渡队形
|
||||
if(type_last == prometheus_msgs::Formation::DIAMOND)
|
||||
{
|
||||
formation_data.type = prometheus_msgs::Formation::DIAMOND_STAGE_1;
|
||||
formation_type_pub.publish(formation_data);
|
||||
is_wait(diamond_intervals);
|
||||
}
|
||||
//切换为一字队形
|
||||
formation_data.type = prometheus_msgs::Formation::HORIZONTAL;
|
||||
formation_type_pub.publish(formation_data);
|
||||
printf_formation_type("Horizontal");
|
||||
break;
|
||||
|
||||
//三角队形
|
||||
case 1:
|
||||
//判断当前队形是否为菱形队形,是菱形则先进入过渡队形
|
||||
if(type_last == prometheus_msgs::Formation::DIAMOND)
|
||||
{
|
||||
formation_data.type = prometheus_msgs::Formation::DIAMOND_STAGE_1;
|
||||
formation_type_pub.publish(formation_data);
|
||||
is_wait(diamond_intervals);
|
||||
}
|
||||
//切换为三角队形
|
||||
formation_data.type = prometheus_msgs::Formation::TRIANGEL;
|
||||
formation_type_pub.publish(formation_data);
|
||||
printf_formation_type("Triangle");
|
||||
break;
|
||||
|
||||
//菱形队形
|
||||
case 2:
|
||||
if(location_source == "mocap")
|
||||
{
|
||||
//判断当前队形是否为菱形队形,是菱形队形则直接跳出当前队形
|
||||
if(type_last == type_now)
|
||||
{
|
||||
break;
|
||||
}
|
||||
//进入过渡队形
|
||||
formation_data.type = prometheus_msgs::Formation::DIAMOND_STAGE_1;
|
||||
formation_type_pub.publish(formation_data);
|
||||
is_wait(diamond_intervals);
|
||||
//切换为菱形队形
|
||||
formation_data.type = prometheus_msgs::Formation::DIAMOND;
|
||||
formation_type_pub.publish(formation_data);
|
||||
printf_formation_type("Diamond");
|
||||
break;
|
||||
}
|
||||
if(location_source == "uwb" || location_source == "gps")
|
||||
{
|
||||
ROS_WARN("not support diamond formation");
|
||||
type_now = type_last;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
//把当前集群队形变量赋值给上一集群队形变量
|
||||
type_last = type_now;
|
||||
}
|
||||
else
|
||||
{
|
||||
type_now = type_last;
|
||||
//输入错误
|
||||
ROS_WARN("inpunt error, please input again");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ros::init(argc, argv, "formation_change");
|
||||
formation Formation;
|
||||
Formation.change();
|
||||
return 0;
|
||||
}
|
@ -1,449 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:mocap_formation_control.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.14
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中集群控制相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
#include "Formation.h"
|
||||
#include "command_to_mavros.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
//控制命令数据订阅者
|
||||
cmd_sub = n.subscribe("/prometheus/control_command", 10, &formation::ControlCallBack, this);
|
||||
//集群队形数据订阅者
|
||||
formation_type_sub = n.subscribe("/prometheus/formation/change", 10, &formation::FormationChangeCallBack, this);
|
||||
|
||||
//集群五台飞机位置控制数据发布者
|
||||
uav1_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav1/mavros/setpoint_raw/local", 10);
|
||||
uav2_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav2/mavros/setpoint_raw/local", 10);
|
||||
uav3_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav3/mavros/setpoint_raw/local", 10);
|
||||
uav4_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav4/mavros/setpoint_raw/local", 10);
|
||||
uav5_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav5/mavros/setpoint_raw/local", 10);
|
||||
|
||||
//获取集群X轴间隔距离参数
|
||||
ros::param::param<double>("~FORMATION_DISTANCE_x", formation_distance_x, 1);
|
||||
|
||||
//获取集群Y轴间隔距离参数
|
||||
ros::param::param<double>("~FORMATION_DISTANCE_y", formation_distance_y, 2);
|
||||
|
||||
//获取定位来源
|
||||
ros::param::param<string>("Location_source", location_source, "fps");
|
||||
|
||||
//获取飞控系统
|
||||
ros::param::param<string>("Flight_controller", flight_controller, "spm");
|
||||
|
||||
//获取仿真中位置差值
|
||||
ros::param::param<double>("uav1_x", uav1_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav1_y", uav1_gazebo_offset_pose[1], 0);
|
||||
|
||||
ros::param::param<double>("uav2_x", uav2_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav2_y", uav2_gazebo_offset_pose[1], 0);
|
||||
|
||||
ros::param::param<double>("uav3_x", uav3_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav3_y", uav3_gazebo_offset_pose[1], 0);
|
||||
|
||||
ros::param::param<double>("uav4_x", uav4_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav4_y", uav4_gazebo_offset_pose[1], 0);
|
||||
|
||||
ros::param::param<double>("uav5_x", uav5_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav5_y", uav5_gazebo_offset_pose[1], 0);
|
||||
|
||||
//获取是否为仿真参数
|
||||
ros::param::param<bool>("~sim",sim,false);
|
||||
|
||||
check_param();
|
||||
|
||||
//初始队形设置为一字形
|
||||
formation_data.type = prometheus_msgs::Formation::HORIZONTAL;
|
||||
|
||||
//设置程序初始时间
|
||||
begin_time = ros::Time::now();
|
||||
}
|
||||
|
||||
bool formation::check_param()
|
||||
{
|
||||
char tmp[100];
|
||||
strncpy(tmp,location_source.c_str(),location_source.length() + 1);
|
||||
if((location_source == "gps" || location_source == "uwb") || location_source == "mocap")
|
||||
{
|
||||
ROS_INFO("Location source is [%s]\n", tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("param [Location_source] value error, value is [%s], not gps, uwb or mocap\n", tmp);
|
||||
ros::shutdown();
|
||||
}
|
||||
|
||||
strncpy(tmp,flight_controller.c_str(),flight_controller.length() + 1);
|
||||
if(flight_controller == "apm" || flight_controller == "px4")
|
||||
{
|
||||
ROS_INFO("Flight_controller is [%s]\n", tmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("param [flight_controller] value error, value is [%s], not apm or px4\n", tmp);
|
||||
ros::shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
//集群位置控制发布函数
|
||||
void formation::formation_pos_pub()
|
||||
{
|
||||
uav1_local_pub.publish(uav1_desired_pose);
|
||||
uav2_local_pub.publish(uav2_desired_pose);
|
||||
uav3_local_pub.publish(uav3_desired_pose);
|
||||
uav4_local_pub.publish(uav4_desired_pose);
|
||||
uav5_local_pub.publish(uav5_desired_pose);
|
||||
}
|
||||
|
||||
//获取单台无人机控制数据
|
||||
void formation::get_uav_cmd(Eigen::Vector3d offset_pose, mavros_msgs::PositionTarget& desired_pose)
|
||||
{
|
||||
desired_pose.header.stamp = ros::Time::now();
|
||||
desired_pose.type_mask = 0b100111111000;
|
||||
desired_pose.coordinate_frame = 1;
|
||||
desired_pose.position.x = control_data.Reference_State.position_ref[0] + offset_pose[0];
|
||||
desired_pose.position.y = control_data.Reference_State.position_ref[1] + offset_pose[1];
|
||||
desired_pose.position.z = control_data.Reference_State.position_ref[2] + offset_pose[2];
|
||||
desired_pose.yaw = control_data.Reference_State.yaw_ref;
|
||||
}
|
||||
|
||||
void formation::is_sim()
|
||||
{
|
||||
if(!sim)
|
||||
{
|
||||
uav1_gazebo_offset_pose[0] = 0;
|
||||
uav1_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav2_gazebo_offset_pose[0] = 0;
|
||||
uav2_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav3_gazebo_offset_pose[0] = 0;
|
||||
uav3_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav4_gazebo_offset_pose[0] = 0;
|
||||
uav4_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav5_gazebo_offset_pose[0] = 0;
|
||||
uav5_gazebo_offset_pose[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
//设置一字队形
|
||||
void formation::set_horizontal()
|
||||
{
|
||||
if(location_source == "mocap")
|
||||
{
|
||||
//1号机
|
||||
uav1_offset_pose[0] = 0 - uav1_gazebo_offset_pose[0];
|
||||
uav1_offset_pose[1] = 0 - uav1_gazebo_offset_pose[1];
|
||||
uav1_offset_pose[2] = 0;
|
||||
|
||||
//2号机
|
||||
uav2_offset_pose[0] = 0 - uav2_gazebo_offset_pose[0];
|
||||
uav2_offset_pose[1] = 2 * formation_distance_y - uav2_gazebo_offset_pose[1];
|
||||
uav2_offset_pose[2] = 0;
|
||||
|
||||
//3号机
|
||||
uav3_offset_pose[0] = 0 - uav3_gazebo_offset_pose[0];
|
||||
uav3_offset_pose[1] = formation_distance_y - uav3_gazebo_offset_pose[1];
|
||||
uav3_offset_pose[2] = 0;
|
||||
|
||||
//4号机
|
||||
uav4_offset_pose[0] = 0 - uav4_gazebo_offset_pose[0];
|
||||
uav4_offset_pose[1] = -formation_distance_y - uav4_gazebo_offset_pose[1];
|
||||
uav4_offset_pose[2] = 0;
|
||||
|
||||
//5号机
|
||||
uav5_offset_pose[0] = 0 - uav5_gazebo_offset_pose[0];
|
||||
uav5_offset_pose[1] = -2 * formation_distance_y - uav5_gazebo_offset_pose[1];
|
||||
uav5_offset_pose[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(location_source == "uwb" || location_source == "gps")
|
||||
{
|
||||
//1号机
|
||||
uav1_offset_pose[0] = 0 - uav1_gazebo_offset_pose[0];
|
||||
uav1_offset_pose[1] = 0 - uav1_gazebo_offset_pose[1];
|
||||
uav1_offset_pose[2] = 0;
|
||||
|
||||
//2号机
|
||||
uav2_offset_pose[0] = 0 - uav2_gazebo_offset_pose[0];
|
||||
uav2_offset_pose[1] = 0- uav2_gazebo_offset_pose[1];
|
||||
uav2_offset_pose[2] = 0;
|
||||
|
||||
//3号机
|
||||
uav3_offset_pose[0] = 0 - uav3_gazebo_offset_pose[0];
|
||||
uav3_offset_pose[1] = 0 - uav3_gazebo_offset_pose[1];
|
||||
uav3_offset_pose[2] = 0;
|
||||
|
||||
//4号机
|
||||
uav4_offset_pose[0] = 0 - uav4_gazebo_offset_pose[0];
|
||||
uav4_offset_pose[1] = 0 - uav4_gazebo_offset_pose[1];
|
||||
uav4_offset_pose[2] = 0;
|
||||
|
||||
//5号机
|
||||
uav5_offset_pose[0] = 0 - uav5_gazebo_offset_pose[0];
|
||||
uav5_offset_pose[1] = 0 - uav5_gazebo_offset_pose[1];
|
||||
uav5_offset_pose[2] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//设置三角队形
|
||||
void formation::set_triangle()
|
||||
{
|
||||
if(location_source == "mocap")
|
||||
{
|
||||
//1号机
|
||||
uav1_offset_pose[0] = 2 * formation_distance_x - uav1_gazebo_offset_pose[0];
|
||||
uav1_offset_pose[1] = 0 - uav1_gazebo_offset_pose[1];
|
||||
uav1_offset_pose[2] = 0;
|
||||
|
||||
//2号机
|
||||
uav2_offset_pose[0] = 0 - uav2_gazebo_offset_pose[0];
|
||||
uav2_offset_pose[1] = 2 * formation_distance_y - uav2_gazebo_offset_pose[1];
|
||||
uav2_offset_pose[2] = 0;
|
||||
|
||||
//3号机
|
||||
uav3_offset_pose[0] = formation_distance_x - uav3_gazebo_offset_pose[0];
|
||||
uav3_offset_pose[1] = formation_distance_y - uav3_gazebo_offset_pose[1];
|
||||
uav3_offset_pose[2] = 0;
|
||||
|
||||
//4号机
|
||||
uav4_offset_pose[0] = formation_distance_x - uav4_gazebo_offset_pose[0];
|
||||
uav4_offset_pose[1] = -formation_distance_y - uav4_gazebo_offset_pose[1];
|
||||
uav4_offset_pose[2] = 0;
|
||||
|
||||
//5号机
|
||||
uav5_offset_pose[0] = 0 - uav5_gazebo_offset_pose[0];
|
||||
uav5_offset_pose[1] = -2 * formation_distance_y - uav5_gazebo_offset_pose[1];
|
||||
uav5_offset_pose[2] = 0;
|
||||
}
|
||||
if(location_source == "uwb" || location_source == "gps")
|
||||
{
|
||||
//1号机
|
||||
uav1_offset_pose[0] = 2 * formation_distance_x - uav1_gazebo_offset_pose[0];
|
||||
uav1_offset_pose[1] = 0 - uav1_gazebo_offset_pose[1];
|
||||
uav1_offset_pose[2] = 0;
|
||||
|
||||
//2号机
|
||||
uav2_offset_pose[0] = 0 - uav2_gazebo_offset_pose[0];
|
||||
uav2_offset_pose[1] = 0 - uav2_gazebo_offset_pose[1];
|
||||
uav2_offset_pose[2] = 0;
|
||||
|
||||
//3号机
|
||||
uav3_offset_pose[0] = formation_distance_x - uav3_gazebo_offset_pose[0];
|
||||
uav3_offset_pose[1] = 0 - uav3_gazebo_offset_pose[1];
|
||||
uav3_offset_pose[2] = 0;
|
||||
|
||||
//4号机
|
||||
uav4_offset_pose[0] = formation_distance_x - uav4_gazebo_offset_pose[0];
|
||||
uav4_offset_pose[1] = 0 - uav4_gazebo_offset_pose[1];
|
||||
uav4_offset_pose[2] = 0;
|
||||
|
||||
//5号机
|
||||
uav5_offset_pose[0] = 0 - uav5_gazebo_offset_pose[0];
|
||||
uav5_offset_pose[1] = 0 - uav5_gazebo_offset_pose[1];
|
||||
uav5_offset_pose[2] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//设置菱形队形
|
||||
void formation::set_diamond()
|
||||
{
|
||||
if(location_source == "mocap")
|
||||
{
|
||||
//1号机
|
||||
uav1_offset_pose[0] = 0 - uav1_gazebo_offset_pose[0];
|
||||
uav1_offset_pose[1] = 0 - uav1_gazebo_offset_pose[1];
|
||||
uav1_offset_pose[2] = 0;
|
||||
|
||||
//2号机
|
||||
uav2_offset_pose[0] = 0 - uav2_gazebo_offset_pose[0];
|
||||
uav2_offset_pose[1] = 2 * formation_distance_y - uav2_gazebo_offset_pose[1];
|
||||
uav2_offset_pose[2] = 0;
|
||||
|
||||
//3号机
|
||||
uav3_offset_pose[0] = 2 * formation_distance_x - uav3_gazebo_offset_pose[0];
|
||||
uav3_offset_pose[1] = 0 - uav3_gazebo_offset_pose[1];
|
||||
uav3_offset_pose[2] = 0;
|
||||
|
||||
//4号机
|
||||
uav4_offset_pose[0] = -2 * formation_distance_x - uav4_gazebo_offset_pose[0];
|
||||
uav4_offset_pose[1] = 0 - uav4_gazebo_offset_pose[1];
|
||||
uav4_offset_pose[2] = 0;
|
||||
|
||||
//5号机
|
||||
uav5_offset_pose[0] = 0 - uav5_gazebo_offset_pose[0];
|
||||
uav5_offset_pose[1] = -2 * formation_distance_y - uav5_gazebo_offset_pose[1];
|
||||
uav5_offset_pose[2] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(location_source == "gps" || location_source == "uwb")
|
||||
{
|
||||
ROS_WARN("gps or uwb location not support diamond formation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//设置菱形队形相关过渡队形
|
||||
void formation::set_diamond_stage1()
|
||||
{
|
||||
//1号机
|
||||
uav1_offset_pose[0] = 0 - uav1_gazebo_offset_pose[0];
|
||||
uav1_offset_pose[1] = 0 - uav1_gazebo_offset_pose[1];
|
||||
uav1_offset_pose[2] = 0;
|
||||
|
||||
//2号机
|
||||
uav2_offset_pose[0] = 0 - uav2_gazebo_offset_pose[0];
|
||||
uav2_offset_pose[1] = 2 * formation_distance_y - uav2_gazebo_offset_pose[1];
|
||||
uav2_offset_pose[2] = 0;
|
||||
|
||||
//3号机
|
||||
uav3_offset_pose[0] = 2 * formation_distance_x - uav3_gazebo_offset_pose[0];
|
||||
uav3_offset_pose[1] = formation_distance_y - uav3_gazebo_offset_pose[1];
|
||||
uav3_offset_pose[2] = 0;
|
||||
|
||||
//4号机
|
||||
uav4_offset_pose[0] = -2 * formation_distance_x - uav4_gazebo_offset_pose[0];
|
||||
uav4_offset_pose[1] = -formation_distance_y - uav4_gazebo_offset_pose[1];
|
||||
uav4_offset_pose[2] = 0;
|
||||
|
||||
//5号机
|
||||
uav5_offset_pose[0] = 0 - uav5_gazebo_offset_pose[0];
|
||||
uav5_offset_pose[1] = -2 * formation_distance_y - uav5_gazebo_offset_pose[1];
|
||||
uav5_offset_pose[2] = 0;
|
||||
}
|
||||
|
||||
//集群控制函数
|
||||
void formation::control()
|
||||
{
|
||||
//初始化
|
||||
init();
|
||||
is_sim();
|
||||
if(flight_controller == "px4")
|
||||
{
|
||||
while(ros::ok())
|
||||
{
|
||||
//处理回调函数
|
||||
ros::spinOnce();
|
||||
//获取集群队形
|
||||
switch(formation_data.type)
|
||||
{
|
||||
//设置为一字队形
|
||||
case prometheus_msgs::Formation::HORIZONTAL:
|
||||
set_horizontal();
|
||||
break;
|
||||
|
||||
//设置为三角队形
|
||||
case prometheus_msgs::Formation::TRIANGEL:
|
||||
set_triangle();
|
||||
break;
|
||||
|
||||
//设置为菱形队形过渡队形
|
||||
case prometheus_msgs::Formation::DIAMOND_STAGE_1:
|
||||
set_diamond_stage1();
|
||||
break;
|
||||
|
||||
//设置为菱形队形
|
||||
case prometheus_msgs::Formation::DIAMOND:
|
||||
set_diamond();
|
||||
break;
|
||||
}
|
||||
//五台无人机获取控制数据
|
||||
get_uav_cmd(uav1_offset_pose, uav1_desired_pose);
|
||||
get_uav_cmd(uav2_offset_pose, uav2_desired_pose);
|
||||
get_uav_cmd(uav3_offset_pose, uav3_desired_pose);
|
||||
get_uav_cmd(uav4_offset_pose, uav4_desired_pose);
|
||||
get_uav_cmd(uav5_offset_pose, uav5_desired_pose);
|
||||
formation_pos_pub();
|
||||
|
||||
//等待0.1秒
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flight_controller == "apm")
|
||||
{
|
||||
//起飞后开始控制无人机集群飞行
|
||||
ROS_INFO("When the drone formation takeoff and the control command input,enter 1 to start formation control");
|
||||
int check_flag;
|
||||
std::cin >> check_flag;
|
||||
if(check_flag != 1)
|
||||
{
|
||||
ros::shutdown();
|
||||
}
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
//处理回调函数
|
||||
ros::spinOnce();
|
||||
//获取集群队形
|
||||
switch(formation_data.type)
|
||||
{
|
||||
//设置为一字队形
|
||||
case prometheus_msgs::Formation::HORIZONTAL:
|
||||
set_horizontal();
|
||||
break;
|
||||
|
||||
//设置为三角队形
|
||||
case prometheus_msgs::Formation::TRIANGEL:
|
||||
set_triangle();
|
||||
break;
|
||||
|
||||
//设置为菱形队形过渡队形
|
||||
case prometheus_msgs::Formation::DIAMOND_STAGE_1:
|
||||
set_diamond_stage1();
|
||||
break;
|
||||
}
|
||||
//五台无人机获取控制数据
|
||||
get_uav_cmd(uav1_offset_pose, uav1_desired_pose);
|
||||
get_uav_cmd(uav2_offset_pose, uav2_desired_pose);
|
||||
get_uav_cmd(uav3_offset_pose, uav3_desired_pose);
|
||||
get_uav_cmd(uav4_offset_pose, uav4_desired_pose);
|
||||
get_uav_cmd(uav5_offset_pose, uav5_desired_pose);
|
||||
formation_pos_pub();
|
||||
|
||||
//等待0.1秒
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
//获取无人机控制指令
|
||||
void formation::ControlCallBack(const prometheus_msgs::ControlCommandConstPtr& control_msgs)
|
||||
{
|
||||
control_data = *control_msgs;
|
||||
}
|
||||
|
||||
//获取无人机集群队形指令
|
||||
void formation::FormationChangeCallBack(const prometheus_msgs::FormationConstPtr& change_msgs)
|
||||
{
|
||||
formation_data.type = change_msgs->type;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ros::init(argc, argv, "formation_control");
|
||||
formation Formation;
|
||||
Formation.control();
|
||||
return 0;
|
||||
}
|
@ -1,91 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:formation_move.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.16
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中获取动捕系统位置数据并转发到飞控相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
|
||||
#include "Formation.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
//动捕系统位置数据订阅者
|
||||
uav1_mocap_pose_sub = n.subscribe("/mocap/uav1/pose", 10, &formation::Uav1MocapPoseCallBack, this);
|
||||
uav2_mocap_pose_sub = n.subscribe("/mocap/uav2/pose", 10, &formation::Uav2MocapPoseCallBack, this);
|
||||
uav3_mocap_pose_sub = n.subscribe("/mocap/uav3/pose", 10, &formation::Uav3MocapPoseCallBack, this);
|
||||
uav4_mocap_pose_sub = n.subscribe("/mocap/uav4/pose", 10, &formation::Uav4MocapPoseCallBack, this);
|
||||
uav5_mocap_pose_sub = n.subscribe("/mocap/uav5/pose", 10, &formation::Uav5MocapPoseCallBack, this);
|
||||
//动捕系统位置数据发布者
|
||||
uav1_mocap_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/uav1/mavros/vision_pose/pose", 10);
|
||||
uav2_mocap_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/uav2/mavros/vision_pose/pose", 10);
|
||||
uav3_mocap_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/uav3/mavros/vision_pose/pose", 10);
|
||||
uav4_mocap_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/uav4/mavros/vision_pose/pose", 10);
|
||||
uav5_mocap_pose_pub = n.advertise<geometry_msgs::PoseStamped>("/uav5/mavros/vision_pose/pose", 10);
|
||||
}
|
||||
|
||||
void formation::getpose()
|
||||
{
|
||||
//初始化
|
||||
init();
|
||||
while(ros::ok())
|
||||
{
|
||||
//处理回调函数,
|
||||
ros::spinOnce();
|
||||
//打上时间戳后,发布位置数据到飞控
|
||||
uav1_current_pose.header.stamp = ros::Time::now();
|
||||
uav2_current_pose.header.stamp = ros::Time::now();
|
||||
uav3_current_pose.header.stamp = ros::Time::now();
|
||||
uav4_current_pose.header.stamp = ros::Time::now();
|
||||
uav5_current_pose.header.stamp = ros::Time::now();
|
||||
uav1_mocap_pose_pub.publish(uav1_current_pose);
|
||||
uav2_mocap_pose_pub.publish(uav2_current_pose);
|
||||
uav3_mocap_pose_pub.publish(uav3_current_pose);
|
||||
uav4_mocap_pose_pub.publish(uav4_current_pose);
|
||||
uav5_mocap_pose_pub.publish(uav5_current_pose);
|
||||
usleep(10000);
|
||||
}
|
||||
}
|
||||
|
||||
//获取动捕系统下的五台无人机位置数据
|
||||
|
||||
//1号机
|
||||
void formation::Uav1MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav1_current_pose.pose = pose_msgs->pose;
|
||||
}
|
||||
|
||||
//2号机
|
||||
void formation::Uav2MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav2_current_pose.pose = pose_msgs->pose;
|
||||
}
|
||||
|
||||
//3号机
|
||||
void formation::Uav3MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav3_current_pose.pose = pose_msgs->pose;
|
||||
}
|
||||
|
||||
//4号机
|
||||
void formation::Uav4MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav4_current_pose.pose = pose_msgs->pose;
|
||||
}
|
||||
|
||||
//5号机
|
||||
void formation::Uav5MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav5_current_pose.pose = pose_msgs->pose;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ros::init(argc, argv, "formation/mocap/get_pose");
|
||||
formation Formation;
|
||||
Formation.getpose();
|
||||
return 0;
|
||||
}
|
@ -1,86 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:formation_move.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.16
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中终端输入控制命令相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
|
||||
#include "Formation.h"
|
||||
#include "unistd.h"
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
//创建控制命令发布者
|
||||
cmd_pub = n.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
|
||||
}
|
||||
|
||||
void formation::move()
|
||||
{
|
||||
//初始化
|
||||
init();
|
||||
while(ros::ok())
|
||||
{
|
||||
//打印提示语句,获取用户输入的控制命令
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--------<<<<<<<<<<<<<<<<<<<<<<<<<<< " << std::endl;
|
||||
std::cout << "Please input control command in LOCAL_FRAME: [x]m [y]m [z]m [yaw]radian" << std::endl;
|
||||
//X轴坐标,单位米
|
||||
std::cout << "input [x]_m" << std::endl;
|
||||
std::cin >> control_data.Reference_State.position_ref[0];
|
||||
//Y轴坐标,单位米
|
||||
std::cout << "input [y]_m" << std::endl;
|
||||
std::cin >> control_data.Reference_State.position_ref[1];
|
||||
//Z轴坐标,单位米
|
||||
std::cout << "input [z]_m" << std::endl;
|
||||
//偏航,单位度
|
||||
std::cin >> control_data.Reference_State.position_ref[2];
|
||||
std::cout << "input [yaw]_radian" << std::endl;
|
||||
std::cin >> control_data.Reference_State.yaw_ref;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
std::cout << "control command: " << std::endl
|
||||
<< "x is [" << control_data.Reference_State.position_ref[0] << "]" << std::endl
|
||||
<< "y is [" << control_data.Reference_State.position_ref[1] << "]" << std::endl
|
||||
<< "z is [" << control_data.Reference_State.position_ref[2] << "]" << std::endl
|
||||
<< "yaw is [" << control_data.Reference_State.yaw_ref << "]" << std::endl;
|
||||
std::cout << "---------------------" << std::endl;
|
||||
sleep(1);
|
||||
//检查确认控制命令是否正确
|
||||
std::cout << "Please check whether the control command is correct, input 0 for continue, input 1 for input again" << std::endl;
|
||||
int check_flag;
|
||||
std::cin >> check_flag;
|
||||
if(check_flag == 1)
|
||||
{
|
||||
//打印重新输入的提示信息
|
||||
ROS_WARN("Input error , input again");
|
||||
std::cout << std::endl;
|
||||
sleep(1);
|
||||
//退出当前循环
|
||||
continue;
|
||||
}
|
||||
if(check_flag == 0)
|
||||
{
|
||||
//将控制命令的其他变量进行填充
|
||||
control_data.header.stamp = ros::Time::now();
|
||||
control_data.Mode = prometheus_msgs::ControlCommand::Move;
|
||||
control_data.source = "formation_move";
|
||||
control_data.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
|
||||
//发布控制命令数据
|
||||
cmd_pub.publish(control_data);
|
||||
ROS_INFO("Control command sent");
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
//ROS初始化
|
||||
ros::init(argc, argv, "formation_move");
|
||||
//创建类并执行move函数
|
||||
formation Formation;
|
||||
Formation.move();
|
||||
return 0;
|
||||
}
|
@ -1,517 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:formation_setmode.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.14
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中模式切换相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
#include "Formation.h"
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
//获取相关参数
|
||||
ros::param::param<int>("~OFFBOARD_intervals", offboard_intervals, 3);
|
||||
ros::param::param<int>("~LAND_intervals", land_intervals, 3);
|
||||
ros::param::param<string>("Flight_controller", flight_controller, "spm");
|
||||
ros::param::param<double>("~Takeoff_height", takeoff_height, 1.0);
|
||||
}
|
||||
|
||||
void formation::is_wait(int time)
|
||||
{
|
||||
//判断是否需要等待,time变量不为0,则等待
|
||||
if(time != 0)
|
||||
{
|
||||
sleep(time);
|
||||
}
|
||||
}
|
||||
|
||||
void formation::set_formation_px4_offboard()
|
||||
{
|
||||
//创建1~5号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
command_to_mavros ctm5("uav5");
|
||||
//设置1~5号机模式变量为offboard,解上锁变量为解锁
|
||||
ctm1.arm_cmd.request.value = true;
|
||||
ctm2.arm_cmd.request.value = true;
|
||||
ctm3.arm_cmd.request.value = true;
|
||||
ctm4.arm_cmd.request.value = true;
|
||||
ctm5.arm_cmd.request.value = true;
|
||||
|
||||
ctm1.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm2.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm3.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm4.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm5.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
|
||||
//集群按照23145的顺序对五台无人机分别解锁并切入offboard模式
|
||||
//当有一台无人机解锁或者切入offboard模式失败,该函数返回false
|
||||
//五台无人机成功解锁并切入offboard模式,该函数返回true
|
||||
if(ctm2.arming_client.call(ctm2.arm_cmd) && ctm2.set_mode_client.call(ctm2.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm3.arming_client.call(ctm3.arm_cmd) && ctm3.set_mode_client.call(ctm3.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm1.arming_client.call(ctm1.arm_cmd) && ctm1.set_mode_client.call(ctm1.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm4.arming_client.call(ctm4.arm_cmd) && ctm4.set_mode_client.call(ctm4.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm5.arming_client.call(ctm5.arm_cmd) && ctm5.set_mode_client.call(ctm5.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav5 armed and set offboard mode success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav5 armed and set offboard mode failed");
|
||||
}
|
||||
}
|
||||
|
||||
void formation::set_formation_apm_guided()
|
||||
{
|
||||
//创建1~5号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
command_to_mavros ctm5("uav5");
|
||||
|
||||
//设置1~5号机模式变量为offboard,解上锁变量为解锁以及设置起飞变量高度
|
||||
ctm1.arm_cmd.request.value = true;
|
||||
ctm2.arm_cmd.request.value = true;
|
||||
ctm3.arm_cmd.request.value = true;
|
||||
ctm4.arm_cmd.request.value = true;
|
||||
ctm5.arm_cmd.request.value = true;
|
||||
|
||||
ctm1.mode_cmd.request.custom_mode = "GUIDED";
|
||||
ctm2.mode_cmd.request.custom_mode = "GUIDED";
|
||||
ctm3.mode_cmd.request.custom_mode = "GUIDED";
|
||||
ctm4.mode_cmd.request.custom_mode = "GUIDED";
|
||||
ctm5.mode_cmd.request.custom_mode = "GUIDED";
|
||||
|
||||
uav1_takeoff_cmd.request.altitude = takeoff_height;
|
||||
uav2_takeoff_cmd.request.altitude = takeoff_height;
|
||||
uav3_takeoff_cmd.request.altitude = takeoff_height;
|
||||
uav4_takeoff_cmd.request.altitude = takeoff_height;
|
||||
uav5_takeoff_cmd.request.altitude = takeoff_height;
|
||||
|
||||
if(ctm2.arming_client.call(ctm2.arm_cmd) && ctm2.set_mode_client.call(ctm2.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 armed and set guided mode success");
|
||||
sleep(1);
|
||||
if(uav2_takeoff_client.call(uav2_takeoff_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 takeoff success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 takeoff failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 armed and set guided mode failed");
|
||||
}
|
||||
|
||||
if(ctm3.arming_client.call(ctm3.arm_cmd) && ctm3.set_mode_client.call(ctm3.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 armed and set guided mode success");
|
||||
sleep(1);
|
||||
if(uav3_takeoff_client.call(uav3_takeoff_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 takeoff success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 takeoff failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 armed and set guided mode failed");
|
||||
}
|
||||
|
||||
if(ctm1.arming_client.call(ctm1.arm_cmd) && ctm1.set_mode_client.call(ctm1.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 armed and set guided mode success");
|
||||
sleep(1);
|
||||
if(uav1_takeoff_client.call(uav1_takeoff_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 takeoff success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 takeoff failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 armed and set guided mode failed");
|
||||
}
|
||||
|
||||
if(ctm4.arming_client.call(ctm4.arm_cmd) && ctm4.set_mode_client.call(ctm4.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 armed and set guided mode success");
|
||||
sleep(1);
|
||||
if(uav4_takeoff_client.call(uav4_takeoff_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 takeoff success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 takeoff failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 armed and set guided mode failed");
|
||||
}
|
||||
|
||||
if(ctm5.arming_client.call(ctm5.arm_cmd) && ctm5.set_mode_client.call(ctm5.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav5 armed and set guided mode success");
|
||||
sleep(1);
|
||||
if(uav5_takeoff_client.call(uav5_takeoff_cmd))
|
||||
{
|
||||
ROS_INFO("uav5 takeoff success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav5 takeoff failed");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav5 armed and set guided mode failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void formation::set_formation_px4_land()
|
||||
{
|
||||
//创建1~5号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
command_to_mavros ctm5("uav5");
|
||||
|
||||
//设置1~5号机模式变量为land
|
||||
ctm1.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm2.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm3.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm4.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm5.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
|
||||
//切换为land模式,并对结果进行打印
|
||||
if(ctm2.set_mode_client.call(ctm2.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm3.set_mode_client.call(ctm3.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm1.set_mode_client.call(ctm1.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm4.set_mode_client.call(ctm4.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 set land mode success");
|
||||
}
|
||||
|
||||
if(ctm5.set_mode_client.call(ctm5.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav5 set land mode success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav5 set land mode failed");
|
||||
}
|
||||
}
|
||||
|
||||
void formation::set_formation_apm_land()
|
||||
{
|
||||
//创建1~5号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
command_to_mavros ctm5("uav5");
|
||||
|
||||
//设置1~5号机模式变量为land
|
||||
ctm1.mode_cmd.request.custom_mode = "LAND";
|
||||
ctm2.mode_cmd.request.custom_mode = "LAND";
|
||||
ctm3.mode_cmd.request.custom_mode = "LAND";
|
||||
ctm4.mode_cmd.request.custom_mode = "LAND";
|
||||
ctm5.mode_cmd.request.custom_mode = "LAND";
|
||||
|
||||
//切换为land模式,并对结果进行打印
|
||||
if(ctm2.set_mode_client.call(ctm2.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm3.set_mode_client.call(ctm3.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm1.set_mode_client.call(ctm1.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm4.set_mode_client.call(ctm4.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 set land mode success");
|
||||
}
|
||||
|
||||
if(ctm5.set_mode_client.call(ctm5.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav5 set land mode success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav5 set land mode failed");
|
||||
}
|
||||
}
|
||||
|
||||
void formation::set_formation_disarmed()
|
||||
{
|
||||
//创建1~5号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
command_to_mavros ctm5("uav5");
|
||||
|
||||
//设置1~5号机解上锁变量为false
|
||||
ctm1.arm_cmd.request.value = false;
|
||||
ctm1.arm_cmd.request.value = false;
|
||||
ctm1.arm_cmd.request.value = false;
|
||||
ctm1.arm_cmd.request.value = false;
|
||||
ctm1.arm_cmd.request.value = false;
|
||||
|
||||
//按照23145的顺序调用上锁服务,并根据结果打印相关提示信息
|
||||
if(ctm2.arming_client.call(ctm2.arm_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 disarmed success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 disarmed failed");
|
||||
}
|
||||
|
||||
if(ctm3.arming_client.call(ctm3.arm_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 disarmed success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 disarmed failed");
|
||||
}
|
||||
|
||||
if(ctm1.arming_client.call(ctm1.arm_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 disarmed success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 disarmed failed");
|
||||
}
|
||||
|
||||
if(ctm4.arming_client.call(ctm4.arm_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 disarmed success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 disarmed failed");
|
||||
}
|
||||
|
||||
if(ctm5.arming_client.call(ctm5.arm_cmd))
|
||||
{
|
||||
ROS_INFO("uav5 disarmed success");
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav5 disarmed failed");
|
||||
}
|
||||
}
|
||||
|
||||
void formation::set_mode()
|
||||
{
|
||||
//初始化,创建服务调用后客户端以及获取参数
|
||||
init();
|
||||
while(ros::ok())
|
||||
{
|
||||
//创建变量用以获取用户输入的值
|
||||
int mode;
|
||||
//打印提示信息
|
||||
if(flight_controller == "px4")
|
||||
{
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--------<<<<<<<<<<<<<<<<<<<<<<<<<<< " << std::endl;
|
||||
std::cout << "Input the drone state: 0 for armed and offboard, 1 for land, 2 for disarmed" << std::endl;
|
||||
//获取用户输入的值
|
||||
std::cin >> formation_mode;
|
||||
switch(formation_mode)
|
||||
{
|
||||
//offboard模式
|
||||
case 0:
|
||||
set_formation_px4_offboard();
|
||||
break;
|
||||
|
||||
//land模式
|
||||
case 1:
|
||||
set_formation_px4_land();
|
||||
break;
|
||||
|
||||
//上锁
|
||||
case 2:
|
||||
set_formation_disarmed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(flight_controller == "apm")
|
||||
{
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>--------<<<<<<<<<<<<<<<<<<<<<<<<<<< " << std::endl;
|
||||
std::cout << "Input the drone state: 0 for armed guided and takeoff, 1 for land, 2 for disarmed" << std::endl;
|
||||
//获取用户输入的值
|
||||
std::cin >> formation_mode;
|
||||
switch(formation_mode)
|
||||
{
|
||||
//guided模式
|
||||
case 0:
|
||||
set_formation_apm_guided();
|
||||
break;
|
||||
|
||||
//land模式
|
||||
case 1:
|
||||
set_formation_apm_land();
|
||||
break;
|
||||
|
||||
//上锁
|
||||
case 2:
|
||||
set_formation_disarmed();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ros::init(argc, argv, "formation_set_mode");
|
||||
formation Formation;
|
||||
Formation.set_mode();
|
||||
return 0;
|
||||
}
|
@ -1,507 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:mocap_formation_control.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.11.20
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中四机绕圈相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
#include "ros/ros.h"
|
||||
#include "Formation.h"
|
||||
#include <unistd.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <mavros_msgs/PositionTarget.h>
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
|
||||
//集群四台飞机位置控制数据发布者
|
||||
uav1_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav1/mavros/setpoint_raw/local", 10);
|
||||
uav2_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav2/mavros/setpoint_raw/local", 10);
|
||||
uav3_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav3/mavros/setpoint_raw/local", 10);
|
||||
uav4_local_pub = n.advertise<mavros_msgs::PositionTarget>("/uav4/mavros/setpoint_raw/local", 10);
|
||||
|
||||
//读取相关参数
|
||||
ros::param::param<double>("~square_length", square_length, 4);
|
||||
ros::param::param<double>("~13_height", point13_height, 1);
|
||||
ros::param::param<double>("~24_height", point24_height, 0.5);
|
||||
ros::param::param<double>("~hold_time", hold_time, 10);
|
||||
ros::param::param<double>("~stage1_time", stage1_time, 5);
|
||||
ros::param::param<int>("~LAND_intervals", land_intervals, 3);
|
||||
ros::param::param<bool>("~sim", sim, false);
|
||||
ros::param::param<double>("uav1_x", uav1_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav1_y", uav1_gazebo_offset_pose[1], 0);
|
||||
ros::param::param<double>("uav2_x", uav2_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav2_y", uav2_gazebo_offset_pose[1], 0);
|
||||
ros::param::param<double>("uav3_x", uav3_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav3_y", uav3_gazebo_offset_pose[1], 0);
|
||||
ros::param::param<double>("uav4_x", uav4_gazebo_offset_pose[0], 0);
|
||||
ros::param::param<double>("uav4_y", uav4_gazebo_offset_pose[1], 0);
|
||||
}
|
||||
|
||||
void formation::is_sim()
|
||||
{
|
||||
if(!sim)
|
||||
{
|
||||
uav1_gazebo_offset_pose[0] = 0;
|
||||
uav1_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav2_gazebo_offset_pose[0] = 0;
|
||||
uav2_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav3_gazebo_offset_pose[0] = 0;
|
||||
uav3_gazebo_offset_pose[1] = 0;
|
||||
|
||||
uav4_gazebo_offset_pose[0] = 0;
|
||||
uav4_gazebo_offset_pose[1] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void formation::square()
|
||||
{
|
||||
init();
|
||||
is_sim();
|
||||
while(ros::ok())
|
||||
{
|
||||
std::cout << "Please input 1 start square formation" << std::endl;
|
||||
int start_flag;
|
||||
std::cin >> start_flag;
|
||||
if(start_flag == 1)
|
||||
{
|
||||
//阶段1
|
||||
int stage = 1;
|
||||
if(stage == 1)
|
||||
{
|
||||
int count = 0;
|
||||
int num = (stage1_time + hold_time) * 10;
|
||||
uav1_desired_pose.type_mask = 0b100111111000;
|
||||
uav1_desired_pose.coordinate_frame = 1;
|
||||
uav1_desired_pose.position.x = square_length/2 - uav1_gazebo_offset_pose[0];
|
||||
uav1_desired_pose.position.y = square_length/2 - uav1_gazebo_offset_pose[1];
|
||||
uav1_desired_pose.position.z = point13_height;
|
||||
|
||||
uav2_desired_pose.type_mask = 0b100111111000;
|
||||
uav2_desired_pose.coordinate_frame = 1;
|
||||
uav2_desired_pose.position.x = square_length/2 - uav2_gazebo_offset_pose[0];
|
||||
uav2_desired_pose.position.y = -square_length/2 - uav2_gazebo_offset_pose[1];
|
||||
uav2_desired_pose.position.z = point24_height;
|
||||
|
||||
uav3_desired_pose.type_mask = 0b100111111000;
|
||||
uav3_desired_pose.coordinate_frame = 1;
|
||||
uav3_desired_pose.position.x = -square_length/2 - uav3_gazebo_offset_pose[0];
|
||||
uav3_desired_pose.position.y = -square_length/2 - uav3_gazebo_offset_pose[1];
|
||||
uav3_desired_pose.position.z = point13_height;
|
||||
|
||||
uav4_desired_pose.type_mask = 0b100111111000;
|
||||
uav4_desired_pose.coordinate_frame = 1;
|
||||
uav4_desired_pose.position.x = -square_length/2 - uav4_gazebo_offset_pose[0];
|
||||
uav4_desired_pose.position.y = square_length/2 - uav4_gazebo_offset_pose[1];
|
||||
uav4_desired_pose.position.z = point24_height;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
uav1_desired_pose.header.stamp = ros::Time::now();
|
||||
uav1_local_pub.publish(uav1_desired_pose);
|
||||
uav2_desired_pose.header.stamp = ros::Time::now();
|
||||
uav2_local_pub.publish(uav2_desired_pose);
|
||||
uav3_desired_pose.header.stamp = ros::Time::now();
|
||||
uav3_local_pub.publish(uav3_desired_pose);
|
||||
uav4_desired_pose.header.stamp = ros::Time::now();
|
||||
uav4_local_pub.publish(uav4_desired_pose);
|
||||
if(count == 0)
|
||||
{
|
||||
set_formation_px4_offboard();
|
||||
}
|
||||
count++;
|
||||
if(count >= num)
|
||||
{
|
||||
stage = 2;
|
||||
break;
|
||||
}
|
||||
ROS_INFO("go to point 1");
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
if(stage == 2)
|
||||
{
|
||||
int count = 0;
|
||||
int num = hold_time * 10;
|
||||
uav1_desired_pose.type_mask = 0b100111111000;
|
||||
uav1_desired_pose.coordinate_frame = 1;
|
||||
uav1_desired_pose.position.x = square_length/2 - uav1_gazebo_offset_pose[0];
|
||||
uav1_desired_pose.position.y = -square_length/2 - uav1_gazebo_offset_pose[1];
|
||||
uav1_desired_pose.position.z = point24_height;
|
||||
|
||||
uav2_desired_pose.type_mask = 0b100111111000;
|
||||
uav2_desired_pose.coordinate_frame = 1;
|
||||
uav2_desired_pose.position.x = -square_length/2 - uav2_gazebo_offset_pose[0];
|
||||
uav2_desired_pose.position.y = -square_length/2 - uav2_gazebo_offset_pose[1];
|
||||
uav2_desired_pose.position.z = point13_height;
|
||||
|
||||
uav3_desired_pose.type_mask = 0b100111111000;
|
||||
uav3_desired_pose.coordinate_frame = 1;
|
||||
uav3_desired_pose.position.x = -square_length/2 - uav3_gazebo_offset_pose[0];
|
||||
uav3_desired_pose.position.y = square_length/2 - uav3_gazebo_offset_pose[1];
|
||||
uav3_desired_pose.position.z = point24_height;
|
||||
|
||||
uav4_desired_pose.type_mask = 0b100111111000;
|
||||
uav4_desired_pose.coordinate_frame = 1;
|
||||
uav4_desired_pose.position.x = square_length/2 - uav4_gazebo_offset_pose[0];
|
||||
uav4_desired_pose.position.y = square_length/2 - uav4_gazebo_offset_pose[1];
|
||||
uav4_desired_pose.position.z = point13_height;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
uav1_desired_pose.header.stamp = ros::Time::now();
|
||||
uav1_local_pub.publish(uav1_desired_pose);
|
||||
uav2_desired_pose.header.stamp = ros::Time::now();
|
||||
uav2_local_pub.publish(uav2_desired_pose);
|
||||
uav3_desired_pose.header.stamp = ros::Time::now();
|
||||
uav3_local_pub.publish(uav3_desired_pose);
|
||||
uav4_desired_pose.header.stamp = ros::Time::now();
|
||||
uav4_local_pub.publish(uav4_desired_pose);
|
||||
count++;
|
||||
if(count >= num)
|
||||
{
|
||||
stage = 3;
|
||||
break;
|
||||
}
|
||||
ROS_INFO("go to point 2");
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
if(stage == 3)
|
||||
{
|
||||
int count = 0;
|
||||
int num = hold_time * 10;
|
||||
uav1_desired_pose.type_mask = 0b100111111000;
|
||||
uav1_desired_pose.coordinate_frame = 1;
|
||||
uav1_desired_pose.position.x = -square_length/2 - uav1_gazebo_offset_pose[0];
|
||||
uav1_desired_pose.position.y = -square_length/2 - uav1_gazebo_offset_pose[1];
|
||||
uav1_desired_pose.position.z = point13_height;
|
||||
|
||||
uav2_desired_pose.type_mask = 0b100111111000;
|
||||
uav2_desired_pose.coordinate_frame = 1;
|
||||
uav2_desired_pose.position.x = -square_length/2 - uav2_gazebo_offset_pose[0];
|
||||
uav2_desired_pose.position.y = square_length/2 - uav2_gazebo_offset_pose[1];
|
||||
uav2_desired_pose.position.z = point24_height;
|
||||
|
||||
uav3_desired_pose.type_mask = 0b100111111000;
|
||||
uav3_desired_pose.coordinate_frame = 1;
|
||||
uav3_desired_pose.position.x = square_length/2 - uav3_gazebo_offset_pose[0];
|
||||
uav3_desired_pose.position.y = square_length/2 - uav3_gazebo_offset_pose[1];
|
||||
uav3_desired_pose.position.z = point13_height;
|
||||
|
||||
uav4_desired_pose.type_mask = 0b100111111000;
|
||||
uav4_desired_pose.coordinate_frame = 1;
|
||||
uav4_desired_pose.position.x = square_length/2 - uav4_gazebo_offset_pose[0];
|
||||
uav4_desired_pose.position.y = -square_length/2 - uav4_gazebo_offset_pose[1];
|
||||
uav4_desired_pose.position.z = point24_height;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
uav1_desired_pose.header.stamp = ros::Time::now();
|
||||
uav1_local_pub.publish(uav1_desired_pose);
|
||||
uav2_desired_pose.header.stamp = ros::Time::now();
|
||||
uav2_local_pub.publish(uav2_desired_pose);
|
||||
uav3_desired_pose.header.stamp = ros::Time::now();
|
||||
uav3_local_pub.publish(uav3_desired_pose);
|
||||
uav4_desired_pose.header.stamp = ros::Time::now();
|
||||
uav4_local_pub.publish(uav4_desired_pose);
|
||||
count++;
|
||||
if(count >= num)
|
||||
{
|
||||
stage = 4;
|
||||
break;
|
||||
}
|
||||
ROS_INFO("go to point 3");
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
if(stage == 4)
|
||||
{
|
||||
int count = 0;
|
||||
int num = hold_time * 10;
|
||||
uav1_desired_pose.type_mask = 0b100111111000;
|
||||
uav1_desired_pose.coordinate_frame = 1;
|
||||
uav1_desired_pose.position.x = -square_length/2 - uav1_gazebo_offset_pose[0];
|
||||
uav1_desired_pose.position.y = square_length/2 - uav1_gazebo_offset_pose[1];
|
||||
uav1_desired_pose.position.z = point24_height;
|
||||
|
||||
uav2_desired_pose.type_mask = 0b100111111000;
|
||||
uav2_desired_pose.coordinate_frame = 1;
|
||||
uav2_desired_pose.position.x = square_length/2 - uav2_gazebo_offset_pose[0];
|
||||
uav2_desired_pose.position.y = square_length/2 - uav2_gazebo_offset_pose[1];
|
||||
uav2_desired_pose.position.z = point13_height;
|
||||
|
||||
uav3_desired_pose.type_mask = 0b100111111000;
|
||||
uav3_desired_pose.coordinate_frame = 1;
|
||||
uav3_desired_pose.position.x = square_length/2 - uav3_gazebo_offset_pose[0];
|
||||
uav3_desired_pose.position.y = -square_length/2 - uav3_gazebo_offset_pose[1];
|
||||
uav3_desired_pose.position.z = point24_height;
|
||||
|
||||
uav4_desired_pose.type_mask = 0b100111111000;
|
||||
uav4_desired_pose.coordinate_frame = 1;
|
||||
uav4_desired_pose.position.x = -square_length/2 - uav4_gazebo_offset_pose[0];
|
||||
uav4_desired_pose.position.y = -square_length/2 - uav4_gazebo_offset_pose[1];
|
||||
uav4_desired_pose.position.z = point13_height;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
uav1_desired_pose.header.stamp = ros::Time::now();
|
||||
uav1_local_pub.publish(uav1_desired_pose);
|
||||
uav2_desired_pose.header.stamp = ros::Time::now();
|
||||
uav2_local_pub.publish(uav2_desired_pose);
|
||||
uav3_desired_pose.header.stamp = ros::Time::now();
|
||||
uav3_local_pub.publish(uav3_desired_pose);
|
||||
uav4_desired_pose.header.stamp = ros::Time::now();
|
||||
uav4_local_pub.publish(uav4_desired_pose);
|
||||
count++;
|
||||
if(count >= num)
|
||||
{
|
||||
stage = 5;
|
||||
break;
|
||||
}
|
||||
ROS_INFO("go to point 4");
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
|
||||
if(stage == 5)
|
||||
{
|
||||
int count = 0;
|
||||
int num = hold_time * 10;
|
||||
uav1_desired_pose.type_mask = 0b100111111000;
|
||||
uav1_desired_pose.coordinate_frame = 1;
|
||||
uav1_desired_pose.position.x = square_length/2 - uav1_gazebo_offset_pose[0];
|
||||
uav1_desired_pose.position.y = square_length/2 - uav1_gazebo_offset_pose[1];
|
||||
uav1_desired_pose.position.z = point13_height;
|
||||
|
||||
uav2_desired_pose.type_mask = 0b100111111000;
|
||||
uav2_desired_pose.coordinate_frame = 1;
|
||||
uav2_desired_pose.position.x = square_length/2 - uav2_gazebo_offset_pose[0];
|
||||
uav2_desired_pose.position.y = -square_length/2 - uav2_gazebo_offset_pose[1];
|
||||
uav2_desired_pose.position.z = point24_height;
|
||||
|
||||
uav3_desired_pose.type_mask = 0b100111111000;
|
||||
uav3_desired_pose.coordinate_frame = 1;
|
||||
uav3_desired_pose.position.x = -square_length/2 - uav3_gazebo_offset_pose[0];
|
||||
uav3_desired_pose.position.y = -square_length/2 - uav3_gazebo_offset_pose[1];
|
||||
uav3_desired_pose.position.z = point13_height;
|
||||
|
||||
uav4_desired_pose.type_mask = 0b100111111000;
|
||||
uav4_desired_pose.coordinate_frame = 1;
|
||||
uav4_desired_pose.position.x = -square_length/2 - uav4_gazebo_offset_pose[0];
|
||||
uav4_desired_pose.position.y = square_length/2 - uav4_gazebo_offset_pose[1];
|
||||
uav4_desired_pose.position.z = point24_height;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
uav1_desired_pose.header.stamp = ros::Time::now();
|
||||
uav1_local_pub.publish(uav1_desired_pose);
|
||||
uav2_desired_pose.header.stamp = ros::Time::now();
|
||||
uav2_local_pub.publish(uav2_desired_pose);
|
||||
uav3_desired_pose.header.stamp = ros::Time::now();
|
||||
uav3_local_pub.publish(uav3_desired_pose);
|
||||
uav4_desired_pose.header.stamp = ros::Time::now();
|
||||
uav4_local_pub.publish(uav4_desired_pose);
|
||||
count++;
|
||||
if(count >= num)
|
||||
{
|
||||
//四机降落
|
||||
set_formation_px4_land();
|
||||
break;
|
||||
}
|
||||
ROS_INFO("go to point 1");
|
||||
usleep(100000);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_WARN("input error, please input again");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void formation::is_wait(int time)
|
||||
{
|
||||
//判断是否需要等待,time变量不为0,则等待
|
||||
if(time != 0)
|
||||
{
|
||||
sleep(time);
|
||||
}
|
||||
}
|
||||
|
||||
void formation::set_formation_px4_offboard()
|
||||
{
|
||||
//创建1~4号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
//设置1~4号机模式变量为offboard,解上锁变量为解锁
|
||||
ctm1.arm_cmd.request.value = true;
|
||||
ctm2.arm_cmd.request.value = true;
|
||||
ctm3.arm_cmd.request.value = true;
|
||||
ctm4.arm_cmd.request.value = true;
|
||||
|
||||
ctm1.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm2.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm3.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
ctm4.mode_cmd.request.custom_mode = "OFFBOARD";
|
||||
|
||||
//集群按照1234的顺序对五台无人机分别解锁并切入offboard模式
|
||||
//当有一台无人机解锁或者切入offboard模式失败,该函数返回false
|
||||
//五台无人机成功解锁并切入offboard模式,该函数返回true
|
||||
if(ctm1.arming_client.call(ctm1.arm_cmd) && ctm1.set_mode_client.call(ctm1.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm2.arming_client.call(ctm2.arm_cmd) && ctm2.set_mode_client.call(ctm2.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm3.arming_client.call(ctm3.arm_cmd) && ctm3.set_mode_client.call(ctm3.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
if(ctm4.arming_client.call(ctm4.arm_cmd) && ctm4.set_mode_client.call(ctm4.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 armed and set offboard mode success");
|
||||
is_wait(offboard_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 armed and set offboard mode failed");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void formation::set_formation_px4_land()
|
||||
{
|
||||
//创建1~4号机的command_to_mavros类
|
||||
command_to_mavros ctm1("uav1");
|
||||
|
||||
command_to_mavros ctm2("uav2");
|
||||
|
||||
command_to_mavros ctm3("uav3");
|
||||
|
||||
command_to_mavros ctm4("uav4");
|
||||
|
||||
//设置1~4号机模式变量为land
|
||||
ctm1.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm2.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm3.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
ctm4.mode_cmd.request.custom_mode = "AUTO.LAND";
|
||||
|
||||
//切换为land模式,并对结果进行打印
|
||||
if(ctm1.set_mode_client.call(ctm1.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav1 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav1 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm2.set_mode_client.call(ctm2.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav2 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav2 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm3.set_mode_client.call(ctm3.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav3 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav3 set land mode failed");
|
||||
}
|
||||
|
||||
if(ctm4.set_mode_client.call(ctm4.mode_cmd))
|
||||
{
|
||||
ROS_INFO("uav4 set land mode success");
|
||||
is_wait(land_intervals);
|
||||
}
|
||||
else
|
||||
{
|
||||
ROS_ERROR("uav4 set land mode success");
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ros::init(argc, argv, "formation_square");
|
||||
formation Formation;
|
||||
Formation.square();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -1,263 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:formation_control.cpp
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.14
|
||||
*
|
||||
* 介绍:该cpp文件主要为动捕集群中集群控制相关函数的实现以及程序的运行
|
||||
* ****************************************************************/
|
||||
#include "Formation.h"
|
||||
#include <unistd.h>
|
||||
|
||||
void formation::init()
|
||||
{
|
||||
//集群五台飞机状态订阅回调函数
|
||||
uav1_state_sub = n.subscribe("/uav1/mavros/state", 10, &formation::Uav1StateCallBack, this);
|
||||
uav2_state_sub = n.subscribe("/uav2/mavros/state", 10, &formation::Uav2StateCallBack, this);
|
||||
uav3_state_sub = n.subscribe("/uav3/mavros/state", 10, &formation::Uav3StateCallBack, this);
|
||||
uav4_state_sub = n.subscribe("/uav4/mavros/state", 10, &formation::Uav4StateCallBack, this);
|
||||
uav5_state_sub = n.subscribe("/uav5/mavros/state", 10, &formation::Uav5StateCallBack, this);
|
||||
|
||||
uav1_pose_sub = n.subscribe("/uav1/mavros/local_position/pose", 10, &formation::Uav1PoseCallBack, this);
|
||||
uav2_pose_sub = n.subscribe("/uav2/mavros/local_position/pose", 10, &formation::Uav2PoseCallBack, this);
|
||||
uav3_pose_sub = n.subscribe("/uav3/mavros/local_position/pose", 10, &formation::Uav3PoseCallBack, this);
|
||||
uav4_pose_sub = n.subscribe("/uav4/mavros/local_position/pose", 10, &formation::Uav4PoseCallBack, this);
|
||||
uav5_pose_sub = n.subscribe("/uav5/mavros/local_position/pose", 10, &formation::Uav5PoseCallBack, this);
|
||||
|
||||
//设置程序初始时间
|
||||
begin_time = ros::Time::now();
|
||||
}
|
||||
|
||||
//获取1号机位置数据回调函数
|
||||
void formation::Uav1PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav1_current_pose = *pose_msgs;
|
||||
}
|
||||
|
||||
//获取2号机位置数据回调函数
|
||||
void formation::Uav2PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav2_current_pose = *pose_msgs;
|
||||
}
|
||||
|
||||
//获取3号机位置数据回调函数
|
||||
void formation::Uav3PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav3_current_pose = *pose_msgs;
|
||||
}
|
||||
|
||||
//获取4号机位置数据回调函数
|
||||
void formation::Uav4PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav4_current_pose = *pose_msgs;
|
||||
}
|
||||
|
||||
//获取5号机位置数据回调函数
|
||||
void formation::Uav5PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs)
|
||||
{
|
||||
uav5_current_pose = *pose_msgs;
|
||||
}
|
||||
|
||||
//打印无人机状态函数
|
||||
void formation::printf_formation_state()
|
||||
{
|
||||
//固定的浮点显示
|
||||
std::cout.setf(std::ios::fixed);
|
||||
//设置小数点后精度为2位
|
||||
std::cout<<std::setprecision(2);
|
||||
//左对齐
|
||||
std::cout.setf(std::ios::left);
|
||||
//显示小数点
|
||||
std::cout.setf(std::ios::showpoint);
|
||||
//强制显示符号
|
||||
std::cout.setf(std::ios::showpos);
|
||||
//打印时间戳
|
||||
std::cout << "Time : " << ros::Time::now().sec - begin_time.sec << std::endl;
|
||||
//1号机
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>UAV1 State<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
|
||||
//是否与飞控连接
|
||||
if(uav1_state.connected == true)
|
||||
{
|
||||
std::cout << " [Connected] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [Unconnected] ";
|
||||
}
|
||||
//是否上锁
|
||||
if(uav1_state.armed == true)
|
||||
{
|
||||
std::cout << " [ Armed ] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [ DisArmed ] ";
|
||||
}
|
||||
|
||||
//1号机当前模式
|
||||
std::cout << " [ " << uav1_state.mode << " ] " << std::endl;
|
||||
//1号机当前位置
|
||||
std::cout << "Position_uav1 [X Y Z]: " << uav1_current_pose.pose.position.x << "[ m ]" << uav1_current_pose.pose.position.y << "[ m ]" << uav1_current_pose.pose.position.z << "[ m ]" << std::endl;
|
||||
|
||||
//2号机
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>UAV2 State<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
|
||||
//是否与飞控连接
|
||||
if(uav2_state.connected == true)
|
||||
{
|
||||
std::cout << " [Connected] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [Unconnected] ";
|
||||
}
|
||||
//是否上锁
|
||||
if(uav2_state.armed == true)
|
||||
{
|
||||
std::cout << " [ Armed ] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [ DisArmed ] ";
|
||||
}
|
||||
|
||||
//2号机当前模式
|
||||
std::cout << " [ " << uav2_state.mode << " ] " << std::endl;
|
||||
//2号机当前位置
|
||||
std::cout << "Position_uav2 [X Y Z]: " << uav2_current_pose.pose.position.x << "[ m ]" << uav2_current_pose.pose.position.y << "[ m ]" << uav2_current_pose.pose.position.z << "[ m ]" << std::endl;
|
||||
|
||||
//3号机
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>UAV3 State<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
|
||||
//是否与飞控连接
|
||||
if(uav3_state.connected == true)
|
||||
{
|
||||
std::cout << " [Connected] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [Unconnected] ";
|
||||
}
|
||||
//是否上锁
|
||||
if(uav3_state.armed == true)
|
||||
{
|
||||
std::cout << " [ Armed ] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [ DisArmed ] ";
|
||||
}
|
||||
|
||||
//3号机当前模式
|
||||
std::cout << " [ " << uav3_state.mode << " ] " << std::endl;
|
||||
//3号机当前位置
|
||||
std::cout << "Position_uav3 [X Y Z]: " << uav3_current_pose.pose.position.x << "[ m ]" << uav3_current_pose.pose.position.y << "[ m ]" << uav3_current_pose.pose.position.z << "[ m ]" << std::endl;
|
||||
|
||||
//4号机
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>UAV4 State<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
|
||||
//是否与飞控连接
|
||||
if(uav4_state.connected == true)
|
||||
{
|
||||
std::cout << " [Connected] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [Unconnected] ";
|
||||
}
|
||||
//是否上锁
|
||||
if(uav4_state.armed == true)
|
||||
{
|
||||
std::cout << " [ Armed ] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [ DisArmed ] ";
|
||||
}
|
||||
|
||||
//4号机当前模式
|
||||
std::cout << " [ " << uav4_state.mode << " ] " << std::endl;
|
||||
//4号机当前位置
|
||||
std::cout << "Position_uav4 [X Y Z]: " << uav4_current_pose.pose.position.x << "[ m ]" << uav4_current_pose.pose.position.y << "[ m ]" << uav4_current_pose.pose.position.z << "[ m ]" << std::endl;
|
||||
|
||||
//5号机
|
||||
std::cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>UAV5 State<<<<<<<<<<<<<<<<<<<<<<<<<<<" << std::endl;
|
||||
//是否与飞控连接
|
||||
if(uav5_state.connected == true)
|
||||
{
|
||||
std::cout << " [Connected] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [Unconnected] ";
|
||||
}
|
||||
//是否上锁
|
||||
if(uav5_state.armed == true)
|
||||
{
|
||||
std::cout << " [ Armed ] ";
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << " [ DisArmed ] ";
|
||||
}
|
||||
|
||||
//5号机当前模式
|
||||
std::cout << " [ " << uav5_state.mode << " ] " << std::endl;
|
||||
//5号机当前位置
|
||||
std::cout << "Position_uav5 [X Y Z]: " << uav5_current_pose.pose.position.x << "[ m ]" << uav5_current_pose.pose.position.y << "[ m ]" << uav5_current_pose.pose.position.z << "[ m ]" << std::endl;
|
||||
}
|
||||
|
||||
//集群控制函数
|
||||
void formation::state()
|
||||
{
|
||||
//初始化
|
||||
init();
|
||||
while(ros::ok())
|
||||
{
|
||||
//处理回调函数
|
||||
ros::spinOnce();
|
||||
//打印无人机相关信息
|
||||
printf_formation_state();
|
||||
//等待0.05秒
|
||||
usleep(50000);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//集群五台无人机状态读取
|
||||
|
||||
//1号机
|
||||
void formation::Uav1StateCallBack(const mavros_msgs::StateConstPtr &state_msgs)
|
||||
{
|
||||
uav1_state = *state_msgs;
|
||||
}
|
||||
|
||||
//2号机
|
||||
void formation::Uav2StateCallBack(const mavros_msgs::StateConstPtr &state_msgs)
|
||||
{
|
||||
uav2_state = *state_msgs;
|
||||
}
|
||||
|
||||
//3号机
|
||||
void formation::Uav3StateCallBack(const mavros_msgs::StateConstPtr &state_msgs)
|
||||
{
|
||||
uav3_state = *state_msgs;
|
||||
}
|
||||
|
||||
//4号机
|
||||
void formation::Uav4StateCallBack(const mavros_msgs::StateConstPtr &state_msgs)
|
||||
{
|
||||
uav4_state = *state_msgs;
|
||||
}
|
||||
|
||||
//5号机
|
||||
void formation::Uav5StateCallBack(const mavros_msgs::StateConstPtr &state_msgs)
|
||||
{
|
||||
uav5_state = *state_msgs;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
ros::init(argc, argv, "formation_state");
|
||||
formation Formation;
|
||||
Formation.state();
|
||||
return 0;
|
||||
}
|
@ -1,180 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
|
||||
//topic 头文件
|
||||
#include <geometry_msgs/Point.h>
|
||||
#include <prometheus_msgs/ControlCommand.h>
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
#include <prometheus_msgs/DetectionInfo.h>
|
||||
#include <prometheus_msgs/PositionReference.h>
|
||||
#include <nav_msgs/Odometry.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 <prometheus_msgs/DroneState.h>
|
||||
#include <nav_msgs/Path.h>
|
||||
#include <std_msgs/Int8.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
# define NODE_NAME "turtlebot_formation"
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>全 局 变 量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
nav_msgs::Odometry tb3_1_odom;
|
||||
nav_msgs::Odometry tb3_2_odom;
|
||||
nav_msgs::Odometry tb3_3_odom;
|
||||
nav_msgs::Odometry tb3_4_odom;
|
||||
|
||||
geometry_msgs::Twist tb3_1_cmd;
|
||||
geometry_msgs::Twist tb3_2_cmd;
|
||||
geometry_msgs::Twist tb3_3_cmd;
|
||||
geometry_msgs::Twist tb3_4_cmd;
|
||||
|
||||
prometheus_msgs::DroneState uav1_state;
|
||||
prometheus_msgs::DroneState uav2_state;
|
||||
prometheus_msgs::DroneState uav3_state;
|
||||
prometheus_msgs::DroneState uav4_state;
|
||||
|
||||
void tb3_1_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_1_odom = *msg;
|
||||
}
|
||||
|
||||
void tb3_2_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_2_odom = *msg;
|
||||
}
|
||||
|
||||
void tb3_3_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_3_odom = *msg;
|
||||
}
|
||||
|
||||
void tb3_4_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_4_odom = *msg;
|
||||
}
|
||||
|
||||
void uav1_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
uav1_state = *msg;
|
||||
}
|
||||
void uav2_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
uav2_state = *msg;
|
||||
}
|
||||
void uav3_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
uav3_state = *msg;
|
||||
}
|
||||
void uav4_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
uav4_state = *msg;
|
||||
}
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "turtlebot_formation");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
ros::Subscriber tb3_1_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_1/odom", 10, tb3_1_odom_cb);
|
||||
ros::Subscriber tb3_2_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_2/odom", 10, tb3_2_odom_cb);
|
||||
ros::Subscriber tb3_3_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_3/odom", 10, tb3_3_odom_cb);
|
||||
ros::Subscriber tb3_4_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_4/odom", 10, tb3_4_odom_cb);
|
||||
|
||||
ros::Subscriber uav1_sub = nh.subscribe<prometheus_msgs::DroneState>("/uav1/prometheus/drone_state", 1, uav1_cb);
|
||||
ros::Subscriber uav2_sub = nh.subscribe<prometheus_msgs::DroneState>("/uav2/prometheus/drone_state", 1, uav2_cb);
|
||||
ros::Subscriber uav3_sub = nh.subscribe<prometheus_msgs::DroneState>("/uav3/prometheus/drone_state", 1, uav3_cb);
|
||||
ros::Subscriber uav4_sub = nh.subscribe<prometheus_msgs::DroneState>("/uav4/prometheus/drone_state", 1, uav4_cb);
|
||||
|
||||
// 【发布】用于地面站显示的提示消息
|
||||
ros::Publisher message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
|
||||
|
||||
ros::Publisher tb3_1_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_1/cmd_vel", 10);
|
||||
ros::Publisher tb3_2_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_2/cmd_vel", 10);
|
||||
ros::Publisher tb3_3_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_3/cmd_vel", 10);
|
||||
ros::Publisher tb3_4_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_4/cmd_vel", 10);
|
||||
|
||||
//固定的浮点显示
|
||||
cout.setf(ios::fixed);
|
||||
//setprecision(n) 设显示小数精度为n位
|
||||
cout<<setprecision(4);
|
||||
//左对齐
|
||||
cout.setf(ios::left);
|
||||
// 强制显示小数点
|
||||
cout.setf(ios::showpoint);
|
||||
// 强制显示符号
|
||||
cout.setf(ios::showpos);
|
||||
|
||||
// Waiting for input
|
||||
int start_flag = 0;
|
||||
|
||||
ros::Rate rate(50.0);
|
||||
|
||||
while(start_flag == 0)
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>turtlebot_formation Mission<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "Please enter 1 to move the turtlebot."<<endl;
|
||||
cin >> start_flag;
|
||||
}
|
||||
|
||||
float time_trajectory = 0.0;
|
||||
|
||||
ros::Duration(2.0).sleep();
|
||||
|
||||
float kp = 0.5;
|
||||
|
||||
float x_sp,y_sp;
|
||||
while (ros::ok())
|
||||
{
|
||||
// turtlebot3命令发布
|
||||
tb3_1_cmd.linear.x = kp * (uav1_state.position[0] - tb3_1_odom.pose.pose.position.x);
|
||||
tb3_1_cmd.linear.y = kp * (uav1_state.position[1] - tb3_1_odom.pose.pose.position.y);
|
||||
tb3_1_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_1_cmd.angular.x = 0.0;
|
||||
tb3_1_cmd.angular.y = 0.0;
|
||||
tb3_1_cmd.angular.z = 0.0;
|
||||
|
||||
tb3_2_cmd.linear.x = kp * (uav2_state.position[0] - tb3_2_odom.pose.pose.position.x);
|
||||
tb3_2_cmd.linear.y = kp * (uav2_state.position[1] - tb3_2_odom.pose.pose.position.x);
|
||||
tb3_2_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_2_cmd.angular.x = 0.0;
|
||||
tb3_2_cmd.angular.y = 0.0;
|
||||
tb3_2_cmd.angular.z = 0.0;
|
||||
|
||||
tb3_3_cmd.linear.x = kp * (uav3_state.position[0] - tb3_3_odom.pose.pose.position.x);
|
||||
tb3_3_cmd.linear.y = kp * (uav3_state.position[1] - tb3_3_odom.pose.pose.position.x);
|
||||
tb3_3_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_3_cmd.angular.x = 0.0;
|
||||
tb3_3_cmd.angular.y = 0.0;
|
||||
tb3_3_cmd.angular.z = 0.0;
|
||||
|
||||
tb3_4_cmd.linear.x = kp * (uav4_state.position[0] - tb3_4_odom.pose.pose.position.x);
|
||||
tb3_4_cmd.linear.y = kp * (uav4_state.position[1] - tb3_4_odom.pose.pose.position.x);
|
||||
tb3_4_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_4_cmd.angular.x = 0.0;
|
||||
tb3_4_cmd.angular.y = 0.0;
|
||||
tb3_4_cmd.angular.z = 0.0;
|
||||
|
||||
tb3_1_cmd_pub.publish(tb3_1_cmd);
|
||||
tb3_2_cmd_pub.publish(tb3_2_cmd);
|
||||
tb3_3_cmd_pub.publish(tb3_3_cmd);
|
||||
tb3_4_cmd_pub.publish(tb3_4_cmd);
|
||||
|
||||
rate.sleep();
|
||||
ros::spinOnce();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,151 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
|
||||
//topic 头文件
|
||||
#include <geometry_msgs/Point.h>
|
||||
#include <prometheus_msgs/ControlCommand.h>
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
#include <prometheus_msgs/DetectionInfo.h>
|
||||
#include <prometheus_msgs/PositionReference.h>
|
||||
#include <nav_msgs/Odometry.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 <prometheus_msgs/DroneState.h>
|
||||
#include <nav_msgs/Path.h>
|
||||
#include <std_msgs/Int8.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
# define NODE_NAME "turtlebot_formation"
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>全 局 变 量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
nav_msgs::Odometry tb3_1_odom;
|
||||
nav_msgs::Odometry tb3_2_odom;
|
||||
nav_msgs::Odometry tb3_3_odom;
|
||||
nav_msgs::Odometry tb3_4_odom;
|
||||
|
||||
geometry_msgs::Twist tb3_1_cmd;
|
||||
geometry_msgs::Twist tb3_2_cmd;
|
||||
geometry_msgs::Twist tb3_3_cmd;
|
||||
geometry_msgs::Twist tb3_4_cmd;
|
||||
|
||||
void tb3_1_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_1_odom = *msg;
|
||||
}
|
||||
|
||||
void tb3_2_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_2_odom = *msg;
|
||||
}
|
||||
|
||||
void tb3_3_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_3_odom = *msg;
|
||||
}
|
||||
|
||||
void tb3_4_odom_cb(const nav_msgs::Odometry::ConstPtr& msg)
|
||||
{
|
||||
tb3_4_odom = *msg;
|
||||
}
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "turtlebot_formation");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
ros::Subscriber tb3_1_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_1/odom", 10, tb3_1_odom_cb);
|
||||
ros::Subscriber tb3_2_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_2/odom", 10, tb3_2_odom_cb);
|
||||
ros::Subscriber tb3_3_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_3/odom", 10, tb3_3_odom_cb);
|
||||
ros::Subscriber tb3_4_odom_sub = nh.subscribe<nav_msgs::Odometry>("/tb3_4/odom", 10, tb3_4_odom_cb);
|
||||
|
||||
// 【发布】用于地面站显示的提示消息
|
||||
ros::Publisher message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
|
||||
|
||||
ros::Publisher tb3_1_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_1/cmd_vel", 10);
|
||||
ros::Publisher tb3_2_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_2/cmd_vel", 10);
|
||||
ros::Publisher tb3_3_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_3/cmd_vel", 10);
|
||||
ros::Publisher tb3_4_cmd_pub = nh.advertise<geometry_msgs::Twist>("/tb3_4/cmd_vel", 10);
|
||||
|
||||
//固定的浮点显示
|
||||
cout.setf(ios::fixed);
|
||||
//setprecision(n) 设显示小数精度为n位
|
||||
cout<<setprecision(4);
|
||||
//左对齐
|
||||
cout.setf(ios::left);
|
||||
// 强制显示小数点
|
||||
cout.setf(ios::showpoint);
|
||||
// 强制显示符号
|
||||
cout.setf(ios::showpos);
|
||||
|
||||
// Waiting for input
|
||||
int start_flag = 0;
|
||||
|
||||
ros::Rate rate(50.0);
|
||||
|
||||
while(start_flag == 0)
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>turtlebot_formation Mission<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "Please enter 1 to move the turtlebot."<<endl;
|
||||
cin >> start_flag;
|
||||
}
|
||||
|
||||
float time_trajectory = 0.0;
|
||||
|
||||
ros::Duration(2.0).sleep();
|
||||
|
||||
float x_sp,y_sp;
|
||||
while (ros::ok())
|
||||
{
|
||||
// turtlebot3命令发布
|
||||
tb3_1_cmd.linear.x = 0.4;
|
||||
tb3_1_cmd.linear.y = 0.0;
|
||||
tb3_1_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_1_cmd.angular.x = 0.0;
|
||||
tb3_1_cmd.angular.y = 0.0;
|
||||
tb3_1_cmd.angular.z = 0.2;
|
||||
|
||||
tb3_2_cmd.linear.x = 0.2;
|
||||
tb3_2_cmd.linear.y = 0.0;
|
||||
tb3_2_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_2_cmd.angular.x = 0.0;
|
||||
tb3_2_cmd.angular.y = 0.0;
|
||||
tb3_2_cmd.angular.z = 0.2;
|
||||
|
||||
tb3_3_cmd.linear.x = 0.2;
|
||||
tb3_3_cmd.linear.y = 0.0;
|
||||
tb3_3_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_3_cmd.angular.x = 0.0;
|
||||
tb3_3_cmd.angular.y = 0.0;
|
||||
tb3_3_cmd.angular.z = 0.2;
|
||||
|
||||
tb3_4_cmd.linear.x = 0.4;
|
||||
tb3_4_cmd.linear.y = 0.0;
|
||||
tb3_4_cmd.linear.z = 0.0;
|
||||
|
||||
tb3_4_cmd.angular.x = 0.0;
|
||||
tb3_4_cmd.angular.y = 0.0;
|
||||
tb3_4_cmd.angular.z = 0.2;
|
||||
|
||||
tb3_1_cmd_pub.publish(tb3_1_cmd);
|
||||
tb3_2_cmd_pub.publish(tb3_2_cmd);
|
||||
tb3_3_cmd_pub.publish(tb3_3_cmd);
|
||||
tb3_4_cmd_pub.publish(tb3_4_cmd);
|
||||
|
||||
rate.sleep();
|
||||
ros::spinOnce();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,417 +0,0 @@
|
||||
/*******************************************************************
|
||||
* 文件名:Formation.h
|
||||
*
|
||||
* 作者: BOSHEN97
|
||||
*
|
||||
* 更新时间: 2020.10.12
|
||||
*
|
||||
* 介绍:该头文件主要声明动捕系统定位下的无人机集群功能当中的变量以及函数等,包含以下功能模块:
|
||||
* 1. 模式切换
|
||||
* 2. 队形变换
|
||||
* 3. 集群控制
|
||||
* ****************************************************************/
|
||||
#ifndef FORMATION_H
|
||||
#define FORMATION_H
|
||||
|
||||
#include "command_to_mavros.h"
|
||||
#include <ros/ros.h>
|
||||
#include <mavros_msgs/PositionTarget.h>
|
||||
#include <mavros_msgs/CommandBool.h>
|
||||
#include <mavros_msgs/CommandTOL.h>
|
||||
#include <mavros_msgs/SetMode.h>
|
||||
#include <mavros_msgs/State.h>
|
||||
#include <prometheus_msgs/ControlCommand.h>
|
||||
#include <prometheus_msgs/Formation.h>
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
#include <std_msgs/Int8.h>
|
||||
#include <Eigen/Eigen>
|
||||
|
||||
class formation
|
||||
{
|
||||
public:
|
||||
|
||||
//初始化函数,创建发布者,订阅者,变量初始化等
|
||||
void init();
|
||||
|
||||
//无人机集群解锁以及切入offboard模式(px4)
|
||||
void set_formation_px4_offboard();
|
||||
|
||||
//无人机集群解锁以及切入guided模式并起飞(apm)
|
||||
void set_formation_apm_guided();
|
||||
|
||||
//无人机集群切入LAND模式(px4)
|
||||
void set_formation_px4_land();
|
||||
|
||||
//无人机集群切入LAND模式(apm)
|
||||
void set_formation_apm_land();
|
||||
//无人机集群上锁
|
||||
void set_formation_disarmed();
|
||||
|
||||
//程序是否等待函数
|
||||
void is_wait(int time);
|
||||
|
||||
//模式设置函数
|
||||
void set_mode();
|
||||
|
||||
//队形变换函数
|
||||
void change();
|
||||
|
||||
//获取动捕系统位置数据函数
|
||||
void getpose();
|
||||
|
||||
//是否为仿真函数
|
||||
void is_sim();
|
||||
|
||||
//状态函数
|
||||
void state();
|
||||
|
||||
//终端输入控制数据函数
|
||||
void move();
|
||||
|
||||
//切换为三角队形函数
|
||||
void set_triangle();
|
||||
|
||||
//切换为一字队形函数
|
||||
void set_horizontal();
|
||||
|
||||
//切换为菱形队形函数
|
||||
void set_diamond();
|
||||
|
||||
//切换为菱形队形过渡队形函数
|
||||
void set_diamond_stage1();
|
||||
|
||||
//打印集群队形函数
|
||||
void printf_formation_type(std::string type_name);
|
||||
|
||||
//集群位置控制发布函数
|
||||
void formation_pos_pub();
|
||||
|
||||
//打印飞机状态函数
|
||||
void printf_formation_state();
|
||||
|
||||
//集群控制函数
|
||||
void control();
|
||||
|
||||
//四边形绕圈函数
|
||||
void square();
|
||||
|
||||
//参数检查函数
|
||||
bool check_param();
|
||||
|
||||
//获取单台无人机控制数据
|
||||
void get_uav_cmd(Eigen::Vector3d offset_pose, mavros_msgs::PositionTarget& desired_pose);
|
||||
|
||||
//集群控制命令回调函数
|
||||
void ControlCallBack(const prometheus_msgs::ControlCommandConstPtr& control_msgs);
|
||||
|
||||
//队形变换命令回调函数
|
||||
void FormationChangeCallBack(const prometheus_msgs::FormationConstPtr& change_msgs);
|
||||
|
||||
//1号机状态数据回调函数
|
||||
void Uav1StateCallBack(const mavros_msgs::StateConstPtr &state_msgs);
|
||||
|
||||
//2号机状态数据回调函数
|
||||
void Uav2StateCallBack(const mavros_msgs::StateConstPtr &state_msgs);
|
||||
|
||||
//3号机状态数据回调函数
|
||||
void Uav3StateCallBack(const mavros_msgs::StateConstPtr &state_msgs);
|
||||
|
||||
//4号机状态数据回调函数
|
||||
void Uav4StateCallBack(const mavros_msgs::StateConstPtr &state_msgs);
|
||||
|
||||
//5号机状态数据回调函数
|
||||
void Uav5StateCallBack(const mavros_msgs::StateConstPtr &state_msgs);
|
||||
|
||||
//1号机动捕位置数据回调函数
|
||||
void Uav1MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//2号机动捕位置数据回调函数
|
||||
void Uav2MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//3号机动捕位置数据回调函数
|
||||
void Uav3MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//4号机动捕位置数据回调函数
|
||||
void Uav4MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//5号机动捕位置数据回调函数
|
||||
void Uav5MocapPoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//1号机位置数据回调函数
|
||||
void Uav1PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//2号机位置数据回调函数
|
||||
void Uav2PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//3号机位置数据回调函数
|
||||
void Uav3PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//4号机位置数据回调函数
|
||||
void Uav4PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
//5号机位置数据回调函数
|
||||
void Uav5PoseCallBack(const geometry_msgs::PoseStampedConstPtr &pose_msgs);
|
||||
|
||||
private:
|
||||
|
||||
//创建句柄
|
||||
ros::NodeHandle n;
|
||||
|
||||
/*******************订阅者*******************/
|
||||
|
||||
//控制命令订阅者
|
||||
ros::Subscriber cmd_sub;
|
||||
|
||||
//队形变换订阅者
|
||||
ros::Subscriber formation_type_sub;
|
||||
|
||||
//1号机状态数据订阅者
|
||||
ros::Subscriber uav1_state_sub;
|
||||
|
||||
//2号机状态数据订阅者
|
||||
ros::Subscriber uav2_state_sub;
|
||||
|
||||
//3号机状态数据订阅者
|
||||
ros::Subscriber uav3_state_sub;
|
||||
|
||||
//4号机状态数据订阅者
|
||||
ros::Subscriber uav4_state_sub;
|
||||
|
||||
//5号机状态数据订阅者
|
||||
ros::Subscriber uav5_state_sub;
|
||||
|
||||
//1号机动捕位置数据订阅者
|
||||
ros::Subscriber uav1_mocap_pose_sub;
|
||||
|
||||
//2号机动捕位置数据订阅者
|
||||
ros::Subscriber uav2_mocap_pose_sub;
|
||||
|
||||
//3号机动捕位置数据订阅者
|
||||
ros::Subscriber uav3_mocap_pose_sub;
|
||||
|
||||
//4号机动捕位置数据订阅者
|
||||
ros::Subscriber uav4_mocap_pose_sub;
|
||||
|
||||
//5号机动捕位置数据订阅者
|
||||
ros::Subscriber uav5_mocap_pose_sub;
|
||||
|
||||
//1号机位置数据订阅者
|
||||
ros::Subscriber uav1_pose_sub;
|
||||
|
||||
//2号机位置数据订阅者
|
||||
ros::Subscriber uav2_pose_sub;
|
||||
|
||||
//3号机位置数据订阅者
|
||||
ros::Subscriber uav3_pose_sub;
|
||||
|
||||
//4号机位置数据订阅者
|
||||
ros::Subscriber uav4_pose_sub;
|
||||
|
||||
//5号机位置数据订阅者
|
||||
ros::Subscriber uav5_pose_sub;
|
||||
|
||||
/*******************客户端*******************/
|
||||
|
||||
ros::ServiceClient uav1_takeoff_client;
|
||||
|
||||
ros::ServiceClient uav2_takeoff_client;
|
||||
|
||||
ros::ServiceClient uav3_takeoff_client;
|
||||
|
||||
ros::ServiceClient uav4_takeoff_client;
|
||||
|
||||
ros::ServiceClient uav5_takeoff_client;
|
||||
|
||||
/*******************发布者*******************/
|
||||
|
||||
//队形变换发布者
|
||||
ros::Publisher formation_type_pub;
|
||||
|
||||
//控制命令发布者
|
||||
ros::Publisher cmd_pub;
|
||||
|
||||
//1号机动捕位置数据发布者
|
||||
ros::Publisher uav1_mocap_pose_pub;
|
||||
|
||||
//2号机动捕位置数据发布者
|
||||
ros::Publisher uav2_mocap_pose_pub;
|
||||
|
||||
//3号机动捕位置数据发布者
|
||||
ros::Publisher uav3_mocap_pose_pub;
|
||||
|
||||
//4号机动捕位置数据发布者
|
||||
ros::Publisher uav4_mocap_pose_pub;
|
||||
|
||||
//5号机动捕位置数据发布者
|
||||
ros::Publisher uav5_mocap_pose_pub;
|
||||
|
||||
//1号机控制指令发布者
|
||||
ros::Publisher uav1_local_pub;
|
||||
|
||||
//1号机控制指令发布者
|
||||
ros::Publisher uav2_local_pub;
|
||||
|
||||
//1号机控制指令发布者
|
||||
ros::Publisher uav3_local_pub;
|
||||
|
||||
//1号机控制指令发布者
|
||||
ros::Publisher uav4_local_pub;
|
||||
|
||||
//1号机控制指令发布者
|
||||
ros::Publisher uav5_local_pub;
|
||||
|
||||
/*******************变量*******************/
|
||||
|
||||
//1号机期望位置
|
||||
mavros_msgs::PositionTarget uav1_desired_pose;
|
||||
|
||||
//2号机期望位置
|
||||
mavros_msgs::PositionTarget uav2_desired_pose;
|
||||
|
||||
//3号机期望位置
|
||||
mavros_msgs::PositionTarget uav3_desired_pose;
|
||||
|
||||
//4号机期望位置
|
||||
mavros_msgs::PositionTarget uav4_desired_pose;
|
||||
|
||||
//5号机期望位置
|
||||
mavros_msgs::PositionTarget uav5_desired_pose;
|
||||
|
||||
//1号机当前位置
|
||||
geometry_msgs::PoseStamped uav1_current_pose;
|
||||
|
||||
//2号机当前位置
|
||||
geometry_msgs::PoseStamped uav2_current_pose;
|
||||
|
||||
//3号机当前位置
|
||||
geometry_msgs::PoseStamped uav3_current_pose;
|
||||
|
||||
//4号机当前位置
|
||||
geometry_msgs::PoseStamped uav4_current_pose;
|
||||
|
||||
//5号机当前位置
|
||||
geometry_msgs::PoseStamped uav5_current_pose;
|
||||
|
||||
//1号机集群队形位置差值
|
||||
Eigen::Vector3d uav1_offset_pose;
|
||||
|
||||
//2号机集群队形位置差值
|
||||
Eigen::Vector3d uav2_offset_pose;
|
||||
|
||||
//3号机集群队形位置差值
|
||||
Eigen::Vector3d uav3_offset_pose;
|
||||
|
||||
//4号机集群队形位置差值
|
||||
Eigen::Vector3d uav4_offset_pose;
|
||||
|
||||
//5号机集群队形位置差值
|
||||
Eigen::Vector3d uav5_offset_pose;
|
||||
|
||||
//1号机仿真位置差值
|
||||
Eigen::Vector3d uav1_gazebo_offset_pose;
|
||||
|
||||
//2号机仿真位置差值
|
||||
Eigen::Vector3d uav2_gazebo_offset_pose;
|
||||
|
||||
//3号机仿真位置差值
|
||||
Eigen::Vector3d uav3_gazebo_offset_pose;
|
||||
|
||||
//4号机仿真位置差值
|
||||
Eigen::Vector3d uav4_gazebo_offset_pose;
|
||||
|
||||
//5号机仿真位置差值
|
||||
Eigen::Vector3d uav5_gazebo_offset_pose;
|
||||
|
||||
//1号机当前状态
|
||||
mavros_msgs::State uav1_state;
|
||||
|
||||
//2号机当前状态
|
||||
mavros_msgs::State uav2_state;
|
||||
|
||||
//3号机当前状态
|
||||
mavros_msgs::State uav3_state;
|
||||
|
||||
//4号机当前状态
|
||||
mavros_msgs::State uav4_state;
|
||||
|
||||
//5号机当前状态
|
||||
mavros_msgs::State uav5_state;
|
||||
|
||||
//1号机起飞客户端变量(apm)
|
||||
mavros_msgs::CommandTOL uav1_takeoff_cmd;
|
||||
|
||||
//2号机起飞客户端变量(apm)
|
||||
mavros_msgs::CommandTOL uav2_takeoff_cmd;
|
||||
|
||||
//3号机起飞客户端变量(apm)
|
||||
mavros_msgs::CommandTOL uav3_takeoff_cmd;
|
||||
|
||||
//4号机起飞客户端变量(apm)
|
||||
mavros_msgs::CommandTOL uav4_takeoff_cmd;
|
||||
|
||||
//5号机起飞客户端变量(apm)
|
||||
mavros_msgs::CommandTOL uav5_takeoff_cmd;
|
||||
|
||||
//集群队形X轴间隔距离:一字队形以及三角队形飞机之间X轴间隔距离为1倍该变量,菱形队形为2倍
|
||||
double formation_distance_x;
|
||||
|
||||
//集群队形Y轴间隔距离:一字队形以及三角队形飞机之间Y轴间隔距离为1倍该变量,菱形队形为2倍
|
||||
double formation_distance_y;
|
||||
|
||||
//集群队形Z轴间隔距离:Z轴距离未设置,暂留该接口
|
||||
double formation_distance_z;
|
||||
|
||||
//集群解锁切入offboard模式时,无人机之间的时间间隔
|
||||
int offboard_intervals;
|
||||
|
||||
//集群降落时,无人机之间的时间间隔
|
||||
int land_intervals;
|
||||
|
||||
//集群切换为菱形队形或由菱形队形切换为其他队形会存在碰撞风险,因此需加入中间过渡队形,该变量为过渡队形保持的时间
|
||||
int diamond_intervals;
|
||||
|
||||
//集群队形
|
||||
prometheus_msgs::Formation formation_data;
|
||||
|
||||
//集群控制
|
||||
prometheus_msgs::ControlCommand control_data;
|
||||
|
||||
//集群模式
|
||||
int formation_mode;
|
||||
|
||||
//是否为仿真.true代表为仿真,false代表真机
|
||||
bool sim;
|
||||
|
||||
//飞行控制系统:px4 或者 apm
|
||||
std::string flight_controller;
|
||||
|
||||
//定位数据来源
|
||||
std::string location_source;
|
||||
|
||||
//起飞高度(apm)
|
||||
double takeoff_height;
|
||||
|
||||
//程序运行初始时间
|
||||
ros::Time begin_time;
|
||||
|
||||
/***************四机正方形绕圈变量***************/
|
||||
|
||||
//正方形边长
|
||||
double square_length;
|
||||
|
||||
//1,3号点飞行高度
|
||||
double point13_height;
|
||||
|
||||
//2,4号点飞行高度
|
||||
double point24_height;
|
||||
|
||||
//发布目标点的保持时间
|
||||
double hold_time;
|
||||
|
||||
//发布第一个目标点的延长时间
|
||||
double stage1_time;
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif //FORMATION_H
|
@ -1,141 +0,0 @@
|
||||
#ifndef GIMBAL_CONTROL_H
|
||||
#define GIMBAL_CONTROL_H
|
||||
|
||||
// PX4云台控制类
|
||||
#include <ros/ros.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <math.h>
|
||||
#include <mavros_msgs/MountControl.h>
|
||||
#include <geometry_msgs/Quaternion.h>
|
||||
#include <prometheus_msgs/ArucoInfo.h>
|
||||
#include "mission_utils.h"
|
||||
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
class gimbal_control
|
||||
{
|
||||
public:
|
||||
gimbal_control(void):
|
||||
nh("~")
|
||||
{
|
||||
// 订阅云台当前角度
|
||||
gimbal_att_sub = nh.subscribe<geometry_msgs::Quaternion>("/mavros/mount_control/orientation", 10, &gimbal_control::gimbal_att_cb,this);
|
||||
|
||||
// 云台控制:本话题要发送至飞控(通过Mavros_extra功能包 /plugins/mount_control.cpp发送)
|
||||
mount_control_pub = nh.advertise<mavros_msgs::MountControl>( "/mavros/mount_control/command", 1);
|
||||
|
||||
// 云台角度初始化
|
||||
gimbal_att = Eigen::Vector3d(0.0,0.0,0.0);
|
||||
gimbal_att_last = Eigen::Vector3d(0.0,0.0,0.0);
|
||||
|
||||
begin_time = ros::Time::now();
|
||||
|
||||
dt_time = 0.0;
|
||||
|
||||
last_time = get_time_in_sec(begin_time);
|
||||
}
|
||||
|
||||
// 云台角度
|
||||
Eigen::Vector3d gimbal_att;
|
||||
// 上一时刻云台角度
|
||||
Eigen::Vector3d gimbal_att_last;
|
||||
// 估算的云台角速度
|
||||
Eigen::Vector3d gimbal_att_rate;
|
||||
|
||||
// 估算云台角速度
|
||||
ros::Time begin_time;
|
||||
float last_time;
|
||||
float dt_time;
|
||||
|
||||
//发送云台控制指令API函数
|
||||
void send_mount_control_command(const Eigen::Vector3d& gimbal_att_sp);
|
||||
|
||||
Eigen::Vector3d get_gimbal_att();
|
||||
|
||||
Eigen::Vector3d get_gimbal_att_rate();
|
||||
|
||||
private:
|
||||
|
||||
ros::NodeHandle nh;
|
||||
|
||||
ros::Subscriber gimbal_att_sub;
|
||||
ros::Publisher mount_control_pub;
|
||||
|
||||
Eigen::Vector3d quaternion_to_euler(const Eigen::Quaterniond &q);
|
||||
|
||||
float get_time_in_sec(const ros::Time& begin_time);
|
||||
|
||||
void gimbal_att_cb(const geometry_msgs::Quaternion::ConstPtr& msg)
|
||||
{
|
||||
Eigen::Quaterniond gimbal_att_quat;
|
||||
|
||||
gimbal_att_quat = Eigen::Quaterniond(msg->w, msg->x, msg->y, msg->z);
|
||||
|
||||
//Transform the Quaternion to euler Angles
|
||||
gimbal_att = quaternion_to_euler(gimbal_att_quat);
|
||||
|
||||
float cur_time = get_time_in_sec(begin_time);
|
||||
dt_time = cur_time - last_time;
|
||||
dt_time = constrain_function2(dt_time, 0.01, 0.03);
|
||||
last_time = cur_time;
|
||||
|
||||
gimbal_att_rate = (gimbal_att - gimbal_att_last)/dt_time;
|
||||
|
||||
gimbal_att_last = gimbal_att;
|
||||
}
|
||||
};
|
||||
|
||||
void gimbal_control::send_mount_control_command(const Eigen::Vector3d& gimbal_att_sp)
|
||||
{
|
||||
mavros_msgs::MountControl mount_setpoint;
|
||||
//
|
||||
mount_setpoint.header.stamp = ros::Time::now();
|
||||
mount_setpoint.header.frame_id = "map";
|
||||
mount_setpoint.mode = 2;
|
||||
mount_setpoint.roll = gimbal_att_sp[0]; // Gimbal Roll [deg]
|
||||
mount_setpoint.pitch = gimbal_att_sp[1]; // Gimbal Pitch[deg]
|
||||
mount_setpoint.yaw = gimbal_att_sp[2]; // Gimbal Yaw [deg]
|
||||
|
||||
mount_control_pub.publish(mount_setpoint);
|
||||
|
||||
}
|
||||
|
||||
Eigen::Vector3d gimbal_control::get_gimbal_att_rate()
|
||||
{
|
||||
return gimbal_att_rate;
|
||||
}
|
||||
|
||||
Eigen::Vector3d gimbal_control::get_gimbal_att()
|
||||
{
|
||||
return gimbal_att;
|
||||
}
|
||||
|
||||
Eigen::Vector3d gimbal_control::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;
|
||||
}
|
||||
|
||||
float gimbal_control::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);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,627 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define START_POINT_X -6.5
|
||||
#define START_POINT_Y 0.0
|
||||
#define START_POINT_Z 1.7
|
||||
#define START_POINT_YAW 0.0
|
||||
|
||||
#define CIRCLE_POINT_X -3.5
|
||||
#define CIRCLE_POINT_Y 0.0
|
||||
#define CIRCLE_POINT_Z 1.8
|
||||
#define CIRCLE_POINT_YAW 0.0
|
||||
|
||||
#define PILLAR_POINT_X 1.5
|
||||
#define PILLAR_POINT_Y 0.0
|
||||
#define PILLAR_POINT_Z 1.8
|
||||
#define PILLAR_POINT_YAW 0.0
|
||||
|
||||
#define CORRIDOR_POINT_X 9.5
|
||||
#define CORRIDOR_POINT_Y -1.0
|
||||
#define CORRIDOR_POINT_Z 1.8
|
||||
#define CORRIDOR_POINT_YAW 0.0
|
||||
|
||||
#define NUM_POINT_X 17
|
||||
#define NUM_POINT_Y 0.0
|
||||
#define NUM_POINT_Z 1.8
|
||||
#define NUM_POINT_YAW 0.0
|
||||
#define FOLLOWING_VEL 0.5
|
||||
#define FOLLOWING_KP 2.0
|
||||
|
||||
#define LAND_POINT_X 23
|
||||
#define LAND_POINT_Y 0.0
|
||||
#define LAND_POINT_Z 1.8
|
||||
#define LAND_POINT_YAW 0.0
|
||||
#define LANDPAD_HEIGHT 0.0
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>全 局 变 量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
Eigen::Vector3f start_point;
|
||||
//椭圆穿越
|
||||
Detection_result ellipse_det;
|
||||
//避障任务
|
||||
geometry_msgs::Point desired_vel;
|
||||
int flag_get_cmd = 0;
|
||||
int flag_get_cmd_a = 0;
|
||||
//走廊穿越
|
||||
struct global_planner
|
||||
{
|
||||
// 规划路径
|
||||
nav_msgs::Path path_cmd;
|
||||
int Num_total_wp;
|
||||
int wp_id;
|
||||
int start_id;
|
||||
}A_star;
|
||||
|
||||
//数字识别+颜色巡线
|
||||
int flag_detection;
|
||||
float error_body_y;
|
||||
float yaw_sp;
|
||||
//自主降落
|
||||
Detection_result landpad_det;
|
||||
Eigen::Vector3f pos_des_prev;
|
||||
|
||||
float kpx_land,kpy_land,kpz_land; //控制参数 - 比例参数
|
||||
|
||||
//无人机状态
|
||||
prometheus_msgs::DroneState _DroneState; //无人机状态量
|
||||
Eigen::Matrix3f R_Body_to_ENU;
|
||||
|
||||
prometheus_msgs::ControlCommand Command_Now; //发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
ros::Publisher command_pub,goal_pub;
|
||||
ros::Publisher local_planner_switch_pub,global_planner_switch_pub,circle_switch_pub, num_det_switch_pub, color_det_switch_pub, pad_det_switch_pub;
|
||||
|
||||
std_msgs::Bool switch_on;
|
||||
std_msgs::Bool switch_off;
|
||||
|
||||
// 状态机
|
||||
int State_Machine = 0;
|
||||
float kpx_circle_track,kpy_circle_track,kpz_circle_track; //控制参数 - 比例参数
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>声 明 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
void A_star_planner();
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回 调 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
void ellipse_det_cb(const prometheus_msgs::DetectionInfo::ConstPtr& msg)
|
||||
{
|
||||
ellipse_det.object_name = "circle";
|
||||
ellipse_det.Detection_info = *msg;
|
||||
ellipse_det.pos_body_frame[0] = ellipse_det.Detection_info.position[2] + FRONT_CAMERA_OFFSET_X;
|
||||
ellipse_det.pos_body_frame[1] = - ellipse_det.Detection_info.position[0] + FRONT_CAMERA_OFFSET_Y;
|
||||
ellipse_det.pos_body_frame[2] = - ellipse_det.Detection_info.position[1] + FRONT_CAMERA_OFFSET_Z;
|
||||
|
||||
ellipse_det.pos_body_enu_frame = R_Body_to_ENU * ellipse_det.pos_body_frame;
|
||||
|
||||
if(ellipse_det.Detection_info.detected)
|
||||
{
|
||||
ellipse_det.num_regain++;
|
||||
ellipse_det.num_lost = 0;
|
||||
}else
|
||||
{
|
||||
ellipse_det.num_regain = 0;
|
||||
ellipse_det.num_lost++;
|
||||
}
|
||||
|
||||
// 当连续一段时间无法检测到目标时,认定目标丢失
|
||||
if(ellipse_det.num_lost > VISION_THRES)
|
||||
{
|
||||
ellipse_det.is_detected = false;
|
||||
}
|
||||
|
||||
// 当连续一段时间检测到目标时,认定目标得到
|
||||
if(ellipse_det.num_regain > VISION_THRES)
|
||||
{
|
||||
ellipse_det.is_detected = true;
|
||||
}
|
||||
}
|
||||
void local_planner_cmd_cb(const geometry_msgs::Point::ConstPtr& msg)
|
||||
{
|
||||
flag_get_cmd = 1;
|
||||
desired_vel = *msg;
|
||||
}
|
||||
void global_planner_cmd_cb(const nav_msgs::Path::ConstPtr& msg)
|
||||
{
|
||||
flag_get_cmd_a = flag_get_cmd_a + 1;
|
||||
A_star.path_cmd = *msg;
|
||||
A_star.Num_total_wp = A_star.path_cmd.poses.size();
|
||||
|
||||
//选择与当前无人机所在位置最近的点,并从该点开始追踪
|
||||
A_star.start_id = 0;
|
||||
float distance_to_wp_min = abs(A_star.path_cmd.poses[0].pose.position.x - _DroneState.position[0])
|
||||
+ abs(A_star.path_cmd.poses[0].pose.position.y - _DroneState.position[1]);
|
||||
for (int j=1;j<A_star.Num_total_wp;j++)
|
||||
{
|
||||
float distance_to_wp = abs(A_star.path_cmd.poses[j].pose.position.x - _DroneState.position[0])
|
||||
+ abs(A_star.path_cmd.poses[j].pose.position.y - _DroneState.position[1]);
|
||||
if(distance_to_wp < distance_to_wp_min)
|
||||
{
|
||||
distance_to_wp_min = distance_to_wp;
|
||||
A_star.start_id = j;
|
||||
}
|
||||
}
|
||||
|
||||
//这里增大开始路径点是为了解决当得到新路径时,无人机会回头的问题
|
||||
A_star.wp_id = A_star.start_id + 1;
|
||||
if(A_star.Num_total_wp - A_star.start_id > 8)
|
||||
{
|
||||
A_star.wp_id = A_star.start_id + 7;
|
||||
}
|
||||
}
|
||||
void color_line_cb(const geometry_msgs::Pose::ConstPtr &msg)
|
||||
{
|
||||
error_body_y = - tan(msg->position.x) * NUM_POINT_Z;
|
||||
flag_detection = msg->position.y;
|
||||
|
||||
float x1 = msg->orientation.w;
|
||||
float y1 = msg->orientation.x;
|
||||
float x2 = msg->orientation.y;
|
||||
float y2 = msg->orientation.z;
|
||||
|
||||
float next_desired_yaw = - atan2(y2 - y1, x2 - x1);
|
||||
|
||||
yaw_sp = (0.7*yaw_sp + 0.3*next_desired_yaw);
|
||||
}
|
||||
void landpad_det_cb(const prometheus_msgs::DetectionInfo::ConstPtr &msg)
|
||||
{
|
||||
landpad_det.object_name = "landpad";
|
||||
landpad_det.Detection_info = *msg;
|
||||
landpad_det.pos_body_frame[0] = - landpad_det.Detection_info.position[1] + DOWN_CAMERA_OFFSET_X;
|
||||
landpad_det.pos_body_frame[1] = - landpad_det.Detection_info.position[0] + DOWN_CAMERA_OFFSET_Y;
|
||||
landpad_det.pos_body_frame[2] = - landpad_det.Detection_info.position[2] + DOWN_CAMERA_OFFSET_Z;
|
||||
|
||||
landpad_det.pos_body_enu_frame = R_Body_to_ENU * landpad_det.pos_body_frame;
|
||||
|
||||
//若已知降落板高度,则无需使用深度信息。
|
||||
landpad_det.pos_body_enu_frame[2] = LANDPAD_HEIGHT - _DroneState.position[2];
|
||||
|
||||
landpad_det.pos_enu_frame[0] = _DroneState.position[0] + landpad_det.pos_body_enu_frame[0];
|
||||
landpad_det.pos_enu_frame[1] = _DroneState.position[1] + landpad_det.pos_body_enu_frame[1];
|
||||
landpad_det.pos_enu_frame[2] = _DroneState.position[2] + landpad_det.pos_body_enu_frame[2];
|
||||
// landpad_det.att_enu_frame[2] = _DroneState.attitude[2] + Detection_raw.attitude[2];
|
||||
landpad_det.att_enu_frame[2] = 0.0;
|
||||
|
||||
if(landpad_det.Detection_info.detected)
|
||||
{
|
||||
landpad_det.num_regain++;
|
||||
landpad_det.num_lost = 0;
|
||||
}else
|
||||
{
|
||||
landpad_det.num_regain = 0;
|
||||
landpad_det.num_lost++;
|
||||
}
|
||||
|
||||
// 当连续一段时间无法检测到目标时,认定目标丢失
|
||||
if(landpad_det.num_lost > VISION_THRES)
|
||||
{
|
||||
landpad_det.is_detected = false;
|
||||
}
|
||||
|
||||
// 当连续一段时间检测到目标时,认定目标得到
|
||||
if(landpad_det.num_regain > VISION_THRES)
|
||||
{
|
||||
landpad_det.is_detected = true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
_DroneState = *msg;
|
||||
R_Body_to_ENU = get_rotation_matrix(_DroneState.attitude[0], _DroneState.attitude[1], _DroneState.attitude[2]);
|
||||
}
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "indoor_competition");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
//【订阅】椭圆识别结果,用于形状穿越
|
||||
ros::Subscriber ellipse_det_sub = nh.subscribe<prometheus_msgs::DetectionInfo>("/prometheus/object_detection/ellipse_det", 10, ellipse_det_cb);
|
||||
|
||||
ros::Subscriber landpad_det_sub = nh.subscribe<prometheus_msgs::DetectionInfo>("/prometheus/object_detection/landpad_det", 10, landpad_det_cb);
|
||||
|
||||
//ros::Subscriber num_det_sub = nh.subscribe<prometheus_msgs::MultiDetectionInfo>("/prometheus/object_detection/num_det", 10, num_det_cb);
|
||||
|
||||
ros::Subscriber color_line_sub = nh.subscribe<geometry_msgs::Pose>("/prometheus/object_detection/color_line_angle", 10, color_line_cb);
|
||||
|
||||
//【订阅】局部路径规划结果,用于避开障碍物 柱子
|
||||
ros::Subscriber local_planner_sub = nh.subscribe<geometry_msgs::Point>("/prometheus/local_planner/desired_vel", 50, local_planner_cmd_cb);
|
||||
|
||||
//【订阅】全局路径规划结果,用于避开障碍物 走廊
|
||||
ros::Subscriber global_planner_sub = nh.subscribe<nav_msgs::Path>("/prometheus/global_planner/path_cmd", 50, global_planner_cmd_cb);
|
||||
|
||||
//【订阅】无人机当前状态
|
||||
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
|
||||
|
||||
// 【发布】发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
command_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
|
||||
|
||||
goal_pub = nh.advertise<geometry_msgs::PoseStamped>("/prometheus/planning/goal", 10);
|
||||
|
||||
// 为了避免同时运行过多程序导致电脑奔溃,设置程序运行/休眠 开关,但这个功能尚未完全启用
|
||||
local_planner_switch_pub = nh.advertise<std_msgs::Bool>("/prometheus/switch/local_planner", 10);
|
||||
global_planner_switch_pub = nh.advertise<std_msgs::Bool>("/prometheus/switch/global_planner", 10);
|
||||
circle_switch_pub = nh.advertise<std_msgs::Bool>("/prometheus/switch/circle_crossing", 10);
|
||||
num_det_switch_pub = nh.advertise<std_msgs::Bool>("/prometheus/switch/num_det", 10);
|
||||
color_det_switch_pub = nh.advertise<std_msgs::Bool>("/prometheus/switch/color_det", 10);
|
||||
pad_det_switch_pub = nh.advertise<std_msgs::Bool>("/prometheus/switch/pad_det", 10);
|
||||
|
||||
switch_on.data = true;
|
||||
switch_off.data = false;
|
||||
//关闭所有节点
|
||||
local_planner_switch_pub.publish(switch_off);
|
||||
global_planner_switch_pub.publish(switch_off);
|
||||
circle_switch_pub.publish(switch_off);
|
||||
num_det_switch_pub.publish(switch_off);
|
||||
color_det_switch_pub.publish(switch_off);
|
||||
pad_det_switch_pub.publish(switch_off);
|
||||
|
||||
nh.param<float>("kpx_circle_track", kpx_circle_track, 0.1);
|
||||
nh.param<float>("kpy_circle_track", kpy_circle_track, 0.1);
|
||||
nh.param<float>("kpz_circle_track", kpz_circle_track, 0.1);
|
||||
|
||||
nh.param<float>("kpx_land", kpx_land, 0.1);
|
||||
nh.param<float>("kpy_land", kpy_land, 0.1);
|
||||
nh.param<float>("kpz_land", kpz_land, 0.1);
|
||||
|
||||
|
||||
//固定的浮点显示
|
||||
cout.setf(ios::fixed);
|
||||
//setprecision(n) 设显示小数精度为n位
|
||||
cout<<setprecision(2);
|
||||
//左对齐
|
||||
cout.setf(ios::left);
|
||||
// 强制显示小数点
|
||||
cout.setf(ios::showpoint);
|
||||
// 强制显示符号
|
||||
cout.setf(ios::showpos);
|
||||
|
||||
// Waiting for input
|
||||
int start_flag = 0;
|
||||
while(start_flag == 0)
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>Indoor Competition<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "Please enter 1 to start the mission..."<<endl;
|
||||
cin >> start_flag;
|
||||
}
|
||||
|
||||
// 阶段1: 解锁并起飞
|
||||
Command_Now.Command_ID = 1;
|
||||
while( State_Machine == 0)
|
||||
{
|
||||
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.Reference_State.yaw_ref = 999;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Switch to OFFBOARD and arm ..."<<endl;
|
||||
ros::Duration(3.0).sleep();
|
||||
|
||||
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.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] = START_POINT_X;
|
||||
Command_Now.Reference_State.position_ref[1] = START_POINT_Y;
|
||||
Command_Now.Reference_State.position_ref[2] = START_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = START_POINT_YAW;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Takeoff ..."<<endl;
|
||||
ros::Duration(2.0).sleep();
|
||||
ros::spinOnce();
|
||||
|
||||
float dis = cal_distance(Eigen::Vector3f(_DroneState.position[0],_DroneState.position[1],_DroneState.position[2]),
|
||||
Eigen::Vector3f(START_POINT_X, START_POINT_Y, START_POINT_Z));
|
||||
ros::spinOnce();
|
||||
if(dis < DIS_THRES)
|
||||
{
|
||||
State_Machine = 1;
|
||||
}
|
||||
}
|
||||
|
||||
//阶段2: 过门,准备穿圆
|
||||
while(State_Machine == 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.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] = CIRCLE_POINT_X;
|
||||
Command_Now.Reference_State.position_ref[1] = CIRCLE_POINT_Y;
|
||||
Command_Now.Reference_State.position_ref[2] = CIRCLE_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = CIRCLE_POINT_YAW;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Moving to CIRCLE_POINT ..."<<endl;
|
||||
ros::Duration(2.0).sleep();
|
||||
|
||||
ros::spinOnce();
|
||||
|
||||
float dis = cal_distance(Eigen::Vector3f(_DroneState.position[0],_DroneState.position[1],_DroneState.position[2]),
|
||||
Eigen::Vector3f(CIRCLE_POINT_X, CIRCLE_POINT_Y, CIRCLE_POINT_Z));
|
||||
|
||||
if(ellipse_det.is_detected && dis < DIS_THRES)
|
||||
{
|
||||
State_Machine = 2;
|
||||
}
|
||||
}
|
||||
|
||||
//阶段3: 传圆
|
||||
circle_switch_pub.publish(switch_on);
|
||||
|
||||
while(State_Machine == 2)
|
||||
{
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_VEL;
|
||||
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] = kpx_circle_track * ellipse_det.pos_body_enu_frame[0];
|
||||
Command_Now.Reference_State.velocity_ref[1] = kpy_circle_track * ellipse_det.pos_body_enu_frame[1];
|
||||
Command_Now.Reference_State.velocity_ref[2] = kpz_circle_track * ellipse_det.pos_body_enu_frame[2];
|
||||
Command_Now.Reference_State.yaw_ref = 0;
|
||||
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Tracking the cricle ..."<<endl;
|
||||
|
||||
printf_detection_result(ellipse_det);
|
||||
ros::spinOnce();
|
||||
ros::Duration(0.05).sleep();
|
||||
|
||||
if(abs(ellipse_det.pos_body_enu_frame[0]) < 1)
|
||||
{
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
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.position_ref[0] = 2.0;
|
||||
Command_Now.Reference_State.position_ref[1] = 0;
|
||||
Command_Now.Reference_State.position_ref[2] = 0;
|
||||
Command_Now.Reference_State.yaw_ref = 0;
|
||||
command_pub.publish(Command_Now);
|
||||
|
||||
ros::Duration(5.0).sleep();
|
||||
|
||||
State_Machine = 3;
|
||||
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.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] = PILLAR_POINT_X;
|
||||
Command_Now.Reference_State.position_ref[1] = PILLAR_POINT_Y;
|
||||
Command_Now.Reference_State.position_ref[2] = PILLAR_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = PILLAR_POINT_YAW;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Moving to PILLAR_POINT ..."<<endl;
|
||||
}
|
||||
}
|
||||
circle_switch_pub.publish(switch_off);
|
||||
|
||||
//发布目标
|
||||
geometry_msgs::PoseStamped goal;
|
||||
goal.pose.position.x = CORRIDOR_POINT_X;
|
||||
goal.pose.position.y = CORRIDOR_POINT_Y;
|
||||
goal.pose.position.z = CORRIDOR_POINT_Z;
|
||||
|
||||
while(flag_get_cmd == 0)
|
||||
{
|
||||
goal_pub.publish(goal);
|
||||
local_planner_switch_pub.publish(switch_on);
|
||||
cout << "Turn on the local planner and pub the goal point ..."<<endl;
|
||||
ros::spinOnce();
|
||||
ros::Duration(0.05).sleep();
|
||||
}
|
||||
|
||||
while(State_Machine == 3)
|
||||
{
|
||||
// 高度改为定高飞行
|
||||
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.Reference_State.Move_mode = prometheus_msgs::PositionReference::XY_VEL_Z_POS;
|
||||
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
|
||||
Command_Now.Reference_State.velocity_ref[0] = desired_vel.x;
|
||||
Command_Now.Reference_State.velocity_ref[1] = desired_vel.y;
|
||||
Command_Now.Reference_State.position_ref[2] = CORRIDOR_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = 0.0;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "APF planner:"<<endl;
|
||||
cout << "desired_vel: " << desired_vel.x << " [m/s] "<< desired_vel.y << " [m/s] "<< desired_vel.z << " [m/s] "<<endl;
|
||||
cout << "drone_pos: " << _DroneState.position[0] << " [m] "<< _DroneState.position[1] << " [m] "<< _DroneState.position[2] << " [m] "<<endl;
|
||||
cout << "goal_pos: " << goal.pose.position.x << " [m] "<< goal.pose.position.y << " [m] "<< goal.pose.position.z << " [m] "<<endl;
|
||||
ros::spinOnce();
|
||||
ros::Duration(0.05).sleep();
|
||||
|
||||
float dis = abs(_DroneState.position[0] - goal.pose.position.x);
|
||||
|
||||
if(dis < (DIS_THRES+0.3))
|
||||
{
|
||||
State_Machine = 4;
|
||||
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.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] = CORRIDOR_POINT_X;
|
||||
Command_Now.Reference_State.position_ref[1] = CORRIDOR_POINT_Y;
|
||||
Command_Now.Reference_State.position_ref[2] = CORRIDOR_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = CORRIDOR_POINT_YAW;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Moving to CORRIDOR_POINT ..."<<endl;
|
||||
ros::Duration(2.0).sleep();
|
||||
}
|
||||
}
|
||||
|
||||
//发布目标
|
||||
goal.pose.position.x = NUM_POINT_X;
|
||||
goal.pose.position.y = NUM_POINT_Y;
|
||||
goal.pose.position.z = NUM_POINT_Z;
|
||||
|
||||
while(flag_get_cmd_a == 0)
|
||||
{
|
||||
goal_pub.publish(goal);
|
||||
local_planner_switch_pub.publish(switch_off);
|
||||
global_planner_switch_pub.publish(switch_on);
|
||||
cout << "Turn on the global planner and pub the goal point ..."<<endl;
|
||||
ros::spinOnce();
|
||||
ros::Duration(0.05).sleep();
|
||||
}
|
||||
|
||||
while(State_Machine == 4)
|
||||
{
|
||||
A_star_planner();
|
||||
|
||||
float dis = abs(_DroneState.position[0] - goal.pose.position.x);
|
||||
|
||||
if(dis < 0.4)
|
||||
{
|
||||
State_Machine = 5;
|
||||
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.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] = NUM_POINT_X;
|
||||
Command_Now.Reference_State.position_ref[1] = NUM_POINT_Y;
|
||||
Command_Now.Reference_State.position_ref[2] = NUM_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = NUM_POINT_YAW;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Moving to NUM_POINT ..."<<endl;
|
||||
ros::Duration(2.0).sleep();
|
||||
}
|
||||
}
|
||||
global_planner_switch_pub.publish(switch_off);
|
||||
|
||||
color_det_switch_pub.publish(switch_on);
|
||||
|
||||
|
||||
//巡线
|
||||
while(State_Machine == 5)
|
||||
{
|
||||
Command_Now.header.stamp = ros::Time::now();
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
|
||||
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XY_VEL_Z_POS;
|
||||
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::MIX_FRAME;
|
||||
Command_Now.Reference_State.velocity_ref[0] = FOLLOWING_VEL;
|
||||
Command_Now.Reference_State.velocity_ref[1] = FOLLOWING_KP * error_body_y;
|
||||
Command_Now.Reference_State.position_ref[2] = NUM_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = yaw_sp;
|
||||
|
||||
//Publish
|
||||
Command_Now.header.stamp = ros::Time::now();
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Color Line Following... "<< endl;
|
||||
cout << "error_body_y: " << error_body_y << " [m] "<<endl;
|
||||
cout << "yaw_sp: " << yaw_sp/3.1415926 *180 << " [deg] "<<endl;
|
||||
ros::spinOnce();
|
||||
ros::Duration(0.05).sleep();
|
||||
|
||||
if(_DroneState.position[0] > LAND_POINT_X - 1.0)
|
||||
{
|
||||
State_Machine = 6;
|
||||
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.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] = LAND_POINT_X;
|
||||
Command_Now.Reference_State.position_ref[1] = LAND_POINT_Y;
|
||||
Command_Now.Reference_State.position_ref[2] = LAND_POINT_Z;
|
||||
Command_Now.Reference_State.yaw_ref = LAND_POINT_YAW;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Moving to LAND_POINT ..."<<endl;
|
||||
ros::Duration(4.0).sleep();
|
||||
}
|
||||
}
|
||||
|
||||
pos_des_prev[0] = _DroneState.position[0];
|
||||
pos_des_prev[1] = _DroneState.position[1];
|
||||
pos_des_prev[2] = _DroneState.position[2];
|
||||
|
||||
color_det_switch_pub.publish(switch_off);
|
||||
pad_det_switch_pub.publish(switch_on);
|
||||
|
||||
while(State_Machine == 6)
|
||||
{
|
||||
float distance_to_setpoint = landpad_det.pos_body_enu_frame.norm();
|
||||
cout <<"[autonomous_landing]: Tracking the Landing Pad, distance_to_setpoint : "<< distance_to_setpoint << " [m] " << endl;
|
||||
|
||||
Command_Now.header.stamp = ros::Time::now();
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Move;
|
||||
Command_Now.Reference_State.Move_frame = prometheus_msgs::PositionReference::ENU_FRAME;
|
||||
Command_Now.Reference_State.Move_mode = prometheus_msgs::PositionReference::XYZ_POS; //xy velocity z position
|
||||
Command_Now.Reference_State.yaw_ref = 0.0;
|
||||
Eigen::Vector3f vel_command;
|
||||
vel_command[0] = kpx_land * landpad_det.pos_body_enu_frame[0];
|
||||
vel_command[1] = kpy_land * landpad_det.pos_body_enu_frame[1];
|
||||
vel_command[2] = kpz_land * landpad_det.pos_body_enu_frame[2];
|
||||
for (int i=0; i<3; i++)
|
||||
{
|
||||
Command_Now.Reference_State.position_ref[i] = pos_des_prev[i] + vel_command[i]* 0.05;
|
||||
pos_des_prev[i] = Command_Now.Reference_State.position_ref[i];
|
||||
}
|
||||
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Autonomous Landing... "<< endl;
|
||||
|
||||
ros::spinOnce();
|
||||
ros::Duration(0.05).sleep();
|
||||
|
||||
while(_DroneState.position[2] < 0.4)
|
||||
{
|
||||
State_Machine = 7;
|
||||
Command_Now.header.stamp = ros::Time::now();
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Disarm;
|
||||
Command_Now.Command_ID = Command_Now.Command_ID + 1;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Landing and disarm ..."<<endl;
|
||||
cout << "The end of the indoor competition ..."<<endl;
|
||||
ros::Duration(2.0).sleep();
|
||||
ros::spinOnce();
|
||||
}
|
||||
}
|
||||
pad_det_switch_pub.publish(switch_off);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
void A_star_planner()
|
||||
{
|
||||
float current_cmd_id = flag_get_cmd_a;
|
||||
//执行给定航点
|
||||
while( A_star.wp_id < A_star.Num_total_wp && flag_get_cmd_a == current_cmd_id)
|
||||
{
|
||||
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.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] = A_star.path_cmd.poses[A_star.wp_id].pose.position.x;
|
||||
Command_Now.Reference_State.position_ref[1] = A_star.path_cmd.poses[A_star.wp_id].pose.position.y;
|
||||
Command_Now.Reference_State.position_ref[2] = A_star.path_cmd.poses[A_star.wp_id].pose.position.z;
|
||||
Command_Now.Reference_State.yaw_ref = 0.0;
|
||||
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "A star planner:"<<endl;
|
||||
cout << "Moving to Waypoint: [ " << A_star.wp_id << " / "<< A_star.Num_total_wp<< " ] "<<endl;
|
||||
cout << "desired_point: " << A_star.path_cmd.poses[A_star.wp_id].pose.position.x << " [m] "
|
||||
<< A_star.path_cmd.poses[A_star.wp_id].pose.position.y << " [m] "
|
||||
<< A_star.path_cmd.poses[A_star.wp_id].pose.position.z << " [m] "<<endl;
|
||||
cout << "drone_pos: " << _DroneState.position[0] << " [m] "<< _DroneState.position[1] << " [m] "<< _DroneState.position[2] << " [m] "<<endl;
|
||||
|
||||
float wait_time = 0.25;
|
||||
ros::spinOnce();
|
||||
A_star.wp_id++;
|
||||
ros::Duration(wait_time).sleep();
|
||||
}
|
||||
}
|
@ -1,153 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <Eigen/Eigen>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
|
||||
//topic 头文件
|
||||
#include <geometry_msgs/Point.h>
|
||||
#include <prometheus_msgs/ControlCommand.h>
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
#include <prometheus_msgs/DetectionInfo.h>
|
||||
#include <prometheus_msgs/MultiDetectionInfo.h>
|
||||
#include <nav_msgs/Odometry.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 <prometheus_msgs/DroneState.h>
|
||||
#include <nav_msgs/Path.h>
|
||||
#include <math.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define MIN_DIS 0.1
|
||||
#define FLY_HEIGHT 1.0
|
||||
# define NODE_NAME "number_detection"
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>全 局 变 量<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
prometheus_msgs::MultiDetectionInfo Detection_info;
|
||||
float size_Detection_info;
|
||||
prometheus_msgs::ControlCommand Command_Now; //发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
prometheus_msgs::DroneState _DroneState; //无人机状态量
|
||||
ros::Publisher command_pub;
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>声 明 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>回 调 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
void num_det_cb(const prometheus_msgs::MultiDetectionInfo::ConstPtr& msg)
|
||||
{
|
||||
Detection_info = *msg;
|
||||
size_Detection_info = Detection_info.num_objs;
|
||||
}
|
||||
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
_DroneState = *msg;
|
||||
}
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "number_detection");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
ros::Subscriber num_det_sub = nh.subscribe<prometheus_msgs::MultiDetectionInfo>("/prometheus/object_detection/num_det", 10, num_det_cb);
|
||||
|
||||
//【订阅】无人机当前状态
|
||||
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
|
||||
|
||||
// 【发布】发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
command_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
|
||||
|
||||
// 【发布】用于地面站显示的提示消息
|
||||
ros::Publisher message_pub = nh.advertise<prometheus_msgs::Message>("/prometheus/message/main", 10);
|
||||
|
||||
//固定的浮点显示
|
||||
cout.setf(ios::fixed);
|
||||
//setprecision(n) 设显示小数精度为n位
|
||||
cout<<setprecision(3);
|
||||
//左对齐
|
||||
cout.setf(ios::left);
|
||||
// 强制显示小数点
|
||||
cout.setf(ios::showpoint);
|
||||
// 强制显示符号
|
||||
cout.setf(ios::showpos);
|
||||
|
||||
// Waiting for input
|
||||
int start_flag = 0;
|
||||
while(start_flag == 0)
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Number Tracking Mission<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "Please enter 1 to takeoff the drone..."<<endl;
|
||||
cin >> start_flag;
|
||||
}
|
||||
|
||||
// 起飞
|
||||
Command_Now.Command_ID = 1;
|
||||
Command_Now.source = NODE_NAME;
|
||||
while( _DroneState.position[2] < 0.3)
|
||||
{
|
||||
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(3.0).sleep();
|
||||
|
||||
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::ENU_FRAME;
|
||||
Command_Now.Reference_State.position_ref[0] = 0.0;
|
||||
Command_Now.Reference_State.position_ref[1] = 0.0;
|
||||
Command_Now.Reference_State.position_ref[2] = 1.5;
|
||||
Command_Now.Reference_State.yaw_ref = 0.5 * M_PI;
|
||||
command_pub.publish(Command_Now);
|
||||
cout << "Takeoff ..."<<endl;
|
||||
ros::Duration(3.0).sleep();
|
||||
|
||||
ros::spinOnce();
|
||||
}
|
||||
|
||||
while (ros::ok())
|
||||
{
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>Number Tracking Mission<<<<<<<<<<<<<<<<<<<<<<<<<"<<endl;
|
||||
cout << "Total_Num: " << size_Detection_info << endl;
|
||||
|
||||
//回调
|
||||
ros::spinOnce();
|
||||
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
cout << "Num: " << i << endl;
|
||||
|
||||
//判断是否识别到
|
||||
int idx = -1;
|
||||
for (int j=0;j<size_Detection_info;j++)
|
||||
{
|
||||
if(Detection_info.detection_infos[j].category == i)
|
||||
{
|
||||
idx = j;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(idx != -1)
|
||||
{
|
||||
cout << "relative_pos: " << Detection_info.detection_infos[idx].position[0] << " [m] "<< Detection_info.detection_infos[idx].position[1] << " [m] "<< Detection_info.detection_infos[idx].position[2] << " [m] "<<endl;
|
||||
}else{
|
||||
cout << "Not detected!!!" << endl;
|
||||
}
|
||||
}
|
||||
|
||||
ros::Duration(1.0).sleep();
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -1,35 +0,0 @@
|
||||
##Parameter for object_tracking.cpp
|
||||
|
||||
##视觉丢失次数阈值
|
||||
Thres_vision_lost : 10
|
||||
|
||||
##追踪的间隔
|
||||
tracking_delta_x : 1.5
|
||||
tracking_delta_y : 0.0
|
||||
tracking_delta_z : -0.3
|
||||
|
||||
camera_offset_x: 0.2
|
||||
camera_offset_y: 0.0
|
||||
camera_offset_z: -0.05
|
||||
|
||||
##比例参数
|
||||
kpx_track: 0.3
|
||||
kpy_track: 0.3
|
||||
kpz_track: 0.3
|
||||
|
||||
##降落起始点 静止目标建议起飞点:[1,2,6] 移动目标建议起飞点[-5,0,5]
|
||||
start_point_x: -3.0
|
||||
start_point_y: 0
|
||||
start_point_z: 1.5
|
||||
start_yaw: 0.0
|
||||
|
||||
UKF_NCV:
|
||||
std_ax_: 0.01
|
||||
std_ay_: 0.01
|
||||
std_az_: 0.01
|
||||
std_px_: 0.02
|
||||
std_py_: 0.02
|
||||
std_pz_: 0.02
|
||||
|
||||
|
||||
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>prometheus_mission</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The prometheus_mission 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/amov-lab/Prometheus.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>
|
@ -1,66 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
//topic 头文件
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "pub_goal");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
//【发布】目标点
|
||||
ros::Publisher goal_pub = nh.advertise<geometry_msgs::PoseStamped>("/prometheus/planning/goal", 10);
|
||||
|
||||
float x,y,z;
|
||||
|
||||
geometry_msgs::PoseStamped goal;
|
||||
int flag;
|
||||
cout << "Please choose 2D or 3D (0 for 2D, 1 for 3D):"<<endl;
|
||||
cin >> flag;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
|
||||
// Waiting for input
|
||||
cout << "Please input the goal position:"<<endl;
|
||||
cout << "goal - x [m] : "<< endl;
|
||||
cin >> x;
|
||||
cout << "goal - y [m] : "<< endl;
|
||||
cin >> y;
|
||||
if(flag == 1)
|
||||
{
|
||||
cout << "goal - z [m] : "<< endl;
|
||||
cin >> z;
|
||||
}else if(flag == 0)
|
||||
{
|
||||
z = 1.0;
|
||||
}
|
||||
|
||||
|
||||
goal.header.stamp =ros::Time::now();
|
||||
goal.header.frame_id = "map";
|
||||
goal.pose.position.x = x;
|
||||
goal.pose.position.y = y;
|
||||
goal.pose.position.z = z;
|
||||
goal.pose.orientation.x = 0.0;
|
||||
goal.pose.orientation.y = 0.0;
|
||||
goal.pose.orientation.z = 0.0;
|
||||
goal.pose.orientation.w = 1.0;
|
||||
|
||||
|
||||
goal_pub.publish(goal);
|
||||
|
||||
sleep(1.0);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,82 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
//topic 头文件
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "pub_goal_swarm");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
//【发布】目标点
|
||||
ros::Publisher goal_pub1 = nh.advertise<geometry_msgs::PoseStamped>("/uav1/prometheus/planning/goal", 10);
|
||||
ros::Publisher goal_pub2 = nh.advertise<geometry_msgs::PoseStamped>("/uav2/prometheus/planning/goal", 10);
|
||||
ros::Publisher goal_pub3 = nh.advertise<geometry_msgs::PoseStamped>("/uav3/prometheus/planning/goal", 10);
|
||||
|
||||
float x,y1,y2,y3,z;
|
||||
|
||||
geometry_msgs::PoseStamped goal1;
|
||||
geometry_msgs::PoseStamped goal2;
|
||||
geometry_msgs::PoseStamped goal3;
|
||||
int flag;
|
||||
cout << "Please choose 2D or 3D (0 for 2D, 1 for 3D):"<<endl;
|
||||
cin >> flag;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
|
||||
// Waiting for input
|
||||
cout << "Please input the goal position:"<<endl;
|
||||
cout << "goal - x [m] : "<< endl;
|
||||
cin >> x;
|
||||
cout << "goal - y_uav1 [m] : "<< endl;
|
||||
cin >> y1;
|
||||
cout << "goal - y_uav2 [m] : "<< endl;
|
||||
cin >> y2;
|
||||
cout << "goal - y_uav2 [m] : "<< endl;
|
||||
cin >> y3;
|
||||
if(flag == 1)
|
||||
{
|
||||
cout << "goal - z [m] : "<< endl;
|
||||
cin >> z;
|
||||
}else if(flag == 0)
|
||||
{
|
||||
z = 1.0;
|
||||
}
|
||||
|
||||
|
||||
goal1.header.stamp =ros::Time::now();
|
||||
goal1.header.frame_id = "map";
|
||||
goal1.pose.position.x = x;
|
||||
goal1.pose.position.y = y1;
|
||||
goal1.pose.position.z = z;
|
||||
goal1.pose.orientation.x = 0.0;
|
||||
goal1.pose.orientation.y = 0.0;
|
||||
goal1.pose.orientation.z = 0.0;
|
||||
goal1.pose.orientation.w = 1.0;
|
||||
goal2 = goal1;
|
||||
|
||||
goal3 = goal1;
|
||||
|
||||
goal2.pose.position.y = y2;
|
||||
goal3.pose.position.y = y3;
|
||||
|
||||
|
||||
goal_pub1.publish(goal1);
|
||||
goal_pub2.publish(goal2);
|
||||
goal_pub3.publish(goal3);
|
||||
|
||||
sleep(1.0);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
//ROS 头文件
|
||||
#include <ros/ros.h>
|
||||
#include <iostream>
|
||||
|
||||
//topic 头文件
|
||||
#include <prometheus_msgs/DetectionInfo.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
prometheus_msgs::DetectionInfo Detection_Info;
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主函数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "fake_detectioninfo");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
//【发布】发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
ros::Publisher detection_pub = nh.advertise<prometheus_msgs::DetectionInfo>("/prometheus/target", 10);
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>参数读取<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
Detection_Info.header.stamp = ros::Time::now();
|
||||
cout << "Please input the detection info: "<<endl;
|
||||
cout << "position[0]: "<<endl;
|
||||
cin >> Detection_Info.position[0];
|
||||
cout << "position[1]: "<<endl;
|
||||
cin >> Detection_Info.position[1];
|
||||
cout << "position[2]: "<<endl;
|
||||
cin >> Detection_Info.position[2];
|
||||
|
||||
cout << "attitude[2]: "<<endl;
|
||||
cin >> Detection_Info.attitude[2];
|
||||
Detection_Info.detected = true;
|
||||
Detection_Info.yaw_error = Detection_Info.attitude[2];
|
||||
|
||||
detection_pub.publish(Detection_Info);
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,54 +0,0 @@
|
||||
//ros头文件
|
||||
#include <ros/ros.h>
|
||||
#include <iostream>
|
||||
#include <mission_utils.h>
|
||||
#include "message_utils.h"
|
||||
|
||||
//topic 头文件
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>主 函 数<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "mission_cmd_pub");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
//【发布】目标点
|
||||
ros::Publisher mission_cmd_pub = nh.advertise<geometry_msgs::PoseStamped>("/prometheus/mission/cmd", 10);
|
||||
|
||||
float x,y,z;
|
||||
|
||||
geometry_msgs::PoseStamped mission_cmd;
|
||||
|
||||
while(ros::ok())
|
||||
{
|
||||
|
||||
// Waiting for input
|
||||
cout << "Please input the mission_cmd:"<<endl;
|
||||
cout << "mission_cmd - x [m] : "<< endl;
|
||||
cin >> x;
|
||||
cout << "mission_cmd - y [m] : "<< endl;
|
||||
cin >> y;
|
||||
|
||||
mission_cmd.header.stamp =ros::Time::now();
|
||||
mission_cmd.header.frame_id = "map";
|
||||
mission_cmd.pose.position.x = x;
|
||||
mission_cmd.pose.position.y = y;
|
||||
mission_cmd.pose.position.z = 0;
|
||||
mission_cmd.pose.orientation.x = 0.0;
|
||||
mission_cmd.pose.orientation.y = 0.0;
|
||||
mission_cmd.pose.orientation.z = 0.0;
|
||||
mission_cmd.pose.orientation.w = 1.0;
|
||||
|
||||
|
||||
mission_cmd_pub.publish(mission_cmd);
|
||||
|
||||
sleep(1.0);
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
@ -1,18 +0,0 @@
|
||||
|
||||
##强制上锁高度
|
||||
arm_height_to_ground: 0.2
|
||||
##强制上锁距离
|
||||
arm_distance_to_pad: 0.55
|
||||
|
||||
##降落追踪 的比例参数
|
||||
kpx_land: 0.35
|
||||
kpy_land: 0.35
|
||||
kpz_land: 0.1
|
||||
|
||||
##降落起始点 静止目标建议起飞点:[1,2,6] 移动目标建议起飞点[-5,0,5]
|
||||
start_point_x: 1
|
||||
start_point_y: 2
|
||||
start_point_z: 4.5
|
||||
|
||||
|
||||
|
@ -1,129 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(prometheus_rapid_quad)
|
||||
|
||||
## 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
|
||||
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(RapidTrajectoryGenerator include/RapidTrajectoryGenerator.cpp)
|
||||
add_library(SingleAxisTrajectory include/SingleAxisTrajectory.cpp)
|
||||
|
||||
#add_library(KeyboardEvent src/lib/KeyboardEvent.cpp)
|
||||
|
||||
###### Main File ##########
|
||||
|
||||
add_executable(main_node src/main_node.cpp)
|
||||
add_dependencies(main_node prometheus_rapid_quad_gencpp)
|
||||
target_link_libraries(main_node ${catkin_LIBRARIES})
|
||||
target_link_libraries(main_node RapidTrajectoryGenerator)
|
||||
target_link_libraries(main_node SingleAxisTrajectory)
|
||||
|
||||
#############
|
||||
## 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_rapid_quad.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,218 +0,0 @@
|
||||
/*!
|
||||
* Rapid trajectory generation for quadrocopters
|
||||
*
|
||||
* Copyright 2014 by Mark W. Mueller <mwm@mwm.im>
|
||||
*
|
||||
* This code is free software: you can redistribute
|
||||
* it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "RapidTrajectoryGenerator.h"
|
||||
#include "RootFinder/quartic.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <limits>
|
||||
|
||||
using namespace RapidQuadrocopterTrajectoryGenerator;
|
||||
|
||||
RapidTrajectoryGenerator::RapidTrajectoryGenerator(const Vec3 x0, const Vec3 v0, const Vec3 a0, const Vec3 gravity)
|
||||
{
|
||||
//initialise each axis:
|
||||
Reset();
|
||||
for(int i=0; i<3; i++) _axis[i].SetInitialState(x0[i],v0[i],a0[i]);
|
||||
_grav = gravity;
|
||||
}
|
||||
|
||||
void RapidTrajectoryGenerator::SetGoalPosition(const Vec3 in)
|
||||
{
|
||||
for(unsigned i=0;i<3;i++) SetGoalPositionInAxis(i, in[i]);
|
||||
}
|
||||
|
||||
void RapidTrajectoryGenerator::SetGoalVelocity(const Vec3 in)
|
||||
{
|
||||
for(int i=0;i<3;i++) SetGoalVelocityInAxis(i, in[i]);
|
||||
}
|
||||
|
||||
void RapidTrajectoryGenerator::SetGoalAcceleration(const Vec3 in)
|
||||
{
|
||||
for(int i=0;i<3;i++) SetGoalAccelerationInAxis(i, in[i]);
|
||||
}
|
||||
|
||||
void RapidTrajectoryGenerator::Reset(void)
|
||||
{
|
||||
for(int i=0; i<3; i++)
|
||||
{
|
||||
_axis[i].Reset();
|
||||
}
|
||||
_tf = 0;
|
||||
}
|
||||
|
||||
//Generate the trajectory:
|
||||
void RapidTrajectoryGenerator::Generate(const double timeToFinish)
|
||||
{
|
||||
_tf = timeToFinish;
|
||||
for(int i=0;i<3;i++)
|
||||
{
|
||||
_axis[i].GenerateTrajectory(_tf);
|
||||
}
|
||||
}
|
||||
|
||||
RapidTrajectoryGenerator::InputFeasibilityResult RapidTrajectoryGenerator::CheckInputFeasibilitySection(double fminAllowed, double fmaxAllowed, double wmaxAllowed, double t1, double t2, double minTimeSection)
|
||||
{
|
||||
if (t2 - t1 < minTimeSection) return InputIndeterminable;
|
||||
//test the acceleration at the two limits:
|
||||
if (std::max(GetThrust(t1), GetThrust(t2)) > fmaxAllowed) return InputInfeasibleThrustHigh;
|
||||
if (std::min(GetThrust(t1), GetThrust(t2)) < fminAllowed) return InputInfeasibleThrustLow;
|
||||
|
||||
double fminSqr = 0;
|
||||
double fmaxSqr = 0;
|
||||
double jmaxSqr = 0;
|
||||
|
||||
//Test the limits of the box we're putting around the trajectory:
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
double amin, amax;
|
||||
_axis[i].GetMinMaxAcc(amin, amax, t1, t2);
|
||||
|
||||
//distance from zero thrust point in this axis
|
||||
double v1 = amin - _grav[i]; //left
|
||||
double v2 = amax - _grav[i]; //right
|
||||
|
||||
//definitely infeasible:
|
||||
if (std::max(pow(v1, 2), pow(v2, 2)) > pow(fmaxAllowed, 2)) return InputInfeasibleThrustHigh;
|
||||
|
||||
if (v1 * v2 < 0)
|
||||
{
|
||||
//sign of acceleration changes, so we've gone through zero
|
||||
fminSqr += 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
fminSqr += pow(std::min(fabs(v1), fabs(v2)), 2);
|
||||
}
|
||||
|
||||
fmaxSqr += pow(std::max(fabs(v1), fabs(v2)), 2);
|
||||
|
||||
jmaxSqr += _axis[i].GetMaxJerkSquared(t1, t2);
|
||||
}
|
||||
|
||||
double fmin = sqrt(fminSqr);
|
||||
double fmax = sqrt(fmaxSqr);
|
||||
double wBound;
|
||||
if (fminSqr > 1e-6) wBound = sqrt(jmaxSqr / fminSqr);//the 1e-6 is a divide-by-zero protection
|
||||
else wBound = std::numeric_limits<double>::max();
|
||||
|
||||
//definitely infeasible:
|
||||
if (fmax < fminAllowed) return InputInfeasibleThrustLow;
|
||||
if (fmin > fmaxAllowed) return InputInfeasibleThrustHigh;
|
||||
|
||||
//possibly infeasible:
|
||||
if (fmin < fminAllowed || fmax > fmaxAllowed || wBound > wmaxAllowed)
|
||||
{ //indeterminate: must check more closely:
|
||||
double tHalf = (t1 + t2) / 2;
|
||||
InputFeasibilityResult r1 = CheckInputFeasibilitySection(fminAllowed, fmaxAllowed, wmaxAllowed, t1, tHalf, minTimeSection);
|
||||
|
||||
if(r1 == InputFeasible)
|
||||
{
|
||||
//continue with second half
|
||||
return CheckInputFeasibilitySection(fminAllowed, fmaxAllowed, wmaxAllowed, tHalf, t2, minTimeSection);
|
||||
}
|
||||
|
||||
//first section is already infeasible, or indeterminate:
|
||||
return r1;
|
||||
}
|
||||
|
||||
//definitely feasible:
|
||||
return InputFeasible;
|
||||
}
|
||||
|
||||
RapidTrajectoryGenerator::InputFeasibilityResult RapidTrajectoryGenerator::CheckInputFeasibility(double fminAllowed, double fmaxAllowed, double wmaxAllowed, double minTimeSection)
|
||||
{
|
||||
//required thrust limits along trajectory
|
||||
double t1 = 0;
|
||||
double t2 = _tf;
|
||||
|
||||
return CheckInputFeasibilitySection(fminAllowed, fmaxAllowed, wmaxAllowed, t1, t2, minTimeSection);
|
||||
}
|
||||
|
||||
|
||||
RapidTrajectoryGenerator::StateFeasibilityResult RapidTrajectoryGenerator::CheckPositionFeasibility(Vec3 boundaryPoint, Vec3 boundaryNormal)
|
||||
{
|
||||
//Ensure that the normal is a unit vector:
|
||||
boundaryNormal = boundaryNormal.GetUnitVector();
|
||||
|
||||
//first, we will build the polynomial describing the velocity of the a
|
||||
//quadrocopter in the direction of the normal. Then we will solve for
|
||||
//the zeros of this, which give us the times when the position is at a
|
||||
//critical point. Then we evaluate the position at these points, and at
|
||||
//the trajectory beginning and end, to see whether we are feasible.
|
||||
|
||||
//need to check that the trajectory stays inside the safe box throughout the flight:
|
||||
|
||||
//the coefficients of the quartic equation: x(t) = c[0]t**4 + c[1]*t**3 + c[2]*t**2 + c[3]*t + c[4]
|
||||
double c[5] = { 0, 0, 0, 0, 0 };
|
||||
|
||||
for(int dim=0; dim<3; dim++)
|
||||
{
|
||||
c[0] += boundaryNormal[dim]*_axis[dim].GetParamAlpha() / 24.0; //t**4
|
||||
c[1] += boundaryNormal[dim]*_axis[dim].GetParamBeta() / 6.0; //t**3
|
||||
c[2] += boundaryNormal[dim]*_axis[dim].GetParamGamma() / 2.0; //t**2
|
||||
c[3] += boundaryNormal[dim]*_axis[dim].GetInitialAcceleration(); //t
|
||||
c[4] += boundaryNormal[dim]*_axis[dim].GetInitialVelocity(); //1
|
||||
}
|
||||
|
||||
//Solve the roots (we prepend the times 0 and tf):
|
||||
double roots[6];
|
||||
roots[0] = 0;
|
||||
roots[1] = _tf;
|
||||
|
||||
size_t rootCount;
|
||||
if(fabs(c[0]) > 1e-6)
|
||||
{
|
||||
rootCount = magnet::math::quarticSolve(c[1] / c[0], c[2] / c[0], c[3] / c[0], c[4] / c[0], roots[2], roots[3], roots[4], roots[5]);
|
||||
}
|
||||
else
|
||||
{
|
||||
rootCount = magnet::math::cubicSolve(c[2] / c[1], c[3] / c[1], c[4] / c[1], roots[2], roots[3], roots[4]);
|
||||
}
|
||||
|
||||
for(unsigned i=0; i<(rootCount+2); i++)
|
||||
{
|
||||
//don't evaluate points outside the domain
|
||||
if(roots[i] < 0) continue;
|
||||
if(roots[i] > _tf) continue;
|
||||
|
||||
if((GetPosition(roots[i]) - boundaryPoint).Dot(boundaryNormal) <= 0)
|
||||
{
|
||||
//touching, or on the wrong side of, the boundary!
|
||||
return StateInfeasible;
|
||||
}
|
||||
}
|
||||
return StateFeasible;
|
||||
}
|
||||
|
||||
Vec3 RapidTrajectoryGenerator::GetOmega(double t, double timeStep) const
|
||||
{
|
||||
//Calculates the body rates necessary at time t, to rotate the normal vector.
|
||||
//The result is coordinated in the world frame, i.e. would have to be rotated into a
|
||||
//body frame.
|
||||
const Vec3 n0 = GetNormalVector(t);
|
||||
const Vec3 n1 = GetNormalVector(t + timeStep);
|
||||
|
||||
const Vec3 crossProd = n0.Cross(n1); //direction of omega, in inertial axes
|
||||
|
||||
if (crossProd.GetNorm2()) return (acos(n0.Dot(n1))/timeStep)*crossProd.GetUnitVector();
|
||||
else return Vec3(0, 0, 0);
|
||||
}
|
||||
|
||||
|
@ -1,187 +0,0 @@
|
||||
/*!
|
||||
* Rapid trajectory generation for quadrocopters
|
||||
*
|
||||
* Copyright 2014 by Mark W. Mueller <mwm@mwm.im>
|
||||
*
|
||||
* This code is free software: you can redistribute
|
||||
* it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include "SingleAxisTrajectory.h"
|
||||
#include "Vec3.h"
|
||||
|
||||
namespace RapidQuadrocopterTrajectoryGenerator
|
||||
{
|
||||
|
||||
//! A quadrocopter state interception trajectory.
|
||||
/*!
|
||||
* A quadrocopter state interception trajectory. The trajectory starts at a
|
||||
* state defined by the vehicle's position, velocity, and acceleration. The
|
||||
* acceleration can be calculated directly from the quadrocopter's attitude
|
||||
* and thrust value. The trajectory duration is fixed, and given by the user.
|
||||
*
|
||||
* The trajectory goal state can include any combination of components from
|
||||
* the quadrocopter's position, velocity, and acceleration. The acceleration
|
||||
* allows to encode the direction of the quadrocopter's thrust at the end time.
|
||||
*
|
||||
* The trajectories are generated without consideration for any constraints,
|
||||
* and are optimal with respect to the integral of the jerk squared (which is
|
||||
* equivalent to an upper bound on a product of the inputs).
|
||||
*
|
||||
* The trajectories can then be tested with respect to input constraints
|
||||
* (thrust/body rates) with an efficient, recursive algorithm. Whether linear
|
||||
* combinations of states along the trajectory remain within some bounds can
|
||||
* also be tested efficiently.
|
||||
*
|
||||
* For more information, please see the publication `A computationally efficient motion primitive for quadrocopter trajectory generation', avaible here: http://www.mwm.im/research/publications/
|
||||
*
|
||||
* NOTE: in the publication, axes are 1-indexed, while here they are
|
||||
* zero-indexed.
|
||||
*/
|
||||
class RapidTrajectoryGenerator
|
||||
{
|
||||
public:
|
||||
|
||||
enum InputFeasibilityResult
|
||||
{
|
||||
InputFeasible = 0,//!<The trajectory is input feasible
|
||||
InputIndeterminable = 1,//!<Cannot determine whether the trajectory is feasible with respect to the inputs
|
||||
InputInfeasibleThrustHigh = 2,//!<Trajectory is infeasible, failed max. thrust test first
|
||||
InputInfeasibleThrustLow = 3,//!<Trajectory is infeasible, failed min. thrust test first
|
||||
InputInfeasibleRates = 4,//!<Trajectory is infeasible, failed max. rates test first
|
||||
};
|
||||
|
||||
enum StateFeasibilityResult
|
||||
{
|
||||
StateFeasible = 0,//!<The trajectory is feasible w.r.t. the test
|
||||
StateInfeasible = 1,//!<Trajectory is infeasible
|
||||
};
|
||||
|
||||
//! Constructor, user must define initial state, and the direction of gravity.
|
||||
RapidTrajectoryGenerator(const Vec3 x0, const Vec3 v0, const Vec3 a0, const Vec3 gravity);
|
||||
|
||||
//set the final state for all axes:
|
||||
//! Fix the full position at the end time (see also the per-axis functions).
|
||||
void SetGoalPosition(const Vec3 in);
|
||||
//! Fix the full velocity at the end time (see also the per-axis functions).
|
||||
void SetGoalVelocity(const Vec3 in);
|
||||
//! Fix the full acceleration at the end time (see also the per-axis functions).
|
||||
void SetGoalAcceleration(const Vec3 in);
|
||||
|
||||
//set final state per axis:
|
||||
//! Fix the position at the end time in one axis. If not set, it is left free.
|
||||
void SetGoalPositionInAxis(const unsigned axNum, const double in){_axis[axNum].SetGoalPosition(in);};
|
||||
//! Fix the velocity at the end time in one axis. If not set, it is left free.
|
||||
void SetGoalVelocityInAxis(const unsigned axNum, const double in){_axis[axNum].SetGoalVelocity(in);};
|
||||
//! Fix the acceleration at the end time in one axis. If not set, it is left free.
|
||||
void SetGoalAccelerationInAxis(const unsigned axNum, const double in){_axis[axNum].SetGoalAcceleration(in);};
|
||||
|
||||
//! Reset the trajectory, clearing any end state constraints.
|
||||
void Reset(void);
|
||||
|
||||
/*! Calculate the optimal trajectory of duration `timeToGo`.
|
||||
*
|
||||
* Calculate the full trajectory, for all the parameters defined so far.
|
||||
* @param timeToGo The trajectory duration, in [s].
|
||||
*/
|
||||
void Generate(const double timeToGo);
|
||||
|
||||
/*! Test the trajectory for input feasibility.
|
||||
*
|
||||
* Test whether the inputs required along the trajectory are within the allowable limits.
|
||||
* Note that the test either
|
||||
* - proves feasibility,
|
||||
* - proves infeasibility,
|
||||
* - fails to prove anything ("indeterminate")
|
||||
*
|
||||
* The user must also specify a minimumTimeSection, which then determines the
|
||||
* precision of tests (and thus limit the number of recursion steps).
|
||||
*
|
||||
* Refer to the paper for a full discussion on these tests.
|
||||
*
|
||||
* Note that if the result is not feasible, the result is that of the first
|
||||
* section which tested infeasible/indeterminate.
|
||||
*
|
||||
* @param fminAllowed Minimum thrust value inputs allowed [m/s**2].
|
||||
* @param fmaxAllowed Maximum thrust value inputs allowed [m/s**2].
|
||||
* @param wmaxAllowed Maximum body rates input allowed [rad/s].
|
||||
* @param minTimeSection Minimum time section to test during the recursion [s].
|
||||
* @return an instance of InputFeasibilityResult.
|
||||
*/
|
||||
InputFeasibilityResult CheckInputFeasibility(double fminAllowed, double fmaxAllowed, double wmaxAllowed, double minTimeSection);
|
||||
|
||||
/*! Test the trajectory for position feasibility.
|
||||
*
|
||||
* Test whether the position flown along the trajectory is feasible with
|
||||
* respect to a user defined boundary (modelled as a plane). The plane is
|
||||
* defined by a point lying on the plane, and the normal of the plane.
|
||||
*
|
||||
* No test is done for degenerate normals (of the form (0,0,0)).
|
||||
*
|
||||
* @param boundaryPoint The coordinates of any point on the plane defining the boundary.
|
||||
* @param boundaryNormal A vector pointing in the allowable direction, away from the boundary.
|
||||
* @return An instance of StateFeasibilityResult.
|
||||
*/
|
||||
StateFeasibilityResult CheckPositionFeasibility(Vec3 boundaryPoint, Vec3 boundaryNormal);
|
||||
|
||||
//! Return the jerk along the trajectory at time t
|
||||
Vec3 GetJerk(double t) const {return Vec3(_axis[0].GetJerk(t), _axis[1].GetJerk(t), _axis[2].GetJerk(t));};
|
||||
//! Return the acceleration along the trajectory at time t
|
||||
Vec3 GetAcceleration(double t) const {return Vec3(_axis[0].GetAcceleration(t), _axis[1].GetAcceleration(t), _axis[2].GetAcceleration(t));};
|
||||
//! Return the velocity along the trajectory at time t
|
||||
Vec3 GetVelocity(double t) const {return Vec3(_axis[0].GetVelocity(t), _axis[1].GetVelocity(t), _axis[2].GetVelocity(t));};
|
||||
//! Return the position along the trajectory at time t
|
||||
Vec3 GetPosition(double t) const {return Vec3(_axis[0].GetPosition(t), _axis[1].GetPosition(t), _axis[2].GetPosition(t));};
|
||||
|
||||
//! Return the quadrocopter's normal vector along the trajectory at time t
|
||||
Vec3 GetNormalVector(double t) const {return (GetAcceleration(t) - _grav).GetUnitVector();};
|
||||
//! Return the quadrocopter's thrust input along the trajectory at time t
|
||||
double GetThrust(double t) const {return (GetAcceleration(t) - _grav).GetNorm2();};
|
||||
/*! Return the quadrocopter's body rates along the trajectory at time t
|
||||
*
|
||||
* Returns the required body rates along the trajectory. These are expressed
|
||||
* in the world frame (in which the trajectory was planned). To convert them
|
||||
* to (p,q,r), this needs to be rotated by the quadrocopter's attitude.
|
||||
*
|
||||
* The rates are calculated by taking the rates required to rotate the
|
||||
* quadrocopter's normal at time `t` to that at time `t+dt`. Therefore, if
|
||||
* the trajectory is used as implicit MPC control law, the value dt should
|
||||
* correspond to the controller period.
|
||||
*
|
||||
* @param t Time along the trajectory to be evaluated [s].
|
||||
* @param timeStep The timestep size for the finite differencing [s].
|
||||
* @return The body rates, expressed in the inertial frame [rad/s]
|
||||
*/
|
||||
Vec3 GetOmega(double t, double timeStep) const;
|
||||
|
||||
//! Return the total cost of the trajectory.
|
||||
double GetCost(void) const { return _axis[0].GetCost() + _axis[1].GetCost() + _axis[2].GetCost();};
|
||||
|
||||
//! Return the parameter defining the trajectory.
|
||||
double GetAxisParamAlpha(int i) const{return _axis[i].GetParamAlpha();};
|
||||
//! Return the parameter defining the trajectory.
|
||||
double GetAxisParamBeta(int i) const{return _axis[i].GetParamBeta();};
|
||||
//! Return the parameter defining the trajectory.
|
||||
double GetAxisParamGamma(int i) const{return _axis[i].GetParamGamma();};
|
||||
|
||||
private:
|
||||
//! Test a section of the trajectory for input feasibility (recursion).
|
||||
InputFeasibilityResult CheckInputFeasibilitySection(double fminAllowed, double fmaxAllowed, double wmaxAllowed, double t1, double t2, double minTimeSection);
|
||||
|
||||
SingleAxisTrajectory _axis[3];//!<The axes along the single trajectories
|
||||
Vec3 _grav;//!<gravity in the frame of the trajectory
|
||||
double _tf; //!<trajectory end time [s]
|
||||
};
|
||||
|
||||
};//namespace
|
@ -1,273 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Slightly modified the original files from https://www.marcusbannerman.co.uk/index.php/downloads.html?func=finishdown&id=20
|
||||
Mark W. Mueller (mwm@mwm.im)
|
||||
|
||||
Changes:
|
||||
- undef max
|
||||
- some readibility tweaks.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include "quadratic.hpp"
|
||||
|
||||
//WinDef.h defines a max() macro, which screws up compilation here...
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
namespace magnet
|
||||
{
|
||||
namespace math
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
inline void
|
||||
cubicNewtonRootPolish(const double& p, const double& q, const double& r, double& root, size_t iterations)
|
||||
{
|
||||
for (size_t it = 0; it < iterations; ++it)
|
||||
{
|
||||
double error = ((root + p) * root + q) * root + r;
|
||||
double derivative = (3.0 * root + 2 * p) * root + q;
|
||||
|
||||
if ((error == 0) || derivative == 0)
|
||||
return;
|
||||
|
||||
root -= error / derivative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Please read http://linus.it.uts.edu.au/~don/pubs/solving.html
|
||||
//For solving cubics like x^3 + p * x^2 + q * x + r == 0
|
||||
//This function always returns root1 >= root2 >= root3!
|
||||
inline size_t
|
||||
cubicSolve(const double& p, const double& q, const double& r, double& root1, double& root2, double& root3)
|
||||
{
|
||||
static const double maxSqrt = std::sqrt(std::numeric_limits<double>::max());
|
||||
// static const double maxCubeRoot = std::pow(std::numeric_limits<double>::max(), 1.0 / 3.0); //Unused
|
||||
|
||||
if (r == 0)
|
||||
{
|
||||
//no constant term, so divide by x and the result is a
|
||||
//quadratic, but we must include the trivial x = 0 root
|
||||
if (quadraticSolve(p, q, root1, root2))
|
||||
{
|
||||
root3 = 0;
|
||||
if (root1 < root2)
|
||||
std::swap(root1, root2);
|
||||
if (root2 < 0)
|
||||
{
|
||||
std::swap(root2, root3);
|
||||
if (root1 < 0)
|
||||
std::swap(root1, root2);
|
||||
}
|
||||
return 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
root1 = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if ((p == 0) && (q == 0))
|
||||
{
|
||||
//Special case
|
||||
//Equation is x^3 == -r
|
||||
root1 = root2 = root3 = std::pow(-r, 1.0 / 3.0);
|
||||
return 3;
|
||||
}
|
||||
|
||||
if ((p > maxSqrt) || (p < -maxSqrt))
|
||||
{
|
||||
//Equation limits to x^3 + p * x^2 == 0
|
||||
root1 = -p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (q > maxSqrt)
|
||||
{
|
||||
//Special case, if q is large and the root is -r/q,
|
||||
//The x^3 term is negligble, and all other terms cancel.
|
||||
root1 = -r / q;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (q < -maxSqrt)
|
||||
{
|
||||
//Special case, equation is x^3 + q x == 0
|
||||
root1 = -std::sqrt(-q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if ((r > maxSqrt) || (r < -maxSqrt))
|
||||
{
|
||||
//Another special case
|
||||
//Equation is x^3 == -r
|
||||
root1 = -std::pow(r, 1.0 / 3.0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
double v = r + (2.0 * p * p / 9.0 - q) * (p / 3.0);
|
||||
|
||||
if ((v > maxSqrt) || (v < -maxSqrt))
|
||||
{
|
||||
root1 = -p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double uo3 = q / 3.0 - p * p / 9.0;
|
||||
double u2o3 = uo3 + uo3;
|
||||
|
||||
if ((u2o3 > maxSqrt) || (u2o3 < -maxSqrt))
|
||||
{
|
||||
if (p == 0)
|
||||
{
|
||||
if (q > 0)
|
||||
{
|
||||
root1 = -r / q;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (q < 0)
|
||||
{
|
||||
root1 = -std::sqrt(-q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
root1 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
root1 = -q / p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double uo3sq4 = u2o3 * u2o3;
|
||||
if (uo3sq4 > maxSqrt)
|
||||
{
|
||||
if (p == 0)
|
||||
{
|
||||
if (q > 0)
|
||||
{
|
||||
root1 = -r / q;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (q < 0)
|
||||
{
|
||||
root1 = -std::sqrt(-q);
|
||||
return 1;
|
||||
}
|
||||
|
||||
root1 = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
root1 = -q / p;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double j = (uo3sq4 * uo3) + v * v;
|
||||
|
||||
if (j > 0)
|
||||
{ //Only one root (but this test can be wrong due to a
|
||||
//catastrophic cancellation in j
|
||||
//(i.e. (uo3sq4 * uo3) == v * v)
|
||||
double w = std::sqrt(j);
|
||||
//double mcube;
|
||||
if (v < 0)
|
||||
root1 = std::pow(0.5 * (w - v), 1.0 / 3.0) - (uo3) * std::pow(2.0 / (w - v), 1.0 / 3.0) - p / 3.0;
|
||||
else
|
||||
root1 = uo3 * std::pow(2.0 / (w + v), 1.0 / 3.0) - std::pow(0.5 * (w + v), 1.0 / 3.0) - p / 3.0;
|
||||
|
||||
//We now polish the root up before we use it in other calculations
|
||||
detail::cubicNewtonRootPolish(p, q, r, root1, 15);
|
||||
|
||||
//We double check that there are no more roots by using a
|
||||
//quadratic formula on the factored problem, this helps when
|
||||
//the j test is wrong due to numerical error.
|
||||
|
||||
//We have a choice of either -r/root1, or q -
|
||||
//(p+root1)*root1 for the constant term of the quadratic.
|
||||
//
|
||||
//The division one usually results in more accurate roots
|
||||
//when it finds them but fails to detect real roots more
|
||||
//often than the multiply.
|
||||
if (quadraticSolve(p + root1, -r / root1, root2, root3))
|
||||
return 3;
|
||||
//
|
||||
//However, the multiply detects roots where there are none,
|
||||
//the division does not. So we must either accept missing
|
||||
//roots or extra roots, here we choose missing roots
|
||||
//
|
||||
//if (quadSolve(q-(p+root1)*root1, p + root1, 1.0, root2, root3))
|
||||
// return 3;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (uo3 >= 0)
|
||||
{ //Multiple root detected
|
||||
root1 = root2 = root3 = std::pow(v, 1.0 / 3.0) - p / 3.0;
|
||||
return 3;
|
||||
}
|
||||
|
||||
double muo3 = -uo3;
|
||||
double s;
|
||||
if (muo3 > 0)
|
||||
{
|
||||
s = std::sqrt(muo3);
|
||||
if (p > 0)
|
||||
s = -s;
|
||||
}
|
||||
else
|
||||
s = 0;
|
||||
|
||||
double scube = s * muo3;
|
||||
if (scube == 0)
|
||||
{
|
||||
root1 = -p / 3.0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
double t = -v / (scube + scube);
|
||||
double k = std::acos(t) / 3.0;
|
||||
double cosk = std::cos(k);
|
||||
root1 = (s + s) * cosk - p / 3.0;
|
||||
|
||||
double sinsqk = 1.0 - cosk * cosk;
|
||||
if (sinsqk < 0)
|
||||
return 1;
|
||||
|
||||
double rt3sink = std::sqrt(3.) * std::sqrt(sinsqk);
|
||||
root2 = s * (-cosk + rt3sink) - p / 3.0;
|
||||
root3 = s * (-cosk - rt3sink) - p / 3.0;
|
||||
|
||||
detail::cubicNewtonRootPolish(p, q, r, root1, 15);
|
||||
detail::cubicNewtonRootPolish(p, q, r, root2, 15);
|
||||
detail::cubicNewtonRootPolish(p, q, r, root3, 15);
|
||||
|
||||
return 3;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,144 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
//Solve a quadratic of the form x^2 + B x + C == 0
|
||||
inline bool quadraticSolve(const double& B, const double& C,
|
||||
double& root1, double& root2)
|
||||
{
|
||||
double discriminant = (B * B) - (4 * C);
|
||||
|
||||
//Cannot do imaginary numbers, yet
|
||||
if (discriminant < 0) return false;
|
||||
|
||||
//This avoids a cancellation of errors. See
|
||||
//http://en.wikipedia.org/wiki/Quadratic_equation#Floating_point_implementation
|
||||
double t = -0.5 * ( B + ((B < 0) ? -1 : 1) * std::sqrt(discriminant));
|
||||
|
||||
root1 = t;
|
||||
if(t==0) root2 = 0;
|
||||
else root2 = C / t;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline bool quadSolve(const double& C, const double& B, const double& A,
|
||||
double& root1, double& root2)
|
||||
{
|
||||
// Contingency: if A = 0, not a quadratic = linear
|
||||
if(A == 0)
|
||||
{
|
||||
//If B is zero then we have a NaN
|
||||
if(B == 0) return false;
|
||||
|
||||
root1 = -1.0 * C / B;
|
||||
root2 = root1;
|
||||
}
|
||||
|
||||
double discriminant = (B * B) - (4 * A * C);
|
||||
|
||||
//Cannot do imaginary numbers, yet
|
||||
if (discriminant < 0) return false;
|
||||
|
||||
//This avoids a cancellation of errors. See
|
||||
//http://en.wikipedia.org/wiki/Quadratic_equation#Floating_point_implementation
|
||||
double t = -0.5 * ( B + ((B < 0) ? -1 : 1) * std::sqrt(discriminant));
|
||||
|
||||
root1 = t / A;
|
||||
root2 = C / t;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
typedef enum {
|
||||
ROOT_SMALLEST_EITHER = 1,
|
||||
ROOT_SMALLEST_POSITIVE = 2,
|
||||
ROOT_SMALLEST_NEGATIVE = 4,
|
||||
ROOT_LARGEST_EITHER = 8,
|
||||
ROOT_LARGEST_POSITIVE = 16,
|
||||
ROOT_LARGEST_NEGATIVE = 32
|
||||
} rootTypeEnum;
|
||||
|
||||
template<rootTypeEnum rootType>
|
||||
inline bool quadSolve(const double& C, const double& B, const double& A, double& ans)
|
||||
{
|
||||
double root1(0), root2(0);
|
||||
|
||||
if (!quadSolve(C,B,A,root1,root2)) return false;
|
||||
|
||||
switch (rootType)
|
||||
{
|
||||
case ROOT_SMALLEST_EITHER:
|
||||
ans = (fabs(root1) < fabs(root2)) ? root1 : root2;
|
||||
break;
|
||||
case ROOT_LARGEST_EITHER:
|
||||
ans = (fabs(root1) < fabs(root2)) ? root2 : root1;
|
||||
case ROOT_LARGEST_NEGATIVE:
|
||||
if (root1 < 0 && root2 < 0)
|
||||
ans = ((root1 < root2) ? root1 : root2);
|
||||
else if (root1 < 0)
|
||||
ans = root1;
|
||||
else if (root2 < 0)
|
||||
ans = root2;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case ROOT_SMALLEST_NEGATIVE:
|
||||
if (root1 < 0 && root2 < 0)
|
||||
ans = ((root1 < root2) ? root2 : root1);
|
||||
else if (root1 < 0)
|
||||
ans = root1;
|
||||
else if (root2 < 0)
|
||||
ans = root2;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case ROOT_LARGEST_POSITIVE:
|
||||
if (root1 > 0 && root2 > 0)
|
||||
ans = ((root1 > root2) ? root1 : root2);
|
||||
else if (root1 > 0)
|
||||
ans = root1;
|
||||
else if (root2 > 0)
|
||||
ans = root2;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
case ROOT_SMALLEST_POSITIVE:
|
||||
if (root1 > 0 && root2 > 0)
|
||||
ans = ((root1 > root2) ? root2 : root1);
|
||||
else if (root1 > 0)
|
||||
ans = root1;
|
||||
else if (root2 > 0)
|
||||
ans = root2;
|
||||
else
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
throw std::runtime_error("Unknown root selected");
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,117 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "quartic_yacfraid.hpp"
|
||||
#include "quartic_descartes.hpp"
|
||||
#include "quartic_neumark.hpp"
|
||||
#include "quartic_ferrari.hpp"
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
namespace detail {
|
||||
inline void quarticNewtonRootPolish(const double& a, const double& b, const double& c, const double& d,
|
||||
double& root, size_t iterations)
|
||||
{
|
||||
for (size_t it = 0; it < iterations; ++it)
|
||||
{
|
||||
double error = (((root + a)*root + b) * root + c) * root + d;
|
||||
double derivative = ((4 * root + 3 * a) * root + 2 * b) * root + c;
|
||||
|
||||
if ((error == 0) || derivative == 0) return;
|
||||
|
||||
root -= error / derivative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Solves quartics of the form x^4 + a x^3 + b x^2 + c x + d ==0
|
||||
inline size_t quarticSolve(const double& a, const double& b, const double& c, const double& d,
|
||||
double& root1, double& root2, double& root3, double& root4)
|
||||
{
|
||||
static const double maxSqrt = std::sqrt(std::numeric_limits<double>::max());
|
||||
|
||||
if (std::abs(a) > maxSqrt)
|
||||
yacfraidQuarticSolve(a,b,c,d,root1,root2,root3,root4);
|
||||
|
||||
if (d == 0)
|
||||
{//Solve a cubic with a trivial root of 0
|
||||
root1 = 0;
|
||||
return 1 + cubicSolve(a, b, c, root2, root3, root4);
|
||||
}
|
||||
|
||||
if ((a == 0) && (c== 0))
|
||||
{//We have a biquadratic
|
||||
double quadRoot1,quadRoot2;
|
||||
if (quadSolve(d,b,1, quadRoot1, quadRoot2))
|
||||
{
|
||||
if (quadRoot1 < quadRoot2) std::swap(quadRoot1,quadRoot2);
|
||||
|
||||
if (quadRoot1 < 0)
|
||||
return 0;
|
||||
|
||||
root1 = std::sqrt(quadRoot1);
|
||||
root2 = -std::sqrt(quadRoot1);
|
||||
|
||||
if (quadRoot2 < 0)
|
||||
return 2;
|
||||
|
||||
root3 = std::sqrt(quadRoot2);
|
||||
root4 = -std::sqrt(quadRoot2);
|
||||
return 4;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
//Now we have to resort to some dodgy formulae!
|
||||
size_t k = 0, nr;
|
||||
if (a < 0.0) k += 2;
|
||||
if (b < 0.0) k += 1;
|
||||
if (c < 0.0) k += 8;
|
||||
if (d < 0.0) k += 4;
|
||||
switch (k)
|
||||
{
|
||||
case 3 :
|
||||
case 9 :
|
||||
nr = ferrariQuarticSolve(a,b,c,d,root1,root2,root3,root4);
|
||||
break;
|
||||
case 5 :
|
||||
nr = descartesQuarticSolve(a,b,c,d,root1,root2,root3,root4);
|
||||
break;
|
||||
case 15 :
|
||||
//This algorithm is stable if we flip the sign of the roots
|
||||
nr = descartesQuarticSolve(-a,b,-c,d,root1,root2,root3,root4);
|
||||
root1 *=-1; root2 *=-1; root3 *=-1; root4 *=-1;
|
||||
break;
|
||||
default:
|
||||
nr = neumarkQuarticSolve(a,b,c,d,root1,root2,root3,root4);
|
||||
//nr = ferrariQuarticSolve(a,b,c,d,root1,root2,root3,root4);
|
||||
//nr = yacfraidQuarticSolve(a,b,c,d,root1,root2,root3,root4);
|
||||
break;
|
||||
}
|
||||
|
||||
if (nr) detail::quarticNewtonRootPolish(a, b, c, d, root1, 15);
|
||||
if (nr>1) detail::quarticNewtonRootPolish(a, b, c, d, root2, 15);
|
||||
if (nr>2) detail::quarticNewtonRootPolish(a, b, c, d, root3, 15);
|
||||
if (nr>3) detail::quarticNewtonRootPolish(a, b, c, d, root4, 15);
|
||||
|
||||
return nr;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,99 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cubic.hpp"
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
inline size_t
|
||||
descartesQuarticSolve(const double& a, const double& b, const double& c, const double& d,
|
||||
double& root1, double& root2, double& root3, double& root4)
|
||||
{
|
||||
double rts[4];
|
||||
double worst3[3];
|
||||
double qrts[4][3]; /* quartic roots for each cubic root */
|
||||
|
||||
if (d == 0.0)
|
||||
{
|
||||
root1 = 0.0;
|
||||
return cubicSolve(a,b,c,root2,root3,root4) + 1;
|
||||
}
|
||||
|
||||
int j, n4[4];
|
||||
double v1[4],v2[4],v3[4];
|
||||
double k,y;
|
||||
double p,q,r;
|
||||
double e0,e1,e2;
|
||||
double g,h;
|
||||
double asq;
|
||||
double ainv4;
|
||||
double e1invk;
|
||||
|
||||
asq = a*a;
|
||||
e2 = b - asq * (3.0/8.0);
|
||||
e1 = c + a*(asq*0.125 - b*0.5);
|
||||
e0 = d + asq*(b*0.0625 - asq*(3.0/256.0)) - a*c*0.25;
|
||||
|
||||
p = 2.0*e2;
|
||||
q = e2*e2 - 4.0*e0;
|
||||
r = -e1*e1;
|
||||
|
||||
size_t n3 = cubicSolve(p,q,r,v3[0],v3[1],v3[2]);
|
||||
for (size_t j3 = 0; j3 < n3; ++j3)
|
||||
{
|
||||
y = v3[j3];
|
||||
if (y <= 0.0)
|
||||
n4[j3] = 0;
|
||||
else
|
||||
{
|
||||
k = std::sqrt(y);
|
||||
ainv4 = a*0.25;
|
||||
e1invk = e1/k;
|
||||
g = (y + e2 + e1invk)*0.5;
|
||||
h = (y + e2 - e1invk)*0.5 ;
|
||||
bool n1 = quadSolve( g, -k, 1.0, v1[0], v1[1]);
|
||||
bool n2 = quadSolve( h, k, 1.0, v2[0], v2[1]);
|
||||
qrts[0][j3] = v1[0] - ainv4;
|
||||
qrts[1][j3] = v1[1] - ainv4;
|
||||
qrts[n1*2][j3] = v2[0] - ainv4;
|
||||
qrts[n1*2+1][j3] = v2[1] - ainv4;
|
||||
n4[j3]= n1*2 + n2*2;
|
||||
} /* y>=0 */
|
||||
for (j = 0; j < n4[j3]; ++j)
|
||||
rts[j] = qrts[j][j3];
|
||||
worst3[j3] = quarticError(a, b, c, d, rts, n4[j3]);
|
||||
} /* j3 loop */
|
||||
size_t j3 = 0;
|
||||
if (n3 != 1)
|
||||
{
|
||||
if ((n4[1] > n4[j3]) ||
|
||||
((worst3[1] < worst3[j3] ) && (n4[1] == n4[j3]))) j3 = 1;
|
||||
if ((n4[2] > n4[j3]) ||
|
||||
((worst3[2] < worst3[j3] ) && (n4[2] == n4[j3]))) j3 = 2;
|
||||
}
|
||||
|
||||
root1 = qrts[0][j3];
|
||||
root2 = qrts[1][j3];
|
||||
root3 = qrts[2][j3];
|
||||
root4 = qrts[3][j3];
|
||||
|
||||
return (n4[j3]);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,75 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Slightly modified the original files from https://www.marcusbannerman.co.uk/index.php/downloads.html?func=finishdown&id=20
|
||||
Mark W. Mueller (mwm@mwm.im)
|
||||
|
||||
Changes:
|
||||
- Removed boost code
|
||||
- some readibility tweaks.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cmath>
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
inline double quarticError(const double& a, const double& b, const double& c,
|
||||
const double& d, const double roots[4], const size_t rootCount) {
|
||||
// boost::array<double, 4> errors;
|
||||
double errors[4];
|
||||
|
||||
for (size_t root = 0; root < rootCount; ++root) {
|
||||
const double value = (((roots[root] + a) * roots[root] + b)
|
||||
* roots[root] + c) * roots[root] + d;
|
||||
|
||||
if (value == 0) {
|
||||
errors[root] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const double deriv = ((4 * roots[root] + 3 * a) * roots[root] + 2 * b)
|
||||
* roots[root] + c;
|
||||
|
||||
if (deriv != 0)
|
||||
errors[root] = std::abs(value / deriv);
|
||||
else {
|
||||
const double secDeriv = (12 * roots[root] + 6 * a) * roots[root]
|
||||
+ 2 * b;
|
||||
if (secDeriv != 0)
|
||||
errors[root] = std::sqrt(std::abs(value / secDeriv));
|
||||
else {
|
||||
const double thirdDeriv = 24 * roots[root] + 6 * a;
|
||||
if (thirdDeriv != 0)
|
||||
errors[root] = std::pow(std::abs(value / thirdDeriv),
|
||||
1.0 / 3.0);
|
||||
else
|
||||
errors[root] = std::sqrt(std::sqrt(std::abs(value) / 24));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
double err = 0;
|
||||
for (unsigned i = 0; i < rootCount; i++) {
|
||||
if(errors[i]>err) err = errors[i];
|
||||
}
|
||||
return err;
|
||||
// return *std::max_element(errors.begin(), errors.begin() + rootCount);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,177 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Slightly modified the original files from https://www.marcusbannerman.co.uk/index.php/downloads.html?func=finishdown&id=20
|
||||
Mark W. Mueller (mwm@mwm.im)
|
||||
|
||||
Changes:
|
||||
- some readibility tweaks (also removes an eclipse warning about braces).
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cubic.hpp"
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
inline size_t
|
||||
ferrariQuarticSolve(const double& a, const double& b, const double& c, const double& d,
|
||||
double& root1, double& root2, double& root3, double& root4)
|
||||
{
|
||||
double rts[4];
|
||||
double worst3[3];
|
||||
double qrts[4][3]; /* quartic roots for each cubic root */
|
||||
|
||||
if (d == 0.0)
|
||||
{
|
||||
root1 = 0.0;
|
||||
return cubicSolve(a,b,c,root2,root3,root4) + 1;
|
||||
}
|
||||
|
||||
int j;
|
||||
int n4[4];
|
||||
double asqinv4;
|
||||
double ainv2;
|
||||
double d4;
|
||||
double yinv2;
|
||||
double v1[4],v2[4],v3[4];
|
||||
double p,q,r;
|
||||
double y;
|
||||
double e,f,esq,fsq,ef;
|
||||
double g,gg,h,hh;
|
||||
|
||||
ainv2 = a*0.5;
|
||||
asqinv4 = ainv2*ainv2;
|
||||
d4 = d*4.0 ;
|
||||
|
||||
p = b;
|
||||
q = a*c-d4;
|
||||
r = (asqinv4 - b)*d4 + c*c;
|
||||
size_t n3 = cubicSolve(p,q,r,v3[0],v3[1],v3[2]);
|
||||
for (size_t j3 = 0; j3 < n3; ++j3)
|
||||
{
|
||||
y = v3[j3];
|
||||
yinv2 = y*0.5;
|
||||
esq = asqinv4 - b - y;
|
||||
fsq = yinv2*yinv2 - d;
|
||||
if ((esq < 0.0) && (fsq < 0.0))
|
||||
n4[j3] = 0;
|
||||
else
|
||||
{
|
||||
ef = -(0.25*a*y + 0.5*c);
|
||||
if ( ((a > 0.0)&&(y > 0.0)&&(c > 0.0))
|
||||
|| ((a > 0.0)&&(y < 0.0)&&(c < 0.0))
|
||||
|| ((a < 0.0)&&(y > 0.0)&&(c < 0.0))
|
||||
|| ((a < 0.0)&&(y < 0.0)&&(c > 0.0))
|
||||
|| (a == 0.0)||(y == 0.0)||(c == 0.0))
|
||||
/* use ef - */
|
||||
{
|
||||
if ((b < 0.0)&&(y < 0.0))
|
||||
{
|
||||
e = sqrt(esq);
|
||||
f = ef/e;
|
||||
}
|
||||
else if (d < 0.0)
|
||||
{
|
||||
f = sqrt(fsq);
|
||||
e = ef/f;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (esq > 0.0)
|
||||
e = sqrt(esq);
|
||||
else
|
||||
e = 0.0;
|
||||
if (fsq > 0.0)
|
||||
f = sqrt(fsq);
|
||||
else
|
||||
f = 0.0;
|
||||
if (ef < 0.0)
|
||||
f = -f;
|
||||
}
|
||||
}
|
||||
else
|
||||
/* use esq and fsq - */
|
||||
{
|
||||
if (esq > 0.0)
|
||||
e = sqrt(esq);
|
||||
else
|
||||
e = 0.0;
|
||||
if (fsq > 0.0)
|
||||
f = sqrt(fsq);
|
||||
else
|
||||
f = 0.0;
|
||||
if (ef < 0.0)
|
||||
f = -f;
|
||||
}
|
||||
/* note that e >= 0.0 */
|
||||
g = ainv2 - e;
|
||||
gg = ainv2 + e;
|
||||
if ( ((b > 0.0)&&(y > 0.0))
|
||||
|| ((b < 0.0)&&(y < 0.0)) )
|
||||
{
|
||||
if (((a > 0.0) && (e > 0.0))
|
||||
|| ((a < 0.0) && (e < 0.0) ))
|
||||
g = (b + y)/gg;
|
||||
else
|
||||
if (((a > 0.0) && (e < 0.0))
|
||||
|| ((a < 0.0) && (e > 0.0) ))
|
||||
gg = (b + y)/g;
|
||||
}
|
||||
hh = -yinv2 + f;
|
||||
h = -yinv2 - f;
|
||||
if ( ((f > 0.0)&&(y < 0.0))
|
||||
|| ((f < 0.0)&&(y > 0.0)) )
|
||||
h = d/hh;
|
||||
else
|
||||
if ( ((f < 0.0)&&(y < 0.0))
|
||||
|| ((f > 0.0)&&(y > 0.0)) )
|
||||
hh = d/h;
|
||||
|
||||
bool n1 = quadSolve(hh,gg,1.0,v1[0],v1[1]);
|
||||
bool n2 = quadSolve(h,g,1.0,v2[0],v2[1]);
|
||||
n4[j3] = n1*2+n2*2;
|
||||
qrts[0][j3] = v1[0];
|
||||
qrts[1][j3] = v1[1];
|
||||
qrts[n1*2+0][j3] = v2[0];
|
||||
qrts[n1*2+1][j3] = v2[1];
|
||||
}
|
||||
for (j = 0; j < n4[j3]; ++j)
|
||||
rts[j] = qrts[j][j3];
|
||||
|
||||
worst3[j3] = quarticError(a, b, c, d, rts, n4[j3]);
|
||||
} /* j3 loop */
|
||||
|
||||
size_t j3 = 0;
|
||||
if (n3 != 1)
|
||||
{
|
||||
if ((n4[1] > n4[j3]) ||
|
||||
((worst3[1] < worst3[j3] ) && (n4[1] == n4[j3]))) j3 = 1;
|
||||
|
||||
if ((n4[2] > n4[j3]) ||
|
||||
((worst3[2] < worst3[j3] ) && (n4[2] == n4[j3]))) j3 = 2;
|
||||
}
|
||||
|
||||
root1 = qrts[0][j3];
|
||||
root2 = qrts[1][j3];
|
||||
root3 = qrts[2][j3];
|
||||
root4 = qrts[3][j3];
|
||||
|
||||
return (n4[j3]);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,179 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cubic.hpp"
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
//solve the quartic equation -
|
||||
//x**4 + a*x**3 + b*x**2 + c*x + d = 0
|
||||
inline size_t
|
||||
neumarkQuarticSolve(const double& a, const double& b, const double& c, const double& d,
|
||||
double& root1, double& root2, double& root3, double& root4)
|
||||
{
|
||||
double rts[4];
|
||||
double worst3[3];
|
||||
double y,g,gg,h,hh,gdis,gdisrt,hdis,hdisrt,g1,g2,h1,h2;
|
||||
double bmy,gerr,herr,y4,bmysq;
|
||||
double v1[4],v2[4],v3[4];
|
||||
double hmax,gmax;
|
||||
double qrts[4][3]; /* quartic roots for each cubic root */
|
||||
|
||||
if (d == 0.0)
|
||||
{
|
||||
root1 = 0.0;
|
||||
return cubicSolve(a,b,c,root2,root3,root4) + 1;
|
||||
}
|
||||
|
||||
double asq = a * a;
|
||||
|
||||
double d4 = d * 4.0;
|
||||
double p = -b * 2.0;
|
||||
double q = b * b + a * c - d4;
|
||||
double r = (c - a*b)*c + asq*d;
|
||||
size_t cubicRoots = cubicSolve(p,q,r,v3[0],v3[1],v3[2]);
|
||||
|
||||
size_t nQuarticRoots[3];
|
||||
|
||||
for (size_t j3 = 0; j3 < cubicRoots; ++j3)
|
||||
{
|
||||
y = v3[j3];
|
||||
|
||||
bmy = b - y;
|
||||
y4 = y * 4.0;
|
||||
bmysq = bmy*bmy;
|
||||
gdis = asq - y4;
|
||||
hdis = bmysq - d4;
|
||||
|
||||
if ((gdis < 0.0) || (hdis < 0.0))
|
||||
nQuarticRoots[j3] = 0;
|
||||
else
|
||||
{
|
||||
g1 = a * 0.5;
|
||||
h1 = bmy* 0.5;
|
||||
gerr = asq + y4;
|
||||
herr = hdis;
|
||||
if (d > 0.0)
|
||||
herr = bmysq + d4;
|
||||
if ((y < 0.0) || (herr*gdis > gerr*hdis))
|
||||
{
|
||||
gdisrt = sqrt(gdis);
|
||||
g2 = gdisrt*0.5;
|
||||
if (gdisrt != 0.0)
|
||||
h2 = (a*h1 - c)/gdisrt;
|
||||
else
|
||||
h2 = 0.0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hdisrt = std::sqrt(hdis);
|
||||
h2 = hdisrt*0.5;
|
||||
if (hdisrt != 0.0)
|
||||
g2 = (a*h1 - c)/hdisrt;
|
||||
else
|
||||
g2 = 0.0;
|
||||
}
|
||||
/*
|
||||
note that in the following, the tests ensure non-zero
|
||||
denominators -
|
||||
*/
|
||||
h = h1 - h2;
|
||||
hh = h1 + h2;
|
||||
hmax = hh;
|
||||
if (hmax < 0.0)
|
||||
hmax = -hmax;
|
||||
if (hmax < h)
|
||||
hmax = h;
|
||||
if (hmax < -h)
|
||||
hmax = -h;
|
||||
if ((h1 > 0.0)&&(h2 > 0.0))
|
||||
h = d/hh;
|
||||
if ((h1 < 0.0)&&(h2 < 0.0))
|
||||
h = d/hh;
|
||||
if ((h1 > 0.0)&&(h2 < 0.0))
|
||||
hh = d/h;
|
||||
if ((h1 < 0.0)&&(h2 > 0.0))
|
||||
hh = d/h;
|
||||
if (h > hmax)
|
||||
h = hmax;
|
||||
if (h < -hmax)
|
||||
h = -hmax;
|
||||
if (hh > hmax)
|
||||
hh = hmax;
|
||||
if (hh < -hmax)
|
||||
hh = -hmax;
|
||||
|
||||
g = g1 - g2;
|
||||
gg = g1 + g2;
|
||||
gmax = gg;
|
||||
if (gmax < 0.0)
|
||||
gmax = -gmax;
|
||||
if (gmax < g)
|
||||
gmax = g;
|
||||
if (gmax < -g)
|
||||
gmax = -g;
|
||||
if ((g1 > 0.0)&&(g2 > 0.0))
|
||||
g = y/gg;
|
||||
if ((g1 < 0.0)&&(g2 < 0.0))
|
||||
g = y/gg;
|
||||
if ((g1 > 0.0)&&(g2 < 0.0))
|
||||
gg = y/g;
|
||||
if ((g1 < 0.0)&&(g2 > 0.0))
|
||||
gg = y/g;
|
||||
if (g > gmax)
|
||||
g = gmax;
|
||||
if (g < -gmax)
|
||||
g = -gmax;
|
||||
if (gg > gmax)
|
||||
gg = gmax;
|
||||
if (gg < -gmax)
|
||||
gg = -gmax;
|
||||
|
||||
size_t n1 = quadSolve(hh,gg, 1.0,v1[0],v1[1]);
|
||||
size_t n2 = quadSolve(h,g,1.0,v2[0],v2[1]);
|
||||
nQuarticRoots[j3] = 2*n1 + 2*n2;
|
||||
qrts[0][j3] = v1[0];
|
||||
qrts[1][j3] = v1[1];
|
||||
qrts[2*n1+0][j3] = v2[0];
|
||||
qrts[2*n1+1][j3] = v2[1];
|
||||
}
|
||||
|
||||
for (size_t j = 0; j < nQuarticRoots[j3]; ++j)
|
||||
rts[j] = qrts[j][j3];
|
||||
worst3[j3] = quarticError(a, b, c, d, rts,nQuarticRoots[j3]);
|
||||
|
||||
} /* j3 loop */
|
||||
size_t j3 = 0;
|
||||
if (cubicRoots > 1)
|
||||
{
|
||||
if ((nQuarticRoots[1] > nQuarticRoots[j3]) ||
|
||||
((worst3[1] < worst3[j3] ) && (nQuarticRoots[1] == nQuarticRoots[j3]))) j3 = 1;
|
||||
if ((nQuarticRoots[2] > nQuarticRoots[j3]) ||
|
||||
((worst3[2] < worst3[j3] ) && (nQuarticRoots[2] == nQuarticRoots[j3]))) j3 = 2;
|
||||
}
|
||||
|
||||
root1 = qrts[0][j3];
|
||||
root2 = qrts[1][j3];
|
||||
root3 = qrts[2][j3];
|
||||
root4 = qrts[3][j3];
|
||||
|
||||
return nQuarticRoots[j3];
|
||||
}
|
||||
}
|
||||
}
|
@ -1,167 +0,0 @@
|
||||
/* DYNAMO:- Event driven molecular dynamics simulator
|
||||
http://www.marcusbannerman.co.uk/dynamo
|
||||
Copyright (C) 2010 Marcus N Campbell Bannerman <m.bannerman@gmail.com>
|
||||
|
||||
This program is free software: you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
version 3 as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "cubic.hpp"
|
||||
#include "quartic_error.hpp"
|
||||
|
||||
namespace magnet {
|
||||
namespace math {
|
||||
inline size_t
|
||||
yacfraidQuarticSolve(const double& a, const double& b, const double& c, const double& d,
|
||||
double& root1, double& root2, double& root3, double& root4)
|
||||
{
|
||||
int j;
|
||||
double y;
|
||||
double v3[4];
|
||||
double det0,det1,det2,det3;
|
||||
double det0rt,det1rt,det2rt,det3rt;
|
||||
double e,f,g,h,k;
|
||||
double fsq,gsq,hsq,invk;
|
||||
double P,Q,R,U;
|
||||
|
||||
double rts[4];
|
||||
double worst3[3];
|
||||
double qrts[4][3]; /* quartic roots for each cubic root */
|
||||
|
||||
if (d == 0.0)
|
||||
{
|
||||
root1 = 0.0;
|
||||
return cubicSolve(a,b,c,root2,root3,root4) + 1;
|
||||
}
|
||||
|
||||
double asq = a * a;
|
||||
double acu = a * asq;
|
||||
double b4 = b * 4.0;
|
||||
size_t n3 = 0;
|
||||
int n4[4];
|
||||
|
||||
P = asq * b - b4 * b + 2.0 * a * c + 16.0 * d ;
|
||||
Q = asq * c - b4 * c + 8.0 * a * d;
|
||||
R = asq * d - c * c;
|
||||
U = acu - b4 * a + 8.0 * c;
|
||||
n4[0] = 0;
|
||||
|
||||
|
||||
asq = a*a;
|
||||
acu = a*asq;
|
||||
b4 = b*4.0;
|
||||
n3 = 0;
|
||||
|
||||
P = asq*b - b4*b + 2.0*a*c + 16.0*d ;
|
||||
Q = asq*c - b4*c + 8.0*a*d;
|
||||
R = asq*d - c*c ;
|
||||
U = acu - b4*a + 8.0*c;
|
||||
n4[0] = 0;
|
||||
if (U == 0.0)
|
||||
{
|
||||
if (P == 0.0)
|
||||
{
|
||||
det0 = 3.0*asq - 8.0*b;
|
||||
if (det0 < 0.0)
|
||||
goto done;
|
||||
det0rt = sqrt(det0);
|
||||
qrts[0][0] = (-a + det0rt)*0.25;
|
||||
qrts[1][0] = qrts[0][0];
|
||||
qrts[2][0] = (-a - det0rt)*0.25;
|
||||
qrts[3][0] = qrts[2][0];
|
||||
n4[0] = 4;
|
||||
goto done;
|
||||
} /* P=0 */
|
||||
else
|
||||
{
|
||||
det1 = asq*asq - 8.0*asq*b + 16.0*b*b - 64.0*d;
|
||||
if (det1 < 0.0)
|
||||
goto done;;
|
||||
n4[0] = 0;
|
||||
det1rt = sqrt(det1);
|
||||
det2 = 3.0*asq - 8.0*b + 2.0*det1rt;
|
||||
if (det2 >= 0.0)
|
||||
{
|
||||
det2rt = sqrt(det2);
|
||||
qrts[0][0] = (-a + det2rt)*0.25;
|
||||
qrts[1][0] = (-a - det2rt)*0.25;
|
||||
n4[0] = 2;
|
||||
}
|
||||
det3 = 3.0*asq - 8.0*b - 2.0*det1rt;
|
||||
if (det3 >= 0.0)
|
||||
{
|
||||
det3rt = sqrt(det3);
|
||||
qrts[n4[0]++][0] = (-a + det3rt)*0.25;
|
||||
qrts[n4[0]++][0] = (-a - det3rt)*0.25;
|
||||
}
|
||||
goto done;
|
||||
} /* P<>0 */
|
||||
}
|
||||
|
||||
n3 = cubicSolve(P/U,Q/U,R/U,v3[0], v3[1], v3[2]);
|
||||
for (size_t j3 = 0; j3 < n3; ++j3)
|
||||
{
|
||||
y = v3[j3];
|
||||
j = 0;
|
||||
k = a + 4.0*y;
|
||||
if (k == 0.0)
|
||||
goto donej3;
|
||||
invk = 1.0/k;
|
||||
e = (acu - 4.0*c - 2.0*a*b + (6.0*asq - 16.0*b)*y)*invk;
|
||||
fsq = (acu + 8.0*c - 4.0*a*b)*invk;
|
||||
if (fsq < 0.0)
|
||||
goto donej3;
|
||||
f = sqrt(fsq);
|
||||
gsq = 2.0*(e + f*k);
|
||||
hsq = 2.0*(e - f*k);
|
||||
if (gsq >= 0.0)
|
||||
{
|
||||
g = sqrt(gsq);
|
||||
qrts[j++][j3] = (-a - f - g)*0.25;
|
||||
qrts[j++][j3] = (-a - f + g)*0.25;
|
||||
}
|
||||
if (hsq >= 0.0)
|
||||
{
|
||||
h = sqrt(hsq);
|
||||
qrts[j++][j3] = (-a + f - h)*0.25;
|
||||
qrts[j++][j3] = (-a + f + h)*0.25;
|
||||
}
|
||||
donej3:
|
||||
n4[j3] = j;
|
||||
for (j = 0; j < n4[j3]; ++j)
|
||||
rts[j] = qrts[j][j3];
|
||||
|
||||
worst3[j3] = quarticError(a, b, c, d, rts, n4[j3]);
|
||||
} /* j3 loop */
|
||||
done:
|
||||
size_t j3 = 0;
|
||||
if (n3 > 1)
|
||||
{
|
||||
if ((n4[1] > n4[j3]) ||
|
||||
((worst3[1] < worst3[j3] ) && (n4[1] == n4[j3]))) j3 = 1;
|
||||
|
||||
if ((n4[2] > n4[j3]) ||
|
||||
((worst3[2] < worst3[j3] ) && (n4[2] == n4[j3]))) j3 = 2;
|
||||
}
|
||||
|
||||
root1 = qrts[0][j3];
|
||||
root2 = qrts[1][j3];
|
||||
root3 = qrts[2][j3];
|
||||
root4 = qrts[3][j3];
|
||||
|
||||
|
||||
return (n4[j3]);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,197 +0,0 @@
|
||||
/*!
|
||||
* Rapid trajectory generation for quadrocopters
|
||||
*
|
||||
* Copyright 2014 by Mark W. Mueller <mwm@mwm.im>
|
||||
*
|
||||
* This code is free software: you can redistribute
|
||||
* it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SingleAxisTrajectory.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <algorithm>//For min/max
|
||||
#include <limits>//for max double
|
||||
|
||||
using namespace RapidQuadrocopterTrajectoryGenerator;
|
||||
|
||||
SingleAxisTrajectory::SingleAxisTrajectory(void)
|
||||
:_a(0),_b(0),_g(0),_cost(std::numeric_limits<double>::max())
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
/*!
|
||||
* Resets the goal state constraints and the cost.
|
||||
*/
|
||||
void SingleAxisTrajectory::Reset(void)
|
||||
{
|
||||
_posGoalDefined = _velGoalDefined = _accGoalDefined = false;
|
||||
_cost = std::numeric_limits<double>::max();
|
||||
_accPeakTimes.initialised = false;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calculate the coefficients that define a trajectory. This solves, in closed form
|
||||
* the optimal trajectory for some given set of goal constraints.
|
||||
* Before calling this,
|
||||
* - define the initial state
|
||||
* - define the relevant parts of the trajectory goal state.
|
||||
*
|
||||
* @param Tf the trajectory duration [s]
|
||||
* @see SetInitialState()
|
||||
* @see SetGoalPosition()
|
||||
* @see SetGoalVelocity()
|
||||
* @see SetGoalAcceleration()
|
||||
*/
|
||||
void SingleAxisTrajectory::GenerateTrajectory(const double Tf)
|
||||
{
|
||||
//define starting position:
|
||||
double delta_a = _af - _a0;
|
||||
double delta_v = _vf - _v0 - _a0*Tf;
|
||||
double delta_p = _pf - _p0 - _v0*Tf - 0.5*_a0*Tf*Tf;
|
||||
|
||||
//powers of the end time:
|
||||
const double T2 = Tf*Tf;
|
||||
const double T3 = T2*Tf;
|
||||
const double T4 = T3*Tf;
|
||||
const double T5 = T4*Tf;
|
||||
|
||||
//solve the trajectories, depending on what's constrained:
|
||||
if(_posGoalDefined && _velGoalDefined && _accGoalDefined)
|
||||
{
|
||||
_a = ( 60*T2*delta_a - 360*Tf*delta_v + 720* 1*delta_p)/T5;
|
||||
_b = (-24*T3*delta_a + 168*T2*delta_v - 360*Tf*delta_p)/T5;
|
||||
_g = ( 3*T4*delta_a - 24*T3*delta_v + 60*T2*delta_p)/T5;
|
||||
}
|
||||
else if(_posGoalDefined && _velGoalDefined)
|
||||
{
|
||||
_a = (-120*Tf*delta_v + 320* delta_p)/T5;
|
||||
_b = ( 72*T2*delta_v - 200*Tf*delta_p)/T5;
|
||||
_g = ( -12*T3*delta_v + 40*T2*delta_p)/T5;
|
||||
}
|
||||
else if(_posGoalDefined && _accGoalDefined)
|
||||
{
|
||||
_a = (-15*T2*delta_a + 90* delta_p)/(2*T5);
|
||||
_b = ( 15*T3*delta_a - 90*Tf*delta_p)/(2*T5);
|
||||
_g = (- 3*T4*delta_a + 30*T2*delta_p)/(2*T5);
|
||||
}
|
||||
else if(_velGoalDefined && _accGoalDefined)
|
||||
{
|
||||
_a = 0;
|
||||
_b = ( 6*Tf*delta_a - 12* delta_v)/T3;
|
||||
_g = (-2*T2*delta_a + 6*Tf*delta_v)/T3;
|
||||
}
|
||||
else if(_posGoalDefined)
|
||||
{
|
||||
_a = 20*delta_p/T5;
|
||||
_b = -20*delta_p/T4;
|
||||
_g = 10*delta_p/T3;
|
||||
}
|
||||
else if(_velGoalDefined)
|
||||
{
|
||||
_a = 0;
|
||||
_b =-3*delta_v/T3;
|
||||
_g = 3*delta_v/T2;
|
||||
}
|
||||
else if(_accGoalDefined)
|
||||
{
|
||||
_a = 0;
|
||||
_b = 0;
|
||||
_g = delta_a/Tf;
|
||||
}
|
||||
else
|
||||
{//Nothing to do!
|
||||
_a = _b = _g = 0;
|
||||
}
|
||||
|
||||
//Calculate the cost:
|
||||
_cost = _g*_g + _b*_g*Tf + _b*_b*T2/3.0 + _a*_g*T2/3.0 + _a*_b*T3/4.0 + _a*_a*T4/20.0;
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calculate the extrema of the acceleration trajectory. This is made relatively
|
||||
* easy by the fact that the acceleration is a cubic polynomial, so we only need
|
||||
* to solve for the roots of a quadratic.
|
||||
* @param aMinOut [out] The minimum acceleration in the segment
|
||||
* @param aMaxOut [out] The maximum acceleration in the segment
|
||||
* @param t1 [in] The start time of the segment
|
||||
* @param t2 [in] The end time of the segment
|
||||
*/
|
||||
void SingleAxisTrajectory::GetMinMaxAcc(double &aMinOut, double &aMaxOut, double t1, double t2)
|
||||
{
|
||||
if(!_accPeakTimes.initialised)
|
||||
{
|
||||
//calculate the roots of the polynomial
|
||||
if(_a)
|
||||
{//solve a quadratic for t
|
||||
double det = _b*_b - 2*_g*_a;
|
||||
if(det<0)
|
||||
{//no real roots
|
||||
_accPeakTimes.t[0] = 0;
|
||||
_accPeakTimes.t[1] = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_accPeakTimes.t[0] = (-_b + sqrt(det))/_a;
|
||||
_accPeakTimes.t[1] = (-_b - sqrt(det))/_a;
|
||||
}
|
||||
}
|
||||
else
|
||||
{//solve linear equation: _g + _b*t == 0:
|
||||
if(_b) _accPeakTimes.t[0] = -_g/_b;
|
||||
else _accPeakTimes.t[0] = 0;
|
||||
_accPeakTimes.t[1] = 0;
|
||||
}
|
||||
|
||||
_accPeakTimes.initialised = 1;
|
||||
}
|
||||
|
||||
//Evaluate the acceleration at the boundaries of the period:
|
||||
aMinOut = std::min(GetAcceleration(t1), GetAcceleration(t2));
|
||||
aMaxOut = std::max(GetAcceleration(t1), GetAcceleration(t2));
|
||||
|
||||
//Evaluate at the maximum/minimum times:
|
||||
for(int i=0; i<2; i++)
|
||||
{
|
||||
if(_accPeakTimes.t[i] <= t1) continue;
|
||||
if(_accPeakTimes.t[i] >= t2) continue;
|
||||
|
||||
aMinOut = std::min(aMinOut, GetAcceleration(_accPeakTimes.t[i]));
|
||||
aMaxOut = std::max(aMaxOut, GetAcceleration(_accPeakTimes.t[i]));
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
* Calculate the maximum jerk squared along the trajectory. This is made easy
|
||||
* because the jerk is quadratic, so we need to evaluate at most three points.
|
||||
* @param t1 [in] The start time of the segment
|
||||
* @param t2 [in] The end time of the segment
|
||||
* @return the maximum jerk
|
||||
*/
|
||||
double SingleAxisTrajectory::GetMaxJerkSquared(double t1, double t2)
|
||||
{
|
||||
double jMaxSqr = std::max(pow(GetJerk(t1),2),pow(GetJerk(t2),2));
|
||||
|
||||
if(_a)
|
||||
{
|
||||
double tMax = -1;
|
||||
tMax = -_b/_a;
|
||||
if(tMax>t1 && tMax<t2)
|
||||
{
|
||||
jMaxSqr = std::max(pow(GetJerk(tMax),2),jMaxSqr);
|
||||
}
|
||||
}
|
||||
|
||||
return jMaxSqr;
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/**
|
||||
* Rapid trajectory generation for quadrocopters
|
||||
*
|
||||
* Copyright 2014 by Mark W. Mueller <mwm@mwm.im>
|
||||
*
|
||||
* This code is free software: you can redistribute
|
||||
* it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace RapidQuadrocopterTrajectoryGenerator
|
||||
{
|
||||
|
||||
//! An axis along one spatial direction
|
||||
/*!
|
||||
* For more information, please refer to Section II of the publication.
|
||||
*/
|
||||
class SingleAxisTrajectory
|
||||
{
|
||||
public:
|
||||
//! Constructor, calls Reset() function.
|
||||
SingleAxisTrajectory(void);
|
||||
|
||||
//! Define the trajectory's initial state (position, velocity, acceleration), at time zero
|
||||
void SetInitialState(const double pos0, const double vel0, const double acc0){_p0=pos0; _v0=vel0; _a0=acc0; Reset();};
|
||||
|
||||
//! Define the trajectory's final position (if you don't call this, it is left free)
|
||||
void SetGoalPosition(const double posf) {_posGoalDefined = true; _pf = posf;};
|
||||
|
||||
//! Define the trajectory's final velocity (if you don't call this, it is left free)
|
||||
void SetGoalVelocity(const double velf) {_velGoalDefined = true; _vf = velf;};
|
||||
|
||||
//! Define the trajectory's final acceleration (if you don't call this, it is left free)
|
||||
void SetGoalAcceleration(const double accf){_accGoalDefined = true; _af = accf;};
|
||||
|
||||
//! Generate the trajectory, from the defined initial state to the defined components of the final state.
|
||||
void GenerateTrajectory(const double timeToGo);
|
||||
|
||||
//! Resets the cost, coefficients, and goal state constraints. Does *not* reset the initial state
|
||||
void Reset(void);
|
||||
|
||||
//! Returns the jerk at time t
|
||||
double GetJerk(double t) const{return _g + _b*t + (1/2.0)*_a*t*t;};
|
||||
|
||||
//! Returns the acceleration at time t
|
||||
double GetAcceleration(double t) const{return _a0 + _g*t + (1/2.0)*_b*t*t + (1/6.0)*_a*t*t*t;};
|
||||
|
||||
//! Returns the velocity at time t
|
||||
double GetVelocity(double t) const{return _v0 + _a0*t + (1/2.0)*_g*t*t + (1/6.0)*_b*t*t*t + (1/24.0)*_a*t*t*t*t;};
|
||||
|
||||
//! Returns the position at time t
|
||||
double GetPosition(double t) const{return _p0 + _v0*t + (1/2.0)*_a0*t*t + (1/6.0)*_g*t*t*t + (1/24.0)*_b*t*t*t*t + (1/120.0)*_a*t*t*t*t*t;};
|
||||
|
||||
//! Calculate the extrema of the acceleration trajectory over a section
|
||||
void GetMinMaxAcc(double &aMinOut, double &aMaxOut, double t1, double t2);
|
||||
|
||||
//! Calculate the extrema of the jerk squared over a section
|
||||
double GetMaxJerkSquared(double t1, double t2);
|
||||
|
||||
//! Get the parameters defining the trajectory
|
||||
double GetParamAlpha(void) const {return _a;};
|
||||
//! Get the parameters defining the trajectory
|
||||
double GetParamBeta (void) const {return _b;};
|
||||
//! Get the parameters defining the trajectory
|
||||
double GetParamGamma(void) const {return _g;};
|
||||
//! Get the parameters defining the trajectory
|
||||
double GetInitialAcceleration(void) const {return _a0;};
|
||||
//! Get the parameters defining the trajectory
|
||||
double GetInitialVelocity(void) const {return _v0;};
|
||||
//! Get the parameters defining the trajectory
|
||||
double GetInitialPosition(void) const {return _p0;};
|
||||
|
||||
//! Get the trajectory cost value
|
||||
double GetCost(void) const{return _cost;};
|
||||
|
||||
private:
|
||||
double _p0, _v0, _a0;//!< The initial state (position, velocity, acceleration)
|
||||
double _pf, _vf, _af;//!< The goal state (position, velocity, acceleration)
|
||||
bool _posGoalDefined, _velGoalDefined, _accGoalDefined;//!< The components of the goal state defined to be fixed (position, velocity, acceleration)
|
||||
double _a, _b, _g;//!< The three coefficients that define the trajectory
|
||||
|
||||
double _cost;//!< The trajectory cost, J
|
||||
|
||||
struct
|
||||
{
|
||||
double t[2];
|
||||
bool initialised;
|
||||
} _accPeakTimes;//!< The times at which the acceleration has minimum/maximum
|
||||
};
|
||||
|
||||
};//namespace
|
@ -1,93 +0,0 @@
|
||||
/*!
|
||||
* Rapid trajectory generation for quadrocopters
|
||||
*
|
||||
* Copyright 2014 by Mark W. Mueller <mwm@mwm.im>
|
||||
*
|
||||
* This code is free software: you can redistribute
|
||||
* it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <limits>
|
||||
|
||||
//! 3D vector class
|
||||
/*!
|
||||
* A 3D vector class, to make passing arguments easier, and allow easy addition etc. of vectors.
|
||||
* Could be readily replaced with arrays of doubles, but this would complicate some of the code.
|
||||
*/
|
||||
class Vec3
|
||||
{
|
||||
public:
|
||||
double x,y,z; //!< the three components of the vector
|
||||
|
||||
Vec3(void):x(std::numeric_limits<double>::quiet_NaN()),y(std::numeric_limits<double>::quiet_NaN()),z(std::numeric_limits<double>::quiet_NaN()){};//!<Initialises all members to NaN
|
||||
Vec3(double xin,double yin,double zin):x(xin),y(yin),z(zin){};//!< Initialise vector
|
||||
|
||||
//!Getter function, index 0 <-> x, 1 <-> y, 2 <-> z
|
||||
inline double operator[](int i) const
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: return x;
|
||||
case 1: return y;
|
||||
case 2: return z;
|
||||
break;
|
||||
}
|
||||
//we're doing something wrong if we get here
|
||||
assert(0);
|
||||
return std::numeric_limits<double>::quiet_NaN();
|
||||
}
|
||||
|
||||
//!Setter function, index 0 <-> x, 1 <-> y, 2 <-> z
|
||||
inline double & operator[](int i)
|
||||
{
|
||||
switch(i)
|
||||
{
|
||||
case 0: return x;
|
||||
case 1: return y;
|
||||
case 2: return z;
|
||||
break;
|
||||
}
|
||||
//we're doing something wrong if we get here
|
||||
assert(0);
|
||||
//fail loudly:
|
||||
x = y = z = std::numeric_limits<double>::quiet_NaN();
|
||||
return x;
|
||||
}
|
||||
|
||||
//!Calculate the dot product of two vectors
|
||||
inline double Dot(const Vec3 rhs) const {return x*rhs.x + y*rhs.y + z*rhs.z;};
|
||||
|
||||
//!Calculate the cross product of two vectors
|
||||
inline Vec3 Cross(const Vec3 rhs) const { return Vec3(y*rhs.z - z*rhs.y, z*rhs.x - x*rhs.z, x*rhs.y - y*rhs.x);};
|
||||
|
||||
//!Calculate the Euclidean norm of the vector, squared (= sum of squared elements).
|
||||
inline double GetNorm2Squared(void) const {return this->Dot(*this);};
|
||||
|
||||
//!Calculate the Euclidean norm of the vector.
|
||||
inline double GetNorm2(void) const {return sqrt(GetNorm2Squared());};
|
||||
|
||||
//!Get the unit vector pointing along the same direction as this vector. Will fail for zero vectors.
|
||||
Vec3 GetUnitVector(void) const {return (*this)/this->GetNorm2();};
|
||||
|
||||
inline Vec3 operator+(const Vec3 rhs)const {return Vec3(x+rhs.x,y+rhs.y,z+rhs.z);};
|
||||
inline Vec3 operator-(const Vec3 rhs)const {return Vec3(x-rhs.x,y-rhs.y,z-rhs.z);};
|
||||
inline Vec3 operator/(const double rhs)const {return Vec3(x/rhs,y/rhs,z/rhs);};
|
||||
};
|
||||
|
||||
//Some operator overloading:
|
||||
inline Vec3 operator*(const double lhs, const Vec3 rhs) {return Vec3(lhs*rhs.x, lhs*rhs.y, lhs*rhs.z);};
|
||||
inline Vec3 operator*(const Vec3 lhs, const double rhs) {return Vec3(lhs.x*rhs, lhs.y*rhs, lhs.z*rhs);};
|
||||
inline Vec3 operator/(const Vec3 lhs, const double rhs) {return Vec3(lhs.x/rhs, lhs.y/rhs, lhs.z/rhs);};
|
@ -1,28 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package format="2">
|
||||
<name>prometheus_rapid_quad</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The prometheus_rapid_quad 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_control.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>
|
@ -1,104 +0,0 @@
|
||||
/*!
|
||||
* Rapid trajectory generation for quadrocopters
|
||||
*
|
||||
* Copyright 2014 by Mark W. Mueller <mwm@mwm.im>
|
||||
*
|
||||
* This code is free software: you can redistribute
|
||||
* it and/or modify it under the terms of the GNU General Public
|
||||
* License as published by the Free Software Foundation, either
|
||||
* version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This code is distributed in the hope that it will
|
||||
* be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
|
||||
* of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with the code. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
#include "RapidTrajectoryGenerator.h"
|
||||
using namespace RapidQuadrocopterTrajectoryGenerator;
|
||||
|
||||
//Two simple helper function to make testing easier
|
||||
const char* GetInputFeasibilityResultName(RapidTrajectoryGenerator::InputFeasibilityResult fr)
|
||||
{
|
||||
switch(fr)
|
||||
{
|
||||
case RapidTrajectoryGenerator::InputFeasible: return "Feasible";
|
||||
case RapidTrajectoryGenerator::InputIndeterminable: return "Indeterminable";
|
||||
case RapidTrajectoryGenerator::InputInfeasibleThrustHigh: return "InfeasibleThrustHigh";
|
||||
case RapidTrajectoryGenerator::InputInfeasibleThrustLow: return "InfeasibleThrustLow";
|
||||
case RapidTrajectoryGenerator::InputInfeasibleRates: return "InfeasibleRates";
|
||||
}
|
||||
return "Unknown!";
|
||||
};
|
||||
|
||||
const char* GetStateFeasibilityResultName(RapidTrajectoryGenerator::StateFeasibilityResult fr)
|
||||
{
|
||||
switch(fr)
|
||||
{
|
||||
case RapidTrajectoryGenerator::StateFeasible: return "Feasible";
|
||||
case RapidTrajectoryGenerator::StateInfeasible: return "Infeasible";
|
||||
}
|
||||
return "Unknown!";
|
||||
};
|
||||
|
||||
int main(void)
|
||||
{
|
||||
//Define the trajectory starting state:
|
||||
Vec3 pos0 = Vec3(0, 0, 2); //position
|
||||
Vec3 vel0 = Vec3(0, 0, 0); //velocity
|
||||
Vec3 acc0 = Vec3(0, 0, 0); //acceleration
|
||||
|
||||
//define the goal state:
|
||||
Vec3 posf = Vec3(1, 0, 1); //position
|
||||
Vec3 velf = Vec3(0, 0, 1); //velocity
|
||||
Vec3 accf = Vec3(0, 0, 0); //acceleration
|
||||
|
||||
//define the duration:
|
||||
double Tf = 1.3;
|
||||
|
||||
double fmin = 5;//[m/s**2]
|
||||
double fmax = 25;//[m/s**2]
|
||||
double wmax = 20;//[rad/s]
|
||||
double minTimeSec = 0.02;//[s]
|
||||
|
||||
//Define how gravity lies in our coordinate system
|
||||
Vec3 gravity = Vec3(0,0,-9.81);//[m/s**2]
|
||||
|
||||
//Define the state constraints. We'll only check that we don't fly into the floor:
|
||||
Vec3 floorPos = Vec3(0,0,0);//any point on the boundary
|
||||
Vec3 floorNormal = Vec3(0,0,1);//we want to be in this direction of the boundary
|
||||
|
||||
RapidTrajectoryGenerator traj(pos0, vel0, acc0, gravity);
|
||||
traj.SetGoalPosition(posf);
|
||||
traj.SetGoalVelocity(velf);
|
||||
traj.SetGoalAcceleration(accf);
|
||||
|
||||
// Note: if you'd like to leave some states free, you can encode it like below.
|
||||
// Here we would be leaving the velocity in `x` (axis 0) free:
|
||||
//
|
||||
// traj.SetGoalVelocityInAxis(1,velf[1]);
|
||||
// traj.SetGoalVelocityInAxis(2,velf[2]);
|
||||
|
||||
traj.Generate(Tf);
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
cout << "Axis #" << i << "\n";
|
||||
cout << "\talpha = " << traj.GetAxisParamAlpha(i);
|
||||
cout << "\tbeta = " << traj.GetAxisParamBeta(i);
|
||||
cout << "\tgamma = " << traj.GetAxisParamGamma(i);
|
||||
cout << "\n";
|
||||
}
|
||||
cout << "Total cost = " << traj.GetCost() << "\n";
|
||||
cout << "Input feasible? " << GetInputFeasibilityResultName(traj.CheckInputFeasibility(fmin,fmax,wmax,minTimeSec)) << "\n";
|
||||
cout << "Position feasible? " << GetStateFeasibilityResultName(traj.CheckPositionFeasibility(floorPos, floorNormal)) << "\n";
|
||||
return 0;
|
||||
}
|
||||
|
@ -1,266 +0,0 @@
|
||||
//头文件
|
||||
#include <ros/ros.h>
|
||||
#include <iostream>
|
||||
|
||||
|
||||
#include <prometheus_msgs/ControlCommand.h>
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
#include <prometheus_msgs/DetectionInfo.h>
|
||||
#include <prometheus_msgs/PositionReference.h>
|
||||
#include <nav_msgs/Odometry.h>
|
||||
#include <geometry_msgs/PoseStamped.h>
|
||||
#include <geometry_msgs/TwistStamped.h>
|
||||
#include <nav_msgs/Path.h>
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
#include <prometheus_msgs/AttitudeReference.h>
|
||||
#include <prometheus_msgs/DroneState.h>
|
||||
|
||||
// #include "message_utils.h"
|
||||
#include "RapidTrajectoryGenerator.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace RapidQuadrocopterTrajectoryGenerator;
|
||||
|
||||
#define NODE_NAME "motion_planning"
|
||||
|
||||
|
||||
prometheus_msgs::ControlCommand Command_Now; //发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
prometheus_msgs::DroneState _DroneState; //无人机状态量
|
||||
geometry_msgs::PoseStamped goal;
|
||||
|
||||
|
||||
Vec3 pos0 = Vec3(0, 0, 2); //position
|
||||
Vec3 vel0 = Vec3(0, 0, 0); //velocity
|
||||
Vec3 acc0 = Vec3(0, 0, 0); //acceleration
|
||||
|
||||
//define the goal state:
|
||||
Vec3 posf = Vec3(1, 0, 1); //position
|
||||
Vec3 velf = Vec3(0, 0, 1); //velocity
|
||||
Vec3 accf = Vec3(0, 0, 0); //acceleration
|
||||
|
||||
int flag_get_goal = 0;
|
||||
float time_trajectory;
|
||||
//define the duration: TF不能打死
|
||||
double Tf = 5.0;
|
||||
float Alpha[3],Beta[3],Gamma[3];
|
||||
|
||||
nav_msgs::Path Optimal_Path;
|
||||
|
||||
ros::Publisher ref_tra_pub;
|
||||
//Two simple helper function to make testing easier
|
||||
const char* GetInputFeasibilityResultName(RapidTrajectoryGenerator::InputFeasibilityResult fr)
|
||||
{
|
||||
switch(fr)
|
||||
{
|
||||
case RapidTrajectoryGenerator::InputFeasible: return "Feasible";
|
||||
case RapidTrajectoryGenerator::InputIndeterminable: return "Indeterminable";
|
||||
case RapidTrajectoryGenerator::InputInfeasibleThrustHigh: return "InfeasibleThrustHigh";
|
||||
case RapidTrajectoryGenerator::InputInfeasibleThrustLow: return "InfeasibleThrustLow";
|
||||
case RapidTrajectoryGenerator::InputInfeasibleRates: return "InfeasibleRates";
|
||||
}
|
||||
return "Unknown!";
|
||||
};
|
||||
|
||||
const char* GetStateFeasibilityResultName(RapidTrajectoryGenerator::StateFeasibilityResult fr)
|
||||
{
|
||||
switch(fr)
|
||||
{
|
||||
case RapidTrajectoryGenerator::StateFeasible: return "Feasible";
|
||||
case RapidTrajectoryGenerator::StateInfeasible: return "Infeasible";
|
||||
}
|
||||
return "Unknown!";
|
||||
};
|
||||
|
||||
|
||||
void goal_cb(const geometry_msgs::PoseStamped::ConstPtr& msg)
|
||||
{
|
||||
goal = *msg;
|
||||
flag_get_goal = 1;
|
||||
cout << "Get a new goal!"<<endl;
|
||||
}
|
||||
|
||||
void drone_state_cb(const prometheus_msgs::DroneState::ConstPtr& msg)
|
||||
{
|
||||
_DroneState = *msg;
|
||||
}
|
||||
|
||||
|
||||
void pub_ref_trajectory();
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
ros::init(argc, argv, "main_node");
|
||||
ros::NodeHandle nh("~");
|
||||
|
||||
ros::Rate rate(20.0);
|
||||
|
||||
// 能用,但距离使用还差前端 和 后端约束
|
||||
|
||||
ros::Subscriber drone_state_sub = nh.subscribe<prometheus_msgs::DroneState>("/prometheus/drone_state", 10, drone_state_cb);
|
||||
|
||||
//【订阅】目标点
|
||||
ros::Subscriber goal_sub = nh.subscribe<geometry_msgs::PoseStamped>("/prometheus/planning/goal", 10, goal_cb);
|
||||
|
||||
// 【发布】发送给控制模块 [px4_pos_controller.cpp]的命令
|
||||
ros::Publisher command_pub = nh.advertise<prometheus_msgs::ControlCommand>("/prometheus/control_command", 10);
|
||||
|
||||
ref_tra_pub = nh.advertise<nav_msgs::Path>("/prometheus/motion_planning/ref_trajectory", 10);
|
||||
|
||||
|
||||
int start_flag;
|
||||
cout << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>Motion Planning Mission<<<<<<<<<<<<<<<<<<<<<<<<<<< "<< endl;
|
||||
cout << "Please enter 1 for takeoff"<<endl;
|
||||
cin >> start_flag;
|
||||
|
||||
// 起飞
|
||||
if( start_flag == 1)
|
||||
{
|
||||
Command_Now.header.stamp = ros::Time::now();
|
||||
Command_Now.Mode = prometheus_msgs::ControlCommand::Idle;
|
||||
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(3.0).sleep();
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
double fmin = 5;//[m/s**2]
|
||||
double fmax = 25;//[m/s**2]
|
||||
double wmax = 20;//[rad/s]
|
||||
double minTimeSec = 0.02;//[s]
|
||||
|
||||
//Define how gravity lies in our coordinate system
|
||||
Vec3 gravity = Vec3(0,0,-9.81);//[m/s**2]
|
||||
|
||||
//Define the state constraints. We'll only check that we don't fly into the floor:
|
||||
Vec3 floorPos = Vec3(0,0,0);//any point on the boundary
|
||||
Vec3 floorNormal = Vec3(0,0,1);//we want to be in this direction of the boundary
|
||||
|
||||
while (ros::ok())
|
||||
{
|
||||
flag_get_goal = 0;
|
||||
ros::spinOnce();
|
||||
|
||||
if(flag_get_goal == 1)
|
||||
{
|
||||
//Define the trajectory starting state:
|
||||
pos0 = Vec3(_DroneState.position[0], _DroneState.position[1], _DroneState.position[2]);
|
||||
vel0 = Vec3(_DroneState.velocity[0], _DroneState.velocity[1], _DroneState.velocity[2]);
|
||||
acc0 = Vec3(0, 0, 0); //acceleration
|
||||
|
||||
posf = Vec3(goal.pose.position.x, goal.pose.position.y, goal.pose.position.z);
|
||||
velf = Vec3(0.0, 0.0, 0.0);
|
||||
accf = Vec3(0, 0, 0); //acceleration
|
||||
|
||||
RapidTrajectoryGenerator traj(pos0, vel0, acc0, gravity);
|
||||
traj.SetGoalPosition(posf);
|
||||
traj.SetGoalVelocity(velf);
|
||||
traj.SetGoalAcceleration(accf);
|
||||
|
||||
// Note: if you'd like to leave some states free, you can encode it like below.
|
||||
// Here we would be leaving the velocity in `x` (axis 0) free:
|
||||
//
|
||||
// traj.SetGoalVelocityInAxis(1,velf[1]);
|
||||
// traj.SetGoalVelocityInAxis(2,velf[2]);
|
||||
|
||||
// 根据目标点重新预估时间,希望平均速度为1m/s
|
||||
Tf = sqrt( pow(posf[0] - pos0[0], 2) + pow(posf[1] - pos0[1], 2) + pow(posf[2] - pos0[2], 2)) / 1.0;
|
||||
|
||||
traj.Generate(Tf);
|
||||
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
Alpha[i] = traj.GetAxisParamAlpha(i);
|
||||
Beta[i] = traj.GetAxisParamBeta(i);
|
||||
Gamma[i] = traj.GetAxisParamGamma(i);
|
||||
|
||||
cout << "Axis #" << i << "\n";
|
||||
cout << "\tAlpha = " << Alpha[i];
|
||||
cout << "\tBeta = " << Beta[i];
|
||||
cout << "\tGamma = " << Gamma[i];
|
||||
cout << "\n";
|
||||
}
|
||||
|
||||
cout << "Tf = " << Tf << " [s] " << endl;
|
||||
cout << "Total cost = " << traj.GetCost() << "\n";
|
||||
cout << "goal_pos: " << goal.pose.position.x << " [m] "<< goal.pose.position.y << " [m] "<< goal.pose.position.z << " [m] "<<endl;
|
||||
cout << "Input feasible? " << GetInputFeasibilityResultName(traj.CheckInputFeasibility(fmin,fmax,wmax,minTimeSec)) << "\n";
|
||||
cout << "Position feasible? " << GetStateFeasibilityResultName(traj.CheckPositionFeasibility(floorPos, floorNormal)) << "\n";
|
||||
|
||||
pub_ref_trajectory();
|
||||
|
||||
time_trajectory = 0.0;
|
||||
while(time_trajectory < Tf)
|
||||
{
|
||||
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::TRAJECTORY;
|
||||
Command_Now.Reference_State.time_from_start = time_trajectory;
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
//时间戳怎么解决?
|
||||
Command_Now.Reference_State.position_ref[i] = 1/120.0 * Alpha[i] * pow(time_trajectory,5) + 1/24.0 * Beta[i] * pow(time_trajectory,4) + 1/6.0 * Gamma[i] * pow(time_trajectory,3) + 1/2.0 * acc0[i] * pow(time_trajectory,2) + vel0[i] * time_trajectory + pos0[i];
|
||||
Command_Now.Reference_State.velocity_ref[i] = 1/24.0 * Alpha[i] * pow(time_trajectory,4) + 1/6.0 * Beta[i] * pow(time_trajectory,3) + 1/2.0 * Gamma[i] * pow(time_trajectory,2) + acc0[i] * time_trajectory + vel0[i];
|
||||
Command_Now.Reference_State.acceleration_ref[i] = 1/6.0 * Alpha[i] * pow(time_trajectory,3) + 1/2.0 * Beta[i] * pow(time_trajectory,2) + Gamma[i] * time_trajectory + acc0[i];
|
||||
}
|
||||
|
||||
|
||||
Command_Now.Reference_State.yaw_ref = 0.0;
|
||||
|
||||
command_pub.publish(Command_Now);
|
||||
time_trajectory = time_trajectory + 0.01;
|
||||
ros::Duration(0.01).sleep();
|
||||
|
||||
|
||||
// cout << "Motion Planning Result:"<<endl;
|
||||
// cout << "Trajectory tracking: "<< time_trajectory << " / " << Tf << " [ s ]" <<endl;
|
||||
// cout << "desired_point: " << Command_Now.Reference_State.position_ref[0] << " [m] "
|
||||
// << Command_Now.Reference_State.position_ref[1] << " [m] "
|
||||
// << Command_Now.Reference_State.position_ref[2] << " [m] "<<endl;
|
||||
// cout << "goal_pos: " << goal.pose.position.x << " [m] "<< goal.pose.position.y << " [m] "<< goal.pose.position.z << " [m] "<<endl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pub_ref_trajectory()
|
||||
{
|
||||
Optimal_Path.header.frame_id = "world";
|
||||
Optimal_Path.header.stamp = ros::Time::now();
|
||||
Optimal_Path.poses.clear();
|
||||
|
||||
|
||||
time_trajectory = 0.0;
|
||||
int k = 0;
|
||||
while(time_trajectory < Tf)
|
||||
{
|
||||
geometry_msgs::PoseStamped way_point;
|
||||
way_point.header.frame_id = "world";
|
||||
way_point.pose.position.x = 1/120.0 * Alpha[0] * pow(time_trajectory,5) + 1/24.0 * Beta[0] * pow(time_trajectory,4) + 1/6.0 * Gamma[0] * pow(time_trajectory,3) + 1/2.0 * acc0[0] * pow(time_trajectory,2) + vel0[0] * time_trajectory + pos0[0];
|
||||
way_point.pose.position.y = 1/120.0 * Alpha[1] * pow(time_trajectory,5) + 1/24.0 * Beta[1] * pow(time_trajectory,4) + 1/6.0 * Gamma[1] * pow(time_trajectory,3) + 1/2.0 * acc0[1] * pow(time_trajectory,2) + vel0[1] * time_trajectory + pos0[1];
|
||||
way_point.pose.position.z = 1/120.0 * Alpha[2] * pow(time_trajectory,5) + 1/24.0 * Beta[2] * pow(time_trajectory,4) + 1/6.0 * Gamma[2] * pow(time_trajectory,3) + 1/2.0 * acc0[2] * pow(time_trajectory,2) + vel0[2] * time_trajectory + pos0[2];
|
||||
Optimal_Path.poses.push_back(way_point);
|
||||
time_trajectory = time_trajectory + 0.01;
|
||||
}
|
||||
|
||||
ref_tra_pub.publish(Optimal_Path);
|
||||
|
||||
}
|
@ -1,185 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.3)
|
||||
project(prometheus_detection_circlex)
|
||||
|
||||
add_definitions(-DCPU_ONLY=1)
|
||||
|
||||
## 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
|
||||
roscpp roslib std_msgs sensor_msgs image_transport cv_bridge prometheus_msgs
|
||||
)
|
||||
|
||||
set(CAFFE_INCLUDEDIR spire_caffe/include spire_caffe/build/src)
|
||||
set(CAFFE_LINK_LIBRARAY spire_caffe/build/lib)
|
||||
|
||||
# SET(CMAKE_MODULE_PATH /home/imav/jario_ws/aruco-2.0.19/build)
|
||||
# SET(ARUCO_INCLUDE_DIRS /home/imav/jario_ws/aruco-2.0.19/src)
|
||||
|
||||
# SET(CMAKE_MODULE_PATH /home/imav/jario_ws/opencv-3.3.1/build)
|
||||
|
||||
## System dependencies are found with CMake's conventions
|
||||
find_package(Boost REQUIRED COMPONENTS system)
|
||||
find_package(OpenCV REQUIRED)
|
||||
|
||||
# FIND_PACKAGE(aruco REQUIRED)
|
||||
|
||||
add_compile_options(-std=c++11)
|
||||
|
||||
## Uncomment this if the package has a setup.py. This macro ensures
|
||||
## modules and global scripts declared therein get installed
|
||||
## See http://ros.org/doc/api/catkin/html/user_guide/setup_dot_py.html
|
||||
# catkin_python_setup()
|
||||
|
||||
################################################
|
||||
## Declare ROS messages, services and actions ##
|
||||
################################################
|
||||
|
||||
## To declare and build messages, services or actions from within this
|
||||
## package, follow these steps:
|
||||
## * Let MSG_DEP_SET be the set of packages whose message types you use in
|
||||
## your messages/services/actions (e.g. std_msgs, actionlib_msgs, ...).
|
||||
## * In the file package.xml:
|
||||
## * add a build_depend and a run_depend tag for each package in MSG_DEP_SET
|
||||
## * If MSG_DEP_SET isn't empty the following dependencies might have been
|
||||
## pulled in transitively but can be declared for certainty nonetheless:
|
||||
## * add a build_depend tag for "message_generation"
|
||||
## * add a run_depend tag for "message_runtime"expected
|
||||
## * In this file (CMakeLists.txt):
|
||||
## * add "message_generation" and every package in MSG_DEP_SET to
|
||||
## find_package(catkin REQUIRED COMPONENTS ...)
|
||||
## * add "message_runtime" and every package in MSG_DEP_SET to
|
||||
## catkin_package(CATKIN_DEPENDS ...)
|
||||
## * uncomment the add_*_files sections below as needed
|
||||
## and list every .msg/.srv/.action file to be processed
|
||||
## * uncomment the generate_messages entry below
|
||||
## * add every package in MSG_DEP_SET to generate_messages(DEPENDENCIES ...)
|
||||
|
||||
## Generate messages in the 'msg' folder
|
||||
# add_message_files(
|
||||
# FILES
|
||||
# Message1.msg
|
||||
# Message2.msg
|
||||
# )
|
||||
|
||||
## Generate services in the 'srv' folder
|
||||
# add_service_files(
|
||||
# FILES
|
||||
# Service1.srv
|
||||
# Service2.srv
|
||||
# )
|
||||
|
||||
## Generate actions in the 'action' folder
|
||||
# add_action_files(
|
||||
# FILES
|
||||
# Action1.action
|
||||
# Action2.action
|
||||
# )
|
||||
|
||||
## Generate added messages and services with any dependencies listed here
|
||||
# generate_messages(
|
||||
# DEPENDENCIES
|
||||
# std_msgs # Or other packages containing msgs
|
||||
# )
|
||||
|
||||
###################################
|
||||
## catkin specific configuration ##
|
||||
###################################
|
||||
## The catkin_package macro generates cmake config files for your package
|
||||
## Declare things to be passed to dependent projects
|
||||
## INCLUDE_DIRS: uncomment this if you package contains header files
|
||||
## LIBRARIES: libraries you create in this project that dependent projects also need
|
||||
## CATKIN_DEPENDS: catkin_packages dependent projects also need
|
||||
## DEPENDS: system dependencies of this project that dependent projects also need
|
||||
catkin_package(
|
||||
# INCLUDE_DIRS include
|
||||
# LIBRARIES ros_caffe
|
||||
# CATKIN_DEPENDS roscpp
|
||||
# DEPENDS system_lib
|
||||
)
|
||||
|
||||
###########
|
||||
## Build ##
|
||||
###########
|
||||
|
||||
## Specify additional locations of header files
|
||||
## Your package locations should be listed before other locations
|
||||
# include_directories(include)
|
||||
include_directories(
|
||||
include
|
||||
${catkin_INCLUDE_DIRS}
|
||||
${OpenCV_INCLUDE_DIRS}
|
||||
/usr/include
|
||||
spire_caffe/build/include
|
||||
)
|
||||
include_directories(${CAFFE_INCLUDEDIR})
|
||||
## Declare a cpp library
|
||||
# add_library(ros_caffe
|
||||
# src/${PROJECT_NAME}/ros_caffe.cpp
|
||||
# )
|
||||
|
||||
## Declare a cpp executable
|
||||
# add_executable(ros_caffe_node src/ros_caffe_node.cpp)
|
||||
|
||||
## Add cmake target dependencies of the executable/library
|
||||
## as an example, message headers may need to be generated before nodes
|
||||
# add_dependencies(ros_caffe_node ros_caffe_generate_messages_cpp)
|
||||
|
||||
## Specify libraries to link a library or executable target against
|
||||
# target_link_libraries(ros_caffe_node
|
||||
# ${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 ros_caffe ros_caffe_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 other files for installation (e.g. launch and bag files, etc.)
|
||||
# install(FILES
|
||||
# # myfile1
|
||||
# # myfile2
|
||||
# DESTINATION ${CATKIN_PACKAGE_SHARE_DESTINATION}
|
||||
# )
|
||||
|
||||
#############
|
||||
## Testing ##
|
||||
#############
|
||||
|
||||
## Add gtest based cpp test target and link libraries
|
||||
# catkin_add_gtest(${PROJECT_NAME}-test test/test_ros_caffe.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)
|
||||
file(GLOB "FILES" "src/*.cpp")
|
||||
set(SRCS src/fly_detector.cpp ${FILES})
|
||||
|
||||
link_directories(${CAFFE_LINK_LIBRARAY})
|
||||
add_executable(fly_detector ${SRCS})
|
||||
target_link_libraries(fly_detector ${catkin_LIBRARIES} ${OpenCV_LIBRARIES} caffe glog)
|
@ -1,180 +0,0 @@
|
||||
#ifndef DERRORH
|
||||
#define DERRORH
|
||||
|
||||
#include <cstdlib>
|
||||
#include <utility>
|
||||
#include <stdlib.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <fstream>
|
||||
#include <math.h>
|
||||
#include "string"
|
||||
#include <time.h>
|
||||
#include <queue>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
class DERROR
|
||||
{
|
||||
|
||||
public:
|
||||
//构造函数
|
||||
DERROR(void)
|
||||
{
|
||||
error = 0;
|
||||
error_list.push_back(make_pair(0.0,0.0));
|
||||
//D_input = 0;
|
||||
// P_Out = 0;
|
||||
// I_Out = 0;
|
||||
D_Out = 0;
|
||||
Output = 0;
|
||||
// Kf = 0;
|
||||
// start_intergrate_flag = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//float D_input, D_input0;
|
||||
|
||||
// float Kp; //参数P
|
||||
// float Ki; //参数I
|
||||
// float Kd; //参数D
|
||||
// float Kf; //微分项的滤波增益
|
||||
|
||||
float error; //误差量 = 实际值 - 期望值
|
||||
float delta_time; //时间间隔dt
|
||||
float cur_time;
|
||||
vector<pair<float, float>> error_list; //误差表,用作计算微分项 平滑窗口 [2nd data, 1st time]
|
||||
|
||||
// float P_Out; //P环节输出
|
||||
// float I_Out; //I环节输出
|
||||
float D_Out; //D环节输出
|
||||
float Output; //输出
|
||||
|
||||
// bool start_intergrate_flag; //是否积分标志[进入offboard(启控)后,才开始积分]
|
||||
// float Imax; //积分上限
|
||||
// float Output_max; //输出最大值
|
||||
float errThres; //误差死区(if error<errThres, error<0)
|
||||
|
||||
//设置PID参数函数[Kp Ki Kd Kf]
|
||||
// void setPID(float p_value, float i_value, float d_value, float f_value);
|
||||
|
||||
//输入 误差 和 当前时间
|
||||
bool add_error(float input_error, float curtime);
|
||||
void show_error(void);
|
||||
//PID输出结果
|
||||
void derror_output(void);
|
||||
|
||||
//设置积分上限 控制量最大值 误差死区
|
||||
// void set_sat(float i_max, float con_max, float thres)
|
||||
// {
|
||||
// Output_max = con_max;
|
||||
// Imax = i_max;
|
||||
// errThres = thres;
|
||||
// }
|
||||
|
||||
//饱和函数
|
||||
// float satfunc(float data, float Max, float Thres)
|
||||
// {
|
||||
// if (abs(data)<Thres)
|
||||
// return 0;
|
||||
// else if(abs(data)>Max){
|
||||
// return (data>0)?Max:-Max;
|
||||
// }
|
||||
// else{
|
||||
// return data;
|
||||
// }
|
||||
// }
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
//void PID::setPID(float p_value, float i_value, float d_value, float f_value)
|
||||
//{
|
||||
// Kp = p_value;
|
||||
// Ki = i_value;
|
||||
// Kd = d_value;
|
||||
// Kf = f_value;
|
||||
//}
|
||||
|
||||
|
||||
void DERROR::derror_output(void)
|
||||
{
|
||||
// P_Out = Kp * error; //P环节输出值
|
||||
// I_Out = I_Out + Ki *error*delta_time; //I环节输出值
|
||||
// I_Out = satfunc(I_Out, Imax, 0); //I环节限幅[I_Out<=Imax]
|
||||
|
||||
|
||||
// if(start_intergrate_flag == 0)
|
||||
// {
|
||||
// I_Out = 0;
|
||||
// }
|
||||
|
||||
|
||||
if (error_list.size() < 3)
|
||||
{
|
||||
D_Out = 0; //initiral process
|
||||
}
|
||||
else if(error_list.size()<7)
|
||||
{
|
||||
vector<pair<float, float>>::reverse_iterator initial_error_k = error_list.rbegin();
|
||||
vector<pair<float, float>>::iterator initial_error_k_initial = error_list.begin();
|
||||
vector<pair<float, float>>::iterator initial_error_k_n = initial_error_k_initial+1;
|
||||
D_Out = (initial_error_k->second - initial_error_k_n->second)/delta_time;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
vector<pair<float, float>>::reverse_iterator error_k = error_list.rbegin();
|
||||
vector<pair<float, float>>::iterator error_k_n = error_list.begin();
|
||||
|
||||
D_Out = (error_k->second - error_k_n->second)/delta_time;
|
||||
|
||||
|
||||
}
|
||||
|
||||
Output = D_Out;
|
||||
// Output = satfunc(Output, Output_max, errThres);
|
||||
}
|
||||
void DERROR::show_error(void){
|
||||
// cout <<"error_size "<< error_list.size()<<" delta_time " << delta_time <<endl;
|
||||
cout << "delta_time: " << delta_time << " cur_time: " << cur_time << " error_list.rbegin() " << error_list.rbegin()->first << " error_list.begin() " << error_list.begin()->first << " error: "<< error_list.begin()->second << error_list.rbegin()->second << " Output: ["<<Output<<"] "<<std::endl;
|
||||
}
|
||||
|
||||
bool DERROR::add_error(float input_error, float curtime)
|
||||
{
|
||||
error = input_error;
|
||||
cur_time=curtime;
|
||||
if(error_list.size()<6)
|
||||
{
|
||||
delta_time = 0.16;
|
||||
}
|
||||
else{
|
||||
delta_time = curtime - error_list.begin()->first;
|
||||
// cout<< "1 "<<"last time "<< error_list.end()->first <<"delta_time: "<< delta_time<<endl;
|
||||
}
|
||||
|
||||
|
||||
if(error_list.size()<6){
|
||||
error_list.push_back(make_pair(curtime, error));
|
||||
}
|
||||
else{
|
||||
// cout<<"*---------*"<<endl;
|
||||
|
||||
vector<pair<float, float>>::iterator k_beg = error_list.begin();
|
||||
error_list.erase(k_beg);
|
||||
std::pair<float,float > p1(curtime, error);
|
||||
// error_list.emplace_back(std::move(p1));
|
||||
error_list.emplace_back(p1);
|
||||
// float tmp_first = error_list.end()->first;
|
||||
/*error_list.end()->first = curtime;
|
||||
error_list.end()->second = error;*/
|
||||
// printf("time: %f, last time: %f\n", curtime, error_list.rbegin()->first);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@ -1,461 +0,0 @@
|
||||
#ifndef __FIND_X__
|
||||
#define __FIND_X__
|
||||
|
||||
#include <iostream>
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
#include "opencv2/opencv.hpp"
|
||||
|
||||
using namespace std;
|
||||
using namespace cv;
|
||||
typedef std::vector<cv::Point> PointsVector;
|
||||
typedef std::vector<PointsVector> ContoursVector;
|
||||
|
||||
struct PointValue
|
||||
{
|
||||
Point p;
|
||||
int value;
|
||||
Point p1;
|
||||
float rad;
|
||||
float length;
|
||||
};
|
||||
|
||||
bool SortPointValue(const PointValue &p1, const PointValue &p2)
|
||||
{ //从大到小
|
||||
return p1.value > p2.value;
|
||||
}
|
||||
|
||||
float GetLineRad(Point &p1, Point &p2)
|
||||
{
|
||||
float rad;
|
||||
Point2f p = p2 - p1;
|
||||
rad = atan2(p.y, p.x);
|
||||
return rad;
|
||||
}
|
||||
float GetLineRad(Vec4i &vec)
|
||||
{
|
||||
Point2i p1, p2;
|
||||
p1.x = vec[0];
|
||||
p1.y = vec[1];
|
||||
p2.x = vec[2];
|
||||
p2.y = vec[3];
|
||||
return GetLineRad(p1, p2);
|
||||
}
|
||||
|
||||
float GetRad(Point &p1, Point &p2)
|
||||
{
|
||||
float rad;
|
||||
Point2f p = p2 - p1;
|
||||
rad = atan2(p.y, p.x);
|
||||
if (rad < 0)
|
||||
rad = rad + CV_PI;
|
||||
return rad;
|
||||
}
|
||||
float GetVertRad(float rad)
|
||||
{
|
||||
float r = rad - CV_PI / 2;
|
||||
if (rad < 0)
|
||||
rad = rad + CV_PI;
|
||||
}
|
||||
|
||||
float O2PI(float rad)
|
||||
{
|
||||
return rad >= 0 ? rad : (rad + CV_PI);
|
||||
}
|
||||
|
||||
bool IsIn(float p1, float p2, float distance)
|
||||
{
|
||||
float dis = abs(p2 - p1);
|
||||
if (dis < distance)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
float GetDistance(Point p1, Point p2)
|
||||
{
|
||||
Point p = p1 - p2;
|
||||
return sqrt(p.dot(p));
|
||||
}
|
||||
float GetDistance(int x1, int y1, int x2, int y2)
|
||||
{
|
||||
Point p1, p2;
|
||||
p1.x = x1;
|
||||
p1.y = y1;
|
||||
p2.x = x2;
|
||||
p2.y = y2;
|
||||
return GetDistance(p1, p2);
|
||||
}
|
||||
|
||||
int Limiter(int number, int min, int max)
|
||||
{
|
||||
if (number > max)
|
||||
return max;
|
||||
if (number < min)
|
||||
return min;
|
||||
return number;
|
||||
}
|
||||
|
||||
void Limiter(Point &p, Mat &m)
|
||||
{
|
||||
p.x = Limiter(p.x, 0, m.cols - 1);
|
||||
p.y = Limiter(p.y, 0, m.rows - 1);
|
||||
}
|
||||
|
||||
Point Limiter(int x, int y, Mat &m)
|
||||
{
|
||||
Point lp;
|
||||
lp.x = Limiter(x, 0, m.cols - 1);
|
||||
lp.y = Limiter(y, 0, m.rows - 1);
|
||||
return lp;
|
||||
}
|
||||
|
||||
Point GetPoint(Point &p1, Point &p2, float length, Mat &limit)
|
||||
{
|
||||
float k = GetLineRad(p1, p2);
|
||||
Point p;
|
||||
p.x = p1.x + length * cos(k);
|
||||
p.y = p1.y + length * sin(k);
|
||||
Limiter(p, limit);
|
||||
return p;
|
||||
}
|
||||
|
||||
void int2str(const int &int_temp, string &string_temp)
|
||||
{
|
||||
stringstream stream;
|
||||
stream << int_temp;
|
||||
string_temp = stream.str(); //此处也可以用 stream>>string_temp
|
||||
}
|
||||
|
||||
void Divide(const Point &beichu, float n, Point &ret)
|
||||
{
|
||||
ret.x = beichu.x / n;
|
||||
ret.y = beichu.y / n;
|
||||
}
|
||||
|
||||
float point2Line(Point &p1, Point &lp1, Point &lp2)
|
||||
{
|
||||
float a, b, c, dis;
|
||||
// 化简两点式为一般式
|
||||
// 两点式公式为(y - y1)/(x - x1) = (y2 - y1)/ (x2 - x1)
|
||||
// 化简为一般式为(y2 - y1)x + (x1 - x2)y + (x2y1 - x1y2) = 0
|
||||
// A = y2 - y1
|
||||
// B = x1 - x2
|
||||
// C = x2y1 - x1y2
|
||||
a = lp2.y - lp1.y;
|
||||
b = lp1.x - lp2.x;
|
||||
c = lp2.x * lp1.y - lp1.x * lp2.y;
|
||||
// 距离公式为d = |A*x0 + B*y0 + C|/√(A^2 + B^2)
|
||||
dis = abs(a * p1.x + b * p1.y + c) / sqrt(a * a + b * b);
|
||||
return dis;
|
||||
}
|
||||
|
||||
int GetGray(Mat &m, Point &p, int s = 3)
|
||||
{
|
||||
Point plu = Limiter(p.x - s, p.y - s, m); //点左上
|
||||
Point prd = Limiter(p.x + s, p.y + s, m); //点右下
|
||||
Range row(plu.y, prd.y);
|
||||
Range col(plu.x, prd.x);
|
||||
// Range row(Limiter(p.y-3,0,m.rows-1),Limiter(p.y+3,0,m.rows-1));
|
||||
// Range col(Limiter(p.x-3,0,m.cols-1),Limiter(p.x+3,0,m.cols-1));
|
||||
Mat poi = m(row, col);
|
||||
Scalar me = mean(poi);
|
||||
return me[0];
|
||||
}
|
||||
|
||||
bool findX(Mat &img, Point &p)
|
||||
{
|
||||
Mat grayImg, bwImg;
|
||||
//设置静态变量,加快计算速度
|
||||
static Mat dilateElement, transMask, transImg;
|
||||
if (dilateElement.empty())
|
||||
{
|
||||
int dilation_size = 1;
|
||||
dilateElement = getStructuringElement(MORPH_ELLIPSE,
|
||||
Size(2 * dilation_size + 1, 2 * dilation_size + 1),
|
||||
Point(dilation_size, dilation_size));
|
||||
}
|
||||
Size transSize(60, 60);
|
||||
if (transMask.empty())
|
||||
{
|
||||
transMask = Mat(transSize.height, transSize.width, CV_8UC1);
|
||||
transMask = Scalar(0);
|
||||
rectangle(transMask, Point(19, 19), Point(59, 59), Scalar(255), -1);
|
||||
}
|
||||
|
||||
static vector<Point2f> trans2d;
|
||||
if (trans2d.size() == 0)
|
||||
{
|
||||
trans2d.push_back(Point2f(0, 0));
|
||||
trans2d.push_back(Point2f(59, 0));
|
||||
trans2d.push_back(Point2f(59, 59));
|
||||
trans2d.push_back(Point2f(0, 59));
|
||||
}
|
||||
|
||||
vector<Vec4i> lines;
|
||||
ContoursVector linesEx, possibleLines;
|
||||
vector<PointValue> resultPoints;
|
||||
|
||||
cvtColor(img, grayImg, COLOR_RGB2GRAY);
|
||||
//
|
||||
GaussianBlur(grayImg, grayImg, Size(11, 11), 0); //可能非最佳参数
|
||||
//imshow("gauss blur",grayImg);
|
||||
Canny(grayImg, bwImg, 70, 150); //可能非最佳参数
|
||||
//imshow("canny",bwImg);
|
||||
//腐蚀
|
||||
dilate(bwImg, bwImg, dilateElement);
|
||||
//imshow("canny",bwImg);
|
||||
int64 t1, t2, t3;
|
||||
t1 = getTickCount();
|
||||
HoughLinesP(bwImg, lines, 2, CV_PI / 360, 60, 30, 3); //可能非最佳参数...慢
|
||||
t2 = getTickCount();
|
||||
int disAsOne = 6;
|
||||
|
||||
Point pi[2], pj[2];
|
||||
for (int i = 0; i < lines.size(); i++)
|
||||
{
|
||||
pi[0].x = lines.at(i)[0];
|
||||
pi[0].y = lines.at(i)[1];
|
||||
pi[1].x = lines.at(i)[2];
|
||||
pi[1].y = lines.at(i)[3];
|
||||
//line(img,pi[0],pi[1],Scalar(255,255,0),2);
|
||||
|
||||
float rad1 = O2PI(GetLineRad(lines.at(i)));
|
||||
|
||||
for (int j = i + 1; j < lines.size(); j++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
pj[0].x = lines.at(j)[0];
|
||||
pj[0].y = lines.at(j)[1];
|
||||
pj[1].x = lines.at(j)[2];
|
||||
pj[1].y = lines.at(j)[3];
|
||||
float rad2 = O2PI(GetLineRad(lines.at(j)));
|
||||
if (IsIn(abs(rad1 - rad2), CV_PI / 2, CV_PI / 3))
|
||||
{
|
||||
float dp[4];
|
||||
dp[0] = GetDistance(pi[0], pj[0]);
|
||||
dp[1] = GetDistance(pi[0], pj[1]);
|
||||
dp[2] = GetDistance(pi[1], pj[0]);
|
||||
dp[3] = GetDistance(pi[1], pj[1]);
|
||||
for (int k = 0; k < 4; k++)
|
||||
{
|
||||
if (dp[k] < disAsOne)
|
||||
{
|
||||
PointsVector line;
|
||||
line.push_back(pi[1 - k / 2]);
|
||||
Point pij;
|
||||
Divide(pi[k / 2] + pj[k % 2], 2, pij);
|
||||
line.push_back(pij);
|
||||
line.push_back(pj[1 - k % 2]);
|
||||
linesEx.push_back(line);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool linesToRemove[linesEx.size()];
|
||||
for (int i = 0; i < linesEx.size(); i++)
|
||||
{
|
||||
for (int j = i + 1; j < linesEx.size(); j++)
|
||||
{
|
||||
if (GetDistance(linesEx.at(i).at(1), linesEx.at(j).at(1)) < disAsOne)
|
||||
{
|
||||
linesToRemove[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < linesEx.size(); i++)
|
||||
{
|
||||
if (!linesToRemove[i])
|
||||
possibleLines.push_back(linesEx.at(i));
|
||||
}
|
||||
//polylines(img,possibleLines,false,Scalar(0,0,255),2);
|
||||
vector<Point2f> fpoints;
|
||||
for (int i = 0; i < possibleLines.size(); i++)
|
||||
{
|
||||
fpoints.clear();
|
||||
Point p[10];
|
||||
p[0] = possibleLines.at(i).at(0);
|
||||
p[1] = possibleLines.at(i).at(1);
|
||||
p[2] = possibleLines.at(i).at(2);
|
||||
float len = GetDistance(p[0], p[1]);
|
||||
//cout<<len<<endl;
|
||||
len = len * 0.4;
|
||||
p[3] = GetPoint(p[1], p[0], len * 2 / 3, grayImg);
|
||||
p[4] = GetPoint(p[1], p[2], len * 2 / 3, grayImg);
|
||||
Divide((p[3] + p[4]), 2, p[5]);
|
||||
p[6] = GetPoint(p[1], p[5], len * 2 / 3 * sqrt(2), grayImg);
|
||||
p[7] = GetPoint(p[6], p[3], len, grayImg);
|
||||
p[9] = GetPoint(p[6], p[4], len, grayImg);
|
||||
p[8] = GetPoint(p[5], p[1], len * 2 / 3 * sqrt(2), grayImg);
|
||||
// p[3]=GetPoint(p[1],p[0],40,grayImg);
|
||||
// p[4]=GetPoint(p[1],p[2],40,grayImg);
|
||||
// p[5]=(p[3]+p[4])/2;
|
||||
// p[6]=GetPoint(p[1],p[5],40*sqrt(2),grayImg);
|
||||
// p[7]=GetPoint(p[6],p[3],60,grayImg);
|
||||
// p[8]=GetPoint(p[5],p[1],40*sqrt(2),grayImg);
|
||||
// p[9]=GetPoint(p[6],p[4],60,grayImg);
|
||||
fpoints.push_back(p[8]);
|
||||
fpoints.push_back(p[9]);
|
||||
fpoints.push_back(p[6]);
|
||||
fpoints.push_back(p[7]);
|
||||
Mat trans = getPerspectiveTransform(fpoints, trans2d);
|
||||
warpPerspective(grayImg, transImg, trans, transSize);
|
||||
|
||||
Scalar s1 = mean(transImg, transMask);
|
||||
Scalar s2 = mean(transImg, 255 - transMask);
|
||||
if (s1[0] - s2[0] > 80) ///////////////////////////
|
||||
{
|
||||
PointValue pv;
|
||||
pv.p = p[1];
|
||||
pv.value = 0;
|
||||
pv.p1 = p[5];
|
||||
pv.length = len * 1.2;
|
||||
//pv.p2=p[4];
|
||||
resultPoints.push_back(pv);
|
||||
}
|
||||
// vector<Point> pp;
|
||||
// pp.push_back(p[8]);
|
||||
// pp.push_back(p[9]);
|
||||
// pp.push_back(p[6]);
|
||||
// pp.push_back(p[7]);
|
||||
// if(s1[0]-s2[0]>80)
|
||||
// {
|
||||
// circle(img,p[1],4,Scalar(0,0,255),-1);
|
||||
// polylines(img,pp,true,Scalar(0,255,255));
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// polylines(img,pp,true,Scalar(255,255,255));
|
||||
// }
|
||||
}
|
||||
|
||||
for (int i = 0; i < resultPoints.size(); i++)
|
||||
{
|
||||
Point i1 = resultPoints.at(i).p - resultPoints.at(i).p1;
|
||||
float radi = atan2(i1.y, i1.x);
|
||||
|
||||
for (int j = i + 1; j < resultPoints.size(); j++)
|
||||
{
|
||||
|
||||
//if(i==j)continue;
|
||||
Point ij = resultPoints.at(j).p - resultPoints.at(i).p;
|
||||
float radij = atan2(ij.y, ij.x);
|
||||
if (IsIn(abs(radi - radij), 0, CV_PI / 3))
|
||||
{
|
||||
Point j1 = resultPoints.at(j).p - resultPoints.at(j).p1;
|
||||
float radj = atan2(j1.y, j1.x);
|
||||
Point ji = resultPoints.at(i).p - resultPoints.at(j).p;
|
||||
float radji = atan2(ji.y, ji.x);
|
||||
if (IsIn(abs(radj - radji), 0, CV_PI / 3))
|
||||
{
|
||||
resultPoints.at(i).value++;
|
||||
resultPoints.at(j).value++;
|
||||
resultPoints.at(i).rad = radi;
|
||||
resultPoints.at(j).rad = radj;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// cout<<resultPoints.size()<<endl;
|
||||
for (int i = 0; i < resultPoints.size(); i++)
|
||||
{
|
||||
for (int j = i + 1; j < resultPoints.size(); j++)
|
||||
{
|
||||
if (i == j)
|
||||
continue;
|
||||
if (IsIn(
|
||||
abs(resultPoints.at(i).rad - resultPoints.at(j).rad),
|
||||
CV_PI,
|
||||
CV_PI / 18))
|
||||
{
|
||||
float dij = point2Line(resultPoints.at(j).p, resultPoints.at(i).p, resultPoints.at(i).p1);
|
||||
float dji = point2Line(resultPoints.at(i).p, resultPoints.at(j).p, resultPoints.at(j).p1);
|
||||
float len = GetDistance(resultPoints.at(i).p, resultPoints.at(j).p);
|
||||
if ((dij < len / 3) && (dji < len / 3))
|
||||
{
|
||||
Divide(resultPoints.at(i).p + resultPoints.at(j).p, 2, p);
|
||||
float gray = GetGray(grayImg, p);
|
||||
float back = GetGray(grayImg, p, 100);
|
||||
if (gray < back)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// sort(resultPoints.begin(),resultPoints.end(),SortPointValue);
|
||||
// if(resultPoints.size()>4)
|
||||
// {
|
||||
// resultPoints.erase(resultPoints.begin()+4,resultPoints.end());
|
||||
// }
|
||||
t3 = getTickCount();
|
||||
//cout<<"hough:"<<(t2-t1)/getTickFrequency()<<"\tother:"<<(t3-t2)/getTickFrequency()<<endl;
|
||||
// for(int i=0;i<resultPoints.size();i++)
|
||||
// {
|
||||
// if(resultPoints.at(i).value>0)
|
||||
// {
|
||||
// circle(img,resultPoints.at(i).p,4,Scalar(0,0,255),-1);
|
||||
// }
|
||||
// }
|
||||
//string ss;
|
||||
//int2str(resultPoints.size(),ss);
|
||||
//putText(img,ss,Point(400,320),FONT_HERSHEY_SIMPLEX ,12,Scalar(0,0,225),2);
|
||||
// cout<<lines.size()/3<<"\t"<<
|
||||
// linesEx.size()<<"\t"<<
|
||||
// possibleLines.size()<<"\t"<<
|
||||
// resultPoints.size()<<"\t"<<endl;
|
||||
//cout<<resultPoints.size()<<endl;
|
||||
// switch (resultPoints.size()) {
|
||||
// case 4:
|
||||
// Divide(resultPoints.at(0).p+
|
||||
// resultPoints.at(1).p+
|
||||
// resultPoints.at(2).p+
|
||||
// resultPoints.at(3).p,4,p);
|
||||
// return true;
|
||||
// break;
|
||||
// case 3:
|
||||
// for(int i=0;i<3;i++)
|
||||
// {
|
||||
// if(IsIn(
|
||||
// abs(resultPoints.at(i).rad-resultPoints.at((i+1)%3).rad),
|
||||
// CV_PI,
|
||||
// CV_PI/4)
|
||||
// )
|
||||
// {
|
||||
// Divide((resultPoints.at(i).p+resultPoints.at((i+1)%3).p),2,p);
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// break;
|
||||
//// case 2:
|
||||
//// if(IsIn(abs(resultPoints.at(0).rad-resultPoints.at(1).rad),CV_PI,CV_PI/4))
|
||||
//// {
|
||||
//// p=(resultPoints.at(0).p+resultPoints.at(1).p)/2;
|
||||
//// return true;
|
||||
//// }
|
||||
//// else
|
||||
//// {
|
||||
//// float radx=(resultPoints.at(0).rad+resultPoints.at(1).rad)/2;
|
||||
//// if(abs(resultPoints.at(0).rad-resultPoints.at(1).rad)>CV_PI)
|
||||
//// {
|
||||
//// radx=radx+CV_PI;
|
||||
//// }
|
||||
//// Point xx=(resultPoints.at(0).p+resultPoints.at(1).p)/2;
|
||||
//// Point xdis=(resultPoints.at(0).p-resultPoints.at(1).p)/2;
|
||||
//// float xd=sqrt(xdis.dot(xdis));
|
||||
//// p.x=xx.x+xd*cos(radx);
|
||||
//// p.y=xx.y+xd*sin(radx);
|
||||
//// return true;
|
||||
//// }
|
||||
// default:
|
||||
// return false;
|
||||
// break;
|
||||
// }
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
@ -1,61 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<package>
|
||||
<name>prometheus_detection_circlex</name>
|
||||
<version>0.0.0</version>
|
||||
<description>The prometheus_detection_circlex package</description>
|
||||
|
||||
<!-- One maintainer tag required, multiple allowed, one person per tag -->
|
||||
<maintainer email="jariof@foxmail.com">jario</maintainer>
|
||||
|
||||
|
||||
<!-- One license tag required, multiple allowed, one license per tag -->
|
||||
<!-- Commonly used license strings: -->
|
||||
<!-- BSD, MIT, Boost Software License, GPLv2, GPLv3, LGPLv2.1, LGPLv3 -->
|
||||
<license>TODO</license>
|
||||
|
||||
|
||||
<!-- Url tags are optional, but mutiple are allowed, one per tag -->
|
||||
<!-- Optional attribute type can be: website, bugtracker, or repository -->
|
||||
<!-- Example: -->
|
||||
<!-- <url type="website">http://wiki.ros.org/ros_caffe</url> -->
|
||||
|
||||
|
||||
<!-- Author tags are optional, mutiple are allowed, one per tag -->
|
||||
<!-- Authors do not have to be maintianers, but could be -->
|
||||
<!-- Example: -->
|
||||
<!-- <author email="jane.doe@example.com">Jane Doe</author> -->
|
||||
|
||||
|
||||
<!-- The *_depend tags are used to specify dependencies -->
|
||||
<!-- Dependencies can be catkin packages or system dependencies -->
|
||||
<!-- Examples: -->
|
||||
<!-- Use build_depend for packages you need at compile time: -->
|
||||
<!-- <build_depend>message_generation</build_depend> -->
|
||||
<!-- Use buildtool_depend for build tool packages: -->
|
||||
<!-- <buildtool_depend>catkin</buildtool_depend> -->
|
||||
<!-- Use run_depend for packages you need at runtime: -->
|
||||
<!-- <run_depend>message_runtime</run_depend> -->
|
||||
<!-- Use test_depend for packages you need only for testing: -->
|
||||
<!-- <test_depend>gtest</test_depend> -->
|
||||
<buildtool_depend>catkin</buildtool_depend>
|
||||
<build_depend>roscpp</build_depend>
|
||||
<build_depend>std_msgs</build_depend>
|
||||
<build_depend>opencv2</build_depend>
|
||||
<build_depend>image_transport</build_depend>
|
||||
<build_depend>sensor_msgs</build_depend>
|
||||
<build_depend>cv_bridge</build_depend>
|
||||
<build_depend>prometheus_msgs</build_depend>
|
||||
<run_depend>roscpp</run_depend>
|
||||
<run_depend>std_msgs</run_depend>
|
||||
<run_depend>opencv2</run_depend>
|
||||
<run_depend>image_transport</run_depend>
|
||||
<run_depend>sensor_msgs</run_depend>
|
||||
<run_depend>cv_bridge</run_depend>
|
||||
<run_depend>prometheus_msgs</run_depend>
|
||||
|
||||
<!-- The export tag contains other, unspecified, tags -->
|
||||
<export>
|
||||
<!-- Other tools can request additional information be placed here -->
|
||||
|
||||
</export>
|
||||
</package>
|
File diff suppressed because it is too large
Load Diff
@ -1,98 +0,0 @@
|
||||
## General
|
||||
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.cuo
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
|
||||
# Compiled protocol buffers
|
||||
*.pb.h
|
||||
*.pb.cc
|
||||
*_pb2.py
|
||||
|
||||
# Compiled python
|
||||
*.pyc
|
||||
|
||||
# Compiled MATLAB
|
||||
*.mex*
|
||||
|
||||
# IPython notebook checkpoints
|
||||
.ipynb_checkpoints
|
||||
|
||||
# Editor temporaries
|
||||
*.swp
|
||||
*~
|
||||
|
||||
# Sublime Text settings
|
||||
*.sublime-workspace
|
||||
*.sublime-project
|
||||
|
||||
# Eclipse Project settings
|
||||
*.*project
|
||||
.settings
|
||||
|
||||
# QtCreator files
|
||||
*.user
|
||||
|
||||
# PyCharm files
|
||||
.idea
|
||||
|
||||
# Visual Studio Code files
|
||||
.vscode
|
||||
|
||||
# OSX dir files
|
||||
.DS_Store
|
||||
|
||||
## Caffe
|
||||
|
||||
# User's build configuration
|
||||
Makefile.config
|
||||
|
||||
# Data and models are either
|
||||
# 1. reference, and not casually committed
|
||||
# 2. custom, and live on their own unless they're deliberated contributed
|
||||
data/*
|
||||
models/*
|
||||
*.caffemodel.h5
|
||||
*.solverstate
|
||||
*.solverstate.h5
|
||||
*.binaryproto
|
||||
*leveldb
|
||||
*lmdb
|
||||
|
||||
# build, distribute, and bins (+ python proto bindings)
|
||||
build
|
||||
.build_debug/*
|
||||
.build_release/*
|
||||
distribute/*
|
||||
*.testbin
|
||||
*.bin
|
||||
python/caffe/proto/
|
||||
cmake_build
|
||||
.cmake_build
|
||||
|
||||
# Generated documentation
|
||||
docs/_site
|
||||
docs/_includes
|
||||
docs/gathered
|
||||
_site
|
||||
doxygen
|
||||
docs/dev
|
||||
|
||||
# LevelDB files
|
||||
*.sst
|
||||
*.ldb
|
||||
LOCK
|
||||
LOG*
|
||||
CURRENT
|
||||
MANIFEST-*
|
@ -1,67 +0,0 @@
|
||||
dist: trusty
|
||||
sudo: required
|
||||
|
||||
language: cpp
|
||||
compiler: gcc
|
||||
|
||||
env:
|
||||
global:
|
||||
- NUM_THREADS=4
|
||||
matrix:
|
||||
# Use a build matrix to test many builds in parallel
|
||||
# envvar defaults:
|
||||
# WITH_CMAKE: false
|
||||
# WITH_PYTHON3: false
|
||||
# WITH_IO: true
|
||||
# WITH_CUDA: false
|
||||
# WITH_CUDNN: false
|
||||
- BUILD_NAME="default-make"
|
||||
# - BUILD_NAME="python3-make" WITH_PYTHON3=true
|
||||
- BUILD_NAME="no-io-make" WITH_IO=false
|
||||
- BUILD_NAME="cuda-make" WITH_CUDA=true
|
||||
- BUILD_NAME="cudnn-make" WITH_CUDA=true WITH_CUDNN=true
|
||||
|
||||
- BUILD_NAME="default-cmake" WITH_CMAKE=true
|
||||
- BUILD_NAME="python3-cmake" WITH_CMAKE=true WITH_PYTHON3=true
|
||||
- BUILD_NAME="no-io-cmake" WITH_CMAKE=true WITH_IO=false
|
||||
- BUILD_NAME="cuda-cmake" WITH_CMAKE=true WITH_CUDA=true
|
||||
- BUILD_NAME="cudnn-cmake" WITH_CMAKE=true WITH_CUDA=true WITH_CUDNN=true
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
directories:
|
||||
- ~/protobuf3
|
||||
|
||||
before_install:
|
||||
- source ./scripts/travis/defaults.sh
|
||||
|
||||
install:
|
||||
- sudo -E ./scripts/travis/install-deps.sh
|
||||
- ./scripts/travis/setup-venv.sh ~/venv
|
||||
- source ~/venv/bin/activate
|
||||
- ./scripts/travis/install-python-deps.sh
|
||||
|
||||
before_script:
|
||||
- ./scripts/travis/configure.sh
|
||||
|
||||
script:
|
||||
- ./scripts/travis/build.sh
|
||||
- ./scripts/travis/test.sh
|
||||
|
||||
notifications:
|
||||
# Emails are sent to the committer's git-configured email address by default,
|
||||
# but only if they have access to the repository. To enable Travis on your
|
||||
# public fork of Caffe, just go to travis-ci.org and flip the switch on for
|
||||
# your Caffe fork. To configure your git email address, use:
|
||||
# git config --global user.email me@example.com
|
||||
email:
|
||||
on_success: always
|
||||
on_failure: always
|
||||
|
||||
# IRC notifications disabled by default.
|
||||
# Uncomment next 5 lines to send notifications to chat.freenode.net#caffe
|
||||
# irc:
|
||||
# channels:
|
||||
# - "chat.freenode.net#caffe"
|
||||
# template:
|
||||
# - "%{repository}/%{branch} (%{commit} - %{author}): %{message}"
|
@ -1,96 +0,0 @@
|
||||
cmake_minimum_required(VERSION 2.8.7)
|
||||
if(POLICY CMP0046)
|
||||
cmake_policy(SET CMP0046 NEW)
|
||||
endif()
|
||||
if(POLICY CMP0054)
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
endif()
|
||||
|
||||
# ---[ Caffe project
|
||||
project(Caffe C CXX)
|
||||
|
||||
# ---[ Caffe version
|
||||
set(CAFFE_TARGET_VERSION "1.0.0-rc4" CACHE STRING "Caffe logical version")
|
||||
set(CAFFE_TARGET_SOVERSION "1.0.0-rc4" CACHE STRING "Caffe soname version")
|
||||
add_definitions(-DCAFFE_VERSION=${CAFFE_TARGET_VERSION})
|
||||
|
||||
# Jario Edit Start
|
||||
add_compile_options(-std=c++11)
|
||||
# Jario Edit End
|
||||
# ---[ Using cmake scripts and modules
|
||||
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake/Modules)
|
||||
|
||||
include(ExternalProject)
|
||||
|
||||
include(cmake/Utils.cmake)
|
||||
include(cmake/Targets.cmake)
|
||||
include(cmake/Misc.cmake)
|
||||
include(cmake/Summary.cmake)
|
||||
include(cmake/ConfigGen.cmake)
|
||||
|
||||
# ---[ Options
|
||||
caffe_option(CPU_ONLY "Build Caffe without CUDA support" ON) # TODO: rename to USE_CUDA
|
||||
caffe_option(USE_CUDNN "Build Caffe with cuDNN library support" OFF)
|
||||
caffe_option(USE_NCCL "Build Caffe with NCCL library support" OFF)
|
||||
caffe_option(BUILD_SHARED_LIBS "Build shared libraries" ON)
|
||||
caffe_option(BUILD_python "Build Python wrapper" ON)
|
||||
set(python_version "2" CACHE STRING "Specify which Python version to use")
|
||||
caffe_option(BUILD_matlab "Build Matlab wrapper" OFF IF UNIX OR APPLE)
|
||||
caffe_option(BUILD_docs "Build documentation" ON IF UNIX OR APPLE)
|
||||
caffe_option(BUILD_python_layer "Build the Caffe Python layer" ON)
|
||||
caffe_option(USE_OPENCV "Build with OpenCV support" ON)
|
||||
caffe_option(USE_LEVELDB "Build with levelDB" ON)
|
||||
caffe_option(USE_LMDB "Build with lmdb" ON)
|
||||
caffe_option(ALLOW_LMDB_NOLOCK "Allow MDB_NOLOCK when reading LMDB files (only if necessary)" OFF)
|
||||
|
||||
# ---[ Dependencies
|
||||
include(cmake/Dependencies.cmake)
|
||||
|
||||
# ---[ Flags
|
||||
if(UNIX OR APPLE)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC -Wall")
|
||||
endif()
|
||||
|
||||
caffe_set_caffe_link()
|
||||
|
||||
if(USE_libstdcpp)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -stdlib=libstdc++")
|
||||
message("-- Warning: forcing libstdc++ (controlled by USE_libstdcpp option in cmake)")
|
||||
endif()
|
||||
|
||||
add_definitions(-DGTEST_USE_OWN_TR1_TUPLE)
|
||||
|
||||
# ---[ Warnings
|
||||
caffe_warnings_disable(CMAKE_CXX_FLAGS -Wno-sign-compare -Wno-uninitialized)
|
||||
|
||||
# ---[ Config generation
|
||||
configure_file(cmake/Templates/caffe_config.h.in "${PROJECT_BINARY_DIR}/caffe_config.h")
|
||||
|
||||
# ---[ Includes
|
||||
set(Caffe_INCLUDE_DIR ${PROJECT_SOURCE_DIR}/include)
|
||||
include_directories(${Caffe_INCLUDE_DIR} ${PROJECT_BINARY_DIR})
|
||||
include_directories(BEFORE src) # This is needed for gtest.
|
||||
|
||||
# ---[ Subdirectories
|
||||
add_subdirectory(src/gtest)
|
||||
add_subdirectory(src/caffe)
|
||||
add_subdirectory(tools)
|
||||
add_subdirectory(examples)
|
||||
add_subdirectory(python)
|
||||
add_subdirectory(matlab)
|
||||
add_subdirectory(docs)
|
||||
|
||||
# ---[ Linter target
|
||||
add_custom_target(lint COMMAND ${CMAKE_COMMAND} -P ${PROJECT_SOURCE_DIR}/cmake/lint.cmake)
|
||||
|
||||
# ---[ pytest target
|
||||
if(BUILD_python)
|
||||
add_custom_target(pytest COMMAND python${python_version} -m unittest discover -s caffe/test WORKING_DIRECTORY ${PROJECT_SOURCE_DIR}/python )
|
||||
add_dependencies(pytest pycaffe)
|
||||
endif()
|
||||
|
||||
# ---[ Configuration summary
|
||||
caffe_print_configuration_summary()
|
||||
|
||||
# ---[ Export configs generation
|
||||
caffe_generate_export_configs()
|
@ -1,30 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
## Issues
|
||||
|
||||
Specific Caffe design and development issues, bugs, and feature requests are maintained by GitHub Issues.
|
||||
|
||||
_Please do not post usage, installation, or modeling questions, or other requests for help to Issues._
|
||||
Use the [caffe-users list](https://groups.google.com/forum/#!forum/caffe-users) instead. This helps developers maintain a clear, uncluttered, and efficient view of the state of Caffe.
|
||||
|
||||
When reporting a bug, it's most helpful to provide the following information, where applicable:
|
||||
|
||||
* What steps reproduce the bug?
|
||||
* Can you reproduce the bug using the latest [master](https://github.com/BVLC/caffe/tree/master), compiled with the `DEBUG` make option?
|
||||
* What hardware and operating system/distribution are you running?
|
||||
* If the bug is a crash, provide the backtrace (usually printed by Caffe; always obtainable with `gdb`).
|
||||
|
||||
Try to give your issue a title that is succinct and specific. The devs will rename issues as needed to keep track of them.
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Caffe welcomes all contributions.
|
||||
|
||||
See the [contributing guide](http://caffe.berkeleyvision.org/development.html) for details.
|
||||
|
||||
Briefly: read commit by commit, a PR should tell a clean, compelling story of _one_ improvement to Caffe. In particular:
|
||||
|
||||
* A PR should do one clear thing that obviously improves Caffe, and nothing more. Making many smaller PRs is better than making one large PR; review effort is superlinear in the amount of code involved.
|
||||
* Similarly, each commit should be a small, atomic change representing one step in development. PRs should be made of many commits where appropriate.
|
||||
* Please do rewrite PR history to be clean rather than chronological. Within-PR bugfixes, style cleanups, reversions, etc. should be squashed and should not appear in merged PR history.
|
||||
* Anything nonobvious from the code should be explained in comments, commit messages, or the PR description, as appropriate.
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue