赤道仪自动寻星方法V2.0(工程源文件)

        本文上传了除导星外的所有代码。

Astronomy.h

#ifndef ASTRONOMY_H
#define ASTRONOMY_H

#include<iostream>
#include<opencv2/opencv.hpp>
#include<Eigen/Dense>
#include<Windows.h>
#include<cmath>
#include"windows.h"
#include"atlstr.h"
#include<string.h>
#include<TCHAR.H>
#include<conio.h>
#include<stdarg.h>
#include"LsxMath.h"
#include"Global.h"
#include"StarPointDeal.h"

namespace lsx {
	namespace astronomy {

		/**
		 * @brief 当地恒星时计算器
		 */
		class AstroTimer {
		public:

			/**
			 * @brief 计算当地恒星时
			 * @param none
			 * @return void
			 */
			double get_local_sidereal_time();

		private:

			unsigned int year = 0, month = 0, day = 0, hour = 0, min = 0, sec = 0;

			/**
			 * @brief 计算系统当前时间
			 * @param none
			 * @return void
			 */
			void get_this_time();

			/**
			 * @brief 计算(0h UT)儒略日,使用星图软件stellarium计算方法,
			          计算方式来源:https://blog.csdn.net/shaoguangleo/article/details/6248315
			 * @param none
			 * @return 返回的儒略日(long double类型)
			 */
			long double JD();

			/**
			 * @brief 计算任意时刻的儒略日,使用星图软件stellarium计算方法,
				      计算方式来源:https://blog.csdn.net/shaoguangleo/article/details/6248315
			 * @param none
			 * @return 返回的儒略日(long double类型)
			 */
			long double _JD();

			/**
			 * @brief 得到中介参数T(T = (JD - 2451545.0) / 36525)
			 * @param is_0h_UT 是否是计算(0h UT)标志位
			 * @return 中介参数T
			 */
			long double T(bool is_0h_UT = true);

			/**
			 * @brief 格林尼治平恒星时(使用IAU1982标准)
			 * @param is_0h_UT 是否是计算(0h UT)标志位,当该位为true时计算格林尼治(0h UT)的平恒星时
			                   ,当该位为false时计算任意时刻的格林尼治平恒星时
			 * @return 格林尼治平恒星时
			 */
			long double Greenwich_mean_sidereal_time(bool is_0h_UT = true);
		};

		/**
		 * @brief 单个观测目标
		 */
		class ObservationTarget {

			public:
				double RA_angle = 0;//赤经角度坐标,单位:°
				double DEC_angle = 0;//赤纬角度坐标,单位:°

				double elevation = 0;//仰角,单位:°
				double azimuth = 0;//方位角,单位:°

				double RA_hour = 0;//赤经时
				double RA_min = 0;//赤经分
				double RA_second = 0;//赤经秒

				double DEC_degree = 0;//赤纬度
				double DEC_min = 0;//赤纬分
				double DEC_second = 0;//赤纬秒

				double position_in_image_x = 0;//该天体在自动寻星图像上的横坐标
				double position_in_image_y = 0;//该天体在自动寻星图像上的纵坐标

				bool error = true;//是否是错误星体
				bool isStar = false;//是否是恒星标志位
				bool origin_show = true;//一开始就展示名字

				std::string name = "赤道仪零位";
				std::string number = "赤道仪零位";
				std::string ShowName = "000";

				/** 
				 * @brief 设置观测天体坐标
				 * @param number 天体编号
				 * @param name 天体名称
				 * @param RA_hour 赤经小时
				 * @param RA_min 赤经分
				 * @param RA_second 赤经秒
				 * @param DEC_degree 赤纬度
				 * @param DEC_min 赤纬分
				 * @param DEC_second 赤纬秒
				 * @return void
				 */
				void inputTarget(std::string number, std::string name, std::string showName, \
					double RA_hour, double RA_min, double RA_second, double DEC_degree, double DEC_min, double DEC_second, \
					bool is_star, bool origin_show = true);

				/**
				 * @brief 打印天体参数
				 * @param none
				 * @return void
				 */
				void printTarget();

				/**
				 * @brief 判断是否为当前天体
				 * @param none
				 * @return void
				 */
				bool isName(std::string& inputName_or_Number);

				ObservationTarget(std::string number, std::string name, std::string showName, \
					double RA_hour, double RA_min, double RA_second, double DEC_degree, double DEC_min, double DEC_second,\
					bool is_star, bool origin_show = true);

				ObservationTarget();
			private:
		};

		/**
		 * @brief 观测目标列表
		 */
		class ObservationTable {
		public:

			std::vector<ObservationTarget> TargetTable;

			/**
			 * @brief 在星表中插入一个新的天体,如果需要观测星表外的天体,可以通过该函数临时插入
			 * @param number 天体编号
			 * @param name 天体名称
			 * @param RA_hour 赤经小时
			 * @param RA_min 赤经分
			 * @param RA_second 赤经秒
			 * @param DEC_degree 赤纬度
			 * @param DEC_min 赤纬分
			 * @param DEC_second 赤纬秒
			 * @param is_star 是否是恒星的标志位,true:该天体为恒星;false:该天体不是恒星
			 * @return void
			 */
			void input_new_target(std::string number, std::string name, std::string showName, \
				double RA_hour, double RA_min, double RA_second, double DEC_degree, double DEC_min, double DEC_second, \
				bool is_star);

			/**
			 * @brief 在目标列表中得到观测目标
			 * @param name_or_number 名称或编号
			 * @return 通过名称或编号寻找的观测目标
			 */
			lsx::astronomy::ObservationTarget findTarget(std::string& name_or_number);

			/**
			 * @brief 判断该表格中是否存在这个天体
			 * @param name_or_number 名称或编号
			 * @return 查询到这个天体则返回true,否则返回false
			 */
			bool tatgetInTable(std::string& name_or_number);

			/**
			 * @brief 生成自动寻星的图像界面
			 * @param width 图像宽度
			 * @param height 图像高度
			 * @return 包含天体位置、中天位置的图像界面
			 */
			cv::Mat getTargetTableImage();

			/**
			 * @brief 用于找到鼠标就近的一个星点
			 */
			lsx::astronomy::ObservationTarget findCloseTarget(double& image_x, double& image_y, double& radius, bool* have_choose);

			/**
			 * @brief 从图像坐标转换到天体实际坐标
			 */
			void get_ra_dec(double& image_x, double& image_y, double* ra, double* dec);

			/**
			 * @brief 从赤经赤纬得到图像坐标
			 */
			void get_image_x_y(double& ra, double& dec, double* image_x, double* image_y);

			ObservationTable();

		private:
			cv::Mat _TargetTableImage;

			/**
			 * @brief 通过名称或者编号得到天体
			 */
			lsx::astronomy::ObservationTarget getTarget(std::string& name_or_number);

			/**
			 * @brief 星表类初始化
			 */
			void input_data();
		};

		/**
		 * @brief 得到星点指向向量
		 * @param ra_degree 赤经,单位:°
		 * @param dec_degree 赤经,单位:°
		 * @param zenith_degree 中天赤经:单位:°
		 * @return 星点在天体坐标系下的指向向量
		 */
		Eigen::MatrixXd StarPointVector(double& ra_degree, double& dec_degree, double& zenith_degree);

		/**
		 * @brief 将赤经角度转换到0~360°区间内
		 * @param inputRA 输入的角度,单位:°
		 * @return 转换后的角度
		 */
		double RA_inRegion_0_360(double inputRA);

		/**
		 * @brief 得到中天位置的假想天体
		 */
		lsx::astronomy::ObservationTarget GetZenith();

		/**
		 * @brief 两个天体之间的最短赤经角距离
		 * @param inputRA1 输入的天体1赤经,单位:°
		 * @param inputRA2 输入的天体2赤经,单位:°
		 * @return 最短角距离,单位:°
		 */
		double getMinAngle(double& inputRA1, double& inputRA2);

		/**
		 * @brief 两个天体之间的最短赤经角距离
		 * @param inputTarget1 输入的天体1
		 * @param inputTarget2 输入的天体2
		 * @return 最短角距离,单位:°
		 */
		double getMinAngle(lsx::astronomy::ObservationTarget& inputTarget1, lsx::astronomy::ObservationTarget& inputTarget2);

		/**
		 * @brief 判断天体是否通过中天
		 * @param inputarget 输入天体
		 * @return 通过中天则为true,否则为false
		 */
		bool RA_PassZenith(lsx::astronomy::ObservationTarget& inputTarget);

		/**
		 * @brief 判断天体是否在地平线以下
		 * @param inputOberveTarget 输入天体
		 * @return 在地平线以下为true,否则为false
		 */
		bool TargetUnderHorizon(lsx::astronomy::ObservationTarget& inputOberveTarget);

		/**
		 * @brief 将天体的赤道坐标转换为地平坐标,并保存在对应的成员变量其中
		 * @param inputTarget 输入天体
		 * @return void
		 */
		void Equ2EleAzi(lsx::astronomy::ObservationTarget* inputTarget);

		/**
		 * @brief 计算地球运行角度
		 * @param inputTime_ms 输入的运行时间,单位:ms
		 * @return 地球运行的角度,单位:°
		 */
		double earthRotateAngle(double inputTime_ms);

		/**
		 * @brief 计算地球转动时间
		 * @param inputAngle_degree 输入的运行角度,单位:°
		 * @return 地球转动的时间,单位:ms
		 */
		int earthRotateTime(double inputAngle_degree);

		/**
		 * @brief 赤经坐标转换为角度
		 * @param hour 赤经时
		 * @param min 赤经分
		 * @param sec 赤经秒
		 * @return RA角度,单位:°
		 */
		double ra2degree(double hour, double min, double sec);

		/**
		 * @brief 赤纬坐标转换为角度
		 * @param degree 赤纬度
		 * @param min 赤纬分
		 * @param sec 赤纬秒
		 * @return DEC角度,单位:°
		 */
		double dec2degree(double degree, double min, double sec);

		/**
		 * @brief 赤纬坐标转换为时间
		 * @param inputAngle_degree 输入的角度
		 * @param ra_hour 赤经时
		 * @param ra_min 赤经分
		 * @param ra_sec 赤经秒
		 * @return void
		*/
		void degree2ra(double inputAngle_degree, double* ra_hour, double* ra_min, double* ra_sec);

		/**
		 * @brief 将角度用度、分、秒表示
		 * @param input_angle_degree 输入的角度
		 * @param deg 度
		 * @param min 分
		 * @param sec 秒
		 * @return void
		*/
		void degree_2_deg_min_sec(double input_angle_degree, double* deg, double* min, double* sec);

		/**
		 * @brief 将赤经角度转换到0~360°区间内
		 * @param inputAngle_degree 输入的角度,单位:°
		 * @return 转换后的角度,单位:°
		 */
		double angle_in_0_360(double inputAngle_degree);

		/**
		 * @brief 得到地平线上的赤经范围
		 * @param dec_angle_degree 天体的赤纬坐标
		 * @param down_threhold 地平线上天体下阈值
		 * @param up_threhold 地平线上天体上阈值
		 * @return 角度范围
		 */
		double theta_on_horizon_degree(double dec_angle_degree, double* down_threhold, double* up_threhold);
	}
}

#endif

Astronomy.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"Astronomy.h"

extern double global_latitude;//观测地纬度
extern double global_longitude;//观测地经度

extern int zenith_line_color[3];//地平线颜色
extern cv::Scalar background;//背景颜色
extern cv::Scalar background_line;//刻度线颜色
extern cv::Scalar star_color;//恒星颜色
extern cv::Scalar not_star_color;//天体颜色
extern cv::Scalar big_word;//图样范围字符颜色
extern cv::Scalar zenith_str_line;//背景颜色

extern int goto_image_width, goto_image_height;//自动寻星的图像大小

void lsx::astronomy::AstroTimer::get_this_time() {
	SYSTEMTIME time_;
	GetLocalTime(&time_);
	this->year = time_.wYear;
	this->month = time_.wMonth;
	this->day = time_.wDay;
	this->hour = time_.wHour;
	this->min = time_.wMinute;
	this->sec = time_.wSecond;
}

long double lsx::astronomy::AstroTimer::_JD() {
	int y, m, B;
	this->get_this_time();
	y = this->year;
	m = this->month;
	if (this->month <= 2)
	{
		y = this->year - 1;
		m = this->month + 12;
	}
	B = -2;
	if (this->year > 1582 || (this->year == 1582 && (this->month > 10 || (this->month == 10 && this->day >= 15))))
	{
		B = y / 400 - y / 100;
	}
	return (floor(365.25 * y) + floor(30.6001 * (double(m) + 1.0)) + B + 1720996.5 + this->day + this->hour / 24.0 + this->min / 1440.0 + this->sec / 86400.0);
}

long double lsx::astronomy::AstroTimer::JD() {
	int y, m, B;
	this->get_this_time();
	y = this->year;
	m = this->month;
	if (this->month <= 2)
	{
		y = this->year - 1;
		m = this->month + 12;
	}
	B = -2;
	if (this->year > 1582 || (this->year == 1582 && (this->month > 10 || (this->month == 10 && this->day >= 15))))
	{
		B = y / 400 - y / 100;
	}
	return (floor(365.25 * y) + floor(30.6001 * (double(m) + 1.0)) + B + 1720996.5 + this->day);
}

long double lsx::astronomy::AstroTimer::T(bool is_0h_UT) {
	if (is_0h_UT) {
		return (this->JD() - long double(2451545.0)) / long double(36525.0);
	}
	else {
		return (this->_JD() - long double(2451545.0)) / long double(36525.0);
	}
}

long double lsx::astronomy::AstroTimer::Greenwich_mean_sidereal_time(bool is_0h_UT) {
	long double this_T = this->T(is_0h_UT), greenwich_mean_sidereal_time = 0;
	long double T = 0;
	if (is_0h_UT) {
		greenwich_mean_sidereal_time = long double(100.46061837) +
			long double(36000.770053608) * this_T +
			long double(0.000387933) * this_T * this_T -
			this_T * this_T * this_T / long double(38710000);
	}
	else {
		greenwich_mean_sidereal_time = long double(280.46061837) +
			long double(360.98564736629) * (this->_JD() - 2451545.0) +
			long double(0.000387933) * this_T * this_T -
			this_T * this_T * this_T / long double(38710000);
	}
	return greenwich_mean_sidereal_time;
}

double lsx::astronomy::AstroTimer::get_local_sidereal_time() {
	double output_local_sidereal_time = 0;
	double local_time = 0;//地方平时
	double greenwich_time = 0;//格林尼治平时
	this->get_this_time();
	local_time = lsx::astronomy::ra2degree(this->hour, this->min, this->sec) + global_longitude - lsx::astronomy::ra2degree(8, 0, 0);//地方平时
	greenwich_time = local_time - global_longitude;//格林尼治平时
	output_local_sidereal_time = local_time + double(this->Greenwich_mean_sidereal_time(true)) + greenwich_time / 365.2422;
	output_local_sidereal_time = lsx::astronomy::RA_inRegion_0_360(output_local_sidereal_time);
	return output_local_sidereal_time;
}

double lsx::astronomy::RA_inRegion_0_360(double inputRA) {
	if (inputRA > 360.0) {
		while (inputRA > 360.0)
			inputRA -= 360.0;
	}
	else if (inputRA < 0) {
		while (inputRA < 0)
			inputRA += 360.0;
	}
	return inputRA;
}

double lsx::astronomy::theta_on_horizon_degree(double dec_angle_degree, double* down_threhold, double* up_threhold) {
	double angle = 0;
	if (dec_angle_degree >= 90.0 - global_latitude) {
		*down_threhold = -180.0;
		*up_threhold = 180.0;
		return 360.0;
	}
	else if (dec_angle_degree >= 0 && 90.0 - global_latitude) {
		angle = 360.0 - 2.0 * acos(tan(fabs(dec_angle_degree) / 180.0 * PI) * tan(fabs(global_latitude) / 180.0 * PI)) / PI * 180.0;
		*down_threhold = lsx::astronomy::angle_in_0_360(local_sidreal_time_degree() - 0.5 * angle);
		*up_threhold = lsx::astronomy::angle_in_0_360(local_sidreal_time_degree() + 0.5 * angle);
		return angle;
	}
	else if (dec_angle_degree > -(90.0 - global_latitude) && dec_angle_degree < 0) {
		angle = 2.0 * acos(tan(fabs(dec_angle_degree) / 180.0 * PI) * tan(global_latitude / 180.0 * PI)) / PI * 180.0;
		*down_threhold = lsx::astronomy::angle_in_0_360(local_sidreal_time_degree() - 0.5 * angle);
		*up_threhold = lsx::astronomy::angle_in_0_360(local_sidreal_time_degree() + 0.5 * angle);
		return angle;
	}
	else {
		*down_threhold = 0;
		*up_threhold = 0;
		return 0;
	}
}

lsx::astronomy::ObservationTarget lsx::astronomy::GetZenith() {
	lsx::astronomy::ObservationTarget outputTarget;
	outputTarget.RA_angle = local_sidreal_time_degree();//*********************************************************
	outputTarget.DEC_angle = 90.0;
	return outputTarget;
}

double lsx::astronomy::getMinAngle(double& inputRA1, double& inputRA2) {
	inputRA1 = lsx::astronomy::RA_inRegion_0_360(inputRA1);
	inputRA2 = lsx::astronomy::RA_inRegion_0_360(inputRA2);
	if (fabs(inputRA1 - inputRA2) > 180.0)
		return 360.0 - fabs(inputRA1 - inputRA2);
	return fabs(inputRA1 - inputRA2);
}

double lsx::astronomy::getMinAngle(lsx::astronomy::ObservationTarget& target1,\
									lsx::astronomy::ObservationTarget& target2) {
	return lsx::astronomy::getMinAngle(target1.RA_angle, target2.RA_angle);
}

bool lsx::astronomy::RA_PassZenith(lsx::astronomy::ObservationTarget& inputTarget) {
	Eigen::MatrixXd zenith_vector(3, 1), target_vector(3, 1), z_axis(3, 1);
	zenith_vector << 0, -1, 0;
	z_axis << 0, 0, 1;
	target_vector = lsx::math::RotationMatrix3(z_axis, (inputTarget.RA_angle - local_sidreal_time_degree()) / 180.0 * PI) * zenith_vector;
	if (target_vector(0, 0) > 0) {
		return false;
	}
	else {
		return true;
	}
}

void lsx::astronomy::ObservationTarget::inputTarget(std::string number, std::string name, std::string showName, \
	double RA_hour, double RA_min, double RA_second, double DEC_degree, double DEC_min, double DEC_second, \
	bool is_star, bool origin_show) {
	this->RA_hour = RA_hour;
	this->RA_min = RA_min;
	this->RA_second = RA_second;
	this->DEC_degree = DEC_degree;
	this->DEC_min = DEC_min;
	this->DEC_second = DEC_second;
	this->RA_angle = lsx::astronomy::ra2degree(this->RA_hour, this->RA_min, this->RA_second);
	if (this->DEC_degree < 0 || this->DEC_min < 0 || this->DEC_second < 0) {
		this->DEC_degree = -fabs(this->DEC_degree);
		this->DEC_min = -fabs(this->DEC_min);
		this->DEC_second = -fabs(this->DEC_second);
	}
	this->DEC_angle = lsx::astronomy::dec2degree(this->DEC_degree, this->DEC_min, this->DEC_second);
	this->name = name;
	this->number = number;
	this->ShowName = showName;
	this->isStar = is_star;
	this->origin_show = origin_show;
}

void lsx::astronomy::ObservationTarget::printTarget() {
	std::cout <<"  "<< this->name << std::endl;
	std::cout << "  " << "RA:" << this->RA_hour << " h " << this->RA_min << " min " << this->RA_second << " sec " << "(" << this->RA_angle << "°)" << std::endl;
	std::cout << "  " << "DEC:" << this->RA_hour << " ° " << this->RA_min << " ′ " << this->RA_second << " ″ " << "(" << this->DEC_angle << "°)" << std::endl;
}

bool lsx::astronomy::ObservationTarget::isName(std::string& inputName_or_Number) {
	if (inputName_or_Number == this->name || inputName_or_Number == this->number) {
		return true;
	}
	else { 
		return false; 
	}
}

lsx::astronomy::ObservationTarget::ObservationTarget(std::string number, std::string name, std::string showName, \
	double RA_hour, double RA_min, double RA_second, double DEC_degree, double DEC_min, double DEC_second, \
	bool is_star, bool origin_show) {
	this->inputTarget(number, name, showName, RA_hour, RA_min, RA_second, DEC_degree, DEC_min, DEC_second, is_star, origin_show);
	this->error = false;
}

lsx::astronomy::ObservationTarget::ObservationTarget() {
	this->error = true;
}

void lsx::astronomy::ObservationTable::input_new_target(std::string number, std::string name, std::string showName, \
	double RA_hour, double RA_min, double RA_second, double DEC_degree, double DEC_min, double DEC_second, \
	bool is_star) {
	this->TargetTable.push_back(lsx::astronomy::ObservationTarget::ObservationTarget(number, name, showName, RA_hour, RA_min, RA_second, DEC_degree, DEC_min, DEC_second, is_star));
}

lsx::astronomy::ObservationTable::ObservationTable() {
	this->_TargetTableImage = cv::Mat(cv::Size(goto_image_width, goto_image_height), CV_8UC3, background);
	cv::Point2d left_mid, right_mid, mid_up, mid_down, ra_gap1, ra_gap2, dec_gap1, dec_gap2;
	std::string coordinate_font_[4] = { "RA(0 h)","RA(24 h)","Dec(90 deg)", "Dec(-90 deg)" };
	cv::Size font_size[4];
	double dec_length = 0, ra_length = 0, font_scale = 0.4;
	double this_dec_degree = 0, down_threhold = 0, up_threhold = 0;
	int image_down_threhold = 0, image_up_threhold = 0, coordinate_font_thickness = 1,
		font_type = cv::FONT_HERSHEY_SIMPLEX, baseLine = 0, gap = 2;
	for (int i = 0; i < 4; i++) {
		font_size[i] = cv::getTextSize(coordinate_font_[i], font_type, font_scale, coordinate_font_thickness, &baseLine);
	}
	this->input_data();
	dec_length = double(_TargetTableImage.rows) / 180.0;
	ra_length = double(_TargetTableImage.cols) / 360.0;
	left_mid = cv::Point2d(0, _TargetTableImage.rows / 2); right_mid = cv::Point2d(_TargetTableImage.cols, _TargetTableImage.rows / 2);
	mid_up = cv::Point2d(_TargetTableImage.cols / 2, 0); mid_down = cv::Point2d(_TargetTableImage.cols / 2, _TargetTableImage.rows);
	for (int i = 1; i < 18; i++) {
		ra_gap1.x = i * double(goto_image_width) / 18.0; ra_gap1.y = 0;
		ra_gap2.x = ra_gap1.x; ra_gap2.y = _TargetTableImage.rows;
		cv::line(_TargetTableImage, ra_gap1, ra_gap2, background_line, 1);
	}
	for (int i = 1; i < 9; i++) {
		dec_gap1.x = 0; dec_gap1.y = i * double(goto_image_height) / 9.0;
		dec_gap2.x = _TargetTableImage.cols; dec_gap2.y = dec_gap1.y;
		cv::line(_TargetTableImage, dec_gap1, dec_gap2, background_line, 1);
	}
	left_mid.x += 2; left_mid.y -= double(goto_image_height) / 160.0; right_mid.y -= double(goto_image_height) / 160.0; right_mid.x -= double(goto_image_height) * 3.0 / 20.0;
	mid_up.x += double(goto_image_height) / 160.0; mid_down.x += double(goto_image_height) / 400.0; mid_up.y += double(goto_image_height) / 70.0; mid_down.y -= double(goto_image_height) / 60.0;
	cv::putText(this->_TargetTableImage, coordinate_font_[0], cv::Point(gap, 0.5 * this->_TargetTableImage.rows - gap),
		font_type, font_scale, big_word, coordinate_font_thickness, cv::LINE_AA);
	cv::putText(this->_TargetTableImage, coordinate_font_[1], cv::Point(this->_TargetTableImage.cols - 2.0 * font_size[1].width - gap, 0.5 * this->_TargetTableImage.rows - gap),
		font_type, font_scale, big_word, coordinate_font_thickness, cv::LINE_AA);
	cv::putText(this->_TargetTableImage, coordinate_font_[2], cv::Point(0.5 * this->_TargetTableImage.cols + gap, gap + font_size[2].height),
		font_type, font_scale, big_word, coordinate_font_thickness, cv::LINE_AA);
	cv::putText(this->_TargetTableImage, coordinate_font_[3], cv::Point(0.5 * double(this->_TargetTableImage.cols) + gap, double(this->_TargetTableImage.rows) - double(gap) - 0.5 * font_size[3].height),
		font_type, font_scale, big_word, coordinate_font_thickness, cv::LINE_AA);
	for (int i = 0; i < this->TargetTable.size(); i++) {
		this->TargetTable[i].position_in_image_x = this->TargetTable[i].RA_angle * ra_length;
		this->TargetTable[i].position_in_image_y = double(this->_TargetTableImage.rows) - (this->TargetTable[i].DEC_angle + 90.0) * dec_length;
		if (this->TargetTable[i].isStar) {
			lsx::starProcessing::DrawStar(this->_TargetTableImage, this->TargetTable[i].position_in_image_x, \
				this->TargetTable[i].position_in_image_y, star_color, 10);
			if (this->TargetTable[i].origin_show) {
				cv::putText(this->_TargetTableImage, this->TargetTable[i].ShowName, cv::Point(this->TargetTable[i].position_in_image_x + 15.0, this->TargetTable[i].position_in_image_y + 4.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.4, star_color, 1, cv::LINE_AA);
			}
		}
		else {
			cv::circle(this->_TargetTableImage, cv::Point(this->TargetTable[i].position_in_image_x, this->TargetTable[i].position_in_image_y), \
				4, not_star_color, -1, cv::LINE_AA);
			if (this->TargetTable[i].origin_show) {
				cv::putText(this->_TargetTableImage, this->TargetTable[i].ShowName, cv::Point(this->TargetTable[i].position_in_image_x + 8.0, this->TargetTable[i].position_in_image_y + 4.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.4, not_star_color, 1, cv::LINE_AA);
			}
		}
	}
}

//cv::Mat lsx::astronomy::ObservationTable::getTargetTableImage(int width, int height) {
//	cv::Mat targetTableImage = cv::Mat(cv::Size(width, height), CV_8UC3, background);
//	cv::Point2d left_mid, right_mid, mid_up, mid_down, zenith_up, zenith_down, ra_gap1, ra_gap2, dec_gap1, dec_gap2;
//	double dec_length = 0, ra_length = 0;
//	double this_dec_degree = 0, down_threhold = 0, up_threhold = 0;
//	int image_down_threhold = 0, image_up_threhold = 0;
//	dec_length = double(targetTableImage.rows) / 180.0;
//	ra_length = double(targetTableImage.cols) / 360.0;
//	left_mid = cv::Point2d(0, targetTableImage.rows / 2); right_mid = cv::Point2d(targetTableImage.cols, targetTableImage.rows / 2);
//	mid_up = cv::Point2d(targetTableImage.cols / 2, 0); mid_down = cv::Point2d(targetTableImage.cols / 2, targetTableImage.rows);
//	zenith_up.x = local_sidreal_time_degree() * ra_length;
//	zenith_down.x = zenith_up.x;
//	zenith_up.y = 0;
//	zenith_down.y = targetTableImage.rows;
//	for (int i = 1; i < 18; i++) {
//		ra_gap1.x = i * double(width) / 18.0; ra_gap1.y = 0;
//		ra_gap2.x = ra_gap1.x; ra_gap2.y = targetTableImage.rows;
//		cv::line(targetTableImage, ra_gap1, ra_gap2, background_line, 1);
//	}
//	for (int i = 1; i < 9; i++) {
//		dec_gap1.x = 0; dec_gap1.y = i * double(height) / 9.0;
//		dec_gap2.x = targetTableImage.cols; dec_gap2.y = dec_gap1.y;
//		cv::line(targetTableImage, dec_gap1, dec_gap2, background_line, 1);
//	}
//	cv::line(targetTableImage, zenith_up, zenith_down, cv::Scalar(zenith_line_color[0], zenith_line_color[1], zenith_line_color[2]), 1);
//	left_mid.x += 2; left_mid.y -= double(height) / 160.0; right_mid.y -= double(height) / 160.0; right_mid.x -= double(height) * 3.0 / 20.0;
//	mid_up.x += double(height) / 160.0; mid_down.x += double(height) / 400.0; mid_up.y += double(height) / 70.0; mid_down.y -= double(height) / 60.0;
//	zenith_down.x += double(height) / 400.0;zenith_down.y -= double(height) / 20.0;
//	cv::putText(targetTableImage, "RA 0h", left_mid, cv::FONT_HERSHEY_SIMPLEX, 0.4, big_word, 1, cv::LINE_AA);
//	cv::putText(targetTableImage, "RA 24h", right_mid, cv::FONT_HERSHEY_SIMPLEX, 0.4, big_word, 1, cv::LINE_AA);
//	cv::putText(targetTableImage, "DEC -90", mid_down, cv::FONT_HERSHEY_SIMPLEX, 0.4, big_word, 1, cv::LINE_AA);
//	cv::putText(targetTableImage, "DEC 90", mid_up, cv::FONT_HERSHEY_SIMPLEX, 0.4, big_word, 1, cv::LINE_AA);
//	cv::putText(targetTableImage, "Zenith", zenith_down, cv::FONT_HERSHEY_SIMPLEX, 0.4, big_word, 1, cv::LINE_AA);
//	for (int i = 0; i < this->TargetTable.size(); i++) {
//		this->TargetTable[i].position_in_image_x = this->TargetTable[i].RA_angle * ra_length;
//		this->TargetTable[i].position_in_image_y = double(targetTableImage.rows) - (this->TargetTable[i].DEC_angle + 90.0) * dec_length;
//		if (this->TargetTable[i].isStar) {
//			lsx::starProcessing::DrawStar(targetTableImage, this->TargetTable[i].position_in_image_x, \
//				this->TargetTable[i].position_in_image_y, star_color, 10);
//			cv::putText(targetTableImage, this->TargetTable[i].ShowName, cv::Point(this->TargetTable[i].position_in_image_x + 15.0, this->TargetTable[i].position_in_image_y + 4.0), \
//				cv::FONT_HERSHEY_SIMPLEX, 0.4, star_color, 1, cv::LINE_AA);
//		}
//		else {
//			cv::circle(targetTableImage, cv::Point(this->TargetTable[i].position_in_image_x, this->TargetTable[i].position_in_image_y), \
//				4, not_star_color, -1, cv::LINE_AA);
//			cv::putText(targetTableImage, this->TargetTable[i].ShowName, cv::Point(this->TargetTable[i].position_in_image_x + 8.0, this->TargetTable[i].position_in_image_y + 4.0), \
//				cv::FONT_HERSHEY_SIMPLEX, 0.4, not_star_color, 1, cv::LINE_AA);
//		}
//	}
//	for (int i = 0; i < targetTableImage.rows; i++) {
//		this_dec_degree = 90.0 - i / dec_length;
//		lsx::astronomy::theta_on_horizon_degree(this_dec_degree, &down_threhold, &up_threhold);
//		if (this_dec_degree <= 90.0 - global_latitude && this_dec_degree >= -(90.0 - global_latitude)) {
//			image_down_threhold = down_threhold * ra_length;
//			image_up_threhold = up_threhold * ra_length;
//			cv::Vec3b* pixelPtr = targetTableImage.ptr<cv::Vec3b>(i);
//			pixelPtr[image_down_threhold][0] = zenith_line_color[0];
//			pixelPtr[image_down_threhold][1] = zenith_line_color[1];
//			pixelPtr[image_down_threhold][2] = zenith_line_color[2];
//			pixelPtr[image_up_threhold] = pixelPtr[image_down_threhold];
//		}
//		
//	}
//	this->_TargetTableImage = targetTableImage;
//	return targetTableImage;
//}

cv::Mat lsx::astronomy::ObservationTable::getTargetTableImage() {
	cv::Mat targetTableImage;
	cv::Point2d zenith_up, zenith_down, ra_gap1;
	double dec_length = 0, ra_length = 0;
	double this_dec_degree = 0, down_threhold = 0, up_threhold = 0;
	int image_down_threhold = 0, image_up_threhold = 0;
	this->_TargetTableImage.copyTo(targetTableImage);
	dec_length = double(targetTableImage.rows) / 180.0;
	ra_length = double(targetTableImage.cols) / 360.0;
	zenith_up.x = local_sidreal_time_degree() * ra_length;
	zenith_down.x = zenith_up.x;
	zenith_up.y = 0;
	zenith_down.y = targetTableImage.rows;
	cv::line(targetTableImage, zenith_up, zenith_down, zenith_str_line, 1, cv::LINE_AA);
	zenith_down.x += double(goto_image_height) / 400.0; zenith_down.y -= double(goto_image_height) / 20.0;
	cv::putText(targetTableImage, "Zenith", zenith_down, cv::FONT_HERSHEY_SIMPLEX, 0.4, big_word, 1, cv::LINE_AA);
	for (int i = 0; i < targetTableImage.rows; i++) {
		this_dec_degree = 90.0 - i / dec_length;
		lsx::astronomy::theta_on_horizon_degree(this_dec_degree, &down_threhold, &up_threhold);
		if (this_dec_degree <= 90.0 - global_latitude && this_dec_degree >= -(90.0 - global_latitude)) {
			image_down_threhold = down_threhold * ra_length;
			image_up_threhold = up_threhold * ra_length;
			cv::Vec3b* pixelPtr = targetTableImage.ptr<cv::Vec3b>(i);
			pixelPtr[image_down_threhold][0] = zenith_line_color[0];
			pixelPtr[image_down_threhold][1] = zenith_line_color[1];
			pixelPtr[image_down_threhold][2] = zenith_line_color[2];
			pixelPtr[image_up_threhold] = pixelPtr[image_down_threhold];
		}
	}
	return targetTableImage;
}

void lsx::astronomy::ObservationTable::get_ra_dec(double& image_x, double& image_y, double* ra, double* dec) {
	double ra_length = double(this->_TargetTableImage.cols) / 360.0, dec_length = double(this->_TargetTableImage.rows) / 180.0;
	(*ra) = image_x / ra_length;
	(*dec) = 90.0 - image_y / dec_length;
}

void lsx::astronomy::ObservationTable::get_image_x_y(double& ra, double& dec, double* image_x, double* image_y) {
	double dec_length = 0, ra_length = 0;
	dec_length = double(this->_TargetTableImage.rows) / 180.0;
	ra_length = double(this->_TargetTableImage.cols) / 360.0;
	(*image_x) = ra * ra_length;
	(*image_y) = double(this->_TargetTableImage.rows) - (dec + 90.0) * dec_length;
}

lsx::astronomy::ObservationTarget lsx::astronomy::ObservationTable::findCloseTarget(double& image_x, double& image_y, double& radius, bool* have_choose) {
	int i = 0, min_length = 2000000, this_length = 0, close_i = 0;
	for (i = 0; i < this->TargetTable.size(); i++) {
		this_length = lsx::math::PointLength(image_x, image_y, this->TargetTable[i].position_in_image_x, this->TargetTable[i].position_in_image_y);
		if (this_length < min_length) {
			close_i = i;
			min_length = this_length;
		}
	}
	if (min_length < radius) {
		(*have_choose) = true;
		return this->TargetTable[close_i];
	}
	else {
		(*have_choose) = false;
		return lsx::astronomy::ObservationTarget::ObservationTarget();
	}
}

bool lsx::astronomy::ObservationTable::tatgetInTable(std::string& name_or_number) {
	for (int i = 0; i < this->TargetTable.size(); i++) {
		if (this->TargetTable[i].isName(name_or_number)) {
			return true;
		}
	}
	return false;
}

lsx::astronomy::ObservationTarget lsx::astronomy::ObservationTable::getTarget(std::string& name_or_number) {
	for (int i = 0; i < this->TargetTable.size(); i++) {
		if (this->TargetTable[i].isName(name_or_number)) {
			return this->TargetTable[i];
		}
	}
}

lsx::astronomy::ObservationTarget lsx::astronomy::ObservationTable::findTarget(std::string& name_or_number) {
	if (this->tatgetInTable(name_or_number)) {
		return this->getTarget(name_or_number);
	}
	else {
		return lsx::astronomy::ObservationTarget();
	}
}

bool lsx::astronomy::TargetUnderHorizon(lsx::astronomy::ObservationTarget& inputOberveTarget) {
	double gama = acos(tan(inputOberveTarget.DEC_angle / 180.0 * PI) * tan(global_latitude / 180.0 * PI));
	lsx::astronomy::ObservationTarget zenithTarget;
	double theta = 0;
	zenithTarget = lsx::astronomy::GetZenith();
	if (inputOberveTarget.DEC_angle > 90.0 - global_latitude) {
		return false;
	}
	if (inputOberveTarget.DEC_angle > 0.0 && inputOberveTarget.DEC_angle < 90.0 - global_latitude) {
		theta = 360.0 - 2.0 * gama;
	}
	else if (inputOberveTarget.DEC_angle < 0.0 && inputOberveTarget.DEC_angle > -(90.0 - global_latitude)) {
		theta = 2.0 * gama;
	}
	else {
		return true;
	}
	if (lsx::astronomy::getMinAngle(inputOberveTarget, zenithTarget) < 0.5 * theta) {
		return false;
	}
	return true;
}

Eigen::MatrixXd lsx::astronomy::StarPointVector(double& ra_degree, double& dec_degree, double& zenith_degree) {
	return lsx::math::StarPointVector3(ra_degree / 180.0 * PI, dec_degree / 180.0 * PI, zenith_degree / 180.0 * PI);
}

void lsx::astronomy::Equ2EleAzi(lsx::astronomy::ObservationTarget* inputTarget) {
	Eigen::MatrixXd star_vector(3, 1), z_axis(3, 1), _x_axis(2, 1), star_vector_floor(2, 1);
	double azimuth = 0;
	z_axis << 0, 0, 1;
	_x_axis << -1, 0;
	star_vector = lsx::math::StarPointVector3(inputTarget->RA_angle / 180.0 * PI,
		inputTarget->DEC_angle / 180.0 * PI,
		local_sidreal_time_degree() / 180.0 * PI);
	inputTarget->elevation = (0.5 * PI - lsx::math::VectorAngle_rad(star_vector, z_axis)) /
		PI * 180.0 ;
	star_vector_floor << star_vector(0, 0), star_vector(1, 0);
	azimuth = lsx::math::VectorAngle_rad(star_vector_floor, _x_axis) / PI * 180.0;
	if (star_vector(1, 0) > 0) {
		inputTarget->azimuth = azimuth;
	}
	else {
		inputTarget->azimuth = 360.0 - azimuth;//加减360°是等效的
	}
}

double lsx::astronomy::earthRotateAngle(double inputTime_ms) {
	return 360.0 * inputTime_ms / (86164.0 * 1000.0);
}

int lsx::astronomy::earthRotateTime(double inputAngle_degree) {
	return int(inputAngle_degree * 1000.0 * 86164.0 / 360.0);
}

double lsx::astronomy::ra2degree(double hour, double min, double sec) {
	return 15.0 * hour + 0.25 * min + sec / 240.0;
}

double lsx::astronomy::dec2degree(double degree, double min, double sec) {
	return degree + min / 60.0 + sec / 3600.0;
}

void lsx::astronomy::degree2ra(double inputAngle_degree, double* ra_hour, double* ra_min, double* ra_sec) {
	double stay_angle = 0;
	inputAngle_degree = lsx::astronomy::angle_in_0_360(inputAngle_degree);
	stay_angle = inputAngle_degree / 15.0;
	(*ra_hour) = int(stay_angle);
	inputAngle_degree -= int(stay_angle) * 15.0;
	stay_angle = inputAngle_degree / 0.25;
	(*ra_min) = int(stay_angle);
	inputAngle_degree -= int(stay_angle) * 0.25;
	stay_angle = inputAngle_degree / (0.25 / 60);
	(*ra_sec) = stay_angle;
}

void lsx::astronomy::degree_2_deg_min_sec(double input_angle_degree, double* deg, double* min, double* sec) {
	double _deg = 0, _min = 0, _sec = 0, angle = fabs(input_angle_degree);
	_deg = floor(angle);
	angle = (angle - _deg) * 60.0;
	_min = floor(angle);
	angle = (angle - _min) * 60.0;
	_sec = angle;
	if (input_angle_degree < 0) {
		_deg *= -1; _min *= -1; _sec *= -1;
	}
	*deg = _deg; *min = _min; *sec = _sec;
}

double lsx::astronomy::angle_in_0_360(double inputAngle_degree) {
	if (inputAngle_degree < 0) {
		while (inputAngle_degree < 0) {
			inputAngle_degree += 360.0;
		}
	}
	else if (inputAngle_degree > 360.0) {
		while (inputAngle_degree > 360.0) {
			inputAngle_degree -= 360.0;
		}
	}
	return inputAngle_degree;
}

AutoStarSearch.h

#ifndef AUTOSTARSEARCH_H
#define AUTOSTARSEARCH_H

#include"Global.h"
#include"Astronomy.h"
#include"EquatorialControl.h"

namespace lsx {
	namespace autoSearch {

		class AutoStarFindController {
		public:

			/**
			 * @brief 自动寻星系统函数
			 */
			void AutomaticStarFinding();

			/**
			 * @brief 预先设置自动寻星控制器,将初始位置调整为当前指向
			 * @param targetName 当前赤道仪指向天体名称
			 * @param targetNumber 当前赤道仪指向天体编号
			 * @param decSide Dec转轴半盘位置,可选:DEC_IS_ON_THE_LEFT;DEC_IS_ON_THE_RIGHT
			 * @param afterGuide 导星结束标志位
			 * @return void
			 */
			void preSet(std::string targetName = "empty target", std::string targetNumber = "empty target", int decSide = DEC_IS_ON_THE_RIGHT);
			
		private:
			lsx::astronomy::ObservationTable targetTable;
			lsx::astronomy::ObservationTarget start, end;
			bool zero2star = false;//是否是从0位置开始的
			bool ra_arrival = false, dec_arrival = false;
			lsx::astronomy::ObservationTarget pointTarget;
			bool this_target_is_star = false;

			/**
			 * @brief 自动寻星系统主函数
			 */
			void gotoControl();

			///**
			// * @brief 判断天体是否在地平线之上
			// */
			//bool onHorizon(lsx::astronomy::ObservationTarget inputTarget);

			/**
			 * @brief 两天体之间的最小赤经角距离
			 */
			double ra_minAngle(lsx::astronomy::ObservationTarget target1, lsx::astronomy::ObservationTarget target2);

			/**
			 * @brief RA通过中天
			 */
			bool passZenith(lsx::astronomy::ObservationTarget inputTarget);

			/**
			 * @brief 将赤经转换在0-360之间
			 */
			double ra_in_region_0_360(double input_ra);

			///**
			// * @brief 显示延时倒计时
			// */
			//void showRunTime(double RA_inputTime_ms, double DEC_inputTime_ms, lsx::astronomy::ObservationTarget start, lsx::astronomy::ObservationTarget end);

			/**
			 * @brief 得到移动的赤道仪位置坐标
			 */
			void get_image_position(double start_x, double start_y, double end_x, double end_y, double x_runtime, double y_runtime, \
				std::clock_t start_time, std::clock_t end_time, \
				cv::Point* now);
		};

	}
}

#endif

AutoStarSearch.cpp

#include"AutoStarSearch.h"

extern bool noTarget;//是否是第一次使用自动寻星
extern bool after_guide;//是否是在导星之后进入自动寻星
extern int DEC_side;//DEC运行半圆所在的方位
extern std::string this_target_name;//当前目标名称
extern std::string this_target_number;//当前观测目标编号(如M42等)

extern cv::Scalar coordinate_words;//鼠标触摸到天体后显示坐标的颜色
extern cv::Scalar show_state_1_color;//Select a star with the mouse to calibrate the '0' position.提示符颜色
extern cv::Scalar my_equatorial_instrument_color;//赤道仪图像显示的颜色
extern cv::Scalar my_equatorial_instrument_line_color;//赤道仪移动线颜色
extern cv::Scalar optional_target_color;//可选天体的图像显示颜色

extern int goto_image_width, goto_image_height;//自动寻星的图像大小

double mouse_botton_x = -1, mouse_botton_y = -1, mouse_touch_x = -1, mouse_touch_y = -1;
bool mouse_get_coondinate = false;
bool goto_origin_position = false;
bool deal_mouse_event = true;

void autoStarSearch_mouse_callback(int event_, int x, int y, int flags, void* userData) {
	if (deal_mouse_event) {
		if (event_ == cv::EVENT_LBUTTONDOWN) {
			mouse_botton_x = x;
			mouse_botton_y = y;
			mouse_get_coondinate = true;
			/*	std::cout << mouse_botton_x << " " << mouse_botton_y << std::endl;*/
		}
		else if (event_ == cv::EVENT_RBUTTONDOWN) {
			mouse_botton_x = x;
			mouse_botton_y = y;
			mouse_get_coondinate = true;
			goto_origin_position = true;
		}
	}
	if (event_ == cv::EVENT_MOUSEMOVE) {
		mouse_touch_x = x;
		mouse_touch_y = y;
	}
}

//bool lsx::autoSearch::AutoStarFindController::onHorizon(lsx::astronomy::ObservationTarget inputTarget) {
//	lsx::astronomy::ObservationTarget thisTarget = inputTarget;
//	lsx::astronomy::Equ2EleAzi(&thisTarget);
//	if (thisTarget.elevation > 0) {
//		return true;
//	}
//	else {
//		return false;
//	}
//}

double lsx::autoSearch::AutoStarFindController::ra_minAngle(lsx::astronomy::ObservationTarget target1, lsx::astronomy::ObservationTarget target2) {
	return lsx::math::Min(fabs(target1.RA_angle - target2.RA_angle), 360.0 - fabs(target1.RA_angle - target2.RA_angle));
}

bool lsx::autoSearch::AutoStarFindController::passZenith(lsx::astronomy::ObservationTarget inputTarget) {
	Eigen::MatrixXd zenith_vector(3, 1), target_vector(3, 1), z_axis(3, 1);
	zenith_vector << 0, -1, 0;
	z_axis << 0, 0, 1;
	target_vector = lsx::math::RotationMatrix3(z_axis, (inputTarget.RA_angle - local_sidreal_time_degree()) / 180.0 * PI) * zenith_vector;
	if (target_vector(0, 0) > 0) {
		return false;
	}
	else {
		return true;
	}
}

double lsx::autoSearch::AutoStarFindController::ra_in_region_0_360(double input_ra) {
	return lsx::astronomy::RA_inRegion_0_360(input_ra);
}

//void lsx::autoSearch::AutoStarFindController::showRunTime(double RA_inputTime_ms, double DEC_inputTime_ms, lsx::astronomy::ObservationTarget start, lsx::astronomy::ObservationTarget end) {
//	int RA_runtime_sec = RA_inputTime_ms / 1000.0 + 1, DEC_runtime_sec = DEC_inputTime_ms / 1000.0 + 1;
//	int max_runtime = lsx::math::Max(RA_runtime_sec, DEC_runtime_sec);
//	std::cout << std::endl;
//	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
//	std::cout << " 起点:" << start.name << "(RA:" << start.RA_hour << " h " << start.RA_min << " min " << start.RA_second << " s , DEC:" \
//		<< start.DEC_degree << "°" << fabs(start.DEC_min) << " min " << fabs(start.DEC_second) << " sec)" << std::endl;
//	std::cout << std::endl;
//	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
//	std::cout << " 终点:" << end.name << "(RA:" << end.RA_hour << " h " << end.RA_min << " min " << end.RA_second << " s , DEC:" \
//		<< end.DEC_degree << "°" << fabs(end.DEC_min) << " min " << fabs(end.DEC_second) << " sec)" << std::endl;
//	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
//	std::cout << std::endl;
//	std::cout << " 赤道仪运行中. . ." << std::endl;
//	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
//	std::cout << std::endl;
//	for (int i = 0; i < max_runtime; i++) {
//		printf_s("\r");
//		if (RA_runtime_sec - i > 0 && DEC_runtime_sec - i > 0)
//			std::cout << " RA剩余时间:" << RA_runtime_sec - i << "秒 | DEC剩余时间:" << DEC_runtime_sec - i << "秒      ";
//		else if (RA_runtime_sec - i <= 0 && DEC_runtime_sec - i > 0)
//			std::cout << " RA运行结束!" << " | DEC剩余时间:" << DEC_runtime_sec - i << "秒              ";
//		else if (RA_runtime_sec - i > 0 && DEC_runtime_sec - i <= 0)
//			std::cout << " RA剩余时间:" << RA_runtime_sec - i << "秒 | DEC运行结束!                 ";
//		else
//			std::cout << "赤道仪到达目标位置!                                                       ";
//		Sleep(1000);
//	}
//	system("cls");
//}

/**
 * @brief 得到赤道仪的图像位置,时间单位都是毫秒
 */
void lsx::autoSearch::AutoStarFindController::get_image_position(double start_x, double start_y, double end_x, double end_y, double x_runtime, double y_runtime, \
	std::clock_t start_time, std::clock_t end_time, \
	cv::Point* now) {
	double k_y = (end_y - start_y) / y_runtime, k_x = (end_x - start_x) / x_runtime;
	double d_time = double(end_time) - double(start_time);
	now->x = k_x * d_time + start_x;
	now->y = k_y * d_time + start_y;
	if (start_x > end_x && start_y > end_y) {
		if (now->x <= end_x) {
			now->x = end_x;
		}
		if (now->y <= end_y) {
			now->y = end_y;
		}
	}
	else if (start_x <= end_x && start_y > end_y) {
		if (now->x >= end_x) {
			now->x = end_x;
		}
		if (now->y <= end_y) {
			now->y = end_y;
		}
	}
	else if (start_x > end_x && start_y <= end_y) {
		if (now->x <= end_x) {
			now->x = end_x;
		}
		if (now->y >= end_y) {
			now->y = end_y;
		}
	}
	else if (start_x <= end_x && start_y <= end_y) {
		if (now->x >= end_x) {
			now->x = end_x;
		}
		if (now->y >= end_y) {
			now->y = end_y;
		}
	}
}

void lsx::autoSearch::AutoStarFindController::gotoControl() {
	int dec_direction = 0, ra_direction = 0;
	double find_radius = 20; double ra_runtime_ms = 0, dec_runtime_ms = 0; 
	double ra_angle = 0, dec_angle = 0, dec_angle_part = 0;
	bool show_warning = false; bool arrive_the_target = false; bool choose_target = false; bool touch_target = false;
	bool get_end_target = false; bool back_origin_position = false;
	char choose_choose = 'n';
	std::string inputTargetName;
	cv::Mat star_image; cv::Point now_position;
	std::clock_t start_time, end_time;
	lsx::astronomy::ObservationTarget mouse_touch_target;//鼠标触摸到的目标
	double now_run_time = 0; double start_x = 0, start_y = 0, end_x = 0, end_y = 0; 
	double width = goto_image_width, heigth = goto_image_height;
	std::string win_name = "Shixuan Liu - Auto Star Search", _EQ = "my EQ";
	std::string show_target_name = " Name: ";
	char show_ra[50] = { 0 }, show_dec[50] = { 0 }, show_my_equ[90] = { 0 }, show_ele[50] = { 0 }, show_azi[50] = { 0 };
	double elevation_2_deg_min_sec[3] = { 0 }, azimuth_2_deg_min_sec[3] = { 0 };
	cv::namedWindow(win_name, cv::WINDOW_AUTOSIZE);
	//cv::setWindowProperty(win_name, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
	cv::setMouseCallback(win_name, autoStarSearch_mouse_callback);
	mouse_get_coondinate = false;
	goto_origin_position = false;
	deal_mouse_event = true;
	star_image = this->targetTable.getTargetTableImage();
	/*----------------------------------------------------目标天体输入---------------------------------------------------------*/
	if (noTarget) {
		this->zero2star = true;
	}
	/*----------------------------------------------------当前天体输入------------------------------------------------------------*/
	if (noTarget && !after_guide) {//从零位开始,没有经过导星
		this->start.RA_angle = this->ra_in_region_0_360(local_sidreal_time_degree() + 90.0);
		this->start.DEC_angle = 90.0;
		this->start.DEC_degree = 90.0;
		this->start.name = "零位";
		this->start.number = "0";
		this->start.ShowName = "E0";
		lsx::astronomy::degree2ra(this->start.RA_angle, &this->start.RA_hour, &this->start.RA_min, &this->start.RA_second);
	}
	else if (noTarget && after_guide) {//从零位模式开始,经过导星
		if (this->targetTable.tatgetInTable(this_target_name)) {
			this->start = this->targetTable.findTarget(this_target_name);
		}
		else {
			this->start = this->targetTable.findTarget(this_target_number);
		}
	}
	else {
		if (!(this_target_name == "零位" || this_target_number == "0")) {
			if (this->targetTable.tatgetInTable(this_target_name)) {
				this->start = this->targetTable.findTarget(this_target_name);
			}
			else {
				this->start = this->targetTable.findTarget(this_target_number);
			}
		}
		else {
			this->start.RA_angle = this->ra_in_region_0_360(local_sidreal_time_degree() + 90.0);
			this->start.DEC_angle = 90.0;
			this->start.DEC_degree = 90.0;
			this->start.name = "零位";
			this->start.number = "0";
			lsx::astronomy::degree2ra(this->start.RA_angle, &this->start.RA_hour, &this->start.RA_min, &this->start.RA_second);
		}
	}
	/*---------------------------------------------------------目标天体输入---------------------------------------------------*/
	get_end_target = false;
	while (!get_end_target) {
		/*-------------对生成图像进行初始化的代码段-------------------*/
		star_image = this->targetTable.getTargetTableImage();
		if (this->zero2star) {
			cv::putText(star_image, "Select a star with the mouse to calibrate the '0' position.", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
				cv::FONT_HERSHEY_SIMPLEX, 0.6, show_state_1_color, 1, cv::LINE_AA);
		}
		else {
			cv::putText(star_image, "Select a observed object with the mouse.", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
				cv::FONT_HERSHEY_SIMPLEX, 0.6, show_state_1_color, 1, cv::LINE_AA);
		}
		this->targetTable.get_image_x_y(this->start.RA_angle, this->start.DEC_angle, &this->start.position_in_image_x, &this->start.position_in_image_y);
		lsx::starProcessing::DrawRegularTriangle(star_image, this->start.position_in_image_x, this->start.position_in_image_y, my_equatorial_instrument_color, double(heigth) / 100.0);
		cv::circle(star_image, cv::Point(this->start.position_in_image_x, this->start.position_in_image_y), double(heigth) / 80.0, my_equatorial_instrument_color, 1, cv::LINE_AA);
		cv::putText(star_image, _EQ, cv::Point(this->start.position_in_image_x + double(heigth) / 60.0, this->start.position_in_image_y - double(heigth) / 60.0), \
			cv::FONT_HERSHEY_SIMPLEX, 0.4, my_equatorial_instrument_color, 1, cv::LINE_AA);
		/*---------------------*/
		if (mouse_touch_target.position_in_image_x > 0 && mouse_touch_target.position_in_image_y > 0) {//鼠标触摸显示
			lsx::astronomy::Equ2EleAzi(&mouse_touch_target);
			lsx::astronomy::degree_2_deg_min_sec(mouse_touch_target.elevation, &elevation_2_deg_min_sec[0], &elevation_2_deg_min_sec[1], &elevation_2_deg_min_sec[2]);
			lsx::astronomy::degree_2_deg_min_sec(mouse_touch_target.azimuth, &azimuth_2_deg_min_sec[0], &azimuth_2_deg_min_sec[1], &azimuth_2_deg_min_sec[2]);
			sprintf_s(show_ra, " RA: %d hour %d min %d sec", int(mouse_touch_target.RA_hour), int(mouse_touch_target.RA_min), int(mouse_touch_target.RA_second));
			sprintf_s(show_dec, " Dec: %d d %d m %d s", int(mouse_touch_target.DEC_degree), int(fabs(mouse_touch_target.DEC_min)), int(fabs(mouse_touch_target.DEC_second)));
			sprintf_s(show_ele, " Ele: %d d %d m %d.%d s", int(elevation_2_deg_min_sec[0]), abs(int(elevation_2_deg_min_sec[1])), abs(int(elevation_2_deg_min_sec[2])), int(100.0 * (elevation_2_deg_min_sec[2] - floor(elevation_2_deg_min_sec[2]))));
			sprintf_s(show_azi, " Azi: %d d %d m %d.%d s", int(azimuth_2_deg_min_sec[0]), int(azimuth_2_deg_min_sec[1]), int(azimuth_2_deg_min_sec[2]), int(100.0 * (azimuth_2_deg_min_sec[2] - floor(azimuth_2_deg_min_sec[2]))));

			if (mouse_touch_target.elevation < 0 || (noTarget && !mouse_touch_target.isStar)) {
				if (mouse_touch_target.elevation < 0) {
					cv::putText(star_image, "this target is below the horizon!", cv::Point(mouse_touch_target.position_in_image_x - double(heigth) / 20.0, mouse_touch_target.position_in_image_y - double(heigth) / 25.0), \
						cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
					cv::circle(star_image, cv::Point(mouse_touch_target.position_in_image_x, mouse_touch_target.position_in_image_y), double(heigth) / 50.0, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
				}
				else if (noTarget && !mouse_touch_target.isStar) {
					cv::putText(star_image, "please select a star!", cv::Point(mouse_touch_target.position_in_image_x - double(heigth) / 20.0, mouse_touch_target.position_in_image_y - double(heigth) / 25.0), \
						cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
					cv::circle(star_image, cv::Point(mouse_touch_target.position_in_image_x, mouse_touch_target.position_in_image_y), double(heigth) / 50.0, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
				}
			}
			else {
				cv::putText(star_image, "choosable star", cv::Point(mouse_touch_target.position_in_image_x - double(heigth) / 20.0, mouse_touch_target.position_in_image_y - double(heigth) / 25.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.5, optional_target_color, 1, cv::LINE_AA);
				cv::circle(star_image, cv::Point(mouse_touch_target.position_in_image_x, mouse_touch_target.position_in_image_y), double(heigth) / 50.0, optional_target_color, 1, cv::LINE_AA);
			}
			if (!mouse_touch_target.isStar) {
				cv::putText(star_image, show_target_name + mouse_touch_target.name, cv::Point(mouse_touch_target.position_in_image_x + double(heigth) / 50.0 + 3, mouse_touch_target.position_in_image_y + double(heigth) / 50.0 + 10), \
					cv::FONT_HERSHEY_SIMPLEX, 0.4, coordinate_words, 1, cv::LINE_AA);
			}
			else {
				cv::putText(star_image, show_target_name + mouse_touch_target.ShowName, cv::Point(mouse_touch_target.position_in_image_x + double(heigth) / 50.0 + 3, mouse_touch_target.position_in_image_y + double(heigth) / 50.0 + 10), \
					cv::FONT_HERSHEY_SIMPLEX, 0.4, coordinate_words, 1, cv::LINE_AA);
			}
			cv::putText(star_image, show_ra, cv::Point(mouse_touch_target.position_in_image_x + double(heigth) / 50.0 + 3, mouse_touch_target.position_in_image_y + 20 + double(heigth) / 50.0 + 10), \
				cv::FONT_HERSHEY_SIMPLEX, 0.4, coordinate_words, 1, cv::LINE_AA);
			cv::putText(star_image, show_dec, cv::Point(mouse_touch_target.position_in_image_x + double(heigth) / 50.0 + 3, mouse_touch_target.position_in_image_y + 40 + double(heigth) / 50.0 + 10), \
				cv::FONT_HERSHEY_SIMPLEX, 0.4, coordinate_words, 1, cv::LINE_AA);
			cv::putText(star_image, show_ele, cv::Point(mouse_touch_target.position_in_image_x + double(heigth) / 50.0 + 3, mouse_touch_target.position_in_image_y + 60 + double(heigth) / 50.0 + 10), \
				cv::FONT_HERSHEY_SIMPLEX, 0.4, coordinate_words, 1, cv::LINE_AA);
			cv::putText(star_image, show_azi, cv::Point(mouse_touch_target.position_in_image_x + double(heigth) / 50.0 + 3, mouse_touch_target.position_in_image_y + 80 + double(heigth) / 50.0 + 10), \
				cv::FONT_HERSHEY_SIMPLEX, 0.4, coordinate_words, 1, cv::LINE_AA);
		}
		/*-------------------------------------*/
		cv::imshow(win_name, star_image);
		cv::waitKey(50);
		if (mouse_get_coondinate) {//鼠标按下显示判断语句
			/*---------------对生成的图像进行初始化的代码段-----------------*/
			star_image = this->targetTable.getTargetTableImage();
			if (this->zero2star) {
				cv::putText(star_image, "Select a star with the mouse to calibrate the '0' position.", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.6, show_state_1_color, 1, cv::LINE_AA);
			}
			else {
				cv::putText(star_image, "Select a observed object with the mouse.", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.6, show_state_1_color, 1, cv::LINE_AA);
			}
			this->targetTable.get_image_x_y(this->start.RA_angle, this->start.DEC_angle, &this->start.position_in_image_x, &this->start.position_in_image_y);
			lsx::starProcessing::DrawRegularTriangle(star_image, this->start.position_in_image_x, this->start.position_in_image_y, my_equatorial_instrument_color, double(heigth) / 100.0);
			cv::circle(star_image, cv::Point(this->start.position_in_image_x, this->start.position_in_image_y), double(heigth) / 80.0, my_equatorial_instrument_color, 1, cv::LINE_AA);
			cv::putText(star_image, _EQ, cv::Point(this->start.position_in_image_x + double(heigth) / 60.0, this->start.position_in_image_y - double(heigth) / 60.0), \
				cv::FONT_HERSHEY_SIMPLEX, 0.4, my_equatorial_instrument_color, 1, cv::LINE_AA);
			/*---------------------*/
			deal_mouse_event = false;//没有处理,则回调函数不接受鼠标事件
			if (!goto_origin_position) {//按下左键
				choose_target = false;
				this->targetTable.findCloseTarget(mouse_botton_x, mouse_botton_y, find_radius, &choose_target);
				if (choose_target) {
					this->end = this->targetTable.findCloseTarget(mouse_botton_x, mouse_botton_y, find_radius, &choose_target);
					lsx::astronomy::Equ2EleAzi(&this->end);
					if (this->end.elevation < 0 || (noTarget && !this->end.isStar)) {
						if (this->end.elevation < 0) {
							cv::putText(star_image, "this target is below the horizon!", cv::Point(this->end.position_in_image_x - double(heigth) / 20.0, this->end.position_in_image_y - double(heigth) / 25.0), \
								cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
							cv::circle(star_image, cv::Point(this->end.position_in_image_x, this->end.position_in_image_y), double(heigth) / 50.0, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
						}
						else if (noTarget && !this->end.isStar) {
							cv::putText(star_image, "please select a star!", cv::Point(this->end.position_in_image_x - double(heigth) / 20.0, this->end.position_in_image_y - double(heigth) / 25.0), \
								cv::FONT_HERSHEY_SIMPLEX, 0.5, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
							cv::circle(star_image, cv::Point(this->end.position_in_image_x, this->end.position_in_image_y), double(heigth) / 50.0, cv::Scalar(0, 0, 255), 2, cv::LINE_AA);
						}
						mouse_get_coondinate = false;
						cv::imshow(win_name, star_image);
						cv::waitKey(60);
					}
					else {
						cv::putText(star_image, "selected successfully!", cv::Point(this->end.position_in_image_x - double(heigth) / 20.0, this->end.position_in_image_y - double(heigth) / 25.0), \
							cv::FONT_HERSHEY_SIMPLEX, 0.5, optional_target_color, 1, cv::LINE_AA);
						cv::circle(star_image, cv::Point(this->end.position_in_image_x, this->end.position_in_image_y), double(heigth) / 50.0, optional_target_color, 2, cv::LINE_AA);
						mouse_get_coondinate = false;
						cv::imshow(win_name, star_image);
						noTarget = false; after_guide = false;
						get_end_target = true;
						cv::waitKey(200);
					}
				}
				else {
					mouse_get_coondinate = false;
				}
			}
			else {//按下右键
				if (noTarget == false) {
					this->targetTable.get_ra_dec(mouse_botton_x, mouse_botton_y, &this->end.RA_angle, &this->end.DEC_angle);
					lsx::astronomy::Equ2EleAzi(&this->end);
					if (this->end.elevation < 0) {
						this->end.RA_angle = this->ra_in_region_0_360(local_sidreal_time_degree() + 90.0);
						this->end.DEC_angle = 90.0;
						this->end.DEC_degree = 90.0;
						this->end.name = "零位";
						this->end.number = "0";
						lsx::astronomy::degree2ra(this->end.RA_angle, &this->end.RA_hour, &this->end.RA_min, &this->end.RA_second);
						get_end_target = true;
						back_origin_position = true;
					}
					else {
						mouse_get_coondinate = false;
					}
				}
				else {
					mouse_get_coondinate = false;
					goto_origin_position = false;
				}
			}
			deal_mouse_event = true;
		}
		this->targetTable.findCloseTarget(mouse_touch_x, mouse_touch_y, find_radius, &touch_target);
		if (touch_target) {
			mouse_touch_target = this->targetTable.findCloseTarget(mouse_touch_x, mouse_touch_y, find_radius, &touch_target);
		}
		else {
			mouse_touch_target.position_in_image_x = -1;
			mouse_touch_target.position_in_image_y = -1;
		}
	}
	this_target_name = this->end.name;
	this_target_number = this->end.number;
	this->pointTarget = this->end;
	if (this->start.name != this->end.name) {
		/*----------------------------------------------------判断语句---------------------------------------------------------*/
		if (this->passZenith(this->start) && this->passZenith(this->end)) {//左左
			//std::cout << "LL" << std::endl;
			if (DEC_side == DEC_IS_ON_THE_RIGHT) {//异常情况处理
				DEC_side = DEC_IS_ON_THE_LEFT;
				ra_angle = 180.0 + this->ra_minAngle(lsx::astronomy::GetZenith(), this->start) - this->ra_minAngle(lsx::astronomy::GetZenith(), this->end);
				dec_angle = 180.0 - this->start.DEC_angle - this->end.DEC_angle;
				ra_direction = RA_DIR_BACKWARD;
				dec_angle = DEC_DIR_UP_WHEN_RIGHT;
			}
			else {
				ra_angle = this->ra_minAngle(lsx::astronomy::GetZenith(), this->start) - this->ra_minAngle(lsx::astronomy::GetZenith(), this->end);
				dec_angle = this->end.DEC_angle - this->start.DEC_angle;
				if (ra_angle > 0) {
					ra_direction = RA_DIR_BACKWARD;
				}
				else {
					ra_direction = RA_DIR_FORWARD;
				}
				if (dec_angle > 0) {
					dec_direction = DEC_DIR_UP_WHEN_LEFT;
				}
				else {
					dec_direction = DEC_DIR_DOWN_WHEN_LEFT;
				}
			}
		}
		else if (this->passZenith(this->start) && !this->passZenith(this->end)) {//左右
			//std::cout << "LR" << std::endl;
			if (DEC_side == DEC_IS_ON_THE_RIGHT) {//异常情况处理
				ra_angle = this->ra_minAngle(lsx::astronomy::GetZenith(), this->start) + this->ra_minAngle(lsx::astronomy::GetZenith(), this->end);
				dec_angle = this->end.DEC_angle - this->start.DEC_angle;
				ra_direction = RA_DIR_BACKWARD;
				if (dec_angle > 0) {
					dec_direction = DEC_DIR_UP_WHEN_RIGHT;
				}
				else {
					dec_direction = DEC_DIR_DOWN_WHEN_RIGHT;
				}
			}
			else {
				DEC_side = DEC_IS_ON_THE_RIGHT;
				ra_angle = 180.0 - this->ra_minAngle(lsx::astronomy::GetZenith(), this->end) - this->ra_minAngle(lsx::astronomy::GetZenith(), this->start);
				dec_angle = 180.0 - this->end.DEC_angle - this->start.DEC_angle;
				dec_direction = DEC_DIR_UP_WHEN_LEFT;
				if (ra_angle > 0) {
					ra_direction = RA_DIR_FORWARD;
				}
				else {
					ra_direction = RA_DIR_BACKWARD;
				}
			}
		}
		else if (!this->passZenith(this->start) && this->passZenith(this->end)) {//右左
			//std::cout << "RL" << std::endl;
			if (DEC_side == DEC_IS_ON_THE_LEFT) {
				ra_angle = this->ra_minAngle(lsx::astronomy::GetZenith(), this->start) + this->ra_minAngle(lsx::astronomy::GetZenith(), this->end);
				dec_angle = this->end.DEC_angle - this->start.DEC_angle;
				ra_direction = RA_DIR_FORWARD;
				if (dec_angle > 0) {
					dec_direction = DEC_DIR_UP_WHEN_LEFT;
				}
				else {
					dec_direction = DEC_DIR_DOWN_WHEN_LEFT;
				}
			}
			else {
				DEC_side = DEC_IS_ON_THE_LEFT;
				ra_angle = 180.0 - this->ra_minAngle(lsx::astronomy::GetZenith(), this->end) - this->ra_minAngle(lsx::astronomy::GetZenith(), this->start);
				dec_angle = 180.0 - this->end.DEC_angle - this->start.DEC_angle;
				dec_direction = DEC_DIR_UP_WHEN_RIGHT;
				if (ra_angle > 0) {
					ra_direction = RA_DIR_BACKWARD;
				}
				else {
					ra_direction = RA_DIR_FORWARD;
				}
			}
		}
		else if (!this->passZenith(this->start) && !this->passZenith(this->end)) {//右右
			//std::cout << "RR" << std::endl;
			if (DEC_side == DEC_IS_ON_THE_LEFT) {
				DEC_side = DEC_IS_ON_THE_RIGHT;
				ra_angle = 180.0 - this->ra_minAngle(lsx::astronomy::GetZenith(), this->end) + this->ra_minAngle(lsx::astronomy::GetZenith(), this->start);
				dec_angle = 180.0 - this->end.DEC_angle - this->start.DEC_angle;
				ra_direction = RA_DIR_FORWARD;
				dec_direction = DEC_DIR_UP_WHEN_LEFT;
			}
			else {
				ra_angle = this->ra_minAngle(lsx::astronomy::GetZenith(), this->end) - this->ra_minAngle(lsx::astronomy::GetZenith(), this->start);
				dec_angle = this->end.DEC_angle - this->start.DEC_angle;
				if (ra_angle > 0) {
					ra_direction = RA_DIR_BACKWARD;
				}
				else {
					ra_direction = RA_DIR_FORWARD;
				}
				if (dec_angle > 0) {
					dec_direction = DEC_DIR_UP_WHEN_RIGHT;
				}
				else {
					dec_direction = DEC_DIR_DOWN_WHEN_RIGHT;
				}
			}
		}
		/*----------------------------------------------------角度修正与信号发出---------------------------------------------------------*/
		if (fabs(dec_angle) > 254.0) {//角度超过串口发送极限
			dec_angle_part = fabs(dec_angle) - 254.0;
			dec_angle = 254.0;
			lsx::control::dec_goto_motion(dec_direction, dec_angle_part);
			Sleep(lsx::control::EquatorialRunTime_ms(dec_angle_part, DEC_STEPMOTOR, RA_WAIT_MODE_NORMAL) + 500);
		}
		lsx::control::dec_goto_motion(dec_direction, dec_angle);
		dec_runtime_ms = lsx::control::EquatorialRunTime_ms(dec_angle, DEC_STEPMOTOR, RA_WAIT_MODE_NORMAL);

		Sleep(2);

		if (!back_origin_position) {//考虑赤道仪的速度和地球速度,补偿赤道仪运行角度
			ra_angle = lsx::control::get_ra_goto_correct_angle(ra_angle, ra_direction);
		}
		lsx::control::ra_goto_motion(ra_direction, ra_angle);
		ra_runtime_ms = lsx::control::EquatorialRunTime_ms(ra_angle, RA_STEPMOTOR, RA_WAIT_MODE_NORMAL);

		/*---------------------------------------------------图像显示------------------------------------------------------*/

		this->targetTable.get_image_x_y(this->start.RA_angle, this->start.DEC_angle, &this->start.position_in_image_x, &this->start.position_in_image_y);
		this->targetTable.get_image_x_y(this->end.RA_angle, this->end.DEC_angle, &this->end.position_in_image_x, &this->end.position_in_image_y);
		start_time = std::clock();
		this->ra_arrival = false; this->dec_arrival = false;
		while (!arrive_the_target) {
			star_image = this->targetTable.getTargetTableImage();
			end_time = std::clock();
			now_run_time = double(end_time) - double(start_time);
			if (now_run_time > lsx::math::Max(ra_runtime_ms, dec_runtime_ms)) {
				cv::circle(star_image, cv::Point(this->end.position_in_image_x, this->end.position_in_image_y), double(heigth) / 50.0, optional_target_color, 2, cv::LINE_AA);
				lsx::starProcessing::DrawRegularTriangle(star_image, now_position.x, now_position.y, my_equatorial_instrument_color, double(heigth) / 100.0);
				cv::circle(star_image, now_position, double(heigth) / 80.0, my_equatorial_instrument_color, 1, cv::LINE_AA);
				cv::putText(star_image, "EQ arrival!", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 255, 0), 1, cv::LINE_AA);
				cv::imshow(win_name, star_image);
				cv::waitKey(700);
				arrive_the_target = true;
				break;
			}
			if (now_run_time < ra_runtime_ms && now_run_time < dec_runtime_ms) {
				sprintf_s(show_my_equ, "my EQ(RA:%d ms, DEC:%d ms)", int(ra_runtime_ms - now_run_time), int(dec_runtime_ms - now_run_time));
			}
			else if (now_run_time >= ra_runtime_ms && now_run_time < dec_runtime_ms) {
				sprintf_s(show_my_equ, "my EQ(RA arrive, DEC:%d ms)", int(dec_runtime_ms - now_run_time));
			}
			else if (now_run_time < ra_runtime_ms && now_run_time >= dec_runtime_ms) {
				sprintf_s(show_my_equ, "my EQ(RA:%d ms, DEC arrive)", int(ra_runtime_ms - now_run_time));
			}
			else {
				sprintf_s(show_my_equ, "my EQ(RA arrive, DEC arrive)");
			}
			this->get_image_position(this->start.position_in_image_x, this->start.position_in_image_y, \
				this->end.position_in_image_x, this->end.position_in_image_y, ra_runtime_ms, dec_runtime_ms, start_time, end_time, &now_position);
			cv::circle(star_image, cv::Point(this->end.position_in_image_x, this->end.position_in_image_y), double(heigth) / 50.0, optional_target_color, 2, cv::LINE_AA);
			if (!back_origin_position) {
				cv::putText(star_image, "EQ on the move...", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
			}
			else {
				cv::putText(star_image, "EQ on the move(return to '0' position)...", cv::Point(0 + double(heigth) / 200.0, 0 + double(heigth) / 50.0), \
					cv::FONT_HERSHEY_SIMPLEX, 0.6, cv::Scalar(0, 0, 255), 1, cv::LINE_AA);
			}
			lsx::starProcessing::DrawRegularTriangle(star_image, now_position.x, now_position.y, my_equatorial_instrument_color, double(heigth) / 100.0);
			cv::circle(star_image, now_position, double(heigth) / 80.0, my_equatorial_instrument_color, 1, cv::LINE_AA);
			//cv::line(star_image, cv::Point(now_position.x + double(heigth) / 80.0, now_position.y), cv::Point(star_image.cols, now_position.y), my_equatorial_instrument_color, 1, cv::LINE_AA);//右侧线
			//cv::line(star_image, cv::Point(now_position.x - double(heigth) / 80.0, now_position.y), cv::Point(0, now_position.y), my_equatorial_instrument_color, 1, cv::LINE_AA);//左侧线
			//cv::line(star_image, cv::Point(now_position.x, now_position.y - double(heigth) / 80.0), cv::Point(now_position.x, 0), my_equatorial_instrument_color, 1, cv::LINE_AA);//上侧线
			//cv::line(star_image, cv::Point(now_position.x, now_position.y + double(heigth) / 80.0), cv::Point(now_position.x, star_image.rows), my_equatorial_instrument_color, 1, cv::LINE_AA);//下侧线
			cv::line(star_image, cv::Point(now_position.x + double(heigth) / 80.0, now_position.y), cv::Point(now_position.x + 6.0 * double(heigth) / 80.0, now_position.y), my_equatorial_instrument_line_color, 1, cv::LINE_AA);//右侧线
			cv::line(star_image, cv::Point(now_position.x - double(heigth) / 80.0, now_position.y), cv::Point(now_position.x - 6.0 * double(heigth) / 80.0, now_position.y), my_equatorial_instrument_line_color, 1, cv::LINE_AA);//左侧线
			cv::line(star_image, cv::Point(now_position.x, now_position.y - double(heigth) / 80.0), cv::Point(now_position.x, now_position.y - 6.0 * double(heigth) / 80.0), my_equatorial_instrument_line_color, 1, cv::LINE_AA);//上侧线
			cv::line(star_image, cv::Point(now_position.x, now_position.y + double(heigth) / 80.0), cv::Point(now_position.x, now_position.y + 6.0 * double(heigth) / 80.0), my_equatorial_instrument_line_color, 1, cv::LINE_AA);//下侧线
			cv::putText(star_image, show_my_equ, cv::Point(now_position.x + double(heigth) / 60.0, now_position.y - double(heigth) / 60.0), \
				cv::FONT_HERSHEY_SIMPLEX, 0.4, my_equatorial_instrument_color, 1, cv::LINE_AA);
			cv::imshow(win_name, star_image);
			cv::waitKey(20);
		}
		cv::destroyAllWindows();
		system("cls");
		if (this->end.isStar && !this->zero2star) {
			std::cout << std::endl;
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
			std::cout << "请将 <" << this->pointTarget.name << "> 放置于视场中心。" << std::endl;
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
			std::cout << std::endl;
			lsx::control::kbControl(CONTROL_RA_DEC);
		}
		if (this->zero2star) {
			this->zero2star = false;
			std::cout << std::endl;
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN);
			std::cout << "为了校准零位,请将 <" << this->pointTarget.name << "> 放置于视场中心。" << std::endl;
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_RED);
			std::cout << std::endl;
			lsx::control::kbControl(CONTROL_RA_DEC);
		}
	}
	else {
		cv::destroyAllWindows();
		system("cls");
	}
}

void lsx::autoSearch::AutoStarFindController::preSet(std::string targetName, std::string targetNumber, int decSide) {
	this_target_name = targetName;
	this_target_number = targetNumber;
	DEC_side = decSide;
	noTarget = false;
}

void lsx::autoSearch::AutoStarFindController::AutomaticStarFinding() {
	this->gotoControl();
}

EquatorialControl.h

#ifndef EQUATORIAL_CONTROL_H
#define EQUATORIAL_CONTROL_H

#include<iostream>
#include<Eigen/Dense>
#include<Windows.h>
#include"windows.h"
#include"atlstr.h"
#include<string.h>
#include<TCHAR.H>
#include<conio.h>
#include<stdarg.h>
#include<vector>

#include"SerialCommunication.h"
#include"Astronomy.h"

namespace lsx {
	namespace control {

#define GUIDE_ADJUST_FORWARD 11//导星过程中向正方向调整一定的角度,对RA:RA减少(天体运动)的方向;对DEC:顺时针旋转
#define GUIDE_ADJUST_BACKWARD 12//导星过程中向反方向调整一定的角度,对RA:RA增加的方向;对DEC:逆时针旋转
#define GUIDE_RA_STOP 17//导星过程中RA转轴停止
#define GUIDE_RA_ADJUST_STOP 18//导星过程中RA转轴停止,等待地球自转一定角度
#define GUIDE_RA_CONTINUE 19//导星过程中RA恢复到盲跟状态

#define GOTO_ADJUST_FORWARD 21//自动寻星过程中向正方向调整一定的角度,对RA:RA减少(天体运动)的方向;对DEC:顺时针旋转
#define GOTO_ADJUST_BACKWARD 22//自动寻星过程中向反方向调整一定的角度,对RA:RA增加的方向;对DEC:逆时针旋转

#define AUTO_ADJUST_FORWARD 31//极轴调整过程中向正方向调整一定的角度,对抬升电机:上升;对方位角电机:顺时针转动
#define AUTO_ADJUST_BACKWARD 32//极轴调整过程中向反方向调整一定的角度,对抬升电机:下降;对方位角电机:逆时针转动

#define RA_STEPMOTOR 1//赤经轴电机
#define DEC_STEPMOTOR 2//赤纬轴电机
#define AZIMUTH_STEPMOTOR 3//极轴方位角电机
#define ELEVATION_STEPMOTOR 4//极轴高度角电机

#define CONTROL_RA_DEC 1//键盘控制选择控制RA,DEC电机
#define CONTROL_ROUND_UP 2//键盘控制选择控制ROUND,UP电机

#define RA_DIR_FORWARD 1//RA减少(天体运动)的方向
#define RA_DIR_BACKWARD 2//RA增加的方向

#define DEC_DIR_FORWARD 1//DEC顺时针旋转
#define DEC_DIR_BACKWARD 2//DEC逆时针选择

#define DEC_DIR_UP_WHEN_RIGHT DEC_DIR_BACKWARD //DEC在右半盘时的DEC上升的方向
#define DEC_DIR_DOWN_WHEN_RIGHT DEC_DIR_FORWARD //DEC在右半盘时的DEC下降的方向

#define DEC_DIR_UP_WHEN_LEFT DEC_DIR_FORWARD //DEC在左半盘时的DEC上升的方向
#define DEC_DIR_DOWN_WHEN_LEFT DEC_DIR_BACKWARD //DEC在左半盘时的DEC下降的方向

#define RA_WAIT_MODE_NORMAL 0
#define RA_WAIT_MODE_WAIT_EARTH 1

		/**
		 * @brief 赤道仪参数类
		 */
		class EquatorialParam {
		public:
			double time_clk = 84.0 * 1000000;
			double ARR = 19.0;
			double speed_up_1_psc_min = 38.0;
			double speed_up_2_psc_min = 122.0;
			double speed_up_3_psc = 500.0;

			double RA_reduceRatio = 0;//RA减速比
			double DEC_reduceRatio = 0;//DEC减速比

			double RA_stepAngle = 0;//RA脉冲对应角距离
			double DEC_stepAngle = 0;//DEC脉冲对应角距离

			double RA_max_pwm_frequency = 0;//RA曲线加速1最大PWM频率
			double DEC_max_pwm_frequency = 0;//DEC曲线加速1最大PWM频率

			double RA_max_pwm_frequency_small = 0;//RA曲线加速2最大PWM频率
			double DEC_max_pwm_frequency_small = 0;//DEC曲线加速2最大PWM频率

			double RA_pwm_frequency_continue = 0;//RA匀速PWM频率
			double DEC_pwm_frequency_continue = 0;//DEC匀速PWM频率

			double RA_speedUpAngle = 0;//RA轴加速角度1
			double DEC_speedUpAngle = 0;//DEC轴加速角度1

			double RA_speedUpAngle_small = 0;//RA加速角度2
			double DEC_speedUpAngle_small = 0;//DEC加速角度2

			double RA_speedUp_1_time = 0;//RA加速时间1
			double RA_speedUp_2_time = 0;//RA加速时间2
			double DEC_speedUp_1_time = 0;//DEC加速时间1
			double DEC_speedUp_2_time = 0;//DEC加速时间2

			double v_RA_max = 0;//RA最大速度,单位:°/s
			double v_DEC_max = 0;//DEC最大速度,单位:°/s
			double v_RA_max_small = 0;//RA最大速度,单位:°/s
			double v_DEC_max_small = 0;//DEC最大速度,单位:°/s
			double v_RA_continue = 0;//RA匀速运动速度
			double v_DEC_continue = 0;//DEC匀速运动速度

			EquatorialParam();
		};

		/** 
		 * @brief 控制赤道仪运行主要函数
		 * @param moveMode 运行模式选择
		 * @param moveAngle 运行角度,单位:°
		 * @param motorChoose 电机选择位
		 * @return void
		 */
		void EquatorialMovement(int moveMode, double moveAngle, char motorChoose);

		/** 
		 * @brief 键盘控制赤道仪
		 * @param modeChoose 模式选择,可选:CONTROL_RA_DEC,控制RA和DEC轴;CONTROL_ROUND_UP,控制纬度座
		 * @return 行向量[RA增加角度,DEC逆时针角度]
		 */
		Eigen::MatrixXd kbControl(int modeChoose = CONTROL_RA_DEC);

		/** 
		 * @brief 计算赤道仪运行时间
		 * @param inputAngle 转轴输出端运行的角度
		 * @param motorChoose 电机选择
		 * @param ra_wait_mode RA的等待模式,可选:RA_WAIT_MODE_NORMAL,RA转轴基本等待时间(自动寻星和导星基向量求解时使用);
		 *						RA_WAIT_MODE_WAIT_EARTH,RA转轴停止等待地球自转(导星修正时使用)
		 * @return 赤道仪的运行时间,单位:ms
		 */
		int EquatorialRunTime_ms(double inputAngle, char motorChoose, char ra_wait_mode = RA_WAIT_MODE_NORMAL);

		/**
		 * @brief RA转轴导星控制
		 * @param direction 运行方向,可选:RA_DIR_FORWARD,RA向天体运行的方向移动;RA_DIR_BACKWARD,RA向天体运行的反方向运动
		 * @param angle_degree 旋转角度,单位:°
		 * @param calc_vector 是否是导星基向量求解标志位,可选:true,此时RA转轴正反转正常移动;false,此时RA转轴反转等待地球自转(导星修正)
		 * @return void
		 */
		void ra_guide_motion(int direction, double angle_degree, bool calc_vector);

		/**
		 * @brief RA转轴自动寻星控制
		 * @param direction 运行方向,可选:RA_DIR_FORWARD,RA向天体运行的方向移动;RA_DIR_BACKWARD,RA向天体运行的反方向运动
		 * @param angle_degree 旋转角度,单位:°
		 * @return void
		 */
		void ra_goto_motion(int direction, double angle_degree);

		/**
		 * @brief DEC转轴导星控制
		 * @param direction 运行方向,可选:DEC_DIR_FORWARD,DEC顺时针转动;DEC_DIR_BACKWARD,DEC逆时针转动
		 * @param angle_degree 旋转角度,单位:°
		 * @return void
		 */
		void dec_guide_motion(int direction, double angle_degree);

		/**
		 * @brief DEC转轴自动寻星控制
		 * @param direction 运行方向,可选:DEC_DIR_FORWARD,DEC顺时针转动;DEC_DIR_BACKWARD,DEC逆时针转动
		 * @param angle_degree 旋转角度,单位:°
		 * @return void
		 */
		void dec_goto_motion(int direction, double angle_degree);

		/**
		 * @brief RA运动角度修正,考虑RA转轴与天球的相遇、追击问题
		 * @param input_angle 输入初始运行的角度
		 * @param direction 输入的运行方向
		 * @param speed_up_mode RA转轴曲线加速模式(与控制单片机结合)
		 * @param re_calc 如果初次求解后模式有跳变,则递归调用的标志位
		 * @return RA转轴运行角度
		 */
		double ra_goto_angle_correct(double input_angle, int direction, int speed_up_mode = 0, bool re_calc = false);

		/**
		 * @brief (调试用)RA运动角度修正,考虑RA转轴与天球的相遇、追击问题
		 * @param input_angle 输入初始运行的角度
		 * @param direction 输入的运行方向
		 * @param output_speed_up_mode 修正后的赤道仪加速模式
		 * @return RA转轴运行角度
		 */
		double get_ra_goto_correct_angle(double input_angle, int direction, int* output_speed_up_mode);

		/**
		 * @brief RA运动角度修正,考虑RA转轴与天球的相遇、追击问题
		 * @param input_angle 输入初始运行的角度
		 * @param direction 输入的运行方向
		 * @param output_speed_up_mode 修正后的赤道仪加速模式
		 * @return RA转轴运行角度
		 */
		double get_ra_goto_correct_angle(double input_angle, int direction);

		/**
		 * @brief 通过鼠标点击图片控制赤道仪
		 * @param width 图形界面的宽度
		 * @param height 图形界面的高度
		 * @return 行向量[RA增加角度,DEC逆时针角度]
		 */
		Eigen::MatrixXd MouseControl(int width = 1920, int height = 1080);
	}
}

#endif

EquatorialControl.cpp

#include"EquatorialControl.h"

extern CString PORTNAME;

double equ_control_mouse_touch_x = -1, equ_control_mouse_touch_y = -1, equ_control_mouse_botton_x = -1, equ_control_mouse_botton_y = -1;
int mouse_wheel_number = 0;
bool equ_control_deal_mouse_botton = true, equ_control_mouse_get_coodinate = false, equ_control_quit = false;
bool equ_control_angle_change_enable = false, equ_control_equ_ra_is_running = false, equ_control_equ_dec_is_running = false;
bool angle_reset_enable = false;
double cell_angle = 0, adjust_angle = 0;

extern int RA_reduction_ratio;
extern int DEC_reduction_ratio;

lsx::serial::serial_writer serialWriter;
bool serial_have_open = false;

lsx::control::EquatorialParam::EquatorialParam() {
	this->time_clk = 84.0 * 1000000.0;//时钟
	this->ARR = 19.0;
	this->speed_up_1_psc_min = 38.0;
	this->speed_up_2_psc_min = 122.0;
	this->speed_up_3_psc = 500.0;

	this->RA_reduceRatio = double(RA_reduction_ratio);//RA减速比
	this->DEC_reduceRatio = double(DEC_reduction_ratio);//DEC减速比

	this->RA_stepAngle = 1.8 / 256.0;//RA脉冲对应角距离
	this->DEC_stepAngle = 1.8 / 256.0;//DEC脉冲对应角距离

	this->RA_max_pwm_frequency = this->time_clk / ((this->ARR + 1.0) * (this->speed_up_1_psc_min + 1.0));//RA最大PWM频率
	this->DEC_max_pwm_frequency = this->time_clk / ((this->ARR + 1.0) * (this->speed_up_1_psc_min + 1.0));//DEC最大PWM频率

	this->RA_max_pwm_frequency_small = this->time_clk / ((this->ARR + 1.0) * (this->speed_up_2_psc_min + 1.0));//RA曲线加速2最大PWM频率
	this->DEC_max_pwm_frequency_small = this->time_clk / ((this->ARR + 1.0) * (this->speed_up_2_psc_min + 1.0));//DEC曲线加速2最大PWM频率

	this->RA_pwm_frequency_continue = this->time_clk / ((this->ARR + 1.0) * (this->speed_up_3_psc + 1.0));
	this->DEC_pwm_frequency_continue = this->time_clk / ((this->ARR + 1.0) * (this->speed_up_3_psc + 1.0));

	this->RA_speedUpAngle = 720.0 / 300.0;//RA轴加速角度
	this->DEC_speedUpAngle = 720.0 / 100.0;//DEC轴加速角度

	this->RA_speedUpAngle_small = 144.0 / 300.0;//RA的加速角度
	this->DEC_speedUpAngle_small = 144.0 / 100.0;//DEC的加速角度

	this->RA_speedUp_1_time = 2.100761904761906;
	this->RA_speedUp_2_time = 1.280761904761905;
	this->DEC_speedUp_1_time = 2.100761904761906;
	this->DEC_speedUp_2_time = 1.280761904761905;

	this->v_RA_max = RA_max_pwm_frequency * RA_stepAngle / RA_reduceRatio;
	this->v_DEC_max = DEC_max_pwm_frequency * DEC_stepAngle / DEC_reduceRatio;
	this->v_RA_max_small = RA_max_pwm_frequency_small * RA_stepAngle / RA_reduceRatio;
	this->v_DEC_max_small = DEC_max_pwm_frequency_small * DEC_stepAngle / DEC_reduceRatio;
	this->v_RA_continue = RA_pwm_frequency_continue * RA_stepAngle / RA_reduceRatio;
	this->v_DEC_continue = DEC_pwm_frequency_continue * DEC_stepAngle / DEC_reduceRatio;
}

void lsx::control::EquatorialMovement(int moveMode, double moveAngle, char motorChoose) {
	double degrees, mins, seconds, arcSeconds;
	char dataHead = 'x', dataTail = 'y', mcuMode, mcuMoveMode;
	std::vector<char> sendArray;
	moveAngle = fabs(moveAngle);
	if (moveAngle > 9.0 / (3600.0 * 60.0) && moveAngle < 255.0 && 
		(motorChoose == 1 || motorChoose == 2 || motorChoose == 3 || motorChoose == 4)) {//角度范围限制
		degrees = floor(moveAngle);
		moveAngle = (moveAngle - degrees) * 60.0;
		mins = floor(moveAngle);
		moveAngle = (moveAngle - mins) * 60.0;
		seconds = floor(moveAngle);
		moveAngle = (moveAngle - seconds) * 60.0;
		arcSeconds = floor(moveAngle);
		mcuMode = moveMode / 10; mcuMoveMode = moveMode % 10;
		sendArray.resize(8);
		if (mcuMoveMode == 1 || mcuMoveMode == 2 || mcuMoveMode == 8) {
			sendArray[0] = dataHead;
			sendArray[1] = motorChoose;
			sendArray[2] = char(moveMode);
			sendArray[3] = char(degrees);
			sendArray[4] = char(mins);
			sendArray[5] = char(seconds);
			sendArray[6] = char(arcSeconds);
			sendArray[7] = dataTail;
		}
		else {
			sendArray[0] = dataHead;
			sendArray[1] = motorChoose;
			sendArray[2] = char(moveMode);
			sendArray[3] = 0;
			sendArray[4] = 0;
			sendArray[5] = 0;
			sendArray[6] = 0;
			sendArray[7] = dataTail;
		}
		if (!serial_have_open) {
			serialWriter.set_serial(PORTNAME);
			serial_have_open = true;
		}
		serialWriter.send_data(sendArray);
		serialWriter.Serial_close();
	}
}

Eigen::MatrixXd lsx::control::kbControl(int modeChoose) {
	Eigen::MatrixXd outputMatrix(1, 2);
	int keyNumber = 0, state = 0; double raAdjustAngle = 0, decAdjustAngle = 0;
	double adjustAngle = 0.1; bool showAngle = false, showControlMode = false;
	int signalFlag = 0;
	outputMatrix *= 0;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
	std::cout << "可通过键盘控制赤道仪。RA( ↓ 向西、↑ 向东);DEC( ← 逆时针、 → 顺时针)"  << std::endl;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
	while (true){
		Sleep(40);
		if (_kbhit()) {
			keyNumber = _getch();
		}
		if (keyNumber == 27) {
			break;
		}
		else {
			switch (keyNumber){
				/*angle set*/
			case 49:adjustAngle = 0.1; keyNumber = 0; showAngle = true; break;
			case 50:adjustAngle = 0.2; keyNumber = 0; showAngle = true; break;
			case 51:adjustAngle = 0.3; keyNumber = 0; showAngle = true; break;
			case 52:adjustAngle = 0.4; keyNumber = 0; showAngle = true; break;
			case 53:adjustAngle = 0.5; keyNumber = 0; showAngle = true; break;
			case 54:adjustAngle = 0.6; keyNumber = 0; showAngle = true; break;
			case 55:adjustAngle = 0.7; keyNumber = 0; showAngle = true; break;
			case 56:adjustAngle = 0.8; keyNumber = 0; showAngle = true; break;
			case 57:adjustAngle = 0.9; keyNumber = 0; showAngle = true; break;
			case 97:adjustAngle = 0.1; keyNumber = 0; showAngle = true; break;
			case 98:adjustAngle = 0.2; keyNumber = 0; showAngle = true; break;
			case 99:adjustAngle = 0.3; keyNumber = 0; showAngle = true; break;
			case 100:adjustAngle = 0.4; keyNumber = 0; showAngle = true; break;
			case 101:adjustAngle = 0.5; keyNumber = 0; showAngle = true; break;
			case 102:adjustAngle = 0.6; keyNumber = 0; showAngle = true; break;
			case 103:adjustAngle = 0.7; keyNumber = 0; showAngle = true; break;
			case 104:adjustAngle = 0.8; keyNumber = 0; showAngle = true; break;
			case 105:adjustAngle = 0.9; keyNumber = 0; showAngle = true; break;
			case 224:state = 1; keyNumber = 0; break;
				/*signal send*/
			case 72: {//方向键上,RA,UP
				if (state == 1) {
					state = 0;
					keyNumber = 0;
					showControlMode = true;
					signalFlag = 1;
				}
				break;
			}
			case 80: {//方向键下,RA,UP
				if (state == 1) {
					state = 0;
					keyNumber = 0;
					showControlMode = true;
					signalFlag = 2;
				}
				break;
			}
			case 75: {//方向键左,DEC,ROUND
				if (state == 1) {
					state = 0;
					keyNumber = 0;
					showControlMode = true;
					signalFlag = 3;
				}
				break;
			}
			case 77: {//方向键右,DEC,ROUND
				if (state == 1) {
					state = 0;
					keyNumber = 0;
					showControlMode = true;
					signalFlag = 4;
				}
				break;
			}
			case 32: {//空格
				state = 0;
				keyNumber = 0;
				showAngle = true;
				std::cout << "输入自定义角度: ";
				std::cin >> adjustAngle;
				while (std::cin.fail()){
					std::cout << "error angle !" << std::endl;
					std::cin >> adjustAngle;
					std::cin.clear();
					std::cin.ignore();
				}
				break;
			}
			}
		}
		if (showAngle) {
			std::cout << "set adjust angle = " << adjustAngle << " °";
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE);
			std::cout << "   RA( ↓ 向西、↑ 向东);DEC( ← 逆时针、 → 顺时针)" << std::endl;
			SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
			showAngle = false;
		}
		if (showControlMode) {
			adjustAngle = fabs(adjustAngle);
			if (adjustAngle > 0) {
				showControlMode = false;
				if (modeChoose == CONTROL_RA_DEC) {
					switch (signalFlag) {
					case 1:lsx::control::EquatorialMovement(GOTO_ADJUST_BACKWARD, adjustAngle, RA_STEPMOTOR); outputMatrix(0, 0) += adjustAngle; std::cout << "RA<向东> " << adjustAngle << " °" << std::endl; break;
					case 2:lsx::control::EquatorialMovement(GOTO_ADJUST_FORWARD, adjustAngle, RA_STEPMOTOR); outputMatrix(0, 0) -= adjustAngle; std::cout << "RA<向西> " << adjustAngle << " °" << std::endl;  break;
					case 3:lsx::control::EquatorialMovement(GOTO_ADJUST_BACKWARD, adjustAngle, DEC_STEPMOTOR); outputMatrix(0, 1) += adjustAngle; std::cout << "DEC<逆时针> " << adjustAngle << " °" << std::endl; break;
					case 4:lsx::control::EquatorialMovement(GOTO_ADJUST_FORWARD, adjustAngle, DEC_STEPMOTOR); outputMatrix(0, 1) -= adjustAngle; std::cout << "DEC<顺时针> " << adjustAngle << " °" << std::endl; break;
					}
				}
				else if (modeChoose == CONTROL_ROUND_UP) {
					switch (signalFlag) {
					case 1:lsx::control::EquatorialMovement(AUTO_ADJUST_FORWARD, adjustAngle, ELEVATION_STEPMOTOR); std::cout << "极轴仰角<上升> " << adjustAngle << " °" << std::endl; break;
					case 2:lsx::control::EquatorialMovement(AUTO_ADJUST_BACKWARD, adjustAngle, ELEVATION_STEPMOTOR); std::cout << "极轴仰角<下降> " << adjustAngle << " °" << std::endl; break;
					case 3:lsx::control::EquatorialMovement(AUTO_ADJUST_FORWARD, adjustAngle, AZIMUTH_STEPMOTOR); std::cout << "极轴<顺时针> " << adjustAngle << " °" << std::endl; break;
					case 4:lsx::control::EquatorialMovement(AUTO_ADJUST_BACKWARD, adjustAngle, AZIMUTH_STEPMOTOR); std::cout << "极轴<逆时针> " << adjustAngle << " °" << std::endl; break;
					}
				}
			}
		}
	}
	system("cls");
	return outputMatrix;
}

int lsx::control::EquatorialRunTime_ms(double inputAngle, char motorChoose, char ra_wait_mode) {
	double outputTime = 0;
	double time_speedUp = 0, time_maxSpeed = 0;
	double angleRemain = 0;
	lsx::control::EquatorialParam eParam;
	inputAngle = fabs(inputAngle);
	if (inputAngle > 0) {
		switch (motorChoose) {
		case RA_STEPMOTOR: {
			if (ra_wait_mode == RA_WAIT_MODE_NORMAL) {
				if (inputAngle > 2.0 * eParam.RA_speedUpAngle) {
					angleRemain = inputAngle - 2.0 * eParam.RA_speedUpAngle;
					time_speedUp = 2.0 * eParam.RA_speedUp_1_time;
					time_maxSpeed = angleRemain / eParam.v_RA_max;
					outputTime = time_speedUp + time_maxSpeed;
				}
				else if (inputAngle > 2.0 * eParam.RA_speedUpAngle_small) {
					angleRemain = inputAngle - 2.0 * eParam.RA_speedUpAngle_small;
					time_speedUp = 2.0 * eParam.RA_speedUp_2_time;
					time_maxSpeed = angleRemain / eParam.v_RA_max_small;
					outputTime = time_speedUp + time_maxSpeed;
				}
				else {
					outputTime = inputAngle / eParam.v_RA_continue;
				}
			}
			else if (ra_wait_mode == RA_WAIT_MODE_WAIT_EARTH) {
				outputTime = lsx::astronomy::earthRotateTime(inputAngle) / 1000.0;
			}
			break;
		}
		case DEC_STEPMOTOR: {
			if (inputAngle > 2.0 * eParam.DEC_speedUpAngle) {
				angleRemain = inputAngle - 2.0 * eParam.DEC_speedUpAngle;
				time_speedUp = 2.0 * eParam.DEC_speedUp_1_time;
				time_maxSpeed = angleRemain / eParam.v_DEC_max;
				outputTime = time_speedUp + time_maxSpeed;
			}
			else if (inputAngle > 2.0 * eParam.DEC_speedUpAngle_small) {
				angleRemain = inputAngle - 2.0 * eParam.DEC_speedUpAngle_small;
				time_speedUp = 2.0 * eParam.DEC_speedUp_2_time;
				time_maxSpeed = angleRemain / eParam.v_DEC_max_small;
				outputTime = time_speedUp + time_maxSpeed;
			}
			else {
				outputTime = inputAngle / eParam.v_DEC_continue;
			}
			break;
		}
		}
	}
	outputTime *= 1000.0;
	return int(outputTime);
}

void lsx::control::ra_guide_motion(int direction, double angle_degree, bool calc_vector) {
	if (!calc_vector) {
		if (direction == RA_DIR_FORWARD) {//ra向天体运动的方向运动
			lsx::control::EquatorialMovement(GUIDE_ADJUST_FORWARD, angle_degree, RA_STEPMOTOR);
		}
		else if (direction == RA_DIR_BACKWARD) {//向反方向运动需要停
			lsx::control::EquatorialMovement(GUIDE_RA_ADJUST_STOP, angle_degree, RA_STEPMOTOR);
		}
	}
	else {
		if (direction == RA_DIR_FORWARD) {//ra向天体运动的方向运动
			lsx::control::EquatorialMovement(GUIDE_ADJUST_FORWARD, angle_degree, RA_STEPMOTOR);
		}
		else if (direction == RA_DIR_BACKWARD) {//在求解向量时直接向反方向运动
			lsx::control::EquatorialMovement(GUIDE_ADJUST_BACKWARD, angle_degree, RA_STEPMOTOR);
		}
	}
}

void lsx::control::ra_goto_motion(int direction, double angle_degree) {
	if (direction == RA_DIR_FORWARD) {
		lsx::control::EquatorialMovement(GOTO_ADJUST_FORWARD, angle_degree, RA_STEPMOTOR);
	}
	else if (direction == RA_DIR_BACKWARD) {
		lsx::control::EquatorialMovement(GOTO_ADJUST_BACKWARD, angle_degree, RA_STEPMOTOR);
	}
}

void lsx::control::dec_guide_motion(int direction, double angle_degree) {
	if (direction == DEC_DIR_FORWARD) {
		lsx::control::EquatorialMovement(GUIDE_ADJUST_FORWARD, angle_degree, DEC_STEPMOTOR);
	}
	else if (direction == DEC_DIR_BACKWARD) {
		lsx::control::EquatorialMovement(GUIDE_ADJUST_BACKWARD, angle_degree, DEC_STEPMOTOR);
	}
}

void lsx::control::dec_goto_motion(int direction, double angle_degree) {
	if (direction == DEC_DIR_FORWARD) {
		lsx::control::EquatorialMovement(GOTO_ADJUST_FORWARD, angle_degree, DEC_STEPMOTOR);
	}
	else if (direction == DEC_DIR_BACKWARD) {
		lsx::control::EquatorialMovement(GOTO_ADJUST_BACKWARD, angle_degree, DEC_STEPMOTOR);
	}
}

/**
 * @brief 赤道仪与天体运行方向相反则该函数为-1,与天体方向相同则该函数为1
 */
double dierection201(int direction) {
	if (direction == RA_DIR_BACKWARD) {//向东
		return -1.0;
	}
	else if (direction == RA_DIR_FORWARD) {//向西
		return 1.0;
	}
}

/**
 * @brief 计算RA转轴曲线加速时的加速模式
 */
int get_ra_speed_up_mode(double input_angle) {
	lsx::control::EquatorialParam eParam;
	if (input_angle > eParam.RA_speedUpAngle * 2.0) {
		return 1;
	}
	else if (input_angle > eParam.RA_speedUpAngle_small * 2.0) {
		return 2;
	}
	else {
		return 3;
	}
}

double lsx::control::ra_goto_angle_correct(double input_angle, int direction, int speed_up_mode, bool re_calc) {
	lsx::control::EquatorialParam eParam;
	double correct_angle = 0;//预处理角度
	double V_earth = 360.0 / 86164.0;//地球转速(恒星时),°/s
	double V_equ = 0;
	double angle_spu = 0, time_spu = 0;
	int now_speed_up_mode = 0;
	input_angle = fabs(input_angle);
	if (input_angle > eParam.RA_speedUpAngle * 2.0 || (re_calc && speed_up_mode == 1)) {
		now_speed_up_mode = 1;
		angle_spu = eParam.RA_speedUpAngle;
		time_spu = eParam.RA_speedUp_1_time;
		V_equ = eParam.v_RA_max;
		correct_angle = 2.0 * angle_spu + V_equ * ((input_angle - 2.0 * angle_spu + dierection201(direction) * 2.0 * V_earth * time_spu) / (-dierection201(direction) * V_earth + V_equ));
	}
	else if (input_angle > eParam.RA_speedUpAngle_small * 2.0 || (re_calc && speed_up_mode == 2)) {
		now_speed_up_mode = 2;
		angle_spu = eParam.RA_speedUpAngle_small;
		time_spu = eParam.RA_speedUp_2_time;
		V_equ = eParam.v_RA_max_small;
		correct_angle = 2.0 * angle_spu + V_equ * ((input_angle - 2.0 * angle_spu + dierection201(direction) * 2.0 * V_earth * time_spu) / (-dierection201(direction) * V_earth + V_equ));
	}
	else if(input_angle > 0 || (re_calc && speed_up_mode == 3)){
		now_speed_up_mode = 3;
		angle_spu = 0;
		time_spu = 0;
		V_equ = eParam.v_RA_continue;
		correct_angle = 2.0 * angle_spu + V_equ * ((input_angle - 2.0 * angle_spu + dierection201(direction) * 2.0 * V_earth * time_spu) / (-dierection201(direction) * V_earth + V_equ));
	}
	if (now_speed_up_mode == get_ra_speed_up_mode(correct_angle)) {
		return correct_angle;
	}
	else {
		lsx::control::ra_goto_angle_correct(input_angle, direction, get_ra_speed_up_mode(correct_angle), true);
	}
}

double lsx::control::get_ra_goto_correct_angle(double input_angle, int direction, int* output_speed_up_mode) {
	lsx::control::EquatorialParam eParam;
	double correct_angle = 0;//预处理角度
	double V_earth = 360.0 / 86164.0;//地球转速(恒星时),°/s
	double angle_spu[3] = { eParam.RA_speedUpAngle, eParam.RA_speedUpAngle_small, 0.0 },//加速角度
		time_spu[3] = { eParam.RA_speedUp_1_time, eParam.RA_speedUp_2_time, 0.0 },//加速时间
		V_equ[3] = { eParam.v_RA_max, eParam.v_RA_max_small, eParam.v_RA_continue };//最大速度
	int speed_up_mode[3] = { 1, 2, 3 },//加速模式
		i = 0;
	input_angle = fabs(input_angle);
	for (i = 0; i < 3; i++) {
		correct_angle = 2.0 * angle_spu[i] + V_equ[i] * ((input_angle - 2.0 * angle_spu[i] + dierection201(direction) * 2.0 * V_earth * time_spu[i]) / (-dierection201(direction) * V_earth + V_equ[i]));
		if (get_ra_speed_up_mode(correct_angle) == speed_up_mode[i]) {//判断加速模式是否匹配
			(*output_speed_up_mode) = speed_up_mode[i];
			return correct_angle;
		}
	}
	*output_speed_up_mode = 0;
	return input_angle;
}

double lsx::control::get_ra_goto_correct_angle(double input_angle, int direction) {
	lsx::control::EquatorialParam eParam;
	double correct_angle = 0;//预处理角度
	double V_earth = 360.0 / 86164.0;//地球转速(恒星时),°/s
	double angle_spu[3] = { eParam.RA_speedUpAngle, eParam.RA_speedUpAngle_small, 0.0 },//加速角度
		time_spu[3] = { eParam.RA_speedUp_1_time, eParam.RA_speedUp_2_time, 0.0 },//加速时间
		V_equ[3] = { eParam.v_RA_max, eParam.v_RA_max_small, eParam.v_RA_continue };//最大速度
	int speed_up_mode[3] = { 1, 2, 3 },//加速模式
		i = 0;
	input_angle = fabs(input_angle);
	for (i = 0; i < 3; i++) {
		correct_angle = 2.0 * angle_spu[i] + V_equ[i] * ((input_angle - 2.0 * angle_spu[i] + dierection201(direction) * 2.0 * V_earth * time_spu[i]) / (-dierection201(direction) * V_earth + V_equ[i]));
		if (get_ra_speed_up_mode(correct_angle) == speed_up_mode[i]) {//判断加速模式是否匹配
			return correct_angle;
		}
	}
	return input_angle;
}

cv::Rect getRect(int left_top_x, int left_top_y, int width, int height, double* center_x, double* center_y) {
	cv::Rect outputRect;
	outputRect.x = left_top_x;
	outputRect.y = left_top_y;
	outputRect.width = width;
	outputRect.height = height;
	*center_x = double(left_top_x) + double(width) / 2.0;
	*center_y = double(left_top_y) + double(height) / 2.0;
	return outputRect;
}

cv::Mat getMouseControlImage(int width, int height, std::vector<cv::Rect>* image_rect) {//上左下右,从上到下x4
	double control_rect_width = height * 200 / 1080, control_rect_center_x = height * 550 / 1080, control_rect_center_y = height * 550 / 1080, control_rect_radius = height * 400 / 1080;
	double angle_rect_x = height * 1200 / 1080, angle_rect_height = height * 100 / 1080, angle_rect_width = height * 500 / 1080, angle_rect_origin_y = height * 400 / 1080, angle_rect_gap = height * 20 / 1080;
	double center_x[5] = { 0 }, center_y[5] = { 0 };
	double angle_word_x = angle_rect_x + angle_rect_width + 5, angle_word_y = angle_rect_origin_y + angle_rect_height / 2 + 15;
	double Triangle_radius_ = 0.3 * double(control_rect_width);
	cv::Mat control_image = cv::Mat(cv::Size(width, height), CV_8UC3, cv::Scalar(80, 0, 0));
	cv::Scalar botton_color = cv::Scalar(100, 100, 100);
	std::vector<cv::Rect> all_rect;
	char angle_[50] = { 0 };
	all_rect.push_back(getRect(control_rect_center_x - control_rect_width / 2, control_rect_center_y - control_rect_radius, control_rect_width, control_rect_width, &center_x[0], &center_y[0]));//上
	all_rect.push_back(getRect(control_rect_center_x - control_rect_radius, control_rect_center_y - control_rect_width / 2, control_rect_width, control_rect_width, &center_x[1], &center_y[1]));//左
	all_rect.push_back(getRect(control_rect_center_x - control_rect_width / 2, control_rect_center_y + control_rect_radius - control_rect_width, control_rect_width, control_rect_width, &center_x[2], &center_y[2]));//下
	all_rect.push_back(getRect(control_rect_center_x + control_rect_radius - control_rect_width, control_rect_center_y - control_rect_width / 2, control_rect_width, control_rect_width, &center_x[3], &center_y[3]));//右
	all_rect.push_back(getRect(angle_rect_x, angle_rect_origin_y, angle_rect_width, angle_rect_height, &center_x[4], &center_y[4]));//1
	all_rect.push_back(getRect(angle_rect_x, angle_rect_origin_y + angle_rect_gap + angle_rect_height, angle_rect_width, angle_rect_height, &center_x[4], &center_y[4]));//2
	all_rect.push_back(getRect(angle_rect_x, angle_rect_origin_y + 2 * (angle_rect_gap + angle_rect_height), angle_rect_width, angle_rect_height, &center_x[4], &center_y[4]));//3
	all_rect.push_back(getRect(angle_rect_x, angle_rect_origin_y + 3 * (angle_rect_gap + angle_rect_height), angle_rect_width, angle_rect_height, &center_x[4], &center_y[4]));//4
	all_rect.push_back(getRect(angle_rect_x, angle_rect_origin_y + 4 * (angle_rect_gap + angle_rect_height), angle_rect_width, angle_rect_height, &center_x[4], &center_y[4]));//4
	all_rect.push_back(getRect(control_rect_center_x - control_rect_width / 2, control_rect_center_y - control_rect_width / 2, control_rect_width, control_rect_width, &center_x[4], &center_y[4]));//4
	*image_rect = all_rect;
	for (int i = 0; i < all_rect.size(); i++) {
		cv::rectangle(control_image, all_rect[i], botton_color, -1, cv::LINE_AA);
	}
	cv::rectangle(control_image, all_rect[8], botton_color, -1, cv::LINE_AA);
	for (int i = 0; i < 4; i++) {
		lsx::starProcessing::DrawTriangle(control_image, cv::Scalar(255, 255, 255), center_x[i], center_y[i], Triangle_radius_, -i * 90.0);
	}
	for (int i = 0; i < 5; i++) {
		if (i == 0) {
			sprintf_s(angle_, "X10");
		}
		else if (i == 1) {
			sprintf_s(angle_, "X1");
		}
		else if (i == 2) {
			sprintf_s(angle_, "X0.1");
		}
		else if (i == 3) {
			sprintf_s(angle_, "X0.01");
		}
		else {
			sprintf_s(angle_, "Reset");
		}
		cv::putText(control_image, angle_, cv::Point(angle_word_x, angle_word_y + i * (angle_rect_gap + angle_rect_height)), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
	}
	cv::circle(control_image, cv::Point(control_rect_center_x, control_rect_center_y), 0.7 * Triangle_radius_, cv::Scalar(255, 255, 255), -1, cv::LINE_AA);
	cv::putText(control_image, "RA East Motion", cv::Point(all_rect[0].x - 10, all_rect[0].y - 8), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
	cv::putText(control_image, "RA West Motion", cv::Point(all_rect[2].x - 10, all_rect[2].y + 28 + all_rect[1].height), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
	cv::putText(control_image, "DEC Anticlockwise", cv::Point(all_rect[1].x - 30, all_rect[1].y - 8), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
	cv::putText(control_image, "DEC Clockwise", cv::Point(all_rect[3].x - 10, all_rect[3].y - 8), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
	return control_image;
}

void equ_control_mouse_callback(int event_, int x, int y, int flags, void* userData) {
	if (equ_control_deal_mouse_botton) {
		if (event_ == cv::EVENT_LBUTTONDOWN) {
			equ_control_mouse_botton_x = x;
			equ_control_mouse_botton_y = y;
			if (equ_control_angle_change_enable) {
				adjust_angle += cell_angle;
				if (adjust_angle > 250) {
					adjust_angle = 250;
				}
			}
			if (angle_reset_enable) {
				adjust_angle = 0;
			}
			equ_control_mouse_get_coodinate = true;
		}
		else if (event_ == cv::EVENT_RBUTTONDOWN) {
			if (!angle_reset_enable) {
				if (!equ_control_angle_change_enable) {
					equ_control_quit = true;
				}
				else {
					adjust_angle -= cell_angle;
					if (adjust_angle < 0) {
						adjust_angle = 0;
					}
				}
			}
		}
	}
	if (event_ == cv::EVENT_MOUSEWHEEL) {
		if (equ_control_angle_change_enable) {
			if (cv::getMouseWheelDelta(flags) > 0) {
				adjust_angle += cell_angle;
				if (adjust_angle > 250) {
					adjust_angle = 250;
				}
			}
			else {
				adjust_angle -= cell_angle;
				if (adjust_angle < 0) {
					adjust_angle = 0;
				}
			}
		}
	}
	if (event_ == cv::EVENT_MOUSEMOVE) {
		equ_control_mouse_touch_x = x;
		equ_control_mouse_touch_y = y;
	}
}

Eigen::MatrixXd lsx::control::MouseControl(int width, int height) {
	Eigen::MatrixXd outputAngle(2, 1);
	std::vector<cv::Rect> rect_table;
	cv::Mat show_image;
	std::string window_name = "Shixuan Liu - Equatorial Control";
	cv::Point show_angle_position = cv::Point(height * 1200 / 1080, height * 300 / 1080);
	std::clock_t ra_start_time = 0, end_time = 0, dec_start_time = 0;
	char show_angle_[50] = { 0 }, show_run_state[100] = { 0 };
	int keyNumber = 0, i = 0, ra_direction = 0, dec_direction = 0;
	int ra_runtime = 0, dec_runtime = 0;
	double ra_now_runtime = 0, dec_now_runtime = 0;
	outputAngle *= 0;
	cv::namedWindow(window_name, cv::WINDOW_NORMAL);
	setWindowProperty(window_name, cv::WND_PROP_FULLSCREEN, cv::WINDOW_FULLSCREEN);
	cv::setMouseCallback(window_name, equ_control_mouse_callback);
	while (!equ_control_quit) {
		show_image = getMouseControlImage(width, height, &rect_table);
		if((equ_control_equ_ra_is_running || equ_control_equ_dec_is_running)){
			end_time = std::clock();
			ra_now_runtime = double(end_time) - double(ra_start_time);
			dec_now_runtime = double(end_time) - double(dec_start_time);
			if (ra_now_runtime > ra_runtime) {
				equ_control_equ_ra_is_running = false;
			}
			if (dec_now_runtime > dec_runtime) {
				equ_control_equ_dec_is_running = false;
			}
			if (ra_now_runtime < ra_runtime && dec_now_runtime < dec_runtime) {
				sprintf_s(show_run_state, "Equatorial is running (RA: %d ms, DEC: %d ms) . . .", int(ra_runtime - ra_now_runtime), int(dec_runtime - dec_now_runtime));
			}
			else if (ra_now_runtime < ra_runtime && dec_now_runtime >= dec_runtime) {
				sprintf_s(show_run_state, "Equatorial is running (RA: %d ms, DEC ready) . . .", int(ra_runtime - ra_now_runtime));
			}
			else if(ra_now_runtime >= ra_runtime && dec_now_runtime < dec_runtime){
				sprintf_s(show_run_state, "Equatorial is running (RA ready, DEC: %d ms) . . .", int(dec_runtime - dec_now_runtime));
			}
			cv::putText(show_image, show_run_state, cv::Point(5, 25), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
		}
		else {
			cv::putText(show_image, "Equatorial ready !", cv::Point(5, 25), cv::FONT_HERSHEY_SIMPLEX, 1, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
		}
		for (i = 0; i < rect_table.size(); i++) {
			if (lsx::math::PointInRect(equ_control_mouse_touch_x, equ_control_mouse_touch_y, rect_table[i])) {
				cv::rectangle(show_image, rect_table[i], cv::Scalar(255, 255, 255), 3, cv::LINE_AA);
				if (i >= 4 && i <= 8) {
					if (i == 4) { cell_angle = 10.0; }
					else if (i == 5) { cell_angle = 1.0; }
					else if (i == 6) { cell_angle = 0.1; }
					else if (i == 7) { cell_angle = 0.01; }
					equ_control_angle_change_enable = true;
					if (i == 8) { 
						angle_reset_enable = true; 
						equ_control_angle_change_enable = false;
					}
				}
				break;
			}
			else {
				equ_control_angle_change_enable = false;
				angle_reset_enable = false;
			}
		}
		if (equ_control_mouse_get_coodinate) {
			equ_control_mouse_get_coodinate = false;
			equ_control_deal_mouse_botton = false;
			for (i = 0; i < rect_table.size(); i++) {
				if (lsx::math::PointInRect(equ_control_mouse_touch_x, equ_control_mouse_touch_y, rect_table[i])) {
					if (i == 0) {
						if (!equ_control_equ_ra_is_running) {
							lsx::control::ra_goto_motion(RA_DIR_BACKWARD, adjust_angle);
							ra_start_time = std::clock();
							ra_runtime = lsx::control::EquatorialRunTime_ms(adjust_angle, RA_STEPMOTOR, RA_WAIT_MODE_NORMAL);
							equ_control_equ_ra_is_running = true;
						}
					}
					else if (i == 1) {
						if (!equ_control_equ_dec_is_running) {
							lsx::control::dec_goto_motion(DEC_DIR_BACKWARD, adjust_angle);
							dec_start_time = std::clock();
							dec_runtime = lsx::control::EquatorialRunTime_ms(adjust_angle, DEC_STEPMOTOR, RA_WAIT_MODE_NORMAL);
							equ_control_equ_dec_is_running = true;
						}
					}
					else if (i == 2) {
						if (!equ_control_equ_ra_is_running) {
							lsx::control::ra_goto_motion(RA_DIR_FORWARD, adjust_angle);
							ra_start_time = std::clock();
							ra_runtime = lsx::control::EquatorialRunTime_ms(adjust_angle, RA_STEPMOTOR, RA_WAIT_MODE_NORMAL);
							equ_control_equ_ra_is_running = true;
						}
					}
					else if (i == 3) {
						if (!equ_control_equ_dec_is_running) {
							lsx::control::dec_goto_motion(DEC_DIR_FORWARD, adjust_angle);
							dec_start_time = std::clock();
							dec_runtime = lsx::control::EquatorialRunTime_ms(adjust_angle, DEC_STEPMOTOR, RA_WAIT_MODE_NORMAL);
							equ_control_equ_dec_is_running = true;
						}
					}
					break;
				}
			}
			equ_control_deal_mouse_botton = true;
		}
		sprintf_s(show_angle_, "Angle setting: %d.%d degree", int(floor(adjust_angle)), int((100.0 * (adjust_angle - floor(adjust_angle)))));
		cv::putText(show_image, show_angle_, show_angle_position, cv::FONT_HERSHEY_SIMPLEX, 1.4, cv::Scalar(255, 255, 255), 2, cv::LINE_AA);
		cv::imshow(window_name, show_image);
		cv::waitKey(20);
	}
	cv::destroyAllWindows();
	return outputAngle;
}

Global.h

#ifndef GLOBAL_H
#define GLOBAL_H

#include<string.h>
#include"LsxMath.h"
#include<ctime>
#include<Windows.h>
#include <stdio.h>
#include<time.h>
#include <chrono>
#include"Astronomy.h"

#define DEC_IS_ON_THE_RIGHT 0//赤纬在右半盘位置
#define DEC_IS_ON_THE_LEFT 1//赤纬在左半盘位置

/**
 * @brief 得到当地恒星时的函数
 * @param none
 * @return 当地恒星时,单位:°
 */
double local_sidreal_time_degree();

#endif

Global.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"Global.h"

/*--------------------------------------观测地设置------------------------------------------------*/

double global_latitude = 26.653;//观测地纬度,单位:°
double global_longitude = 102.240;//观测地经度,单位:°

/*--------------------------------------串口------------------------------------------------*/

CString PORTNAME = "COM4";//连接赤道仪的串口号

/*-------------------------------------------星点识别参数-----------------------------------------------*/

double contrastIndex_log_gamma = 50;//灰度图像对比度前乘系数
double contrastIndex_gamma = 0.4;//在对比度gamma变换时的幂指数

int erodeSize = 3;//图像腐蚀卷积核大小
int dilateSize = 11;//图像膨胀卷积核大小
double imageThreshold = 45;//图像二值化阈值
int maxStarNumber = 70;//函数寻找的最多星点
int maxSize_contours = 1000;//轮廓上边界
int minSize_contours = 12;//轮廓下边界
int fitEllipseRegion = 60;//使用椭圆拟合时矩形方框与图像边界的最小距离

cv::Scalar star_frame_color = cv::Scalar(0, 255, 0);//星点外框的颜色(适用于矩形外框、圆形外框)
cv::Scalar star_size_brightness_word_color = cv::Scalar(220, 184, 190);//表示字体的颜色
cv::Scalar star_number_word_color = cv::Scalar(0, 255, 255);//表示字体的颜色

/*--------------------------------------赤道仪参数------------------------------------------------*/

int RA_reduction_ratio = 300;
int DEC_reduction_ratio = 100;
int RA_teeth_number = 202;//赤经轴输出端的齿数,最后一级输出的齿数,对于100:1的谐波减速机,其钢轮齿数为2*100+2=202
double RA_teeth_period = 86164.0 / double(RA_teeth_number);//赤经轴齿轮大周期,谐波减速机每一个齿经过的时间

/*--------------------------------------电子极轴镜参数、电子极轴镜类参数------------------------------------------------*/

double PIXEL_SIZE_POLAR_MIRROR_um = 3.75;//极轴相机像元大小 2.9
double FOCAL_LENGTH_POLAR_MIRROR_mm = 25.5;//极轴相机焦距 51.5803
double pixel_per_degree_polar_mirror = (PI * FOCAL_LENGTH_POLAR_MIRROR_mm * 1000.0) / (180.0 * PIXEL_SIZE_POLAR_MIRROR_um);//像素/度,电子极轴镜的分辨系数
double emirror_frame_width_pixel = 1280;//电子极轴镜图像宽度 1920 6248
double emirror_frame_height_pixel = 960;//电子极轴镜图像高度 1080 4176
double emirror_angle_to_dec_axis_degree = 0;//电子极轴镜CMOS正方向与DEC轴的偏转角,在这款电子极轴镜中为45°

/**
 * opencv曝光参数于输入参数对应表:
 * exposure = -1: 曝光时间:640ms  1
 * exposure = -2: 曝光时间:320ms  2
 * exposure = -3: 曝光时间:160ms  4
 * exposure = -4: 曝光时间:80ms  8
 * exposure = -5: 曝光时间:40ms  16
 * exposure = -6: 曝光时间:20ms
 * exposure = -7: 曝光时间:10ms
 * exposure = -8: 曝光时间:5ms
 * exposure = -9: 曝光时间:2.5ms
 * exposure = -10: 曝光时间:1.25ms
 * exposure = -11: 曝光时间:0.625ms
 * exposure = -12: 曝光时间:0.3125ms
 * exposure = -13: 曝光时间:0.15625ms
 * exposure = -14: 曝光时间:0.078125ms
 */
double emirror_exposure = -4;//极轴相机曝光,640ms
int emirror_frame_sum_number = 6;//叠加图像张数
double emirror_exposure_when_calc_ra = -5;//当RA运行时的极轴相机曝光,160ms
double emirror_brightness = 10;//极轴相机的亮度
double emirror_gain = 0;//极轴相机的ISO(增益)

cv::Scalar e_polar_color = cv::Scalar(255, 255, 0);//赤道仪极轴绘制颜色
cv::Scalar ncp_polar_color = cv::Scalar(0, 0, 255);//北天极绘制颜色

double error_amplification_factor = 4.0;//极轴误差放大倍数
double max_calc_angle_region = 40.0;//求解赤道仪极轴时的移动角度,单位:°
double step_angle_calc_e_polar = 2;//求解赤道仪极轴时的最小移动角度,单位:°
int ncp_position_data_set_size = 3;//调整时北天极位置更新数据集的大小
int polarMirrorAdjustImageSize = 800;//放大图的大小

double one_frame_radius = 12.0 * emirror_frame_height_pixel / 1080.0;//星点框半径

/*--------------------------------------导星镜参数------------------------------------------------*/

double PIXEL_SIZE_GUIDE_MIRROR_um = 2.9;//导星相机像元大小,单位:um
double FOCAL_LENGTH_GUIDE_MIRROR_mm = 180.0;//导星相机焦距,单位:mm
double pixel_per_degree_guide_mirror = (PI * FOCAL_LENGTH_GUIDE_MIRROR_mm * 1000.0) / (180.0 * PIXEL_SIZE_GUIDE_MIRROR_um);//像素/度,导星镜的分辨系数
double guide_mirror_frame_width_pixel = 1920;//导星镜图像宽度
double guide_mirror_frame_height_pixel = 1080;//导星镜图像高度
double guide_mirror_view_angle_width = 2.0 * atan(guide_mirror_frame_width_pixel * PIXEL_SIZE_GUIDE_MIRROR_um / (1000.0 * 2.0 * FOCAL_LENGTH_GUIDE_MIRROR_mm)) / PI * 180.0;//横向视角大小
double guide_mirror_view_angle_height = 2.0 * atan(guide_mirror_frame_height_pixel * PIXEL_SIZE_GUIDE_MIRROR_um / (1000.0 * 2.0 * FOCAL_LENGTH_GUIDE_MIRROR_mm)) / PI * 180.0;//纵向视角大小

/**
 * opencv曝光参数于输入参数对应表:
 * exposure = -1: 曝光时间:640ms  1
 * exposure = -2: 曝光时间:320ms  2
 * exposure = -3: 曝光时间:160ms  4
 * exposure = -4: 曝光时间:80ms  8
 * exposure = -5: 曝光时间:40ms  16
 * exposure = -6: 曝光时间:20ms
 * exposure = -7: 曝光时间:10ms
 * exposure = -8: 曝光时间:5ms
 * exposure = -9: 曝光时间:2.5ms
 * exposure = -10: 曝光时间:1.25ms
 * exposure = -11: 曝光时间:0.625ms
 * exposure = -12: 曝光时间:0.3125ms
 * exposure = -13: 曝光时间:0.15625ms
 * exposure = -14: 曝光时间:0.078125ms
 */
double guide_mirror_exposure = -4;//导星相机曝光,320ms
int guide_mirror_frame_sum_number = 12;//叠加图像张数
double guide_mirror_brightness = 30;//导星相机的亮度
double guide_mirror_gain = 2.0;//导星相机的ISO(增益)

/*--------------------------------------相机ID参数------------------------------------------------*/

int video_id = 0;//相机ID选择
int api_preference = cv::CAP_DSHOW;//相机编码方式选择

/*--------------------------------------自动寻星控制器------------------------------------------------*/

int DEC_side = DEC_IS_ON_THE_RIGHT;//赤道仪DEC的位置
std::string this_target_name = "empty";//当前目标名称
std::string this_target_number = "empty";//当前观测目标编号(如M42等)
bool noTarget = true;//是否是第一次观测的标志
bool after_guide = false;//是否是在导星之后进入自动寻星

int zenith_line_color[3] = { 150, 150, 150 };//地平线颜色
cv::Scalar zenith_str_line(238, 104, 123);//中天直线颜色
cv::Scalar background(0, 0, 0);//背景颜色
cv::Scalar background_line(50, 50, 50);//刻度线颜色
cv::Scalar star_color(133, 217, 253);//恒星颜色
cv::Scalar not_star_color(254, 235, 233);//天体颜色
cv::Scalar big_word(238, 104, 123);//图样范围字符颜色

cv::Scalar coordinate_words(159, 255, 84);//鼠标触摸到天体后显示坐标的颜色
cv::Scalar show_state_1_color(255, 255, 255);//Select a star with the mouse to calibrate the '0' position.提示符颜色

cv::Scalar my_equatorial_instrument_color(238, 104, 123);//赤道仪图像显示的颜色
cv::Scalar my_equatorial_instrument_line_color(238, 104, 123);//赤道仪移动线颜色

cv::Scalar optional_target_color(159, 255, 84);//可选天体的图像显示颜色

int goto_image_width = 1600, goto_image_height = 800;//自动寻星的图像大小

/*-------------------------------------------星点跟踪参数-----------------------------------------------*/

double maxField = 50;//最大求解像素区域
double maxFieldIndex = 0.8;//求解指数

/*-------------------------------------------导星控制器参数-----------------------------------------------*/

int guide_period_ms = 800;//导星周期期望值,当实际周期大于该值时无效

double adjust_threhold = 0.3;//调整阈值,当误差绝对值大于该值时进行调整
double force_adjust_threshold = 1.5;//强制调整阈值,大于该值时必须调整
double guide_kd_adjust_threshold = 0.8;//当误差变化量大于该值时,启用d控制分量

double LPF_index = 0.4;//低通滤波器保留波比例
double error_track_threhold = 60;//错误阈值,当超过此值后认为跟踪错误

double guide_kp = 0.8;//导星PI控制中的P系数
double guide_ki = 0.3;//导星PI控制中的I系数
double guide_kd = 0.5;//导星控制中的D系数
double guide_ki_long = 0.05;//导星第二I系数

double guide_kp_dec = 0.8;//P系数
double guide_ki_dec = 0.3;//I系数
double guide_kd_dec = 0.3;//导星控制中的D系数
double guide_ki_dec_long = 0.05;//导星第二I系数

double differential_coefficient_region = 1.5;//在频谱分析模块中,如果当前误差的导数和预测误差的导数值差距小于该值时,认为正确预测
double guide_star_max_predict_control = 2.0;//导星控制器预测调整的最大值
double GPR_run_index = 0.08;//为了减少导星控制器的计算,当导星控制器高斯过程回归预测模块开始求解后,在下一次求解之前需要检测到预备数据集刷新GPR_run_index * GPR_sample_number次
double Spectral_analysis_run_index = 0;//为了减少导星控制器的计算,当导星控制器高斯过程回归预测模块开始求解后,在下一次求解之前需要检测到预备数据集刷新GPR_run_index * GPR_sample_number次
int harmonic_number = 50;//频谱分析预测模块预测的周期函数数量
int sum_error_number = 5;//误差累计范围
int sum_error_number_long = 10;//误差长时间累计范围
int guide_median_filter_length_RA = 7;//RA中值滤波窗口大小
int guide_median_filter_length_DEC = 7;//DEC中值滤波窗口大小
int guide_error_vector_sum_number = 3;//导星过程中对偏移向量进行求和平均值的数量

int error_frame_width = 1550, error_frame_height = 750, error_frame_scatter_width = 749;//导星控制器图像显示大小

cv::Scalar ra_error_line_color = cv::Scalar(255, 164, 30);//RA轴相对误差曲线颜色
cv::Scalar dec_error_line_color = cv::Scalar(0, 0, 255);//DEC轴相对误差曲线颜色
cv::Scalar ra_control_line_color = cv::Scalar(100, 24, 0);//RA轴控制量直线颜色
cv::Scalar dec_control_line_color = cv::Scalar(0, 0, 80);//DEC轴控制量直线颜色
cv::Scalar guide_image_background = cv::Scalar(0, 0, 0);//控制器背景颜色
cv::Scalar guide_image_scale = cv::Scalar(100, 100, 100);//控制器横向刻度颜色
cv::Scalar scatter_point_color = cv::Scalar(205, 38, 125);//散点颜色
int scatter_point_radius = 2;//散点图点半径

double guide_star_image_max_error = 4.0;//导星控制器显示的最大误差

char file_saving_path_E_RA[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\E_RA.xlsx";//真周期误差文件保存路径
char file_saving_path_e_RA[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\e_RA_.xlsx";//相对误差文件保存路径
char file_saving_path_u_RA[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\u_RA.xlsx";//控制量文件保存路径

char file_saving_path_E_DEC[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\E_DEC.xlsx";//真周期误差文件保存路径
char file_saving_path_e_DEC[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\e_DEC_.xlsx";//相对误差文件保存路径
char file_saving_path_u_DEC[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\u_DEC.xlsx";//控制量文件保存路径

char guide_time_saving_path[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\guide_time.xlsx";//控制量文件保存路径

char error_scatter_image_saving_path[] = "C:\\Users\\Administrator\\Desktop\\Guide Star Output\\Guide Data\\guide_star_drift_scatter_image.jpg";//控制量文件保存路径

/*--------------------------------------当地恒星时函数------------------------------------------------*/

lsx::astronomy::AstroTimer global_astro_timer;//恒星时计算器,确定天体运行规律

double local_sidreal_time_degree() {
	return global_astro_timer.get_local_sidereal_time();
}

SerialCommunication.h

#ifndef SERIALCOMMUNICATION_H
#define SERIALCOMMUNICATION_H

#include<iostream>
#include<Eigen/Dense>
#include<Windows.h>
#include<cmath>
#include"windows.h"
#include"atlstr.h"
#include<string.h>
#include<TCHAR.H>
#include<conio.h>
#include<stdarg.h>
#include<vector>

/*串口通信及赤道仪运行控制*/
namespace lsx {
	namespace serial {
		class serial_writer {
		public:
			bool have_open = false;

			/** 
			 * @brief 设置串口参数。
			 * @param port_name 串口名称,请打开<设备管理器>查找电脑连接单片机的串口,如令port_name = "COM5";
			 * @param baud_rate 波特率。
			 * @return void
			 */
			void set_serial(CString port_name, int baud_rate = 9600);

			/** 
			 * @brief 发送单字节数据,调用该函数立即发送
			 * @param input_data_1_byte 字符型(8位)数据。
			 * @return void
			 */
			void send_data(char input_data_1_byte);

			/** 
			 * @brief 发送一个数据包,调用该函数立即发送,从input_data[0]开始发送。
			 * @param input_data 待发送的字符容器
			 * @return void
			 */
			void send_data(std::vector<char> input_data);

			/**
			 * @brief 关闭串口
			 * @param none
			 * @return void
			 */
			void Serial_close();
		private:
			LPCWSTR COM_port;
			HANDLE hCom;
			int baud_rate = 9600;
			int serial_open(LPCWSTR COMx, int BaudRate);
			int serial_write(char lpOutBuffer[]);
		};

		int serial_open(LPCWSTR COMx);

		/**
		 * @brief 寻找赤道仪端口,并将全局变量置位
		 */
		void FindEquatorial();
	}
}

#endif

SerialCommunication.cpp

#include"SerialCommunication.h"

extern CString PORTNAME;

void lsx::serial::serial_writer::set_serial(CString port_name, int baud_rate) {
	this->COM_port = port_name.AllocSysString();
	this->baud_rate = baud_rate;
}

void lsx::serial::serial_writer::send_data(char input_data_1_byte) {
	bool serial_open = false;
	serial_open = this->serial_open(this->COM_port, this->baud_rate);
	if (serial_open) {
		this->serial_write(&input_data_1_byte);
	}
}

void lsx::serial::serial_writer::send_data(std::vector<char> input_data) {
	bool serial_open = false;
	int i;
	serial_open = this->serial_open(this->COM_port, this->baud_rate);
	if (serial_open) {
		for (i = 0; i < input_data.size(); i++) {
			this->serial_write(&input_data[i]);
		}
	}
}

int lsx::serial::serial_writer::serial_open(LPCWSTR COMx, int BaudRate) {
	this->hCom = CreateFile(COMx, //COMx口    
		GENERIC_READ | GENERIC_WRITE, //允许读和写    
		0, //独占方式    
		NULL,
		OPEN_EXISTING, //打开而不是创建     
		0, //重叠方式FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED  (同步方式设置为0)
		NULL);
	if (this->hCom == INVALID_HANDLE_VALUE)
	{
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED);
		std::cout << "没有连接赤道仪!" << std::endl;
		SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE);
		this->have_open = false;
		return false;
	}
	SetupComm(this->hCom, 1024, 1024); //输入缓冲区和输出缓冲区的大小都是1024 

								 //设定读写超时 
								 /*COMMTIMEOUTS TimeOuts;
								 TimeOuts.ReadIntervalTimeout=1000;
								 TimeOuts.ReadTotalTimeoutMultiplier=500;
								 TimeOuts.ReadTotalTimeoutConstant=5000; //设定写超时
								 TimeOuts.WriteTotalTimeoutMultiplier=500;
								 TimeOuts.WriteTotalTimeoutConstant = 2000;
								 SetCommTimeouts(hCom, &TimeOuts); //设置超时
								 */
	DCB dcb;
	GetCommState(this->hCom, &dcb);
	dcb.BaudRate = BaudRate;		//设置波特率为BaudRate
	dcb.ByteSize = 8;					//每个字节有8位 
	dcb.Parity = NOPARITY;			//无奇偶校验位 
	dcb.StopBits = ONESTOPBIT;		//一个停止位
	SetCommState(this->hCom, &dcb);		//设置参数到hCom
	PurgeComm(this->hCom, PURGE_TXCLEAR | PURGE_RXCLEAR);//清空缓存区		//PURGE_TXABORT 中断所有写操作并立即返回,即使写操作还没有完成。
												   //PURGE_RXABORT 中断所有读操作并立即返回,即使读操作还没有完成。
												   //PURGE_TXCLEAR 清除输出缓冲区 
												   //PURGE_RXCLEAR 清除输入缓冲区  
	this->have_open = true;
	return true;
}

int lsx::serial::serial_writer::serial_write(char lpOutBuffer[]) {//同步写串口
	DWORD dwBytesWrite = sizeof(lpOutBuffer);
	COMSTAT ComStat;
	DWORD dwErrorFlags;
	BOOL bWriteStat;
	ClearCommError(this->hCom, &dwErrorFlags, &ComStat);
	bWriteStat = WriteFile(this->hCom, lpOutBuffer, dwBytesWrite, &dwBytesWrite, NULL);
	if (!bWriteStat)
	{
		//printf("写串口失败!\n");
		this->have_open = false;
		return false;
	}
	PurgeComm(this->hCom, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
	return true;
}

void lsx::serial::serial_writer::Serial_close() {//关闭串口
	CloseHandle(this->hCom);
}

int lsx::serial::serial_open(LPCWSTR COMx) {
	HANDLE hCom;
	bool output;
	hCom = CreateFile(COMx, //COMx口    
		GENERIC_READ | GENERIC_WRITE, //允许读和写    
		0, //独占方式    
		0,
		OPEN_EXISTING, //打开而不是创建     
		FILE_ATTRIBUTE_NORMAL, //重叠方式FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED  (同步方式设置为0)
		0);
	if (hCom == INVALID_HANDLE_VALUE){
		CloseHandle(hCom);
		return false;
	}
	CloseHandle(hCom);
	return true;
}

CString PORTNAME_3 = "COM3";
CString PORTNAME_4 = "COM4";
CString PORTNAME_5 = "COM5";

void lsx::serial::FindEquatorial() {
	int i;
	CString CcomArray[3] = { "COM3" ,"COM4" ,"COM5" };
	/*LPCWSTR comArray[3] = {_T("COM3") ,_T("COM4") ,_T("COM5") };*/
	for (i = 0; i < 3; i++) {
		if (lsx::serial::serial_open(CcomArray[i].AllocSysString())) {
			//PORTNAME = CcomArray[i];
			std::cout << "COM" << i + 3 << std::endl;
			switch (i + 3) {
			case 3:PORTNAME = PORTNAME_3;
			case 4:PORTNAME = PORTNAME_4;
			case 5:PORTNAME = PORTNAME_5;
			}
			break;
		}
	}
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

伪程序猿l S x

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值