Skip to content
This repository was archived by the owner on Dec 3, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
40fafa1
refactor(utils): rename transform.hpp to coordinate.hpp
heyeuu Sep 1, 2025
83751c5
feat(classifier): add classifier
heyeuu Sep 2, 2025
477a35f
fix(classifier): resolve issues in classifier class implementation
heyeuu Sep 2, 2025
cd95986
添加注释
fans963 Sep 2, 2025
879682b
feat(logging): add logger module
heyeuu Sep 2, 2025
0e7e505
fix(build): correct CMakeLists.txt include directory configuration
heyeuu Sep 3, 2025
78f16f9
feat(logging): add logger module
heyeuu Sep 3, 2025
7e477e6
feat(debug): add stringifier utility for ID string conversion
heyeuu Sep 3, 2025
1586caf
feat(identifier): add identifier module for armor identification
heyeuu Sep 3, 2025
541f531
fix(utils): correct incomplete namespace in stringifier module
heyeuu Sep 3, 2025
4304b8c
refactor(solver): rewrite interface implementation and add index-to-i…
heyeuu Sep 4, 2025
43109dc
add comment
fans963 Sep 4, 2025
cbff1ad
Merge remote-tracking branch 'upstream/main' into tongji-dev
heyeuu Sep 4, 2025
ac59b59
Merge remote-tracking branch 'upstream/with_comment' into tongji-dev
heyeuu Sep 4, 2025
8b24d98
fix(identifier):enhance identifier debug output and change target col…
heyeuu Sep 4, 2025
2bc4e9d
fix(identifier):enhance identifier debug output
heyeuu Sep 5, 2025
99a4bc7
fix(identifier):add internal recording flag
heyeuu Sep 5, 2025
53fd55a
添加了接口的注释
AlrayQiu Sep 7, 2025
570d100
修复错误的函数签名
AlrayQiu Sep 12, 2025
7fe53df
feat: add state machine
heyeuu Sep 14, 2025
244d7c5
feat: Add predictor module
heyeuu Sep 15, 2025
af9017c
feat(env): Add libfmt-dev and libspdlog-dev dependencies
heyeuu Sep 15, 2025
399aa78
Merge branch 'main' into tongji-dev
AlrayQiu Sep 15, 2025
d024183
refactor(interface): Rename the file of armors and change the armor i…
heyeuu Sep 17, 2025
deef680
WIP: partially implement ITargetPredictor interface
heyeuu Sep 17, 2025
00fdd5e
WIP: partially implement ITargetPredictor interface
heyeuu Sep 18, 2025
9596d7a
WIP: partially implement ITargetPredictor interface
heyeuu Sep 18, 2025
dc596de
refactor(prediction): refactor IPredictor and ITargetPredictor implem…
heyeuu Sep 20, 2025
0dcffbf
refactor(predictor): overhaul predictor implementation
heyeuu Sep 22, 2025
eeb09ae
Merge branch 'main' into tongji-dev
AlrayQiu Sep 22, 2025
b873347
feat: add state machine
heyeuu Sep 14, 2025
e746464
merge: fix conflicts from git merge
heyeuu Sep 23, 2025
2d7eb52
fix(targeting): correct armor target acquisition logic
heyeuu Sep 25, 2025
30235d2
refactor(predict, utils): move Extended Kalman Filter from utils to p…
heyeuu Sep 26, 2025
1538095
feat: add trajectory
heyeuu Sep 28, 2025
442f366
[Add] 添加火控实现的头文件
AlrayQiu Oct 1, 2025
da83d40
Merge remote-tracking branch 'origin/main' into tongji-dev
heyeuu Oct 1, 2025
337fc34
Merge remote-tracking branch 'origin/tongji-dev' into tongji-dev
heyeuu Oct 1, 2025
ba1f6fb
[Add] 添加Tracker实现
AlrayQiu Oct 2, 2025
e38116e
Merge branch 'tongji-dev' of github.com:Alliance-Algorithm/alliance_a…
heyeuu Oct 2, 2025
3e0fe3d
fix(tracker): fix data structure in tracker.hpp
heyeuu Oct 2, 2025
64e372a
fix(tracker): fix data structure in tracker.hpp
heyeuu Oct 2, 2025
44a79ff
feat(fire_controller): add aim point selection and trajectory classes
heyeuu Oct 3, 2025
2dc6cd8
feat(fire_control): add fire command validation class fire_judge
heyeuu Oct 3, 2025
c44607a
refactor(control): rename classes and refine fire logic
heyeuu Oct 4, 2025
3aa3c9d
feat(fire_control): implement basic module interfaces
heyeuu Oct 4, 2025
890a40a
fix(tracking): improve live_target convergence logic
heyeuu Oct 6, 2025
e599cb4
feat: complete core logic across multiple modules
heyeuu Oct 6, 2025
b11971e
chore(state_machine):refactor StateMachine to PIMPL pattern and do so…
heyeuu Oct 7, 2025
faaa5b1
feat(tracking): complete LiveTargetManager update logic
heyeuu Oct 7, 2025
08b7ebd
feat(fire_control):enhance CalculateTarget logic and add miss public …
heyeuu Oct 8, 2025
7e3b743
refactor(state_machine): complete state machine update logic
heyeuu Oct 8, 2025
010b466
perf(filter): make Kalman filter type inference compile-time
heyeuu Oct 8, 2025
ab6f47a
feat(decider): implement priority assessment logic
heyeuu Oct 9, 2025
344ee50
chore(state): remove redundant logic from state machine
heyeuu Oct 9, 2025
6b29508
chore: remove miscellaneous trivial cruft
heyeuu Oct 9, 2025
919cae3
chore(fire controller): remove redundant timestamp setter function
heyeuu Oct 10, 2025
5111275
refactor: complete initial architectural restructuring
heyeuu Oct 13, 2025
7b15810
refactor(project): reorganize directory structure to match new archit…
heyeuu Oct 13, 2025
9ccbf65
refactor(namespace): update namespaces to align with new architecture
heyeuu Oct 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 114 additions & 0 deletions src/tongji/fire_controller/fire_controller.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
#include "fire_controller.hpp"

#include <memory>
#include <utility>

#include "../identifier/identified_armor.hpp"
#include "../predictor/live_target_manager/live_target_manager.hpp"
#include "../predictor/target_snapshot_manager/target_snapshot_manager.hpp"
#include "../state_machine/state_machine.hpp"
#include "data/fire_control.hpp"
#include "fire_decision.hpp"
#include "interfaces/target_predictor.hpp"

namespace world_exe::tongji::fire_control {

using TargetSnapshotManager = predictor::TargetSnapshotManager;
using StateMachine = state_machine::StateMachine;
using IdentifiedArmor = identifier::IdentifiedArmor;
using CarIDFlag = enumeration::CarIDFlag;
using LiveTargetManager = predictor::LiveTargetManager;
using TimeStamp = time_stamp::TimeStamp;

class FireController::Impl {
public:
Impl(bool auto_fire, const double& control_delay_in_second, const double& bullet_speed,
double yaw_offset, double pitch_offset,
std::shared_ptr<interfaces::ICarState> state_machine,
std::shared_ptr<interfaces::ITargetPredictor> live_target_manager)
: control_delay_(control_delay_in_second)
, bullet_speed_(bullet_speed)
, fire_decision_(std::make_unique<FireDecision>(auto_fire))
, state_machine_(state_machine)
, live_target_manager_(std::move(live_target_manager)) { }

// TODO:std::time_t
const data ::FireControl CalculateTarget(const std ::time_t& time_duration) const {

if (!identified_armors_ || !fire_decision_ || !state_machine_ || !live_target_manager_)
return { .fire_allowance = false };

auto converged_cars = state_machine_->GetAllowdToFires();
auto snapshot_manager = live_target_manager_->GetPredictor(converged_cars);
if (!snapshot_manager)
return data::FireControl { .time_stamp = time_stamp_.GetTimeStamp(),
.gimbal_dir = Eigen::Vector3d::Constant(std::numeric_limits<double>::quiet_NaN()),
.fire_allowance = false };

auto armors_in_gimbal_control = snapshot_manager->Predictor(control_delay_);
allowed_target_id_ = state_machine_->GetAllowdToFires();

auto target_gimbal_spacing =
armors_in_gimbal_control->GetArmors(allowed_target_id_).front();

auto gimbal_command =
std::dynamic_pointer_cast<TargetSnapshotManager>(snapshot_manager)->GetGimbalCommand();

auto fire_command =
fire_decision_->ShouldFire(gimbal_command, target_gimbal_spacing.position);
firable_ = fire_command;

data::FireControl result;
result.fire_allowance = fire_command;
result.gimbal_dir << gimbal_command.yaw, gimbal_command.pitch, 0;
result.time_stamp = time_stamp_.GetTimeStamp();
return result;
}

const CarIDFlag GetAttackCarId() const {
if (firable_) { }
return allowed_target_id_;
}

void Update(std::shared_ptr<interfaces::IArmorInImage> armors, const double& gimbal_yaw) {
time_stamp_.SetTimeStamp(std::time(nullptr));
UpdateIdentifiedArmor(armors);
UpdateGimbalPosition(gimbal_yaw);
}

private:
void UpdateIdentifiedArmor(std::shared_ptr<interfaces::IArmorInImage> armors) {
identified_armors_ = armors;
}
void UpdateGimbalPosition(const double& gimbal_yaw) { gimbal_yaw_ = gimbal_yaw; };
TimeStamp GetTimeStamp() const { return time_stamp_; }

double gimbal_yaw_;
double control_delay_;
double bullet_speed_;

mutable CarIDFlag allowed_target_id_;
mutable double firable_ { false };

std::shared_ptr<interfaces::IArmorInImage> identified_armors_;

std::unique_ptr<FireDecision> fire_decision_;
time_stamp::TimeStamp time_stamp_ { std::time(nullptr) };

std::shared_ptr<interfaces::ICarState> state_machine_;
std::shared_ptr<interfaces::ITargetPredictor> live_target_manager_;
};

FireController::FireController(std::shared_ptr<interfaces::ICarState> state_machine, bool auto_fire,
const double& control_delay_in_second, const double& bullet_speed, double yaw_offset,
double pitch_offset, std::shared_ptr<interfaces::ITargetPredictor> live_target_manager)
: pimpl_(std::make_unique<Impl>(auto_fire, control_delay_in_second, bullet_speed, yaw_offset,
pitch_offset, state_machine, live_target_manager)) { }

const data ::FireControl FireController::CalculateTarget(const std ::time_t& time_duration) const {
return pimpl_->CalculateTarget(time_duration);
}

const CarIDFlag FireController::GetAttackCarId() const { return pimpl_->GetAttackCarId(); }

}
31 changes: 31 additions & 0 deletions src/tongji/fire_controller/fire_controller.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#pragma once

#include <memory>

#include "../time_stamp/time_stamp.hpp"
#include "interfaces/armor_in_image.hpp"
#include "interfaces/car_state.hpp"
#include "interfaces/fire_controller.hpp"
#include "interfaces/target_predictor.hpp"

namespace world_exe::tongji::fire_control {

class FireController final : public interfaces::IFireControl {
public:
FireController(std::shared_ptr<interfaces::ICarState> state_machine, bool auto_fire,
const double& control_delay_in_second, const double& bullet_speed, double yaw_offset,
double pitch_offset, std::shared_ptr<interfaces::ITargetPredictor> live_target_manager);

const data ::FireControl CalculateTarget(const std ::time_t& time_duration) const override;
const enumeration ::CarIDFlag GetAttackCarId() const override;

void Update(std::shared_ptr<interfaces::IArmorInImage> armors, const double& gimbal_yaw);

time_stamp::TimeStamp GetTimeStamp() const;

private:
class Impl;
std::unique_ptr<Impl> pimpl_;
};

}
52 changes: 52 additions & 0 deletions src/tongji/fire_controller/fire_decision.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
#pragma once

#include <cmath>
#include <cstdlib>

#include "tongji/predictor/target_snapshot_manager/target_snapshot_manager.hpp"

namespace world_exe::tongji::fire_control {

class FireDecision {
public:
explicit FireDecision(const bool& auto_fire, const double& first_tolerance = 5,
const double& second_tolerance = 2, const double& judge_distance = 3)
: auto_fire_(auto_fire)
, last_gimbal_command_({ std::numeric_limits<double>::quiet_NaN(),
std::numeric_limits<double>::quiet_NaN() })
, first_tolerance_(first_tolerance)
, second_tolerance_(second_tolerance)
, judge_distance_(judge_distance) { }

bool ShouldFire(
predictor::GimbalCommand gimbal_command, const Eigen::Vector3d& valid_target_pos) {

if (!auto_fire_) return false;
const auto& tolerance = std::sqrt(valid_target_pos.x() * valid_target_pos.x()
+ valid_target_pos.y() * valid_target_pos.y())
> judge_distance_
? second_tolerance_
: first_tolerance_;

if (std::abs(last_gimbal_command_.yaw - gimbal_yaw_)
< tolerance * 2 // 此时认为command突变不应该射击
&& std::abs(gimbal_yaw_ - last_gimbal_command_.yaw) < tolerance) {
last_gimbal_command_ = gimbal_command;
return true;
}
last_gimbal_command_ = gimbal_command;
return false;
}

private:
bool auto_fire_;
predictor::GimbalCommand last_gimbal_command_;

double gimbal_yaw_;

double first_tolerance_ { 5 }; // 近距离射击容差,degree
double second_tolerance_ { 2 }; // 远距离射击容差,degree
double judge_distance_ { 3 }; // 距离判断阈值
};

}
45 changes: 45 additions & 0 deletions src/tongji/identifier/armor_filter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#pragma once

#include <unordered_set>
#include <utility>
#include <vector>

#include "data/armor_image_spaceing.hpp"
#include "enum/armor_id.hpp"
#include "enum/car_id.hpp"
#include "util/index.hpp"

namespace world_exe::tongji::identifier {

class ArmorFilter {
public:
explicit ArmorFilter()
: invincible_armor_({ }) { }
std::vector<data::ArmorImageSpacing> FilterArmor(
std::vector<data::ArmorImageSpacing> armors) const {

// 25赛季没有5号装甲板
armors.erase(std::remove_if(armors.begin(), armors.end(),
[](const auto& armor) { return armor.id == enumeration::ArmorIdFlag::InfantryV; }));
// 不打前哨站
armors.erase(std::remove_if(armors.begin(), armors.end(),
[](const auto& armor) { return armor.id == enumeration::ArmorIdFlag::Outpost; }));
// 过滤掉刚复活无敌的装甲板
armors.erase(std::remove_if(armors.begin(), armors.end(),
[&](const auto& armor) { return invincible_armor_.count(armor.id); }),
armors.end());

return std::move(armors);
}

void Update(enumeration::CarIDFlag ids) {
invincible_armor_.clear();
for (auto id : util::enumeration::ExpandArmorIdFlags(ids)) {
invincible_armor_.emplace(std::move(id));
}
}

private:
std::unordered_set<enumeration::ArmorIdFlag> invincible_armor_;
};
}
7 changes: 6 additions & 1 deletion src/tongji/identifier/identified_armor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "util/index.hpp"

namespace world_exe::tongji::identifier {

class IdentifiedArmor final : public interfaces::IArmorInImage, public interfaces::ITimeStamped {
public:
explicit IdentifiedArmor(const std::vector<data::ArmorImageSpacing>& armors) {
Expand All @@ -23,8 +24,12 @@ class IdentifiedArmor final : public interfaces::IArmorInImage, public interface
return armors_[util::enumeration::GetIndex(armor_id)];
}

static IdentifiedArmor DecorateIArmorInImage(const interfaces::IArmorInImage& armor) {
throw std::runtime_error("Not implemented");
}

private:
std::time_t time_stamp_ { 0 };
std::time_t time_stamp_ { std::time(nullptr) };
std::array<std::vector<data::ArmorImageSpacing>, 8> armors_;
};
}
2 changes: 1 addition & 1 deletion src/tongji/identifier/identifier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
#include "enum/armor_id.hpp"
#include "identified_armor.hpp"
#include "interfaces/armor_in_image.hpp"
#include "tongji/identifier/classifier.hpp"
#include "../identifier/classifier.hpp"
#include "util/logger.hpp"
#include "util/stringifier.hpp"

Expand Down
4 changes: 2 additions & 2 deletions src/tongji/predictor/in_gimbal_control_armor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@
#include <unordered_map>
#include <vector>

#include "../time_stamp/time_stamp.hpp"
#include "data/armor_gimbal_control_spacing.hpp"
#include "enum/armor_id.hpp"
#include "interfaces/armor_in_gimbal_control.hpp"
#include "tongji/predictor/time_stamp.hpp"

namespace world_exe::tongji::predictor {

Expand All @@ -28,7 +28,7 @@ class InGimbalControlArmor final : public interfaces::IArmorInGimbalControl {
const interfaces::ITimeStamped& GetTimeStamped() const override { return time_stamp_; }

private:
TimeStamp time_stamp_;
time_stamp::TimeStamp time_stamp_;
std::unordered_map<enumeration::ArmorIdFlag, std::vector<data::ArmorGimbalControlSpacing>>
armors_map_;
static const std::vector<data::ArmorGimbalControlSpacing> empty;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,36 @@
#pragma once

#include <Eigen/Dense>
#include <deque>
#include <functional>
#include <map>
#include <numeric>

namespace world_exe::util {
#include <Eigen/Dense>

namespace world_exe::tongji::predictor {
template <int xn, int zn> //
class ExtendedKalmanFilter {
public:
Eigen::VectorXd x;
Eigen::MatrixXd P;
using XVec = Eigen::Matrix<double, xn, 1>;
using ZVec = Eigen::Matrix<double, zn, 1>;
using AMat = Eigen::Matrix<double, xn, xn>;
using PMat = Eigen::Matrix<double, xn, xn>;
using PDig = Eigen::Matrix<double, xn, 1>;
using RMat = Eigen::Matrix<double, zn, zn>;
using RDig = Eigen::Matrix<double, zn, 1>;
using QMat = Eigen::Matrix<double, xn, xn>;
using HMat = Eigen::Matrix<double, zn, xn>;

XVec x;
PMat P;

ExtendedKalmanFilter() = default;

ExtendedKalmanFilter(
const Eigen::VectorXd& x0, const Eigen::MatrixXd& P0,
std::function<Eigen::VectorXd(const Eigen::VectorXd&, const Eigen::VectorXd&)> x_add =
[](const Eigen::VectorXd& a, const Eigen::VectorXd& b) { return a + b; }) {
const XVec& x0, const PMat& P0,
std::function<XVec(const XVec&, const XVec&)> x_add = [](const XVec& a, const XVec& b) {
return a + b;
}) {
data["residual_yaw"] = 0.0;
data["residual_pitch"] = 0.0;
data["residual_distance"] = 0.0;
Expand All @@ -29,13 +42,12 @@ class ExtendedKalmanFilter {
data["recent_nis_failures"] = 0.0;
}

Eigen::VectorXd Update(
const double& dt, const Eigen::MatrixXd& A, const Eigen::MatrixXd& Q,
std::function<Eigen::VectorXd(const Eigen::VectorXd&, const double&)> f,
const Eigen::VectorXd& z, const Eigen::MatrixXd& H, const Eigen::MatrixXd& R,
std::function<Eigen::VectorXd(const Eigen::VectorXd&)> h,
std::function<Eigen::VectorXd(const Eigen::VectorXd&, const Eigen::VectorXd&)> z_subtract =
[](const Eigen::VectorXd& a, const Eigen::VectorXd& b) { return a - b; }) {
XVec Update(
const double& dt, const AMat& A, const QMat& Q,
std::function<XVec(const XVec&, const double&)> f, const ZVec& z, const HMat& H,
const RMat& R, std::function<ZVec(const XVec&)> h,
std::function<ZVec(const ZVec&, const ZVec&)> z_subtract =
[](const ZVec& a, const ZVec& b) { return a - b; }) {

auto x_n = f(x, dt);

Expand Down Expand Up @@ -90,8 +102,8 @@ class ExtendedKalmanFilter {
double last_nis;

private:
Eigen::MatrixXd I;
std::function<Eigen::VectorXd(const Eigen::VectorXd&, const Eigen::VectorXd&)> x_add;
Eigen::Matrix<double, xn, xn> I;
std::function<XVec(const XVec&, const XVec&)> x_add;

int nees_count_ = 0;
int nis_count_ = 0;
Expand Down
Loading