浏览代码

add:通过rosbridge获取机器人状态位置信息并开放http接口

miloma93@163.com 4 月之前
父节点
当前提交
06ce10fbb9

+ 39 - 0
src/main/java/com/sw/patroleditor/component/rosBridge/RobotDataCallBack.java

@@ -0,0 +1,39 @@
+package com.sw.patroleditor.component.rosBridge;
+
+import com.alibaba.fastjson2.JSONObject;
+import edu.wpi.rail.jrosbridge.callback.TopicCallback;
+import edu.wpi.rail.jrosbridge.messages.Message;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+
+/**
+ * 通过rosBridge获取机器人数据
+ */
+@Component
+public class RobotDataCallBack implements TopicCallback {
+    private static final Logger logger = LoggerFactory.getLogger(RobotDataCallBack.class);
+
+    RobotDataModel robotDataModel = new RobotDataModel();
+
+    @Override
+    public void handleMessage(Message message) {
+        if (null == message) {
+            return;
+        }
+        try {
+            robotDataModel = JSONObject.parseObject(message.toString(), RobotDataModel.class);   //message即该话题的广播消息
+            //System.out.println(robotDataModel.toString());
+        } catch (Exception e) {
+            logger.error(e.toString());
+        }
+    }
+
+    // 获取数据
+    public RobotDataModel getRobotDataModel() {
+        return robotDataModel;
+    }
+
+
+}

+ 201 - 0
src/main/java/com/sw/patroleditor/component/rosBridge/RobotDataModel.java

@@ -0,0 +1,201 @@
+package com.sw.patroleditor.component.rosBridge;
+
+import com.alibaba.fastjson2.annotation.JSONField;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+@Data
+@NoArgsConstructor
+@AllArgsConstructor
+public class RobotDataModel {
+
+    /**************************************机器人数据***********************************************************************/
+    @ApiModelProperty(value = " X 位置(mm)")
+    @JSONField(name = "pos_x")
+    private int posX;
+
+    @ApiModelProperty(value = "Y 位置(mm)")
+    @JSONField(name = "pos_y")
+    private int posY;
+
+    @ApiModelProperty(value = " Z 位置(mm)- Height ")
+    @JSONField(name = "pos_z")
+    private int posZ;
+
+    @ApiModelProperty(value = "YAW 航线角(实际角度(°)*100)")
+    @JSONField(name = "ang_yaw")
+    private int angYaw;
+
+    @ApiModelProperty(value = "电机工作速度(实际速度(m/s)*100)")
+    @JSONField(name = "work_speed")
+    private int workSpeed;
+
+    @ApiModelProperty(value = "左轮速度(实际速度(m/s)*100)")
+    @JSONField(name = "left_speed")
+    private int leftSpeed;
+
+    @ApiModelProperty(value = "右轮轮速度(实际速度(m/s)*100)")
+    @JSONField(name = "right_speed")
+    private int rightSpeed;
+
+
+    /**************************************云台数据***********************************************************************/
+
+    @ApiModelProperty(value = "俯仰 单位:(实际角度(°)*100) 实际角度范围:(-180.00° ~ 180.00°)")
+    @JSONField(name = "pitch")
+    private int pitch;
+
+    @ApiModelProperty(value = "旋转 单位:(实际角度(°)*100) 实际角度范围:(- 90.00° ~  90.00°)")
+    @JSONField(name = "yaw")
+    private int yaw;
+
+    @ApiModelProperty(value = "倾斜 单位:(实际角度(°)*100) 实际角度范围:(-180.00° ~ 180.00°)")
+    private int roll;
+
+    @ApiModelProperty(value = "云台运行速度 (实际角度(°/s))")
+    @JSONField(name = "ptz_speed")
+    private int ptzSpeed;
+
+    @ApiModelProperty(value = " 倍率")
+    private int ratio;
+
+    @ApiModelProperty(value = "焦距")
+    @JSONField(name = "focal_distance")
+    private int focalDistance;
+
+    @ApiModelProperty(value = "光圈")
+    private int diaphragm;
+
+    @ApiModelProperty(value = "自动对焦(0:自动对焦, 1:手动对焦)")
+    private int focusing;
+
+    /**********************************工作状态*******************************************/
+    /// 工作状态
+    /// 0待机,1:开机,2:休息,3:自动巡检模式
+    /// 4:手动模式,5:充电模式,6:检修模式
+    /// 7:故障状态
+    /// 8:遥控模式
+    /// 9: 紧急定位模式(半自动)
+    @ApiModelProperty(value = "工作状态")
+    @JSONField(name = "work_status")
+    private int workStatus;
+
+    /**********************************运行状态*******************************************/
+    @ApiModelProperty(value = " 运行温度(℃)")
+    @JSONField(name = "work_temp")
+    private double workTemp;
+
+    @ApiModelProperty(value = "运行里程(km)")
+    @JSONField(name = "work_mile")
+    private double workMile;
+
+    @ApiModelProperty(value = "运行时间(hour)")
+    @JSONField(name = "work_time")
+    private double workTime;
+
+    @ApiModelProperty(value = "巡检设备数(每次任务)")
+    @JSONField(name = "point_count")
+    private int pointCount;
+
+    @ApiModelProperty(value = "缺陷设备数(每次任务)")
+    @JSONField(name = "bad_count")
+    private int badCount;
+
+
+    /**********************************通讯状态*******************************************/
+    @ApiModelProperty(value = "充电基站通信")
+    @JSONField(name = "charge_com")
+    private int roomCom;
+
+    @ApiModelProperty(value = "可见光通信")
+    @JSONField(name = "camera_com")
+    private int cameraCom;
+
+    @ApiModelProperty(value = "无线基站通信")
+    @JSONField(name = "wifi_com")
+    private int wifiCom;
+
+    @ApiModelProperty(value = "红外通信")
+    @JSONField(name = "infrared_com")
+    private int infraredCom;
+
+    @ApiModelProperty(value = "控制系统通信")
+    @JSONField(name = "system_com")
+    private int systemCom;
+
+    /**********************************bms电池信息*******************************************/
+    @ApiModelProperty(value = "充电状态0未充电,1正在充电")
+    @JSONField(name = "charging_status")
+    private boolean chargingStatus;
+
+    @ApiModelProperty(value = "电池稳定性(不为零,即电池报废)")
+    private int bal;
+
+    @ApiModelProperty(value = "电池温度(℃)")
+    private double temp;
+
+    @ApiModelProperty(value = "电流(A)")
+    private int cur;
+
+    @ApiModelProperty(value = "容量(%)(0.00~100.00%)")
+    private double cap;
+
+    @ApiModelProperty(value = "充电电压(V)")
+    @JSONField(name = "charging_vol")
+    private int chargingVol;
+
+    @ApiModelProperty(value = "电压(V)")
+    private double vol;
+
+    /**********************************其他开关量状态*******************************************/
+
+
+    @ApiModelProperty(value = "充电房开关")
+    @JSONField(name = "open_room")
+    private boolean openRoom;
+
+    @ApiModelProperty(value = "车灯开关")
+    @JSONField(name = "open_light")
+    private boolean openLight;
+
+    @ApiModelProperty(value = "可见光开关")
+    @JSONField(name = "open_camera")
+    private boolean openCamera;
+
+    @ApiModelProperty(value = "机器人状态,0待机,1运行")
+    @JSONField(name = "robot_status")
+    private boolean openRobot;
+
+    @ApiModelProperty(value = "雷达避障开关")
+    @JSONField(name = "open_radar")
+    private boolean openRadar;
+
+    @ApiModelProperty(value = "红外开关")
+    @JSONField(name = "open_infrared")
+    private boolean openInfrared;
+
+    @ApiModelProperty(value = "雨刷开关")
+    @JSONField(name = "open_wiper")
+    private boolean openWiper;
+
+
+    /**********************************err code*******************************************/
+
+    /// err code
+    /// 1.电池温度过高
+    /// 2.电量过低
+    /// 3.碰撞
+    /// 4.存储空间不足
+    /// 5.CPU温度过高
+    /// 6.超出条码范围
+    /// 7.电机控制异常(行走/卷扬/TEV电机)
+    /// 8.云台控制异常
+    @ApiModelProperty(value = "err code")
+    @JSONField(name = "err_code")
+    private int errorCode;
+}
+
+
+

+ 85 - 0
src/main/java/com/sw/patroleditor/controller/RosRobotDataController.java

@@ -0,0 +1,85 @@
+package com.sw.patroleditor.controller;
+
+import com.sw.patroleditor.component.rosBridge.RobotDataCallBack;
+import edu.wpi.rail.jrosbridge.Ros;
+import edu.wpi.rail.jrosbridge.Topic;
+import edu.wpi.rail.jrosbridge.handler.RosHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.Resource;
+import javax.websocket.Session;
+
+/**
+ * 接收ros服务器数据:robotData
+ */
+
+@RestController
+public class RosRobotDataController implements RosHandler {
+    private static final Logger logger = LoggerFactory.getLogger(RosRobotDataController.class);
+    //properties配置文件配置
+    //ros服务器ip
+    @Value("${ros.ip}")
+    private String ip;
+    //指定订阅的话题名称
+    @Value("${ros.topic.robot.data.name}")
+    private String gnssName;
+    //指定订阅的话题类型
+    @Value("${ros.topic.robot.data.type}")
+    private String gnssType;
+
+    //实现了话题消息接收(可对消息进行逻辑处理)
+    @Resource
+    private RobotDataCallBack robotDataCallBack;
+
+    Ros ros = null;
+    boolean connect = false;
+
+    /**
+     * ros服务器故障断开每隔五秒重连
+     */
+    @Scheduled(cron = "*/5 * * * * ?")
+    void reconnect() {
+        if (connect == false) {
+            logger.error("未连接服务!正在重连ros服务器!");
+            init();
+        }
+    }
+
+    @PostConstruct
+    void init() {
+        try {
+            ros = new Ros(ip);
+            connect = ros.connect();
+            if (connect) {
+                Topic topic = new Topic(ros, gnssName, gnssType);
+                topic.subscribe(robotDataCallBack);    //开始订阅话题
+                ros.addRosHandler(this);    //监听器监听ros连接状态
+            }
+        } catch (Exception e) {
+            logger.error("ros服务器连接错误:" + e.toString());
+            connect = false;
+        }
+    }
+
+    @Override
+    public void handleConnection(Session session) {
+        logger.info("ros已连接:" + session.getId());
+    }
+
+    @Override
+    public void handleDisconnection(Session session) {
+        logger.error("断开ros连接:" + session.getId());
+        connect = false;
+    }
+
+    @Override
+    public void handleError(Session session, Throwable t) {
+        logger.error("ros连接失败:" + session.getId() + "-----失败原因:" + t.toString());
+        connect = false;
+    }
+}