gun fire project 尚未实现多线程处理

本文介绍了一个简单的战斗模拟器设计,该模拟器通过随机选择角色和军队进行战斗,并使用多线程来模拟战斗过程中的射击延迟。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

package com.fire.action;


import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;




public class Main {


public static void main(String[] args) {
Main main = new Main();
main.init();
// System.out.println(String.format("%s","1","2"));
// System.out.println(11.11/100);
}
public void init(){
Role aLan = new ALan();
aLan.setYifu(130f);
aLan.setToukui(90f);
aLan.setGun(new XinFengYing());
JiDi jiDi = new JiDi();
caculFight(aLan, jiDi);
}

public void caculFight(Role role, Map map){
i(begin);
while(map.getArmys().size()>0 && role.getBlood()>0){
randomFree();
randomFindAndFire(role,map);
}
i("role message :"+role+", \n armys message :"+map.getArmys()+", \n armys size :"+map.getArmys().size());
i(end);
}

public void i(String message){
System.out.println(new SimpleDateFormat("HH:mm:ss").format(new Date())+" : " +message);
}
public void i(String msg, Object...args){
System.out.println(String.format(new SimpleDateFormat("HH:mm:ss").format(new Date())+" : "+msg, args));
}

public void randomFree(){
try {
Thread.sleep(new Random().nextInt(3000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}


public void fireFree(long time){
try {
Thread.sleep(new Random().nextInt((int)time));
} catch (InterruptedException e) {
e.printStackTrace();
}
}


public void randomFindAndFire(Role role, Map map){
Army army=certionArmy(map); //certion one army
if(isMeFindFirst()){
i(role.getName()+" find "+army.getName()+" first, begin to fire");
fightEachOtherUtilEnd("i",role,army,map);
}else {
i(army.getName()+" find "+role.getName()+" first, begin to fire");
fightEachOtherUtilEnd("he",role,army,map);
}
}
public Army certionArmy(Map map){
return map.getArmys().get(new Random().nextInt(map.getArmys().size()));
}
static boolean reFight = false;
public void fightEachOtherUtilEnd(final String whoBegin,final Role role, final Army army, final Map map){
reFight = true;
while((role.getBlood()>0 || army.getBlood()>0 ) && reFight){
reFight = false;
fireFree(3000);
new Thread(new Runnable() {
@Override
public void run() {
boolean flg=true;
int i=1;
if("i".equals(whoBegin)){
fireFree(100);
}
while(i<=30 && flg){
i++;
fireFree(1000/role.getGun().getSpeed());
int left = alarmOther(i,role, army);
if(left==-1){
i(army.getName() +"is dead, fight end");
map.getArmys().remove(army);
flg=false;
reFight = false;
}else if(left==-2) {
i(role.getName() +"is dead, fight end");
flg = false;
reFight = false;
}
}
reFight = true;
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
boolean flg=true;
int i=1;
if("he".equals(whoBegin)){
fireFree(100);
}
while(i<30 && flg){
i++;
fireFree(1000/army.getGun().getSpeed());
int left = alarmOther(i,army, role);
if(left==-1){
//i(role.getName() +"is dead, fight end");
flg=false;
reFight = false;
}else if(left ==-2){
//i(army.getName() +"is dead, fight end");
flg=false;
reFight = false;
}
}
reFight = true;
}
}).start();
}
}

public int alarmOther( int i,Role role, Role army){
float jingdu = new Float(i==1 ? 1: 1*Math.pow((double)role.getGun().getWending()/100, i));
float alarm = role.getGun().getAlarm()*jingdu -(army.getYifu());
int left =0;
if(alarm>0){
left = new Float(army.getBlood()-alarm).intValue() ;
army.setBlood(left>0 ?left:0 );
}else {
left = army.getBlood();
}
float fy = army.getYifu()-role.getGun().getAlarm()*jingdu;
army.setYifu(fy >0 ?fy:0);
army.setBlood(left>0 ?left:0 );
if(role.getBlood()==0){
return -2;
}
i(role.getName()+"has alarm "+army.getName()+" damage "+ role.getGun().getAlarm()*jingdu+","+army.getName()+"'blood left"+(int)army.getBlood()+", fangyu is "+(int)army.getYifu());
i(role.getName() +"left blood is "+(int)role.getBlood()+",fangyu is "+(int)role.getYifu() );
if(left>0){
return left;
}else {
return -1;
}
}

boolean isMeFindFirst(){
return new Random().nextInt(3) %3 !=0;
}

String begin = "begin to play";
String end = "fight end";
String ifind = "I find army first, begin to fire";
String hefind = "He find me first, begin to fire";
}




 class Map {


protected String name;
protected Army army;
protected List<Army> armys ;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Army> getArmys() {
return armys;
}
public void setArmys(List<Army> armys) {
this.armys = armys;
}
public Role getArmy() {
return army;

public void setArmy(Army army) {
this.army = army;


}
 class JiDi extends Map{


public JiDi(){
super.name="Ji Di";
super.army = new Army();
super.armys= new ArrayList<Army>();
for (int i = 1; i < 11; i++) {
Army army = new Army(i);
army.setGun(new AKGun());
armys.add(army);
}

}
}


  class Role {


protected String name;
protected float degree;
protected float wXishu;
protected float hXishu;
protected float width=50;
protected float height=180;
protected float yifu;
protected float toukui;
protected Gun gun;
protected int blood=100;

public int getBlood() {
return blood;
}
public void setBlood(int blood) {
this.blood = blood;
}
public Gun getGun() {
return gun;
}
public void setGun(Gun gun) {
this.gun = gun;
}
public float getYifu() {
return yifu;
}
public void setYifu(float yifu) {
this.yifu = yifu;
}
public float getToukui() {
return toukui;
}
public void setToukui(float toukui) {
this.toukui = toukui;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getDegree() {
return degree;
}
public void setDegree(float degree) {
this.degree = degree;
}
public float getwXishu() {
return wXishu;
}
public void setwXishu(float wXishu) {
this.wXishu = wXishu;
}
public float gethXishu() {
return hXishu;
}
public void sethXishu(float hXishu) {
this.hXishu = hXishu;
}
public float getWidth() {
return width;
}
public void setWidth(float width) {
this.width = width;
}
public float getHeight() {
return height;
}
public void setHeight(float height) {
this.height = height;
}
@Override
public String toString() {
return "Role [name=" + name + ", degree=" + degree + ", wXishu="
+ wXishu + ", hXishu=" + hXishu + ", width=" + width
+ ", height=" + height + ", yifu=" + yifu + ", toukui="
+ toukui + ", gun=" + gun + ", blood=" + blood + "]";
}

}
   class Army extends Role{


public Army(){
super.degree=0.11f;
super.name="Common-Army";
super.wXishu=1.55f;
super.hXishu=1.55f;
super.blood=100;
}

public Army(int index){
this();
super.name=super.name +"-"+index;
}
}
   
   
   class ALan extends Role{


public ALan(){
super.degree=0.99f;
super.name="A-Lan";
super.wXishu=0.75f;
super.hXishu=0.75f;
super.blood=130;
}
}
   class Gun {


protected int alarm;
protected int distance;
protected int range;
protected int speed;
protected float wending;


protected String name;


public int getAlarm() {
return alarm;
}


public void setAlarm(int alarm) {
this.alarm = alarm;
}


public int getDistance() {
return distance;
}


public void setDistance(int distance) {
this.distance = distance;
}


public int getRange() {
return range;
}


public void setRange(int range) {
this.range = range;
}


public int getSpeed() {
return speed;
}


public void setSpeed(int speed) {
this.speed = speed;
}


public float getWending() {
return wending;
}


public void setWending(float wending) {
this.wending = wending;
}


public String getName() {
return name;
}


public void setName(String name) {
this.name = name;
}

}
   class AKGun extends Gun{


public AKGun(){
super.alarm =45;
super.distance=60;
super.range = 1;
super.name="AK Gun";
super.speed=60;
super.wending=60;
}
}
   class XinFengYing extends AKGun{


public XinFengYing(){
super.alarm =71;
super.distance=95;
super.range = 1;
super.name="Xin Feng Ying";
super.speed=99;
super.wending=90;
}
}
关于上面的问题,有没有可能是我运行代码的问题,如果有问题,那大概是哪一个部分出了问题import argparse import csv import os import platform import sys import time from pathlib import Path import torch import serial import cv2 import rospy from std_srvs.srv import Trigger, TriggerResponse from ultralytics.utils.plotting import Annotator, colors, save_one_box from models.common import DetectMultiBackend from utils.dataloaders import LoadStreams from utils.general import ( LOGGER, Profile, check_img_size, increment_path, non_max_suppression, scale_boxes, xyxy2xywh, ) from utils.torch_utils import select_device, smart_inference_mode @smart_inference_mode() class GunControllerNode: def __init__(self, opt): self.opt = opt self.save_img = not opt.nosave self.source = str(opt.source) self.project = opt.project self.name = opt.name self.exist_ok = opt.exist_ok # 初始化变量以跟踪射击状态 self.gun_state = "idle" # idle, firing, cooling self.fire_start_time = 0 self.dt = [Profile(), Profile(), Profile()] # 初始化计时器 # 初始化串口连接 try: self.ser = serial.Serial(opt.port, opt.baudrate, timeout=1) LOGGER.info(f"Successfully opened serial port {opt.port} at {opt.baudrate} baudrate") except Exception as e: LOGGER.error(f"Failed to open serial port {opt.port}: {e}") self.ser = None # 初始化云台角度 self.servo1_angle = 90 # 水平云台 (0-180) self.servo2_angle = 90 # 垂直云台 (70-110) # 跟踪调整状态 self.is_adjusting = False self.adjustment_complete_time = 0 self.save_dir = increment_path(Path(opt.project) / opt.name, exist_ok=opt.exist_ok) (self.save_dir / "labels" if opt.save_txt else self.save_dir).mkdir(parents=True, exist_ok=True) self.device = select_device(opt.device) self.model = DetectMultiBackend(opt.weights, device=self.device, dnn=opt.dnn, data=opt.data, fp16=opt.half) self.stride, self.names, self.pt = self.model.stride, self.model.names, self.model.pt self.imgsz = check_img_size(opt.imgsz, s=self.stride) self.dataset = LoadStreams(self.source, img_size=self.imgsz, stride=self.stride, auto=self.pt) self.vid_path, self.vid_writer = [None] * len(self.dataset), [None] * len(self.dataset) self.model.warmup(imgsz=(1 if self.pt or self.model.triton else len(self.dataset), 3, *self.imgsz)) self.gun_service = rospy.Service('/gun', Trigger, self.gun_callback) rospy.init_node('gun_controller', anonymous=True) self.view_img = opt.view_img self.windows = [] def send_servo_command(self, servo_id, angle): if self.ser is not None: try: cmd = bytes([0xAA, 0xBB, servo_id, angle, 0x0D, 0x0A]) self.ser.write(cmd) return True except Exception as e: LOGGER.error(f"Failed to send servo command: {e}") return False return False def send_gun_command(self, is_fire): if self.ser is not None: try: if is_fire: cmd = bytes([0xAA, 0xBB, 0x03, 0x01, 0x0D, 0x0A]) else: cmd = bytes([0xAA, 0xBB, 0x03, 0x00, 0x0D, 0x0A]) self.ser.write(cmd) return True except Exception as e: LOGGER.error(f"Failed to send gun command: {e}") return False return False def gun_callback(self, req): response = TriggerResponse() try: for path, im, im0s, vid_cap, s in self.dataset: with self.dt[0]: im = torch.from_numpy(im).to(self.model.device) im = im.half() if self.model.fp16 else im.float() im /= 255 if len(im.shape) == 3: im = im[None] with self.dt[1]: pred = self.model(im, augment=self.opt.augment, visualize=self.opt.visualize) with self.dt[2]: pred = non_max_suppression(pred, self.opt.conf_thres, self.opt.iou_thres, self.opt.classes, self.opt.agnostic_nms, max_det=self.opt.max_det) for i, det in enumerate(pred): p, im0, frame = path[i], im0s[i].copy(), self.dataset.count p = Path(p) save_path = str(self.save_dir / p.name) txt_path = str(self.save_dir / "labels" / p.stem) + ("" if self.dataset.mode == "image" else f"_{frame}") s += f"{im.shape[2]}x{im.shape[3]} " gn = torch.tensor(im0.shape)[[1, 0, 1, 0]] annotator = Annotator(im0, line_width=self.opt.line_thickness, example=str(self.names)) if det is not None and len(det): det[:, :4] = scale_boxes(im.shape[2:], det[:, :4], im0.shape).round() for c in det[:, 5].unique(): n = (det[:, 5] == c).sum() s += f"{n} {self.names[int(c)]}{'s' * (n > 1)}, " max_area = 0 selected_det = None for *xyxy, conf, cls in reversed(det): area = (xyxy[2] - xyxy[0]) * (xyxy[3] - xyxy[1]) if area > max_area: max_area = area selected_det = (xyxy, conf, cls) if selected_det is not None: xyxy, conf, cls = selected_det x_center = float((xyxy[0] + xyxy[2]) / 2) y_center = float((xyxy[1] + xyxy[3]) / 2) cv2.circle(im0, (int(x_center), int(y_center)), 5, (0, 0, 255), -1) H, W = im0.shape[:2] center_x, center_y = W // 2, H // 2 threshold_x = W * 0.05 threshold_y = H * 0.05 CAMERA_OFFSET_ANGLE = -5 # 相机安装导致的固定向右偏移1° pixels_per_degree = W / 60 # 假设水平视场角约60度,计算每度对应的像素值 fixed_offset_pixels = int(CAMERA_OFFSET_ANGLE * pixels_per_degree) # 计算像素偏移量 # 在目标处理部分修改(替换原来的中心线计算) adjusted_center_x = center_x + fixed_offset_pixels # 补偿后的中心位置 cv2.line(im0, (adjusted_center_x, 0), (adjusted_center_x, H), (255, 0, 0), 1) # 用蓝色显示补偿中心线 # 修改目标偏差计算(替换原来的dx计算) dx = x_center - adjusted_center_x # 使用补偿后的中心位置计算偏差 dy = y_center - center_y # 垂直方向保持不变 needs_adjustment = abs(dx) > threshold_x * 0.5 or abs(dy) > threshold_y * 0.5 if needs_adjustment: self.is_adjusting = True if self.gun_state == "firing": self.gun_state = "idle" self.send_gun_command(False) LOGGER.info("Aborting fire due to target movement") if abs(dx) > threshold_x: if dx < 0: self.servo1_angle += 2 else: self.servo1_angle -= 2 self.servo1_angle = max(0, min(180, self.servo1_angle)) self.send_servo_command(0x01, self.servo1_angle) elif abs(dx) > threshold_x * 0.5: if dx < 0: self.servo1_angle += 1 else: self.servo1_angle -= 1 self.servo1_angle = max(0, min(180, self.servo1_angle)) self.send_servo_command(0x01, self.servo1_angle) if abs(dy) > threshold_y: if dy < 0: self.servo2_angle += 2 else: self.servo2_angle -= 2 self.servo2_angle = max(70, min(110, self.servo2_angle)) self.send_servo_command(0x02, self.servo2_angle) elif abs(dy) > threshold_y * 0.5: if dy < 0: self.servo2_angle += 1 else: self.servo2_angle -= 1 self.servo2_angle = max(70, min(110, self.servo2_angle)) self.send_servo_command(0x02, self.servo2_angle) LOGGER.info(f"Adjusting: dx={dx:.1f}, dy={dy:.1f} | Servo angles: {self.servo1_angle}°, {self.servo2_angle}°") else: if self.is_adjusting: self.adjustment_complete_time = time.time() self.is_adjusting = False LOGGER.info("Adjustment completed, waiting 2 seconds before firing") if self.gun_state == "idle" and not self.is_adjusting and time.time() - self.adjustment_complete_time >= 2: if self.send_gun_command(True): self.fire_start_time = time.time() self.gun_state = "firing" LOGGER.info("Firing started") if self.gun_state == "firing" and time.time() - self.fire_start_time >= 2: if self.send_gun_command(False): self.gun_state = "cooling" LOGGER.info("Firing stopped, entering 3-second cooling period") if self.gun_state == "cooling" and time.time() - self.fire_start_time >= 5: self.gun_state = "idle" LOGGER.info("Cooling completed, ready to fire again") else: if self.gun_state in ["firing", "cooling"]: self.send_gun_command(False) self.gun_state = "idle" LOGGER.info("No target detected, gun turned off") response.success = False response.message = "No target detected, gun turned off" return response im0 = annotator.result() if self.view_img: if platform.system() == "Linux" and p not in self.windows: self.windows.append(p) cv2.namedWindow(str(p), cv2.WINDOW_NORMAL | cv2.WINDOW_KEEPRATIO) cv2.resizeWindow(str(p), im0.shape[1], im0.shape[0]) cv2.imshow(str(p), im0) cv2.waitKey(1) LOGGER.info(f"{s}{'' if len(det) else '(no detections), '}{self.dt[1].dt * 1e3:.1f}ms") if self.ser is not None: self.ser.close() response.success = True response.message = "Gun operation completed successfully" except Exception as e: LOGGER.error(f"Error during gun operation: {e}") response.success = False response.message = f"Error during gun operation: {e}" return response def run(self): rospy.spin() def parse_opt(): parser = argparse.ArgumentParser() parser.add_argument("--weights", nargs="+", type=str, default=Path("target.pt"), help="model path or triton URL") parser.add_argument("--source", type=str, default=Path("0"), help="file/dir/URL/glob/screen/0(webcam)") parser.add_argument("--data", type=str, default=Path("data/coco128.yaml"), help="(optional) dataset.yaml path") parser.add_argument("--imgsz", "--img", "--img-size", nargs="+", type=int, default=[640], help="inference size h,w") parser.add_argument("--conf-thres", type=float, default=0.25, help="confidence threshold") parser.add_argument("--iou-thres", type=float, default=0.25, help="NMS IoU threshold") parser.add_argument("--max-det", type=int, default=1000, help="maximum detections per image") parser.add_argument("--device", default="", help="cuda device, i.e. 0 or 0,1,2,3 or cpu") parser.add_argument("--view-img", action="store_true", help="show results") parser.add_argument("--save-txt", action="store_true", help="save results to *.txt") parser.add_argument("--save-conf", action="store_true", help="save confidences in --save-txt labels") parser.add_argument("--save-crop", action="store_true", help="save cropped prediction boxes") parser.add_argument("--nosave", action="store_true", help="do not save images/videos") parser.add_argument("--classes", nargs="+", type=int, help="filter by class: --classes 0, or --classes 0 2 3") parser.add_argument("--agnostic-nms", action="store_true", help="class-agnostic NMS") parser.add_argument("--augment", action="store_true", help="augmented inference") parser.add_argument("--visualize", action="store_true", help="visualize features") parser.add_argument("--update", action="store_true", help="update all models") parser.add_argument("--project", default=Path("runs/detect"), help="save results to project/name") parser.add_argument("--name", default="exp", help="save results to project/name") parser.add_argument("--exist-ok", action="store_true", help="existing project/name ok, do not increment") parser.add_argument("--line-thickness", default=3, type=int, help="bounding box thickness (pixels)") parser.add_argument("--hide-labels", default=False, action="store_true", help="hide labels") parser.add_argument("--hide-conf", default=False, action="store_true", help="hide confidences") parser.add_argument("--half", action="store_true", help="use FP16 half-precision inference") parser.add_argument("--dnn", action="store_true", help="use OpenCV DNN for ONNX inference") parser.add_argument("--port", type=str, default="/dev/gun", help="serial port for servo control") parser.add_argument("--baudrate", type=int, default=115200, help="baud rate for serial communication") opt = parser.parse_args() opt.imgsz *= 2 if len(opt.imgsz) == 1 else 1 return opt def main(opt): controller = GunControllerNode(opt) controller.run() if __name__ == "__main__": opt = parse_opt() main(opt)
07-28
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

静山晚风

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

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

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

打赏作者

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

抵扣说明:

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

余额充值