File diff suppressed because it is too large
Load Diff
@ -0,0 +1,178 @@
|
|||||||
|
package com.jilk.ros.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by super_yu on 2018/1/8.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class FootPrintResult {
|
||||||
|
/**
|
||||||
|
* header : {"seq":4297,"frame_id":"odom","stamp":{"secs":1515378187,"nsecs":125325857}}
|
||||||
|
* polygon : {"points":[{"z":0,"x":0.31369608640670776,"y":-0.5355392694473267},{"z":0,"x":0.35115259885787964,"y":-0.016890067607164383},{"z":0,"x":-0.30713292956352234,"y":0.03065088950097561},{"z":0,"x":-0.3445894420146942,"y":-0.4879983365535736}]}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBean header;
|
||||||
|
private PolygonBean polygon;
|
||||||
|
|
||||||
|
public HeaderBean getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBean header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PolygonBean getPolygon() {
|
||||||
|
return polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPolygon(PolygonBean polygon) {
|
||||||
|
this.polygon = polygon;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBean {
|
||||||
|
/**
|
||||||
|
* seq : 4297
|
||||||
|
* frame_id : odom
|
||||||
|
* stamp : {"secs":1515378187,"nsecs":125325857}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int seq;
|
||||||
|
private String frame_id;
|
||||||
|
private StampBean stamp;
|
||||||
|
|
||||||
|
public int getSeq() {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeq(int seq) {
|
||||||
|
this.seq = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrame_id(String frame_id) {
|
||||||
|
this.frame_id = frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StampBean getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBean stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBean {
|
||||||
|
/**
|
||||||
|
* secs : 1515378187
|
||||||
|
* nsecs : 125325857
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs;
|
||||||
|
private int nsecs;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecs(int secs) {
|
||||||
|
this.secs = secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNsecs(int nsecs) {
|
||||||
|
this.nsecs = nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PolygonBean {
|
||||||
|
private List<PointsBean> points;
|
||||||
|
|
||||||
|
public List<PointsBean> getPoints() {
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPoints(List<PointsBean> points) {
|
||||||
|
this.points = points;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PointsBean {
|
||||||
|
/**
|
||||||
|
* z : 0
|
||||||
|
* x : 0.31369608640670776
|
||||||
|
* y : -0.5355392694473267
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int z;
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(int z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "header": {
|
||||||
|
// "seq": 4297,
|
||||||
|
// "frame_id": "odom",
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 1515378187,
|
||||||
|
// "nsecs": 125325857
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "polygon": {
|
||||||
|
// "points": [
|
||||||
|
// {
|
||||||
|
// "z": 0,
|
||||||
|
// "x": 0.31369608640670776,
|
||||||
|
// "y": -0.5355392694473267
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "z": 0,
|
||||||
|
// "x": 0.35115259885787964,
|
||||||
|
// "y": -0.016890067607164383
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "z": 0,
|
||||||
|
// "x": -0.30713292956352234,
|
||||||
|
// "y": 0.03065088950097561
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "z": 0,
|
||||||
|
// "x": -0.3445894420146942,
|
||||||
|
// "y": -0.4879983365535736
|
||||||
|
// }
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,274 @@
|
|||||||
|
package com.jilk.ros.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by super_yu on 2018/2/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class InitPoseResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* op : publish
|
||||||
|
* topic : /initialpose
|
||||||
|
* msg : {"header":{"frame_id":"map"},"pose":{"pose":{"position":{"x":0,"y":0,"z":0},"orientation":{"x":0,"y":0,"z":0,"w":1}},"covariance":[0.25,0,0,0,0,0,0,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.06853891945200942]}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String op = "publish";
|
||||||
|
private String topic = "/initialpose";
|
||||||
|
private MsgBean msg;
|
||||||
|
|
||||||
|
|
||||||
|
public MsgBean getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(MsgBean msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MsgBean {
|
||||||
|
/**
|
||||||
|
* header : {"frame_id":"map"}
|
||||||
|
* pose : {"pose":{"position":{"x":0,"y":0,"z":0},"orientation":{"x":0,"y":0,"z":0,"w":1}},"covariance":[0.25,0,0,0,0,0,0,0.25,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.06853891945200942]}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBean header;
|
||||||
|
private PoseBeanX pose;
|
||||||
|
|
||||||
|
public HeaderBean getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBean header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoseBeanX getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBeanX pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBean {
|
||||||
|
/**
|
||||||
|
* frame_id : map
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String frame_id = "map";
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBeanX {
|
||||||
|
/**
|
||||||
|
* pose : {"position":{"x":0,"y":0,"z":0},"orientation":{"x":0,"y":0,"z":0,"w":1}}
|
||||||
|
* covariance :
|
||||||
|
* 0.25,0,0,0,0,0,0,0.25,
|
||||||
|
* 0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
* 0,0,0,0,0,0,0,0,0,0,0,
|
||||||
|
* 0,0,0,0,0,0.06853891945200942
|
||||||
|
*/
|
||||||
|
|
||||||
|
private PoseBean pose;
|
||||||
|
private List<Double> covariance;
|
||||||
|
|
||||||
|
public PoseBean getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBean pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCovariance() {
|
||||||
|
covariance = new ArrayList<Double>();
|
||||||
|
for (int i = 0; i < 36; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
covariance.add(0.25);
|
||||||
|
} else if (i == 7) {
|
||||||
|
covariance.add(0.25);
|
||||||
|
} else if (i == 35) {
|
||||||
|
covariance.add(0.06853891945200942);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
covariance.add((double) 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBean {
|
||||||
|
/**
|
||||||
|
* position : {"x":0,"y":0,"z":0}
|
||||||
|
* orientation : {"x":0,"y":0,"z":0,"w":1}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private PositionBean position;
|
||||||
|
private OrientationBean orientation;
|
||||||
|
|
||||||
|
public PositionBean getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(PositionBean position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrientationBean getOrientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(OrientationBean orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PositionBean {
|
||||||
|
/**
|
||||||
|
* x : 0
|
||||||
|
* y : 0
|
||||||
|
* z : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class OrientationBean {
|
||||||
|
/**
|
||||||
|
* x : 0
|
||||||
|
* y : 0
|
||||||
|
* z : 0
|
||||||
|
* w : 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
private double w;
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getW() {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setW(double w) {
|
||||||
|
this.w = w;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "op": "publish",
|
||||||
|
// "topic": "/initialpose",
|
||||||
|
// "msg": {
|
||||||
|
// "header": {
|
||||||
|
// "frame_id": "map"
|
||||||
|
// },
|
||||||
|
// "pose": {
|
||||||
|
// "pose": {
|
||||||
|
// "position": {
|
||||||
|
// "x": 0,
|
||||||
|
// "y": 0,
|
||||||
|
// "z": 0
|
||||||
|
// },
|
||||||
|
// "orientation": {
|
||||||
|
// "x": 0,
|
||||||
|
// "y": 0,
|
||||||
|
// "z": 0,
|
||||||
|
// "w": 1
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "covariance": [
|
||||||
|
// 0.25,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0.25,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0.06853891945200942
|
||||||
|
// ]
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,501 @@
|
|||||||
|
package com.jilk.ros.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by super_yu on 2018/1/5.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*对位置移动有数据变化的是
|
||||||
|
* orientation z、w
|
||||||
|
* position x、y
|
||||||
|
* twist x
|
||||||
|
* angular z
|
||||||
|
* Created by super_yu on 2017/9/29.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class PoiResult {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* twist : {"twist":{"angular":{"z":0,"y":0,"x":0},"linear":{"z":0,"y":0,"x":0}},"covariance":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]}
|
||||||
|
* child_frame_id : base_footprint
|
||||||
|
* pose : {"covariance":[0.1,0,0,0,0,0,0,0.1,0,0,0,0,0,0,1.7976931348623157E308,0,0,0,0,0,0,1.7976931348623157E308,0,0,0,0,0,0,1.7976931348623157E308,0,0,0,0,0,0,0.2],"pose":{"position":{"z":0,"y":-0.16137039724419636,"x":0.001470031525333453},"orientation":{"w":-0.08271030624895466,"z":-0.9965736326234024,"y":"-0","x":0}}}
|
||||||
|
* header : {"seq":69712,"stamp":{"secs":1506650141,"nsecs":455670567},"frame_id":"odom"}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private TwistBeanX twist;
|
||||||
|
private String child_frame_id;
|
||||||
|
private PoseBeanX pose;
|
||||||
|
private HeaderBean header;
|
||||||
|
|
||||||
|
public TwistBeanX getTwist() {
|
||||||
|
return twist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTwist(TwistBeanX twist) {
|
||||||
|
this.twist = twist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChild_frame_id() {
|
||||||
|
return child_frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChild_frame_id(String child_frame_id) {
|
||||||
|
this.child_frame_id = child_frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoseBeanX getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBeanX pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HeaderBean getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBean header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TwistBeanX {
|
||||||
|
/**
|
||||||
|
* twist : {"angular":{"z":0,"y":0,"x":0},"linear":{"z":0,"y":0,"x":0}}
|
||||||
|
* covariance : [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
|
||||||
|
*/
|
||||||
|
|
||||||
|
private TwistBean twist;
|
||||||
|
private List<Integer> covariance;
|
||||||
|
|
||||||
|
public TwistBean getTwist() {
|
||||||
|
return twist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTwist(TwistBean twist) {
|
||||||
|
this.twist = twist;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getCovariance() {
|
||||||
|
return covariance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCovariance(List<Integer> covariance) {
|
||||||
|
this.covariance = covariance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TwistBean {
|
||||||
|
/**
|
||||||
|
* angular : {"z":0,"y":0,"x":0}
|
||||||
|
* linear : {"z":0,"y":0,"x":0}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private AngularBean angular;
|
||||||
|
private LinearBean linear;
|
||||||
|
|
||||||
|
public AngularBean getAngular() {
|
||||||
|
return angular;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAngular(AngularBean angular) {
|
||||||
|
this.angular = angular;
|
||||||
|
}
|
||||||
|
|
||||||
|
public LinearBean getLinear() {
|
||||||
|
return linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLinear(LinearBean linear) {
|
||||||
|
this.linear = linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class AngularBean {
|
||||||
|
/**
|
||||||
|
* z : 0
|
||||||
|
* y : 0
|
||||||
|
* x : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int z;
|
||||||
|
private int y;
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(int z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LinearBean {
|
||||||
|
/**
|
||||||
|
* z : 0
|
||||||
|
* y : 0
|
||||||
|
* x : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int z;
|
||||||
|
private int y;
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(int z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(int y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBeanX {
|
||||||
|
/**
|
||||||
|
* covariance : [0.1,0,0,0,0,0,0,0.1,0,0,0,0,0,0,1.7976931348623157E308,0,0,0,0,0,0,1.7976931348623157E308,0,0,0,0,0,0,1.7976931348623157E308,0,0,0,0,0,0,0.2]
|
||||||
|
* pose : {"position":{"z":0,"y":-0.16137039724419636,"x":0.001470031525333453},"orientation":{"w":-0.08271030624895466,"z":-0.9965736326234024,"y":"-0","x":0}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private PoseBean pose;
|
||||||
|
private List<Double> covariance;
|
||||||
|
|
||||||
|
public PoseBean getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBean pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Double> getCovariance() {
|
||||||
|
return covariance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCovariance(List<Double> covariance) {
|
||||||
|
this.covariance = covariance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBean {
|
||||||
|
/**
|
||||||
|
* position : {"z":0,"y":-0.16137039724419636,"x":0.001470031525333453}
|
||||||
|
* orientation : {"w":-0.08271030624895466,"z":-0.9965736326234024,"y":"-0","x":0}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private PositionBean position;
|
||||||
|
private OrientationBean orientation;
|
||||||
|
|
||||||
|
public PositionBean getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(PositionBean position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrientationBean getOrientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(OrientationBean orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PositionBean {
|
||||||
|
/**
|
||||||
|
* z : 0
|
||||||
|
* y : -0.16137039724419636
|
||||||
|
* x : 0.001470031525333453
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int z;
|
||||||
|
private double y;
|
||||||
|
private double x;
|
||||||
|
|
||||||
|
public int getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(int z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class OrientationBean {
|
||||||
|
/**
|
||||||
|
* w : -0.08271030624895466
|
||||||
|
* z : -0.9965736326234024
|
||||||
|
* y : -0
|
||||||
|
* x : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double w;
|
||||||
|
private double z;
|
||||||
|
private String y;
|
||||||
|
private int x;
|
||||||
|
|
||||||
|
public double getW() {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setW(double w) {
|
||||||
|
this.w = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(String y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(int x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBean {
|
||||||
|
/**
|
||||||
|
* seq : 69712
|
||||||
|
* stamp : {"secs":1506650141,"nsecs":455670567}
|
||||||
|
* frame_id : odom
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int seq;
|
||||||
|
private StampBean stamp;
|
||||||
|
private String frame_id;
|
||||||
|
|
||||||
|
public int getSeq() {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeq(int seq) {
|
||||||
|
this.seq = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StampBean getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBean stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrame_id(String frame_id) {
|
||||||
|
this.frame_id = frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBean {
|
||||||
|
/**
|
||||||
|
* secs : 1506650141
|
||||||
|
* nsecs : 455670567
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs;
|
||||||
|
private int nsecs;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecs(int secs) {
|
||||||
|
this.secs = secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNsecs(int nsecs) {
|
||||||
|
this.nsecs = nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
// {
|
||||||
|
// "twist": {
|
||||||
|
// "twist": {
|
||||||
|
// "angular": {
|
||||||
|
// "z": 0,
|
||||||
|
// "y": 0,
|
||||||
|
// "x": 0
|
||||||
|
// },
|
||||||
|
// "linear": {
|
||||||
|
// "z": 0,
|
||||||
|
// "y": 0,
|
||||||
|
// "x": 0
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "covariance": [
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// "child_frame_id": "base_footprint",
|
||||||
|
// "pose": {
|
||||||
|
// "covariance": [
|
||||||
|
// 0.1,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0.1,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 1.7976931348623157E308,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 1.7976931348623157E308,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 1.7976931348623157E308,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0,
|
||||||
|
// 0.2
|
||||||
|
// ],
|
||||||
|
// "pose": {
|
||||||
|
// "position": {
|
||||||
|
// "z": 0,
|
||||||
|
// "y": -0.16137039724419636,
|
||||||
|
// "x": 0.001470031525333453
|
||||||
|
// },
|
||||||
|
// "orientation": {
|
||||||
|
// "w": -0.08271030624895466,
|
||||||
|
// "z": -0.9965736326234024,
|
||||||
|
// "y": -0,
|
||||||
|
// "x": 0
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "header": {
|
||||||
|
// "seq": 69712,
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 1506650141,
|
||||||
|
// "nsecs": 455670567
|
||||||
|
// },
|
||||||
|
// "frame_id": "odom"
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,246 @@
|
|||||||
|
package com.jilk.ros.nav;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by super_yu on 27/10/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Move_Base_Goal {
|
||||||
|
/**
|
||||||
|
* msg : {"target_pose":{"header":{"frame_id":"/map"},"pose":{"w":0.72508,"x":0.00455891,"y":0.0110448,"z":-0.688561}},"base_position":{"header":{"frame_id":"/map"},"pose":{"x":-5.56034,"y":0.543951,"z":2.96803E-4}}}
|
||||||
|
* op : publish
|
||||||
|
* topic : /move_base/goal
|
||||||
|
*/
|
||||||
|
|
||||||
|
private MsgBean msg;
|
||||||
|
private String op = "publish";
|
||||||
|
private String topic = "/move_base/goal";
|
||||||
|
|
||||||
|
public MsgBean getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(MsgBean msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOp() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTopic() {
|
||||||
|
return topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MsgBean {
|
||||||
|
/**
|
||||||
|
* target_pose : {"header":{"frame_id":"/map"},"pose":{"w":0.72508,"x":0.00455891,"y":0.0110448,"z":-0.688561}}
|
||||||
|
* base_position : {"header":{"frame_id":"/map"},"pose":{"x":-5.56034,"y":0.543951,"z":2.96803E-4}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private TargetPoseBean target_pose;
|
||||||
|
private BasePositionBean base_position;
|
||||||
|
|
||||||
|
public TargetPoseBean getTarget_pose() {
|
||||||
|
return target_pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget_pose(TargetPoseBean target_pose) {
|
||||||
|
this.target_pose = target_pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BasePositionBean getBase_position() {
|
||||||
|
return base_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBase_position(BasePositionBean base_position) {
|
||||||
|
this.base_position = base_position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TargetPoseBean {
|
||||||
|
/**
|
||||||
|
* header : {"frame_id":"/map"}
|
||||||
|
* pose : {"w":0.72508,"x":0.00455891,"y":0.0110448,"z":-0.688561}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBean header;
|
||||||
|
private PoseBean pose;
|
||||||
|
|
||||||
|
public HeaderBean getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBean header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoseBean getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBean pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBean {
|
||||||
|
/**
|
||||||
|
* frame_id : /map
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String frame_id = "/map";
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBean {
|
||||||
|
/**
|
||||||
|
* w : 0.72508
|
||||||
|
* x : 0.00455891
|
||||||
|
* y : 0.0110448
|
||||||
|
* z : -0.688561
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double w;
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
public double getW() {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setW(double w) {
|
||||||
|
this.w = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class BasePositionBean {
|
||||||
|
/**
|
||||||
|
* header : {"frame_id":"/map"}
|
||||||
|
* pose : {"x":-5.56034,"y":0.543951,"z":2.96803E-4}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBeanX header;
|
||||||
|
private PoseBeanX pose;
|
||||||
|
|
||||||
|
public HeaderBeanX getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBeanX header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoseBeanX getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBeanX pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBeanX {
|
||||||
|
/**
|
||||||
|
* frame_id : /map
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String frame_id = "/map";
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBeanX {
|
||||||
|
/**
|
||||||
|
* x : -5.56034
|
||||||
|
* y : 0.543951
|
||||||
|
* z : 2.96803E-4
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
private double z;
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "op": "publish",
|
||||||
|
// "topic": "/move_base/goal",
|
||||||
|
// "msg": {
|
||||||
|
// "target_pose": {
|
||||||
|
// "header": {
|
||||||
|
// "frame_id": "/map"
|
||||||
|
// },
|
||||||
|
// "pose": {
|
||||||
|
// "z": -0.695688,
|
||||||
|
// "x": 0.000728705,
|
||||||
|
// "w": 0.71834,
|
||||||
|
// "y": 0.00213251
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "base_position": {
|
||||||
|
// "header": {
|
||||||
|
// "frame_id": "/map"
|
||||||
|
// },
|
||||||
|
// "pose": {
|
||||||
|
// "z": 0.00984454,
|
||||||
|
// "x": -0.0483838,
|
||||||
|
// "y": -0.00480753
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,219 @@
|
|||||||
|
package com.jilk.ros.nav;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by super_yu on 30/10/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class Move_Base_Status {
|
||||||
|
/**
|
||||||
|
* status_list : [{"goal_id":{"id":"map_6_A_603","stamp":{"secs":1509348841,"nsecs":490135242}},"text":"Goal reached.","status":3},{"goal_id":{"id":"map_6_A_601","stamp":{"secs":1509348875,"nsecs":650002258}},"text":"This goal has been accepted by the simple action server","status":1}]
|
||||||
|
* header : {"seq":13516,"frame_id":"","stamp":{"secs":1509348876,"nsecs":156902566}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBean header;
|
||||||
|
private List<StatusListBean> status_list;
|
||||||
|
|
||||||
|
public HeaderBean getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBean header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<StatusListBean> getStatus_list() {
|
||||||
|
return status_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus_list(List<StatusListBean> status_list) {
|
||||||
|
this.status_list = status_list;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBean {
|
||||||
|
/**
|
||||||
|
* seq : 13516
|
||||||
|
* frame_id :
|
||||||
|
* stamp : {"secs":1509348876,"nsecs":156902566}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int seq;
|
||||||
|
private String frame_id;
|
||||||
|
private StampBean stamp;
|
||||||
|
|
||||||
|
public int getSeq() {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSeq(int seq) {
|
||||||
|
this.seq = seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFrame_id(String frame_id) {
|
||||||
|
this.frame_id = frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StampBean getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBean stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBean {
|
||||||
|
/**
|
||||||
|
* secs : 1509348876
|
||||||
|
* nsecs : 156902566
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs;
|
||||||
|
private int nsecs;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecs(int secs) {
|
||||||
|
this.secs = secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNsecs(int nsecs) {
|
||||||
|
this.nsecs = nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StatusListBean {
|
||||||
|
/**
|
||||||
|
* goal_id : {"id":"map_6_A_603","stamp":{"secs":1509348841,"nsecs":490135242}}
|
||||||
|
* text : Goal reached.
|
||||||
|
* status : 3
|
||||||
|
*/
|
||||||
|
|
||||||
|
private GoalIdBean goal_id;
|
||||||
|
private String text;
|
||||||
|
private int status;
|
||||||
|
|
||||||
|
public GoalIdBean getGoal_id() {
|
||||||
|
return goal_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoal_id(GoalIdBean goal_id) {
|
||||||
|
this.goal_id = goal_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
this.text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(int status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GoalIdBean {
|
||||||
|
/**
|
||||||
|
* id : map_6_A_603
|
||||||
|
* stamp : {"secs":1509348841,"nsecs":490135242}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
private StampBeanX stamp;
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StampBeanX getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBeanX stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBeanX {
|
||||||
|
/**
|
||||||
|
* secs : 1509348841
|
||||||
|
* nsecs : 490135242
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs;
|
||||||
|
private int nsecs;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSecs(int secs) {
|
||||||
|
this.secs = secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNsecs(int nsecs) {
|
||||||
|
this.nsecs = nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "status_list": [
|
||||||
|
// {
|
||||||
|
// "goal_id": {
|
||||||
|
// "id": "map_6_A_603",
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 1509348841,
|
||||||
|
// "nsecs": 490135242
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "text": "Goal reached.",
|
||||||
|
// "status": 3
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// "goal_id": {
|
||||||
|
// "id": "map_6_A_601",
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 1509348875,
|
||||||
|
// "nsecs": 650002258
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// "text": "This goal has been accepted by the simple action server",
|
||||||
|
// "status": 1
|
||||||
|
// }
|
||||||
|
// ],
|
||||||
|
// "header": {
|
||||||
|
// "seq": 13516,
|
||||||
|
// "frame_id": "",
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 1509348876,
|
||||||
|
// "nsecs": 156902566
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,38 @@
|
|||||||
|
package com.jilk.ros.nav;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 存储导航对象
|
||||||
|
* Created by super_yu on 27/10/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NavPublich {
|
||||||
|
|
||||||
|
private List<String> wayPointsNames;
|
||||||
|
|
||||||
|
private HashMap<String, TMove_Base_Goal> navPublishHashMap;
|
||||||
|
|
||||||
|
public List<String> getWayPointsNames() {
|
||||||
|
return wayPointsNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWayPointsNames(List<String> wayPointsNames) {
|
||||||
|
this.wayPointsNames = wayPointsNames;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashMap<String, TMove_Base_Goal> getNavPublishHashMap() {
|
||||||
|
return navPublishHashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNavPublishHashMap(HashMap<String, TMove_Base_Goal> navPublishHashMap) {
|
||||||
|
this.navPublishHashMap = navPublishHashMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
if (wayPointsNames != null) wayPointsNames.clear();
|
||||||
|
if (navPublishHashMap != null) navPublishHashMap.clear();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,402 @@
|
|||||||
|
package com.jilk.ros.nav;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by super_yu on 30/10/2017.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class TMove_Base_Goal {
|
||||||
|
/**
|
||||||
|
* op : publish
|
||||||
|
* topic : /move_base/goal
|
||||||
|
* msg : {"header":{"seq":0,"stamp":{"secs":0,"nsecs":0},"frame_id":"map"},"goal_id":{"stamp":{"secs":0,"nsecs":0},"id":"map_6_A_601"},"goal":{"target_pose":{"header":{"seq":0,"stamp":{"secs":0,"nsecs":0},"frame_id":"map"},"pose":{"position":{"z":2.96803E-4,"x":-5.56034,"y":0.543951},"orientation":{"z":-0.688561,"x":0.00455891,"w":0.72508,"y":0.0110448}}}}}
|
||||||
|
*/
|
||||||
|
private String op = "publish";
|
||||||
|
private String topic = "/move_base/goal";
|
||||||
|
private MsgBean msg;
|
||||||
|
|
||||||
|
public String getOp() {
|
||||||
|
return op;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTopic() {
|
||||||
|
return topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MsgBean getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMsg(MsgBean msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class MsgBean {
|
||||||
|
/**
|
||||||
|
* header : {"seq":0,"stamp":{"secs":0,"nsecs":0},"frame_id":"map"}
|
||||||
|
* goal_id : {"stamp":{"secs":0,"nsecs":0},"id":"map_6_A_601"}
|
||||||
|
* goal : {"target_pose":{"header":{"seq":0,"stamp":{"secs":0,"nsecs":0},"frame_id":"map"},"pose":{"position":{"z":2.96803E-4,"x":-5.56034,"y":0.543951},"orientation":{"z":-0.688561,"x":0.00455891,"w":0.72508,"y":0.0110448}}}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBean header;
|
||||||
|
private GoalIdBean goal_id;
|
||||||
|
private GoalBean goal;
|
||||||
|
|
||||||
|
public HeaderBean getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBean header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GoalIdBean getGoal_id() {
|
||||||
|
return goal_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoal_id(GoalIdBean goal_id) {
|
||||||
|
this.goal_id = goal_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GoalBean getGoal() {
|
||||||
|
return goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGoal(GoalBean goal) {
|
||||||
|
this.goal = goal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBean {
|
||||||
|
/**
|
||||||
|
* seq : 0
|
||||||
|
* stamp : {"secs":0,"nsecs":0}
|
||||||
|
* frame_id : map
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int seq = 0;
|
||||||
|
private StampBean stamp;
|
||||||
|
private String frame_id = "map";
|
||||||
|
|
||||||
|
public int getSeq() {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StampBean getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBean stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBean {
|
||||||
|
/**
|
||||||
|
* secs : 0
|
||||||
|
* nsecs : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs = 0;
|
||||||
|
private int nsecs = 0;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GoalIdBean {
|
||||||
|
/**
|
||||||
|
* stamp : {"secs":0,"nsecs":0}
|
||||||
|
* id : map_6_A_601
|
||||||
|
*/
|
||||||
|
|
||||||
|
private StampBeanX stamp;
|
||||||
|
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
public StampBeanX getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBeanX stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBeanX {
|
||||||
|
/**
|
||||||
|
* secs : 0
|
||||||
|
* nsecs : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs = 0;
|
||||||
|
private int nsecs = 0;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class GoalBean {
|
||||||
|
/**
|
||||||
|
* target_pose : {"header":{"seq":0,"stamp":{"secs":0,"nsecs":0},"frame_id":"map"},"pose":{"position":{"z":2.96803E-4,"x":-5.56034,"y":0.543951},"orientation":{"z":-0.688561,"x":0.00455891,"w":0.72508,"y":0.0110448}}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private TargetPoseBean target_pose;
|
||||||
|
|
||||||
|
public TargetPoseBean getTarget_pose() {
|
||||||
|
return target_pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTarget_pose(TargetPoseBean target_pose) {
|
||||||
|
this.target_pose = target_pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class TargetPoseBean {
|
||||||
|
/**
|
||||||
|
* header : {"seq":0,"stamp":{"secs":0,"nsecs":0},"frame_id":"map"}
|
||||||
|
* pose : {"position":{"z":2.96803E-4,"x":-5.56034,"y":0.543951},"orientation":{"z":-0.688561,"x":0.00455891,"w":0.72508,"y":0.0110448}}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private HeaderBeanX header;
|
||||||
|
private PoseBean pose;
|
||||||
|
|
||||||
|
public HeaderBeanX getHeader() {
|
||||||
|
return header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHeader(HeaderBeanX header) {
|
||||||
|
this.header = header;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PoseBean getPose() {
|
||||||
|
return pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPose(PoseBean pose) {
|
||||||
|
this.pose = pose;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class HeaderBeanX {
|
||||||
|
/**
|
||||||
|
* seq : 0
|
||||||
|
* stamp : {"secs":0,"nsecs":0}
|
||||||
|
* frame_id : map
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int seq = 0;
|
||||||
|
private StampBeanXX stamp;
|
||||||
|
private String frame_id = "map";
|
||||||
|
|
||||||
|
public int getSeq() {
|
||||||
|
return seq;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StampBeanXX getStamp() {
|
||||||
|
return stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStamp(StampBeanXX stamp) {
|
||||||
|
this.stamp = stamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getFrame_id() {
|
||||||
|
return frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class StampBeanXX {
|
||||||
|
/**
|
||||||
|
* secs : 0
|
||||||
|
* nsecs : 0
|
||||||
|
*/
|
||||||
|
|
||||||
|
private int secs = 0;
|
||||||
|
private int nsecs = 0;
|
||||||
|
|
||||||
|
public int getSecs() {
|
||||||
|
return secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getNsecs() {
|
||||||
|
return nsecs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PoseBean {
|
||||||
|
/**
|
||||||
|
* position : {"z":2.96803E-4,"x":-5.56034,"y":0.543951}
|
||||||
|
* orientation : {"z":-0.688561,"x":0.00455891,"w":0.72508,"y":0.0110448}
|
||||||
|
*/
|
||||||
|
|
||||||
|
private PositionBean position;
|
||||||
|
private OrientationBean orientation;
|
||||||
|
|
||||||
|
public PositionBean getPosition() {
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPosition(PositionBean position) {
|
||||||
|
this.position = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OrientationBean getOrientation() {
|
||||||
|
return orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrientation(OrientationBean orientation) {
|
||||||
|
this.orientation = orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class PositionBean {
|
||||||
|
/**
|
||||||
|
* z : 2.96803E-4
|
||||||
|
* x : -5.56034
|
||||||
|
* y : 0.543951
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double z;
|
||||||
|
private double x;
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class OrientationBean {
|
||||||
|
/**
|
||||||
|
* z : -0.688561
|
||||||
|
* x : 0.00455891
|
||||||
|
* w : 0.72508
|
||||||
|
* y : 0.0110448
|
||||||
|
*/
|
||||||
|
|
||||||
|
private double z;
|
||||||
|
private double x;
|
||||||
|
private double w;
|
||||||
|
private double y;
|
||||||
|
|
||||||
|
public double getZ() {
|
||||||
|
return z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setZ(double z) {
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getX() {
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setX(double x) {
|
||||||
|
this.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getW() {
|
||||||
|
return w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setW(double w) {
|
||||||
|
this.w = w;
|
||||||
|
}
|
||||||
|
|
||||||
|
public double getY() {
|
||||||
|
return y;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setY(double y) {
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// {
|
||||||
|
// "op": "publish",
|
||||||
|
// "topic": "/move_base/goal",
|
||||||
|
// "msg": {
|
||||||
|
// "header": {
|
||||||
|
// "seq": 0,
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 0,
|
||||||
|
// "nsecs": 0
|
||||||
|
// },
|
||||||
|
// "frame_id": "map"
|
||||||
|
// },
|
||||||
|
// "goal_id": {
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 0,
|
||||||
|
// "nsecs": 0
|
||||||
|
// },
|
||||||
|
// "id": "map_6_A_601"
|
||||||
|
// },
|
||||||
|
// "goal": {
|
||||||
|
// "target_pose": {
|
||||||
|
// "header": {
|
||||||
|
// "seq": 0,
|
||||||
|
// "stamp": {
|
||||||
|
// "secs": 0,
|
||||||
|
// "nsecs": 0
|
||||||
|
// },
|
||||||
|
// "frame_id": "map"
|
||||||
|
// },
|
||||||
|
// "pose": {
|
||||||
|
// "position": {
|
||||||
|
// "z": 0.000296803,
|
||||||
|
// "x": -5.56034,
|
||||||
|
// "y": 0.543951
|
||||||
|
// },
|
||||||
|
// "orientation": {
|
||||||
|
// "z": -0.688561,
|
||||||
|
// "x": 0.00455891,
|
||||||
|
// "w": 0.72508,
|
||||||
|
// "y": 0.0110448
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
package com.jilk.ros.net;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2017/5/22 0022.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NetBroadcastReceiver extends BroadcastReceiver {
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
// TODO Auto-generated method stub
|
||||||
|
// 如果相等的话就说明网络状态发生了变化
|
||||||
|
if (intent.getAction().equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
|
||||||
|
int netWorkState = NetUtil.getNetWorkState(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package com.jilk.ros.net;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.net.ConnectivityManager;
|
||||||
|
import android.net.NetworkInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Administrator on 2017/5/22 0022.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public class NetUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 没有连接网络
|
||||||
|
*/
|
||||||
|
private static final int NETWORK_NONE = -1;
|
||||||
|
/**
|
||||||
|
* 移动网络
|
||||||
|
*/
|
||||||
|
private static final int NETWORK_MOBILE = 0;
|
||||||
|
/**
|
||||||
|
* 无线网络
|
||||||
|
*/
|
||||||
|
private static final int NETWORK_WIFI = 1;
|
||||||
|
|
||||||
|
public static int getNetWorkState(Context context) {
|
||||||
|
// 得到连接管理器对象
|
||||||
|
ConnectivityManager connectivityManager = (ConnectivityManager) context
|
||||||
|
.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||||
|
|
||||||
|
NetworkInfo activeNetworkInfo = connectivityManager
|
||||||
|
.getActiveNetworkInfo();
|
||||||
|
if (activeNetworkInfo != null && activeNetworkInfo.isConnected()) {
|
||||||
|
|
||||||
|
if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_WIFI)) {
|
||||||
|
return NETWORK_WIFI;
|
||||||
|
} else if (activeNetworkInfo.getType() == (ConnectivityManager.TYPE_MOBILE)) {
|
||||||
|
return NETWORK_MOBILE;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return NETWORK_NONE;
|
||||||
|
}
|
||||||
|
return NETWORK_NONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,18 @@
|
|||||||
|
package com.example.testdemo;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
|
|
||||||
|
@SpringBootApplication
|
||||||
|
public class ServerApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
|
||||||
|
SpringApplication.run(ServerApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,42 +0,0 @@
|
|||||||
package com.example.testdemo;
|
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSON;
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
|
||||||
import com.sun.javafx.webkit.EventLoopImpl;
|
|
||||||
import org.openqa.selenium.*;
|
|
||||||
import org.openqa.selenium.chrome.ChromeDriver;
|
|
||||||
import org.openqa.selenium.chrome.ChromeOptions;
|
|
||||||
import org.springframework.boot.SpringApplication;
|
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|
||||||
import org.springframework.scheduling.annotation.EnableScheduling;
|
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
|
||||||
import org.springframework.stereotype.Controller;
|
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
|
||||||
|
|
||||||
import javax.script.ScriptEngine;
|
|
||||||
import javax.script.ScriptEngineManager;
|
|
||||||
import javax.script.ScriptException;
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.FileReader;
|
|
||||||
import java.sql.Driver;
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Random;
|
|
||||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
|
||||||
|
|
||||||
|
|
||||||
@SpringBootApplication
|
|
||||||
public class TestdemoApplication {
|
|
||||||
|
|
||||||
public static void main(String[] args) {
|
|
||||||
|
|
||||||
SpringApplication.run(TestdemoApplication.class, args);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,57 @@
|
|||||||
|
package com.example.testdemo.ros;
|
||||||
|
|
||||||
|
|
||||||
|
public class Publisher {
|
||||||
|
|
||||||
|
protected String topic;
|
||||||
|
protected String msgType;
|
||||||
|
protected int rosBridge;
|
||||||
|
|
||||||
|
|
||||||
|
public Publisher(String topic, String msgType, int rosBridge){
|
||||||
|
this.topic = topic;
|
||||||
|
this.msgType = msgType;
|
||||||
|
this.rosBridge = rosBridge;
|
||||||
|
|
||||||
|
//this.rosBridge.advertise(this.topic, this.msgType);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Publisher(String topic, String msgType, int rosBridge, boolean advertiseNow){
|
||||||
|
this.topic = topic;
|
||||||
|
this.msgType = msgType;
|
||||||
|
this.rosBridge = rosBridge;
|
||||||
|
|
||||||
|
if(advertiseNow) {
|
||||||
|
//this.rosBridge.advertise(this.topic, this.msgType);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public String getTopic() {
|
||||||
|
return topic;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ROS message type of the topic to which this object publishes.
|
||||||
|
* @return the ROS message type of the topic to which this object publishes.
|
||||||
|
*/
|
||||||
|
public String getMsgType() {
|
||||||
|
return msgType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link ros.RosBridge} object that manages the connection to the ROS Bridge server.
|
||||||
|
* @return the {@link ros.RosBridge} object that manages the connection to the ROS Bridge server.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unadvertises that you are publishing to the topic.
|
||||||
|
*/
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
package com.example.testdemo.ros;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonFactory;
|
||||||
|
import com.fasterxml.jackson.core.JsonParseException;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a delegate interface for handling ros topic subscriptions. The {@link #receive(JsonNode, String)}
|
||||||
|
* is called every time the topic with which this delegate is associated has a new message published.
|
||||||
|
* The JSON data, given as a {@link JsonNode}, has four top-level fields:<p>
|
||||||
|
* op: what kind of operation it was; should always be "publish"<p>
|
||||||
|
* topic: to which topic the message was published<p>
|
||||||
|
* type: the ROS message type of the topic<p>
|
||||||
|
* msg: the provided ros message in JSON format. This the primary field you will work with.<p>
|
||||||
|
* There are generally two ways you can parse the message into a more usable Java object. The first involves manually
|
||||||
|
* iterating through the JSON fields of the msg. For example,
|
||||||
|
* for a geometry_msgs/Twist message, you can get out the linear x value as follows:<p>
|
||||||
|
* <code>double x = data.get("msg").get("linear").get("x").asDouble();</code><p>
|
||||||
|
* (If an element is na array, JSON methods exist for handling it such as {@link JsonNode#get(int)}
|
||||||
|
* and {@link JsonNode#size()}). The the other way is to let the Jackson library unpack
|
||||||
|
* it into a JavaBean. The {@link ros.tools.MessageUnpacker} class further streamlines this process. See its documentation
|
||||||
|
* for more information.
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public interface RosListenDelegate {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Receives a new published message to a subscribed topic. The JSON data, given as a {@link JsonNode}, has four top-level fields:<p>
|
||||||
|
* op: what kind of operation it was; should always be "publish"<p>
|
||||||
|
* topic: to which topic the message was published<p>
|
||||||
|
* type: the ROS message type of the topic<p>
|
||||||
|
* msg: the provided ros message in JSON format. This the primary field you will work with.<p>
|
||||||
|
* This method also receives the full string representation of the received JSON message from ROSBridge.
|
||||||
|
* @param data the {@link JsonNode} containing the JSON data received.
|
||||||
|
* @param stringRep the string representation of the JSON object.
|
||||||
|
*/
|
||||||
|
void receive(JsonNode data, String stringRep);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A class for easy conversion to the legacy java_rosbridge {@link #receive(JsonNode, String)}
|
||||||
|
* message format that presented the JSON data
|
||||||
|
* in a {@link Map} from {@link String} to {@link Object} instances
|
||||||
|
* in which the values were ether primitives, {@link Map} objects themselves, or {@link java.util.List}
|
||||||
|
* objects.
|
||||||
|
*/
|
||||||
|
public static class LegacyFormat{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A method for easy conversion to the legacy java_rosbridge {@link #receive(JsonNode, String)}
|
||||||
|
* message format that presented the JSON data
|
||||||
|
* in a {@link Map} from {@link String} to {@link Object} instances
|
||||||
|
* in which the values were ether primitives, {@link Map} objects themselves, or {@link java.util.List}
|
||||||
|
* objects.
|
||||||
|
* @param jsonString the source JSON string message that was received
|
||||||
|
* @return a {@link Map} data structure of the JSON data.
|
||||||
|
*/
|
||||||
|
public static Map<String, Object> legacyFormat(String jsonString){
|
||||||
|
|
||||||
|
JsonFactory jsonFactory = new JsonFactory();
|
||||||
|
Map<String, Object> messageData = new HashMap<String, Object>();
|
||||||
|
try {
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper(jsonFactory);
|
||||||
|
TypeReference<Map<String, Object>> listTypeRef =
|
||||||
|
new TypeReference<Map<String, Object>>() {};
|
||||||
|
messageData = objectMapper.readValue(jsonString, listTypeRef);
|
||||||
|
} catch (JsonParseException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return messageData;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,118 @@
|
|||||||
|
package com.example.testdemo.ros;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Subscription request builder. Supports all Rosbridge protocol fields for
|
||||||
|
* a subscription request except png compression. Requires a topic to be set,
|
||||||
|
* with the rest of the optional values set with setter methods that return
|
||||||
|
* the this object so that you can chain settters on a single line. Use
|
||||||
|
* the static {@link #generate(String)} to start the sequence. If a value is set
|
||||||
|
* to null, it will be removed from the message.
|
||||||
|
* <p>
|
||||||
|
* When everything is set, the JSON message can be retrieved with the {@link #generateJsonString()}
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class SubscriptionRequestMsg {
|
||||||
|
|
||||||
|
protected Map<String, Object> keyValues = new HashMap<String, Object>(7);
|
||||||
|
|
||||||
|
public static SubscriptionRequestMsg generate(String topic){
|
||||||
|
return new SubscriptionRequestMsg(topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg(String topic){
|
||||||
|
if(topic == null){
|
||||||
|
throw new RuntimeException("ROS topic cannot be null in subscription request.");
|
||||||
|
}
|
||||||
|
keyValues.put("op", "subscribe");
|
||||||
|
keyValues.put("topic", topic);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg setTopic(String topic){
|
||||||
|
this.setKeyValue("topic", topic);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg setType(String type){
|
||||||
|
this.setKeyValue("type", type);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg setThrottleRate(Integer throttleRate){
|
||||||
|
this.setKeyValue("throttle_rate", throttleRate);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg setQueueLength(Integer queueLength){
|
||||||
|
this.setKeyValue("queue_length", queueLength);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg setFragmentSize(Integer fragmentSize){
|
||||||
|
this.setKeyValue("fragment_size", fragmentSize);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public SubscriptionRequestMsg setId(String id){
|
||||||
|
this.setKeyValue("id", id);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTopic(){
|
||||||
|
return (String)this.keyValues.get("topic");
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getType(){
|
||||||
|
return (String)this.keyValues.get("type");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getThrottleRate(){
|
||||||
|
return (Integer)this.keyValues.get("throttle_rate");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getQueueLength(){
|
||||||
|
return (Integer)this.keyValues.get("queue_length");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getFragmentSize(){
|
||||||
|
return (Integer)this.keyValues.get("fragment_size");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public String getId(){
|
||||||
|
return (String)this.keyValues.get("id");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the JSON string for this subscription request.
|
||||||
|
* @return the JSON string for this subscription request.
|
||||||
|
*/
|
||||||
|
public String generateJsonString(){
|
||||||
|
ObjectMapper mapper = new ObjectMapper();
|
||||||
|
String jsonString = null;
|
||||||
|
try {
|
||||||
|
jsonString = mapper.writeValueAsString(this.keyValues);
|
||||||
|
} catch(JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return jsonString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
protected void setKeyValue(String key, Object value){
|
||||||
|
if(value == null){
|
||||||
|
this.keyValues.remove(key);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
this.keyValues.put(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,19 @@
|
|||||||
|
package com.example.testdemo.ros.msgs.geometry_msgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Java Bean for the Vector3 ROS geometry_msgs/Twist message type. This can be used both for publishing Twist messages to
|
||||||
|
* {@link ros.RosBridge} and unpacking Twist messages received from {@link ros.RosBridge} (see the {@link ros.tools.MessageUnpacker}
|
||||||
|
* documentation for how to easily unpack a ROS Bridge message into a Java object).
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class Twist {
|
||||||
|
public Vector3 linear = new Vector3();
|
||||||
|
public Vector3 angular = new Vector3();
|
||||||
|
|
||||||
|
public Twist(){}
|
||||||
|
|
||||||
|
public Twist(Vector3 linear, Vector3 angular) {
|
||||||
|
this.linear = linear;
|
||||||
|
this.angular = angular;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.example.testdemo.ros.msgs.geometry_msgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A Java Bean for the Vector3 ROS geometry_msgs/Vector3 message type. This can be used both for publishing Vector3 messages to
|
||||||
|
* {@link ros.RosBridge} and unpacking Vector3 messages received from {@link ros.RosBridge} (see the {@link ros.tools.MessageUnpacker}
|
||||||
|
* documentation for how to easily unpack a ROS Bridge message into a Java object).
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class Vector3 {
|
||||||
|
public double x;
|
||||||
|
public double y;
|
||||||
|
public double z;
|
||||||
|
|
||||||
|
public Vector3(){}
|
||||||
|
|
||||||
|
public Vector3(double x, double y, double z) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
this.z = z;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
package com.example.testdemo.ros.msgs.sensor_msgs;
|
||||||
|
|
||||||
|
import com.example.testdemo.ros.message.Header;
|
||||||
|
|
||||||
|
import java.awt.image.BufferedImage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of ROS sensor_msgs/Image.msg:
|
||||||
|
* <a href="http://docs.ros.org/api/sensor_msgs/html/msg/Image.html">http://docs.ros.org/api/sensor_msgs/html/msg/Image.html</a>.
|
||||||
|
* This class can also decode the ROS Image into a Java Buffered Image for images that are encoded in either
|
||||||
|
* bgr8, rgb8, or mono8, by using the {@link #toBufferedImage()} method.
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class Image {
|
||||||
|
|
||||||
|
public Header header;
|
||||||
|
public int height;
|
||||||
|
public int width;
|
||||||
|
public String encoding;
|
||||||
|
public int is_bigendian;
|
||||||
|
public int step;
|
||||||
|
public byte[] data;
|
||||||
|
|
||||||
|
public Image() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Image(Header header, int height, int width, String encoding, int is_bigendian, int step, byte[] data) {
|
||||||
|
this.header = header;
|
||||||
|
this.height = height;
|
||||||
|
this.width = width;
|
||||||
|
this.encoding = encoding;
|
||||||
|
this.is_bigendian = is_bigendian;
|
||||||
|
this.step = step;
|
||||||
|
this.data = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link BufferedImage} from this ROS Image, provided the encoding is either rgb8, bgr8, or mono8.
|
||||||
|
* If it is not one of those encodings, then a runtime exception will be thrown.
|
||||||
|
* @return a {@link BufferedImage} representation of this image.
|
||||||
|
*/
|
||||||
|
public BufferedImage toBufferedImage(){
|
||||||
|
|
||||||
|
if(this.encoding.equals("bgr8") || this.encoding.equals("rgb8")){
|
||||||
|
return this.toBufferedImageFromRGB8();
|
||||||
|
}
|
||||||
|
else if(this.encoding.equals("mono8")){
|
||||||
|
return this.toBufferedImageFromMono8();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
throw new RuntimeException("ROS Image does not currently decode " + this.encoding + ". See Java doc for support types.");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link BufferedImage} from this ROS Image assuming the encoding is mono8
|
||||||
|
* @return a {@link BufferedImage} representation of this image.
|
||||||
|
*/
|
||||||
|
protected BufferedImage toBufferedImageFromMono8(){
|
||||||
|
int w = this.width;
|
||||||
|
int h = this.height;
|
||||||
|
|
||||||
|
BufferedImage i = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for(int x = 0; x < w; ++x) {
|
||||||
|
|
||||||
|
//row major
|
||||||
|
int index = (y * w) + x;
|
||||||
|
// combine to RGB format
|
||||||
|
int anded = data[index++] & 0xFF;
|
||||||
|
int rgb = anded |
|
||||||
|
(anded << 8) |
|
||||||
|
(anded << 16) |
|
||||||
|
0xFF000000;
|
||||||
|
|
||||||
|
i.setRGB(x, y, rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a {@link BufferedImage} representation from this ROS Image assuming the encoding is either rgb8 or bgr8.
|
||||||
|
* @return a {@link BufferedImage} representation of this image.
|
||||||
|
*/
|
||||||
|
protected BufferedImage toBufferedImageFromRGB8(){
|
||||||
|
|
||||||
|
int w = this.width;
|
||||||
|
int h = this.height;
|
||||||
|
|
||||||
|
BufferedImage i = new BufferedImage(w, h, BufferedImage.TYPE_INT_RGB);
|
||||||
|
for (int y = 0; y < h; ++y) {
|
||||||
|
for (int x = 0; x < w; ++x) {
|
||||||
|
|
||||||
|
//row major, consecutive channels
|
||||||
|
int index = (y * w * 3) + (x * 3);
|
||||||
|
// combine to RGB format
|
||||||
|
int rgb;
|
||||||
|
if(this.encoding.equals("bgr8")){
|
||||||
|
rgb = ((data[index++] & 0xFF)) |
|
||||||
|
((data[index++] & 0xFF) << 8) |
|
||||||
|
((data[index++] & 0xFF) << 16) |
|
||||||
|
0xFF000000;
|
||||||
|
}
|
||||||
|
else if(this.encoding.equals("rgb8")){
|
||||||
|
rgb = ((data[index++] & 0xFF) << 16) |
|
||||||
|
((data[index++] & 0xFF) << 8) |
|
||||||
|
((data[index++] & 0xFF)) |
|
||||||
|
0xFF000000;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
throw new RuntimeException("ROS Image toBufferedImageFromRGB8 does not decode " + this.encoding);
|
||||||
|
}
|
||||||
|
i.setRGB(x, y, rgb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
package com.example.testdemo.ros.msgs.std_msgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class Header {
|
||||||
|
|
||||||
|
public int seq;
|
||||||
|
public Time stamp;
|
||||||
|
public String frame_id;
|
||||||
|
|
||||||
|
public Header() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Header(int seq, Time stamp, String frame_id) {
|
||||||
|
this.seq = seq;
|
||||||
|
this.stamp = stamp;
|
||||||
|
this.frame_id = frame_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,12 @@
|
|||||||
|
package com.example.testdemo.ros.msgs.std_msgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A generic specified Java Bean for capturing many of the primitive data-type messages used by ROS in the std_msgs
|
||||||
|
* package. The class has a single public data member called "data" that belongs to the specified primitive type.
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class PrimitiveMsg <T> {
|
||||||
|
public T data;
|
||||||
|
public PrimitiveMsg(){}
|
||||||
|
public PrimitiveMsg(T data){this.data = data;}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package com.example.testdemo.ros.msgs.std_msgs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class Time {
|
||||||
|
public int secs;
|
||||||
|
public int nsecs;
|
||||||
|
|
||||||
|
public Time() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Time(int secs, int nsecs) {
|
||||||
|
this.secs = secs;
|
||||||
|
this.nsecs = nsecs;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
package com.example.testdemo.ros.tools;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.JsonNode;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This is a helper class that may be used for taking a JSON message returned from Ros bridge, and unpacking
|
||||||
|
* the actual ros message inside it into a Java bean object. (A Java bean is a Java object that has a default
|
||||||
|
* constructor and getter and has either public data members or getter and setter methods for the data members
|
||||||
|
* using standard Java naming conventions.)
|
||||||
|
* <p>
|
||||||
|
* To use this class, type the generic to the Java Bean class to which the message will be unpacked and provide
|
||||||
|
* the constructor the class of it as well. For example:<p>
|
||||||
|
* <code>MessageUnpacker<Twist> unpacker = new MessageUnpacker<Twist>(Twist.class);</code>. Then provide the
|
||||||
|
* {@link #unpackRosMessage(JsonNode)} method the {@link JsonNode}
|
||||||
|
* provided to a {@link ros.RosListenDelegate} to unpack the "msg" field into the Java Bean. This will also work
|
||||||
|
* with Java Beans with generics. For example, you can do
|
||||||
|
* <code>MessageUnpacker<PrimitiveMsg<String>> unpacker = new MessageUnpacker<PrimitiveMsg<String>>(PrimitiveMsg.class);</code>.
|
||||||
|
*
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class MessageUnpacker <T> {
|
||||||
|
protected ObjectMapper mapper = new ObjectMapper();
|
||||||
|
protected Class<?> javaClass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
* @param javaClass a {@link Class} specifying the class of the Java bean into which
|
||||||
|
* a ros message will be unpacked.
|
||||||
|
*/
|
||||||
|
public MessageUnpacker(Class<?> javaClass) {
|
||||||
|
this.javaClass = javaClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpacks a ros message into the appropriate Java bean from the JSON message returned by
|
||||||
|
* ros bridge. Note that the Ros bridge JSON message contains header information and the actual
|
||||||
|
* ROS message is stored in the 'msg' field in the JSON message. Therefore, this method should be provided the
|
||||||
|
* {@link JsonNode} that is given to a {@link ros.RosListenDelegate}
|
||||||
|
* {@link ros.RosListenDelegate#receive(JsonNode, String)} method.
|
||||||
|
* If the provided {@link JsonNode} argument of this method
|
||||||
|
* does not have a "msg" field, then it will attempt to unpack from the whole JSON node.
|
||||||
|
* @param rosBridgeMessage the {@link JsonNode} from RosBridge.
|
||||||
|
* @return the unpacked Java Bean of the ROS message.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public T unpackRosMessage(JsonNode rosBridgeMessage){
|
||||||
|
JsonNode rosMsgNode = rosBridgeMessage.get("msg");
|
||||||
|
if(rosMsgNode == null){
|
||||||
|
rosMsgNode = rosBridgeMessage;
|
||||||
|
}
|
||||||
|
T rosMsg = null;
|
||||||
|
try {
|
||||||
|
rosMsg = (T)mapper.treeToValue(rosMsgNode, javaClass);
|
||||||
|
} catch(JsonProcessingException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
return rosMsg;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,178 @@
|
|||||||
|
package com.example.testdemo.ros.tools;
|
||||||
|
|
||||||
|
import com.example.testdemo.ros.Publisher;
|
||||||
|
|
||||||
|
import java.util.Timer;
|
||||||
|
import java.util.TimerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class is a tool for causing a ROS message to be periodically published at a given rate. To start periodic publishing
|
||||||
|
* use the {@link #beginPublishing(int)} or {@link #beginPublishing(Object, int)} methods. Note that subsequent calls
|
||||||
|
* to these method will automatically cancel the previous periodic publishing and start again at the newly specified rate.
|
||||||
|
* To cancel periodic publishing, use the {@link #cancelPublishing()} method. You can also change the message that is
|
||||||
|
* being published without stopping or restarting the publishing by using the {@link #setMsg(Object)} method.
|
||||||
|
* @author James MacGlashan.
|
||||||
|
*/
|
||||||
|
public class PeriodicPublisher {
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The {@link Publisher} to which publish calls are made
|
||||||
|
*/
|
||||||
|
protected Publisher pub;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ROS message that will be periodically published
|
||||||
|
*/
|
||||||
|
protected volatile Object msg = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The period at which this object is publishing; -1 if it is not currently publishing.
|
||||||
|
*/
|
||||||
|
protected int period = -1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The timer task that calls the publish. Null if this object is not periodically publishing.
|
||||||
|
*/
|
||||||
|
protected PublisherTimerTask timerTask;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes with a {@link Publisher} for this action using the specified topic, message type, and {@link RosBridge} connection.
|
||||||
|
* @param topic the ros topic to which messages will be published
|
||||||
|
* @param msgType the ros message type of th target topic
|
||||||
|
* @param rosBridge the {@link RosBridge} connection to use.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes with a {@link Publisher} for this action using the specified topic, message type, and {@link RosBridge} connection.
|
||||||
|
* @param topic the ros topic to which messages will be published
|
||||||
|
* @param msgType the ros message type of th target topic
|
||||||
|
* @param rosBridge the {@link RosBridge} connection to use.
|
||||||
|
* @param msg the ROS message to periodically publish when publishing begins
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes with a {@link Publisher} for publishing action messages to ROS.
|
||||||
|
* @param pub the {@link Publisher} to which to publish
|
||||||
|
*/
|
||||||
|
public PeriodicPublisher(Publisher pub){
|
||||||
|
this.pub = pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes with a {@link Publisher} for publishing action messages to ROS.
|
||||||
|
* @param pub the {@link Publisher} to which to publish
|
||||||
|
* @param msg the ROS message to periodically publish when publishing begins
|
||||||
|
*/
|
||||||
|
public PeriodicPublisher(Publisher pub, Object msg) {
|
||||||
|
this.pub = pub;
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Publisher getPub() {
|
||||||
|
return pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPub(Publisher pub) {
|
||||||
|
this.pub = pub;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the ROS message that is being or will be periodically published.
|
||||||
|
* @return the ROS message that is being or will be periodically published.
|
||||||
|
*/
|
||||||
|
public Object getMsg() {
|
||||||
|
return msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the ROS message that will be periodically published. Note that if the provided message is null and this
|
||||||
|
* object is already periodically publishing, a runtime error will be thrown.
|
||||||
|
* @param msg the ROS message that will be published.
|
||||||
|
*/
|
||||||
|
public void setMsg(Object msg) {
|
||||||
|
if(msg == null && this.timerTask != null){
|
||||||
|
System.out.println("PeriodicPublisher is not setting message because new message is null and publisher is currently publishing.");
|
||||||
|
}
|
||||||
|
this.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The delay in milliseconds between subsequent periodic publishes. Returns -1 if this object is not currently periodically publishing.
|
||||||
|
* @return The delay in milliseconds between subsequent publishes. Returns -1 if this object is not currently periodically publishing.
|
||||||
|
*/
|
||||||
|
public int getPublishingPeriod(){
|
||||||
|
return this.period;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops this object from periodically publishing, or does nothing if it is not currently periodically publishing.
|
||||||
|
*/
|
||||||
|
public void cancelPublishing(){
|
||||||
|
if(this.timerTask != null) {
|
||||||
|
this.timerTask.cancel();
|
||||||
|
this.timerTask = null;
|
||||||
|
this.period = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether this object is currently periodically publishing.
|
||||||
|
* @return true if this object is periodically publishing; false if it is not.
|
||||||
|
*/
|
||||||
|
public boolean isPublishing(){
|
||||||
|
return this.timerTask != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes this object to begin periodically publishing at the specified rate. If this object is
|
||||||
|
* already publishing then the previous publishing rate is canceled and started at the new rate.
|
||||||
|
* If the current message to
|
||||||
|
* publish is not set, then a runtime exception will be thrown. The message can be set either with the
|
||||||
|
* {@link #setMsg(Object)} method or by using the alternative {@link #beginPublishing(Object, int)}
|
||||||
|
* method that takes the message to publish.
|
||||||
|
* @param period the time in milliseconds between publishes
|
||||||
|
*/
|
||||||
|
public void beginPublishing(int period){
|
||||||
|
if(this.msg == null){
|
||||||
|
throw new RuntimeException("Cannot begin publishing because the message to publish is unset. " +
|
||||||
|
"Use the setMsg method or beginPublishing(Object msg, int period)");
|
||||||
|
}
|
||||||
|
if(this.timerTask != null){
|
||||||
|
this.timerTask.cancel();
|
||||||
|
}
|
||||||
|
this.timerTask = new PublisherTimerTask();
|
||||||
|
Timer timer = new Timer();
|
||||||
|
timer.schedule(this.timerTask, 0, period);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Causes this object to begin periodically publishing the specified message at the specified rate.
|
||||||
|
* If this object is already publishing then the previous publishing rate is canceled and started at the new rate.
|
||||||
|
* Note that if the provided message is null then a runtime exception will be thrown.
|
||||||
|
* @param msg the ROS message to publish
|
||||||
|
* @param period the time in milliseconds between publishes
|
||||||
|
*/
|
||||||
|
public void beginPublishing(Object msg, int period){
|
||||||
|
this.msg = msg;
|
||||||
|
this.beginPublishing(period);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The class that is called by Java's {@link Timer} and invokes the actual
|
||||||
|
* publish call.
|
||||||
|
*/
|
||||||
|
protected class PublisherTimerTask extends TimerTask{
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
//pub.publish(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,181 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JRosbridge class contains constant definitions used in the rosbridge
|
||||||
|
* protocol itself (e.g., op code types).
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class JRosbridge {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The args field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_ARGS = "args";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The client field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_CLIENT = "client";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The compression field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_COMPRESSION = "compression";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The data field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_DATA = "data";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The destination field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_DESTINATION = "dest";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The end time field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_END_TIME = "end";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ID field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_ID = "id";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The user level field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_LEVEL = "level";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The MAC field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_MAC = "mac";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message data field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_MESSAGE = "msg";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The op code field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_OP = "op";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The random field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_RAND = "rand";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The result field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_RESULT = "result";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_SERVICE = "service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The throttle rate field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_THROTTLE_RATE = "throttle_rate";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The time field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_TIME = "t";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The topic field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_TOPIC = "topic";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The message/service type field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_TYPE = "type";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The values field for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_VALUES = "values";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The advertise op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_ADVERTISE = "advertise";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The advertise service op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_ADVERTISE_SERVICE = "advertise_service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unadvertise service op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_UNADVERTISE_SERVICE = "unadvertise_service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The authenticate op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_AUTH = "auth";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The call service op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_CALL_SERVICE = "call_service";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The png compression op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_PNG = "png";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The publish op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_PUBLISH = "publish";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service response op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_SERVICE_RESPONSE = "service_response";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The subscribe op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_SUBSCRIBE = "subscribe";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unadvertise op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_UNADVERTISE = "unadvertise";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The unsubscribe op code for the rosbridge protocol.
|
||||||
|
*/
|
||||||
|
public static final String OP_CODE_UNSUBSCRIBE = "unsubscribe";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of websocket protocols supported by jrosbridge and rosbridge.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public enum WebSocketType {
|
||||||
|
ws, wss
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The types of compression supported by jrosbridge and rosbridge.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public enum CompressionType {
|
||||||
|
png, none
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,106 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JsonWrapper objects are used as a wrapper around JSON objects. That is, they
|
||||||
|
* are a reusable convince for messages and services. This objects are immutable
|
||||||
|
* and declared abstract as they should not be used directly.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public abstract class JsonWrapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The String representation of an empty message in JSON.
|
||||||
|
*/
|
||||||
|
public static final String EMPTY_JSON = "{}";
|
||||||
|
|
||||||
|
private final JsonObject jsonObject;
|
||||||
|
private final String jsonString;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new, empty JSON object.
|
||||||
|
*/
|
||||||
|
public JsonWrapper() {
|
||||||
|
this(JsonWrapper.EMPTY_JSON);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a JSON object based on the given String representation of a JSON
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param json
|
||||||
|
* The JSON String to parse.
|
||||||
|
*/
|
||||||
|
public JsonWrapper(String jsonString) {
|
||||||
|
// parse and pass it to the JSON constructor
|
||||||
|
this(Json.createReader(new StringReader(jsonString)).readObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Message based on the given JSON object.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object containing the message data.
|
||||||
|
*/
|
||||||
|
public JsonWrapper(JsonObject jsonObject) {
|
||||||
|
this.jsonObject = jsonObject;
|
||||||
|
// only need to do this once
|
||||||
|
this.jsonString = this.jsonObject.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the JSON object.
|
||||||
|
*
|
||||||
|
* @return The JSON object.
|
||||||
|
*/
|
||||||
|
public JsonObject toJsonObject() {
|
||||||
|
return this.jsonObject;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the String representation of this JSON object in JSON format.
|
||||||
|
*
|
||||||
|
* @return The String representation of this JSON object in JSON format.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.jsonString;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this JSON object.
|
||||||
|
*/
|
||||||
|
public abstract JsonWrapper clone();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the hash code of this JSON object, which is the hash code of the
|
||||||
|
* JSON string.
|
||||||
|
*
|
||||||
|
* @return The hash code of the message.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return this.jsonString.hashCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test if the given Object is equal to this JsonWrapper. Two JsonWrappers
|
||||||
|
* are equal if and only if their JSON strings match.
|
||||||
|
*
|
||||||
|
* @param o
|
||||||
|
* The Object to test equality with.
|
||||||
|
* @return If the given Object is equal to this JsonWrapper.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
return o == this
|
||||||
|
|| (o instanceof JsonWrapper && this.jsonString.equals(o
|
||||||
|
.toString()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,535 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge;
|
||||||
|
|
||||||
|
import java.awt.image.Raster;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.net.URI;
|
||||||
|
import java.net.URISyntaxException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import javax.imageio.ImageIO;
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
import javax.json.stream.JsonParsingException;
|
||||||
|
import javax.websocket.ClientEndpoint;
|
||||||
|
import javax.websocket.ContainerProvider;
|
||||||
|
import javax.websocket.DeploymentException;
|
||||||
|
import javax.websocket.OnClose;
|
||||||
|
import javax.websocket.OnError;
|
||||||
|
import javax.websocket.OnMessage;
|
||||||
|
import javax.websocket.OnOpen;
|
||||||
|
import javax.websocket.Session;
|
||||||
|
|
||||||
|
import com.example.testdemo.ros.message.Message;
|
||||||
|
import edu.wpi.rail.jrosbridge.callback.CallServiceCallback;
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceRequest;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.callback.ServiceCallback;
|
||||||
|
import edu.wpi.rail.jrosbridge.callback.TopicCallback;
|
||||||
|
import edu.wpi.rail.jrosbridge.handler.RosHandler;
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceResponse;
|
||||||
|
import org.springframework.util.Base64Utils;
|
||||||
|
|
||||||
|
@ClientEndpoint
|
||||||
|
public class Ros {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default hostname used if none is provided.
|
||||||
|
*/
|
||||||
|
public static final String DEFAULT_HOSTNAME = "localhost";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The default port used if none is provided.
|
||||||
|
*/
|
||||||
|
public static final int DEFAULT_PORT = 9090;
|
||||||
|
|
||||||
|
private final String hostname;
|
||||||
|
private final int port;
|
||||||
|
private final JRosbridge.WebSocketType protocol;
|
||||||
|
|
||||||
|
// active session (stored upon connection)
|
||||||
|
private Session session;
|
||||||
|
|
||||||
|
// used throughout the library to create unique IDs for requests.
|
||||||
|
private long idCounter;
|
||||||
|
|
||||||
|
// keeps track of callback functions for a given topic
|
||||||
|
private final HashMap<String, ArrayList<TopicCallback>> topicCallbacks;
|
||||||
|
|
||||||
|
// keeps track of callback functions for a given service request
|
||||||
|
private final HashMap<String, ServiceCallback> serviceCallbacks;
|
||||||
|
|
||||||
|
// keeps track of callback functions for a given advertised service
|
||||||
|
private final HashMap<String, CallServiceCallback> callServiceCallbacks;
|
||||||
|
|
||||||
|
// keeps track of handlers for this connection
|
||||||
|
private final ArrayList<RosHandler> handlers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a connection to ROS with the default hostname and port. A call to
|
||||||
|
* connect must be made to establish a connection.
|
||||||
|
*/
|
||||||
|
public Ros() {
|
||||||
|
this(Ros.DEFAULT_HOSTNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a connection to ROS with the given hostname and default port. A
|
||||||
|
* call to connect must be made to establish a connection. By default,
|
||||||
|
* WebSockets is used (as opposed to WSS).
|
||||||
|
*
|
||||||
|
* @param hostname
|
||||||
|
* The hostname to connect to.
|
||||||
|
*/
|
||||||
|
public Ros(String hostname) {
|
||||||
|
this(hostname, Ros.DEFAULT_PORT);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a connection to ROS with the given hostname and port. A call to
|
||||||
|
* connect must be made to establish a connection. By default, WebSockets is
|
||||||
|
* used (as opposed to WSS).
|
||||||
|
*
|
||||||
|
* @param hostname
|
||||||
|
* The hostname to connect to.
|
||||||
|
* @param port
|
||||||
|
* The port to connect to.
|
||||||
|
*/
|
||||||
|
public Ros(String hostname, int port) {
|
||||||
|
this(hostname, port, JRosbridge.WebSocketType.ws);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a connection to ROS with the given hostname and port. A call to
|
||||||
|
* connect must be made to establish a connection.
|
||||||
|
*
|
||||||
|
* @param hostname
|
||||||
|
* The hostname to connect to.
|
||||||
|
* @param port
|
||||||
|
* The port to connect to.
|
||||||
|
* @param protocol
|
||||||
|
* The WebSocket protocol to use.
|
||||||
|
*/
|
||||||
|
public Ros(String hostname, int port, JRosbridge.WebSocketType protocol) {
|
||||||
|
this.hostname = hostname;
|
||||||
|
this.port = port;
|
||||||
|
this.protocol = protocol;
|
||||||
|
this.session = null;
|
||||||
|
this.idCounter = 0;
|
||||||
|
this.topicCallbacks = new HashMap<String, ArrayList<TopicCallback>>();
|
||||||
|
this.serviceCallbacks = new HashMap<String, ServiceCallback>();
|
||||||
|
this.callServiceCallbacks = new HashMap<String, CallServiceCallback>();
|
||||||
|
this.handlers = new ArrayList<RosHandler>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the hostname associated with this connection.
|
||||||
|
*
|
||||||
|
* @return The hostname associated with this connection.
|
||||||
|
*/
|
||||||
|
public String getHostname() {
|
||||||
|
return this.hostname;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the port associated with this connection.
|
||||||
|
*
|
||||||
|
* @return The port associated with this connection.
|
||||||
|
*/
|
||||||
|
public int getPort() {
|
||||||
|
return this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of WebSocket protocol being used.
|
||||||
|
*
|
||||||
|
* @return The type of WebSocket protocol being used.
|
||||||
|
*/
|
||||||
|
public JRosbridge.WebSocketType getProtocol() {
|
||||||
|
return this.protocol;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the full URL this client is connecting to.
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public String getURL() {
|
||||||
|
return this.protocol.toString() + "://" + this.hostname + ":"
|
||||||
|
+ this.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next unique ID number for this connection.
|
||||||
|
*
|
||||||
|
* @return The next unique ID number for this connection.
|
||||||
|
*/
|
||||||
|
public long nextId() {
|
||||||
|
return this.idCounter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a handler to this connection. This handler is called when the
|
||||||
|
* associated events occur.
|
||||||
|
*
|
||||||
|
* @param handler
|
||||||
|
* The handler to add.
|
||||||
|
*/
|
||||||
|
public void addRosHandler(RosHandler handler) {
|
||||||
|
this.handlers.add(handler);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to establish a connection to rosbridge. Errors are printed to the
|
||||||
|
* error output stream.
|
||||||
|
*
|
||||||
|
* @return Returns true if the connection was established successfully and
|
||||||
|
* false otherwise.
|
||||||
|
*/
|
||||||
|
public boolean connect() {
|
||||||
|
try {
|
||||||
|
// create a WebSocket connection here
|
||||||
|
URI uri = new URI(this.getURL());
|
||||||
|
ContainerProvider.getWebSocketContainer()
|
||||||
|
.connectToServer(this, uri);
|
||||||
|
return true;
|
||||||
|
} catch (DeploymentException | URISyntaxException | IOException e) {
|
||||||
|
// failed connection, return false
|
||||||
|
System.err.println("[ERROR]: Could not create WebSocket: "
|
||||||
|
+ e.getMessage());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnect the connection to rosbridge. Errors are printed to the error
|
||||||
|
* output stream.
|
||||||
|
*
|
||||||
|
* @return Returns true if the disconnection was successful and false
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
public boolean disconnect() {
|
||||||
|
if (this.isConnected()) {
|
||||||
|
try {
|
||||||
|
this.session.close();
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("[ERROR]: Could not disconnect: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// could not disconnect cleanly
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if there is a connection to rosbridge.
|
||||||
|
*
|
||||||
|
* @return If there is a connection to rosbridge.
|
||||||
|
*/
|
||||||
|
public boolean isConnected() {
|
||||||
|
return this.session != null && this.session.isOpen();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called once a successful connection is made.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The session associated with the connection.
|
||||||
|
*/
|
||||||
|
@OnOpen
|
||||||
|
public void onOpen(Session session) {
|
||||||
|
// store the session
|
||||||
|
this.session = session;
|
||||||
|
|
||||||
|
// call the handlers
|
||||||
|
for (RosHandler handler : this.handlers) {
|
||||||
|
handler.handleConnection(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called once a successful disconnection is made.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The session associated with the disconnection.
|
||||||
|
*/
|
||||||
|
@OnClose
|
||||||
|
public void onClose(Session session) {
|
||||||
|
// remove the session
|
||||||
|
this.session = null;
|
||||||
|
|
||||||
|
// call the handlers
|
||||||
|
for (RosHandler handler : this.handlers) {
|
||||||
|
handler.handleDisconnection(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called if an error occurs.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The session for the error.
|
||||||
|
* @param session
|
||||||
|
* The session for the error.
|
||||||
|
*/
|
||||||
|
@OnError
|
||||||
|
public void onError(Session session, Throwable t) {
|
||||||
|
// call the handlers
|
||||||
|
for (RosHandler handler : this.handlers) {
|
||||||
|
handler.handleError(session, t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method is called once an entire message has been read in by the
|
||||||
|
* connection from rosbridge. It will parse the incoming JSON and attempt to
|
||||||
|
* handle the request appropriately.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* The incoming JSON message from rosbridge.
|
||||||
|
*/
|
||||||
|
@OnMessage
|
||||||
|
public void onMessage(String message) {
|
||||||
|
try {
|
||||||
|
// parse the JSON
|
||||||
|
JsonObject jsonObject = Json
|
||||||
|
.createReader(new StringReader(message)).readObject();
|
||||||
|
|
||||||
|
// check for compression
|
||||||
|
String op = jsonObject.getString(JRosbridge.FIELD_OP);
|
||||||
|
if (op.equals(JRosbridge.OP_CODE_PNG)) {
|
||||||
|
String data = jsonObject.getString(JRosbridge.FIELD_DATA);
|
||||||
|
// decompress the PNG data
|
||||||
|
byte[] bytes = Base64Utils.decode(data.getBytes());
|
||||||
|
Raster imageData = ImageIO
|
||||||
|
.read(new ByteArrayInputStream(bytes)).getRaster();
|
||||||
|
|
||||||
|
// read the RGB data
|
||||||
|
int[] rawData = null;
|
||||||
|
rawData = imageData.getPixels(0, 0, imageData.getWidth(),
|
||||||
|
imageData.getHeight(), rawData);
|
||||||
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
for (int i = 0; i < rawData.length; i++) {
|
||||||
|
buffer.append(Character.toString((char) rawData[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
// reparse the JSON
|
||||||
|
JsonObject newJsonObject = Json.createReader(
|
||||||
|
new StringReader(buffer.toString())).readObject();
|
||||||
|
handleMessage(newJsonObject);
|
||||||
|
} else {
|
||||||
|
handleMessage(jsonObject);
|
||||||
|
}
|
||||||
|
} catch (NullPointerException | IOException | JsonParsingException e) {
|
||||||
|
// only occurs if there was an error with the JSON
|
||||||
|
System.err.println("[WARN]: Invalid incoming rosbridge protocol: "
|
||||||
|
+ message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the incoming rosbridge message by calling the appropriate
|
||||||
|
* callbacks.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object from the incoming rosbridge message.
|
||||||
|
*/
|
||||||
|
private void handleMessage(JsonObject jsonObject) {
|
||||||
|
// check for the correct fields
|
||||||
|
String op = jsonObject.getString(JRosbridge.FIELD_OP);
|
||||||
|
if (op.equals(JRosbridge.OP_CODE_PUBLISH)) {
|
||||||
|
// check for the topic name
|
||||||
|
String topic = jsonObject.getString(JRosbridge.FIELD_TOPIC);
|
||||||
|
|
||||||
|
// call each callback with the message
|
||||||
|
ArrayList<TopicCallback> callbacks = topicCallbacks.get(topic);
|
||||||
|
if (callbacks != null) {
|
||||||
|
Message msg = new Message() {
|
||||||
|
@Override
|
||||||
|
public void print() {
|
||||||
|
super.print();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
for (TopicCallback cb : callbacks) {
|
||||||
|
cb.handleMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (op.equals(JRosbridge.OP_CODE_SERVICE_RESPONSE)) {
|
||||||
|
// check for the request ID
|
||||||
|
String id = jsonObject.getString(JRosbridge.FIELD_ID);
|
||||||
|
|
||||||
|
// call the callback for the request
|
||||||
|
ServiceCallback cb = serviceCallbacks.get(id);
|
||||||
|
if (cb != null) {
|
||||||
|
// check if a success code was given
|
||||||
|
boolean success = jsonObject
|
||||||
|
.containsKey(JRosbridge.FIELD_RESULT) ? jsonObject
|
||||||
|
.getBoolean(JRosbridge.FIELD_RESULT) : true;
|
||||||
|
// get the response
|
||||||
|
JsonObject values = jsonObject
|
||||||
|
.getJsonObject(JRosbridge.FIELD_VALUES);
|
||||||
|
ServiceResponse response = new ServiceResponse(values, success);
|
||||||
|
cb.handleServiceResponse(response);
|
||||||
|
}
|
||||||
|
} else if (op.equals(JRosbridge.OP_CODE_CALL_SERVICE)) {
|
||||||
|
// check for the request ID
|
||||||
|
String id = jsonObject.getString("id");
|
||||||
|
String service = jsonObject.getString("service");
|
||||||
|
|
||||||
|
// call the callback for the request
|
||||||
|
CallServiceCallback cb = callServiceCallbacks.get(service);
|
||||||
|
if (cb != null) {
|
||||||
|
// get the response
|
||||||
|
JsonObject args = jsonObject
|
||||||
|
.getJsonObject(JRosbridge.FIELD_ARGS);
|
||||||
|
ServiceRequest request = new ServiceRequest(args);
|
||||||
|
request.setId(id);
|
||||||
|
cb.handleServiceCall(request);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
System.err.println("[WARN]: Unrecognized op code: "
|
||||||
|
+ jsonObject.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send the given JSON object to rosbridge.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object to send to rosbridge.
|
||||||
|
* @return If the sending of the message was successful.
|
||||||
|
*/
|
||||||
|
public boolean send(JsonObject jsonObject) {
|
||||||
|
// check the connection
|
||||||
|
if (this.isConnected()) {
|
||||||
|
try {
|
||||||
|
// send it as text
|
||||||
|
this.session.getBasicRemote().sendText(jsonObject.toString());
|
||||||
|
return true;
|
||||||
|
} catch (IOException e) {
|
||||||
|
System.err.println("[ERROR]: Could not send message: "
|
||||||
|
+ e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// message send failed
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an authorization request to the server.
|
||||||
|
*
|
||||||
|
* @param mac
|
||||||
|
* The MAC (hash) string given by the trusted source.
|
||||||
|
* @param client
|
||||||
|
* The IP of the client.
|
||||||
|
* @param dest
|
||||||
|
* The IP of the destination.
|
||||||
|
* @param rand
|
||||||
|
* The random string given by the trusted source.
|
||||||
|
* @param t
|
||||||
|
* The time of the authorization request.
|
||||||
|
* @param level
|
||||||
|
* The user level as a string given by the client.
|
||||||
|
* @param end
|
||||||
|
* The end time of the client's session.
|
||||||
|
*/
|
||||||
|
public void authenticate(String mac, String client, String dest,
|
||||||
|
String rand, int t, String level, int end) {
|
||||||
|
// build and send the rosbridge call
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_AUTH)
|
||||||
|
.add(JRosbridge.FIELD_MAC, mac)
|
||||||
|
.add(JRosbridge.FIELD_CLIENT, client)
|
||||||
|
.add(JRosbridge.FIELD_DESTINATION, dest)
|
||||||
|
.add(JRosbridge.FIELD_RAND, rand).add(JRosbridge.FIELD_TIME, t)
|
||||||
|
.add(JRosbridge.FIELD_LEVEL, level)
|
||||||
|
.add(JRosbridge.FIELD_END_TIME, end).build();
|
||||||
|
this.send(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback for a given topic.
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* The topic to register this callback with.
|
||||||
|
* @param cb
|
||||||
|
* The callback that will be called when messages come in for the
|
||||||
|
* associated topic.
|
||||||
|
*/
|
||||||
|
public void registerTopicCallback(String topic, TopicCallback cb) {
|
||||||
|
// check if any callbacks exist yet
|
||||||
|
if (!this.topicCallbacks.containsKey(topic)) {
|
||||||
|
this.topicCallbacks.put(topic, new ArrayList<TopicCallback>());
|
||||||
|
}
|
||||||
|
|
||||||
|
// add the callback
|
||||||
|
this.topicCallbacks.get(topic).add(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deregister a callback for a given topic.
|
||||||
|
*
|
||||||
|
* @param topic
|
||||||
|
* The topic associated with the callback.
|
||||||
|
* @param cb
|
||||||
|
* The callback to remove.
|
||||||
|
*/
|
||||||
|
public void deregisterTopicCallback(String topic, TopicCallback cb) {
|
||||||
|
// check if any exist for this topic
|
||||||
|
if (this.topicCallbacks.containsKey(topic)) {
|
||||||
|
// remove the callback if it exists
|
||||||
|
ArrayList<TopicCallback> callbacks = this.topicCallbacks.get(topic);
|
||||||
|
if (callbacks.contains(cb)) {
|
||||||
|
callbacks.remove(cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove the list if it is empty
|
||||||
|
if (callbacks.size() == 0) {
|
||||||
|
this.topicCallbacks.remove(topic);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback for a given outgoing service call.
|
||||||
|
*
|
||||||
|
* @param serviceCallId
|
||||||
|
* The unique ID of the service call.
|
||||||
|
* @param cb
|
||||||
|
* The callback that will be called when a service response comes
|
||||||
|
* back for the associated request.
|
||||||
|
*/
|
||||||
|
public void registerServiceCallback(String serviceCallId, ServiceCallback cb) {
|
||||||
|
// add the callback
|
||||||
|
this.serviceCallbacks.put(serviceCallId, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register a callback for a given incoming service request.
|
||||||
|
*
|
||||||
|
* @param serviceName
|
||||||
|
* The unique name of the service call.
|
||||||
|
* @param cb
|
||||||
|
* The callback that will be called when a service request comes
|
||||||
|
* in for the associated request.
|
||||||
|
*/
|
||||||
|
public void registerCallServiceCallback(String serviceName, CallServiceCallback cb) {
|
||||||
|
// add the callback
|
||||||
|
this.callServiceCallbacks.put(serviceName, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deregister a callback for a given incoming service request.
|
||||||
|
*
|
||||||
|
* @param serviceName
|
||||||
|
* The unique name of the service call.
|
||||||
|
*/
|
||||||
|
public void deregisterCallServiceCallback(String serviceName) {
|
||||||
|
// remove the callback
|
||||||
|
callServiceCallbacks.remove(serviceName);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,240 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.callback.ServiceCallback;
|
||||||
|
import edu.wpi.rail.jrosbridge.callback.CallServiceCallback;
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceRequest;
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Service object is responsible for calling or advertising a service in ROS.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version November 26, 2014
|
||||||
|
*/
|
||||||
|
public class Service {
|
||||||
|
|
||||||
|
private final Ros ros;
|
||||||
|
private final String name;
|
||||||
|
private final String type;
|
||||||
|
private boolean isAdvertised;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ROS service with the given information.
|
||||||
|
*
|
||||||
|
* @param ros
|
||||||
|
* A handle to the ROS connection.
|
||||||
|
* @param name
|
||||||
|
* The name of the service (e.g., "/add_two_ints").
|
||||||
|
* @param type
|
||||||
|
* The service type (e.g., "rospy_tutorials/AddTwoInts").
|
||||||
|
*/
|
||||||
|
public Service(Ros ros, String name, String type) {
|
||||||
|
this.ros = ros;
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.isAdvertised = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ROS connection handle for this service.
|
||||||
|
*
|
||||||
|
* @return The ROS connection handle for this service.
|
||||||
|
*/
|
||||||
|
public Ros getRos() {
|
||||||
|
return this.ros;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this service.
|
||||||
|
*
|
||||||
|
* @return The name of this service.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the service type of this service.
|
||||||
|
*
|
||||||
|
* @return The service type of this service.
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current service is advertising to ROS.
|
||||||
|
*
|
||||||
|
* @return If the current service is advertising to ROS.
|
||||||
|
*/
|
||||||
|
public boolean isAdvertised() {
|
||||||
|
return this.isAdvertised;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this service. The callback function will be called with the
|
||||||
|
* associated service response.
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* The service request to send.
|
||||||
|
* @param cb
|
||||||
|
* The callback used when the associated response comes back.
|
||||||
|
*/
|
||||||
|
public void callService(ServiceRequest request, ServiceCallback cb) {
|
||||||
|
// construct the unique ID
|
||||||
|
String callServceId = "call_service:" + this.name + ":"
|
||||||
|
+ this.ros.nextId();
|
||||||
|
|
||||||
|
// register the callback function
|
||||||
|
this.ros.registerServiceCallback(callServceId, cb);
|
||||||
|
|
||||||
|
// build and send the rosbridge call
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_CALL_SERVICE)
|
||||||
|
.add(JRosbridge.FIELD_ID, callServceId)
|
||||||
|
.add(JRosbridge.FIELD_TYPE, this.type)
|
||||||
|
.add(JRosbridge.FIELD_SERVICE, this.name)
|
||||||
|
.add(JRosbridge.FIELD_ARGS, request.toJsonObject()).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Send a service response.
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* The service response to send.
|
||||||
|
* @param id
|
||||||
|
* The ID of the response (matching that of the service call).
|
||||||
|
*/
|
||||||
|
public void sendResponse(ServiceResponse response, String id) {
|
||||||
|
// build and send the rosbridge call
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_SERVICE_RESPONSE)
|
||||||
|
.add(JRosbridge.FIELD_ID, id)
|
||||||
|
.add(JRosbridge.FIELD_SERVICE, this.name)
|
||||||
|
.add(JRosbridge.FIELD_VALUES, response.toJsonObject())
|
||||||
|
.add(JRosbridge.FIELD_RESULT, response.getResult()).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers as service advertiser.
|
||||||
|
*/
|
||||||
|
public void advertiseService(CallServiceCallback cb) {
|
||||||
|
// register the callback
|
||||||
|
this.ros.registerCallServiceCallback(this.name, cb);
|
||||||
|
|
||||||
|
// build and send the rosbridge call
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_ADVERTISE_SERVICE)
|
||||||
|
.add(JRosbridge.FIELD_TYPE, this.type)
|
||||||
|
.add(JRosbridge.FIELD_SERVICE, this.name).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
|
||||||
|
// set the flag indicating we are registered
|
||||||
|
this.isAdvertised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters as service advertiser.
|
||||||
|
*/
|
||||||
|
public void unadvertiseService() {
|
||||||
|
this.ros.deregisterCallServiceCallback(this.name);
|
||||||
|
|
||||||
|
// build and send the rosbridge call
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_UNADVERTISE_SERVICE)
|
||||||
|
.add(JRosbridge.FIELD_SERVICE, this.name).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
|
||||||
|
// set the flag indicating we are registered
|
||||||
|
this.isAdvertised = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call the service and wait for a response. This is a blocking call and
|
||||||
|
* will only return once rosbridge returns the service response. For an
|
||||||
|
* asynchronous version of this call, see the
|
||||||
|
* {@link #callService(ServiceRequest request, ServiceCallback cb)
|
||||||
|
* callService} method.
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* The service request to send.
|
||||||
|
* @return The corresponding service response from ROS.
|
||||||
|
*/
|
||||||
|
public synchronized ServiceResponse callServiceAndWait(
|
||||||
|
ServiceRequest request) {
|
||||||
|
|
||||||
|
// private inner class to use as a callback
|
||||||
|
BlockingCallback cb = new BlockingCallback(this);
|
||||||
|
// use the asynchronous version and block on the result
|
||||||
|
this.callService(request, cb);
|
||||||
|
|
||||||
|
// wait for a response
|
||||||
|
while (cb.getResponse() == null) {
|
||||||
|
try {
|
||||||
|
this.wait();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
// continue on
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return cb.getResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A private {@link ServiceCallback
|
||||||
|
* ServiceCallback} used to block and wait for a response from rosbridge.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
private class BlockingCallback implements ServiceCallback {
|
||||||
|
|
||||||
|
private ServiceResponse response;
|
||||||
|
private Service service;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new callback function which will notify the given
|
||||||
|
* {@link Service Service} once a response
|
||||||
|
* has been received.
|
||||||
|
*
|
||||||
|
* @param service
|
||||||
|
* The {@link Service Service}
|
||||||
|
* to notify once a response has been received.
|
||||||
|
*/
|
||||||
|
public BlockingCallback(Service service) {
|
||||||
|
this.response = null;
|
||||||
|
this.service = service;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store the response internally and notify the corresponding
|
||||||
|
* {@link Service Service}.
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* The incoming service response from ROS.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void handleServiceResponse(ServiceResponse response) {
|
||||||
|
this.response = response;
|
||||||
|
synchronized (this.service) {
|
||||||
|
this.service.notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the response stored in this callback, if one exists. Otherwise,
|
||||||
|
* null is returned.
|
||||||
|
*
|
||||||
|
* @return The resulting service response from ROS, or null if one does
|
||||||
|
* not exist yet.
|
||||||
|
*/
|
||||||
|
public ServiceResponse getResponse() {
|
||||||
|
return this.response;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,279 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
import com.example.testdemo.ros.message.Message;
|
||||||
|
import edu.wpi.rail.jrosbridge.callback.TopicCallback;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The Topic object is responsible for publishing and/or subscribing to a topic
|
||||||
|
* in ROS.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class Topic {
|
||||||
|
|
||||||
|
private final Ros ros;
|
||||||
|
private final String name;
|
||||||
|
private final String type;
|
||||||
|
private boolean isAdvertised;
|
||||||
|
private boolean isSubscribed;
|
||||||
|
private final JRosbridge.CompressionType compression;
|
||||||
|
private final int throttleRate;
|
||||||
|
|
||||||
|
// used to keep track of this object's callbacks
|
||||||
|
private final ArrayList<TopicCallback> callbacks;
|
||||||
|
|
||||||
|
// used to keep track of the subscription IDs
|
||||||
|
private final ArrayList<String> ids;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ROS topic with the given information. No compression or
|
||||||
|
* throttling is used.
|
||||||
|
*
|
||||||
|
* @param ros
|
||||||
|
* A handle to the ROS connection.
|
||||||
|
* @param name
|
||||||
|
* The name of the topic (e.g., "/cmd_vel").
|
||||||
|
* @param type
|
||||||
|
* The message type (e.g., "std_msgs/String").
|
||||||
|
*/
|
||||||
|
public Topic(Ros ros, String name, String type) {
|
||||||
|
this(ros, name, type, JRosbridge.CompressionType.none, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ROS topic with the given information. No throttling is used.
|
||||||
|
*
|
||||||
|
* @param ros
|
||||||
|
* A handle to the ROS connection.
|
||||||
|
* @param name
|
||||||
|
* The name of the topic (e.g., "/cmd_vel").
|
||||||
|
* @param type
|
||||||
|
* The message type (e.g., "std_msgs/String").
|
||||||
|
* @param compression
|
||||||
|
* The type of compression used for this topic.
|
||||||
|
*/
|
||||||
|
public Topic(Ros ros, String name, String type,
|
||||||
|
JRosbridge.CompressionType compression) {
|
||||||
|
this(ros, name, type, compression, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ROS topic with the given information. No compression is used.
|
||||||
|
*
|
||||||
|
* @param ros
|
||||||
|
* A handle to the ROS connection.
|
||||||
|
* @param name
|
||||||
|
* The name of the topic (e.g., "/cmd_vel").
|
||||||
|
* @param type
|
||||||
|
* The message type (e.g., "std_msgs/String").
|
||||||
|
* @param throttleRate
|
||||||
|
* The throttle rate to use for this topic.
|
||||||
|
*/
|
||||||
|
public Topic(Ros ros, String name, String type, int throttleRate) {
|
||||||
|
this(ros, name, type, JRosbridge.CompressionType.none, throttleRate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ROS topic with the given information.
|
||||||
|
*
|
||||||
|
* @param ros
|
||||||
|
* A handle to the ROS connection.
|
||||||
|
* @param name
|
||||||
|
* The name of the topic (e.g., "/cmd_vel").
|
||||||
|
* @param type
|
||||||
|
* The message type (e.g., "std_msgs/String").
|
||||||
|
* @param compression
|
||||||
|
* The type of compression used for this topic.
|
||||||
|
* @param throttleRate
|
||||||
|
* The throttle rate to use for this topic.
|
||||||
|
*/
|
||||||
|
public Topic(Ros ros, String name, String type,
|
||||||
|
JRosbridge.CompressionType compression, int throttleRate) {
|
||||||
|
this.ros = ros;
|
||||||
|
this.name = name;
|
||||||
|
this.type = type;
|
||||||
|
this.isAdvertised = false;
|
||||||
|
this.isSubscribed = false;
|
||||||
|
this.compression = compression;
|
||||||
|
this.throttleRate = throttleRate;
|
||||||
|
this.callbacks = new ArrayList<TopicCallback>();
|
||||||
|
this.ids = new ArrayList<String>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ROS connection handle for this topic.
|
||||||
|
*
|
||||||
|
* @return The ROS connection handle for this topic.
|
||||||
|
*/
|
||||||
|
public Ros getRos() {
|
||||||
|
return this.ros;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of this topic.
|
||||||
|
*
|
||||||
|
* @return The name of this topic.
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the message type of this topic.
|
||||||
|
*
|
||||||
|
* @return The message type of this topic.
|
||||||
|
*/
|
||||||
|
public String getType() {
|
||||||
|
return this.type;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current topic is advertising to ROS.
|
||||||
|
*
|
||||||
|
* @return If the current topic is advertising to ROS.
|
||||||
|
*/
|
||||||
|
public boolean isAdvertised() {
|
||||||
|
return this.isAdvertised;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the current topic is subscribed to ROS.
|
||||||
|
*
|
||||||
|
* @return If the current topic is subscribed to ROS.
|
||||||
|
*/
|
||||||
|
public boolean isSubscribed() {
|
||||||
|
return this.isSubscribed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the compression type for this topic.
|
||||||
|
*
|
||||||
|
* @return The compression type for this topic.
|
||||||
|
*/
|
||||||
|
public JRosbridge.CompressionType getCompression() {
|
||||||
|
return this.compression;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the throttle rate for this topic.
|
||||||
|
*
|
||||||
|
* @return The throttle rate for this topic.
|
||||||
|
*/
|
||||||
|
public int getThrottleRate() {
|
||||||
|
return this.throttleRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribe to this topic. A callback function is required and will be
|
||||||
|
* called with any incoming message for this topic.
|
||||||
|
*
|
||||||
|
* @param cb
|
||||||
|
* The callback that will be called when incoming messages are
|
||||||
|
* received.
|
||||||
|
*/
|
||||||
|
public void subscribe(TopicCallback cb) {
|
||||||
|
// register the callback function
|
||||||
|
this.ros.registerTopicCallback(this.name, cb);
|
||||||
|
// internal reference used during unsubscribe
|
||||||
|
this.callbacks.add(cb);
|
||||||
|
|
||||||
|
String subscribeId = "subscribe:" + this.name + ":" + this.ros.nextId();
|
||||||
|
this.ids.add(subscribeId);
|
||||||
|
|
||||||
|
// build and send the rosbridge call
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_SUBSCRIBE)
|
||||||
|
.add(JRosbridge.FIELD_ID, subscribeId)
|
||||||
|
.add(JRosbridge.FIELD_TYPE, this.type)
|
||||||
|
.add(JRosbridge.FIELD_TOPIC, this.name)
|
||||||
|
.add(JRosbridge.FIELD_COMPRESSION, this.compression.toString())
|
||||||
|
.add(JRosbridge.FIELD_THROTTLE_RATE, this.throttleRate).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
|
||||||
|
// set the flag indicating we have subscribed
|
||||||
|
this.isSubscribed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregisters as a subscriber for the topic. Unsubscribing will remove all
|
||||||
|
* the associated subscribe callbacks.
|
||||||
|
*/
|
||||||
|
public void unsubscribe() {
|
||||||
|
// remove this object's associated callbacks.
|
||||||
|
for (TopicCallback cb : this.callbacks) {
|
||||||
|
this.ros.deregisterTopicCallback(this.name, cb);
|
||||||
|
}
|
||||||
|
this.callbacks.clear();
|
||||||
|
|
||||||
|
// build and send the rosbridge calls
|
||||||
|
for (String id : this.ids) {
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_UNSUBSCRIBE)
|
||||||
|
.add(JRosbridge.FIELD_ID, id)
|
||||||
|
.add(JRosbridge.FIELD_TOPIC, this.name).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
}
|
||||||
|
|
||||||
|
// set the flag indicating we are not longer subscribed
|
||||||
|
this.isSubscribed = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers as a publisher for the topic. This call will be automatically
|
||||||
|
* called by publish if you do not explicitly call it.
|
||||||
|
*/
|
||||||
|
public void advertise() {
|
||||||
|
// build and send the rosbridge call
|
||||||
|
String advertiseId = "advertise:" + this.name + ":" + this.ros.nextId();
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_ADVERTISE)
|
||||||
|
.add(JRosbridge.FIELD_ID, advertiseId)
|
||||||
|
.add(JRosbridge.FIELD_TYPE, this.type)
|
||||||
|
.add(JRosbridge.FIELD_TOPIC, this.name).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
|
||||||
|
// set the flag indicating we are registered
|
||||||
|
this.isAdvertised = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unregister as a publisher for the topic.
|
||||||
|
*/
|
||||||
|
public void unadvertise() {
|
||||||
|
// build and send the rosbridge call
|
||||||
|
String unadvertiseId = "unadvertise:" + this.name + ":"
|
||||||
|
+ this.ros.nextId();
|
||||||
|
JsonObject call = Json.createObjectBuilder()
|
||||||
|
.add(JRosbridge.FIELD_OP, JRosbridge.OP_CODE_UNADVERTISE)
|
||||||
|
.add(JRosbridge.FIELD_ID, unadvertiseId)
|
||||||
|
.add(JRosbridge.FIELD_TOPIC, this.name).build();
|
||||||
|
this.ros.send(call);
|
||||||
|
|
||||||
|
// set the flag indicating we are no longer registered
|
||||||
|
this.isAdvertised = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publish the given message to ROS on this topic. If the topic is not
|
||||||
|
* advertised, it will be advertised first.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* The message to publish.
|
||||||
|
*/
|
||||||
|
public void publish(Message message) {
|
||||||
|
// check if we have advertised yet.
|
||||||
|
if (!this.isAdvertised()) {
|
||||||
|
this.advertise();
|
||||||
|
}
|
||||||
|
|
||||||
|
// build and send the rosbridge call
|
||||||
|
String publishId = "publish:" + this.name + ":" + this.ros.nextId();
|
||||||
|
//JsonObject call = Json.createObjectBuilder()
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.callback;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceRequest;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CallServiceCallback interface defines a single method which will be called
|
||||||
|
* when an incoming service request is received for an associated service request.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version November 26, 2014
|
||||||
|
*/
|
||||||
|
public interface CallServiceCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when an incoming service request is received for
|
||||||
|
* a given service request. No ROS type checking is done on the internal
|
||||||
|
* data.
|
||||||
|
*
|
||||||
|
* @param request
|
||||||
|
* The service request that was received.
|
||||||
|
*/
|
||||||
|
public void handleServiceCall(ServiceRequest request);
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.callback;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ServiceCallback interface defines a single method which will be called
|
||||||
|
* when an incoming service response is received for an associated service
|
||||||
|
* request.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public interface ServiceCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when an incoming service response is received for
|
||||||
|
* a given service request. No ROS type checking is done on the internal
|
||||||
|
* data. A flag indicating if the call was successful is given.
|
||||||
|
*
|
||||||
|
* @param response
|
||||||
|
* The service response that was received.
|
||||||
|
*/
|
||||||
|
public void handleServiceResponse(ServiceResponse response);
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.callback;
|
||||||
|
|
||||||
|
|
||||||
|
import com.example.testdemo.ros.message.Message;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TopicCallback interface defines a single method which will be called when
|
||||||
|
* an incoming message is received for an associated topic.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public interface TopicCallback {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This function is called when an incoming message is received for a given
|
||||||
|
* topic. No ROS type checking is done on the internal message data.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
* The message that was received.
|
||||||
|
*/
|
||||||
|
public void handleMessage(Message message);
|
||||||
|
}
|
@ -0,0 +1,41 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.handler;
|
||||||
|
|
||||||
|
import javax.websocket.Session;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The RosHandler interface defines the methods that will be called during
|
||||||
|
* certain events in the Ros connection object.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public interface RosHandler {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the connection event. This occurs during a successful connection
|
||||||
|
* to rosbridge.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The session associated with the connection.
|
||||||
|
*/
|
||||||
|
public void handleConnection(Session session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the disconnection event. This occurs during a successful
|
||||||
|
* disconnection from rosbridge.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The session associated with the disconnection.
|
||||||
|
*/
|
||||||
|
public void handleDisconnection(Session session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle the error event.
|
||||||
|
*
|
||||||
|
* @param session
|
||||||
|
* The session associated with the error.
|
||||||
|
* @param t
|
||||||
|
* The error.
|
||||||
|
*/
|
||||||
|
public void handleError(Session session, Throwable t);
|
||||||
|
}
|
@ -0,0 +1,166 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.primitives;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ROS duration primitive.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class Duration extends TimeBase<Duration> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primitive type.
|
||||||
|
*/
|
||||||
|
public static final String TYPE = "duration";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration with a default of 0.
|
||||||
|
*/
|
||||||
|
public Duration() {
|
||||||
|
super(Duration.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration with the given seconds and nanoseconds values.
|
||||||
|
*
|
||||||
|
* @param secs
|
||||||
|
* The seconds value of this duration.
|
||||||
|
* @param nsecs
|
||||||
|
* The nanoseconds value of this duration.
|
||||||
|
*/
|
||||||
|
public Duration(int secs, int nsecs) {
|
||||||
|
super(secs, nsecs, Duration.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration with the given duration in seconds (and partial
|
||||||
|
* seconds).
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The duration in seconds.
|
||||||
|
*/
|
||||||
|
public Duration(double sec) {
|
||||||
|
super(sec, Duration.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration with the given duration in nanoseconds.
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The duration in nanoseconds.
|
||||||
|
*/
|
||||||
|
public Duration(long nano) {
|
||||||
|
super(nano, Duration.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given Duration to this Duration and return a new Duration with
|
||||||
|
* that value.
|
||||||
|
*
|
||||||
|
* @param d
|
||||||
|
* The Duration to add.
|
||||||
|
* @return A new Duration with the new value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Duration add(Duration d) {
|
||||||
|
return new Duration(this.toSec() + d.toSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract the given Duration from this Duration and return a new Duration
|
||||||
|
* with that value.
|
||||||
|
*
|
||||||
|
* @param d
|
||||||
|
* The Duration to subtract.
|
||||||
|
* @return A new Duration with the new value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Duration subtract(Duration d) {
|
||||||
|
return new Duration(this.toSec() - d.toSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to sleep for the duration specified in this object.
|
||||||
|
*
|
||||||
|
* @return If the sleep was successful.
|
||||||
|
*/
|
||||||
|
public boolean sleep() {
|
||||||
|
try {
|
||||||
|
Thread.sleep(
|
||||||
|
(this.secs * TimeBase.SECS_TO_MILLI)
|
||||||
|
+ ((long) ((double) this.nsecs / (double) TimeBase.MILLI_TO_NSECS)),
|
||||||
|
this.nsecs % (int) TimeBase.MILLI_TO_NSECS);
|
||||||
|
return true;
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this Duration.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Duration clone() {
|
||||||
|
return new Duration(this.secs, this.nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration message based on the given seconds.
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The duration in seconds.
|
||||||
|
*
|
||||||
|
* @return The new Duration primitive.
|
||||||
|
*/
|
||||||
|
public static Duration fromSec(double sec) {
|
||||||
|
return new Duration(sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration message based on the given nanoseconds.
|
||||||
|
*
|
||||||
|
* @param nano
|
||||||
|
* The duration in nanoseconds.
|
||||||
|
*
|
||||||
|
* @return The new Duration primitive.
|
||||||
|
*/
|
||||||
|
public static Duration fromNano(long nano) {
|
||||||
|
return new Duration(nano);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration based on the given JSON string. Any missing values
|
||||||
|
* will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON string to parse.
|
||||||
|
* @return A Duration message based on the given JSON string.
|
||||||
|
*/
|
||||||
|
public static Duration fromJsonString(String jsonString) {
|
||||||
|
// convert to a JSON object
|
||||||
|
return Duration.fromJsonObject(Json.createReader(
|
||||||
|
new StringReader(jsonString)).readObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Duration based on the given JSON object. Any missing values
|
||||||
|
* will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object to parse.
|
||||||
|
* @return A Duration message based on the given JSON object.
|
||||||
|
*/
|
||||||
|
public static Duration fromJsonObject(JsonObject jsonObject) {
|
||||||
|
// check the fields
|
||||||
|
int secs = jsonObject.containsKey(Duration.FIELD_SECS) ? jsonObject
|
||||||
|
.getInt(Duration.FIELD_SECS) : 0;
|
||||||
|
int nsecs = jsonObject.containsKey(Duration.FIELD_NSECS) ? jsonObject
|
||||||
|
.getInt(Duration.FIELD_NSECS) : 0;
|
||||||
|
return new Duration(secs, nsecs);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,313 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.primitives;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.JsonWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Primitive objects are used as a wrapper for non-native ROS primitives. These
|
||||||
|
* primitives act as wrappers around JSON objects.
|
||||||
|
*
|
||||||
|
* This class also contains static functions for dealing with ROS' unsigned
|
||||||
|
* numbers.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public abstract class Primitive extends JsonWrapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The String representation of an empty primitive in JSON.
|
||||||
|
*/
|
||||||
|
public static final String EMPTY_MESSAGE = JsonWrapper.EMPTY_JSON;
|
||||||
|
|
||||||
|
private String primitiveType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Primitive based on the given String representation of a JSON
|
||||||
|
* object.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON String to parse.
|
||||||
|
* @param primitiveType
|
||||||
|
* The type of the primitive (e.g., "geometry_msgs/Twist").
|
||||||
|
*/
|
||||||
|
public Primitive(String jsonString, String primitiveType) {
|
||||||
|
// parse and pass it to the JSON constructor
|
||||||
|
this(Json.createReader(new StringReader(jsonString)).readObject(),
|
||||||
|
primitiveType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a Primitive based on the given JSON object.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object containing the primitive data.
|
||||||
|
* @param primitiveType
|
||||||
|
* The type of the primitive (e.g., "time").
|
||||||
|
*/
|
||||||
|
public Primitive(JsonObject jsonObject, String primitiveType) {
|
||||||
|
// setup the JSON information
|
||||||
|
super(jsonObject);
|
||||||
|
// set the type
|
||||||
|
this.primitiveType = primitiveType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of the primitive.
|
||||||
|
*
|
||||||
|
* @return The type of the primitive.
|
||||||
|
*/
|
||||||
|
public String getPrimitiveType() {
|
||||||
|
return this.primitiveType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the type of the primitive.
|
||||||
|
*
|
||||||
|
* @param primitiveType
|
||||||
|
* The type of the primitive (e.g., "time").
|
||||||
|
*/
|
||||||
|
public void setPrimitiveType(String primitiveType) {
|
||||||
|
this.primitiveType = primitiveType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value to an unsigned 8-bit unsigned integer. This
|
||||||
|
* ignores the high 8-bits of the short.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The value to convert.
|
||||||
|
* @return The value encoded as an 8-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static byte toUInt8(short value) {
|
||||||
|
// zero out the high 8-bits
|
||||||
|
short tmp = (short) ((value >> 8) << 8);
|
||||||
|
return (byte) (value - tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values to unsigned 8-bit unsigned integers. This
|
||||||
|
* ignores the high 8-bits of the input.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The values to convert.
|
||||||
|
* @return The values encoded as an 8-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static byte[] toUInt8(short[] values) {
|
||||||
|
byte[] tmp = new byte[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.toUInt8(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value in unsigned 8-bit representation into its actual
|
||||||
|
* value. That is, all return values of this function will be positive.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The unsigned 8-bit value to convert.
|
||||||
|
* @return The value of the given 8-bit unsigned value.
|
||||||
|
*/
|
||||||
|
public static short fromUInt8(byte value) {
|
||||||
|
return (short) (value & (short) 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values in unsigned 8-bit representation into their
|
||||||
|
* actual values. That is, all return values of this function will be
|
||||||
|
* positive.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The unsigned 8-bit values to convert.
|
||||||
|
* @return The values of the given 8-bit unsigned values.
|
||||||
|
*/
|
||||||
|
public static short[] fromUInt8(byte[] values) {
|
||||||
|
short[] tmp = new short[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.fromUInt8(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value to an unsigned 16-bit unsigned integer. This
|
||||||
|
* ignores the high 16-bits of the input.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The value to convert.
|
||||||
|
* @return The value encoded as an 16-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static short toUInt16(int value) {
|
||||||
|
// zero out the high 16-bits
|
||||||
|
int tmp = (int) ((value >> 16) << 16);
|
||||||
|
return (short) (value - tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values to unsigned 16-bit unsigned integers. This
|
||||||
|
* ignores the high 16-bits of the input.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The values to convert.
|
||||||
|
* @return The values encoded as an 16-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static short[] toUInt16(int[] values) {
|
||||||
|
short[] tmp = new short[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.toUInt16(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value in unsigned 16-bit representation into its actual
|
||||||
|
* value. That is, all return values of this function will be positive.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The unsigned 16-bit value to convert.
|
||||||
|
* @return The value of the given 16-bit unsigned value.
|
||||||
|
*/
|
||||||
|
public static int fromUInt16(short value) {
|
||||||
|
return (int) (value & 0xFFFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values in unsigned 16-bit representation into their
|
||||||
|
* actual values. That is, all return values of this function will be
|
||||||
|
* positive.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The unsigned 16-bit values to convert.
|
||||||
|
* @return The values of the given 16-bit unsigned values.
|
||||||
|
*/
|
||||||
|
public static int[] fromUInt16(short[] values) {
|
||||||
|
int[] tmp = new int[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.fromUInt16(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value to an unsigned 32-bit unsigned integer. This
|
||||||
|
* ignores the high 32-bits of the input.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The value to convert.
|
||||||
|
* @return The value encoded as an 32-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static int toUInt32(long value) {
|
||||||
|
// zero out the high 32-bits
|
||||||
|
long tmp = (long) ((value >> 32) << 32);
|
||||||
|
return (int) (value - tmp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values to unsigned 32-bit unsigned integers. This
|
||||||
|
* ignores the high 32-bits of the input.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The values to convert.
|
||||||
|
* @return The values encoded as an 32-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static int[] toUInt32(long[] values) {
|
||||||
|
int[] tmp = new int[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.toUInt32(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value in unsigned 32-bit representation into its actual
|
||||||
|
* value. That is, all return values of this function will be positive.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The unsigned 32-bit value to convert.
|
||||||
|
* @return The value of the given 32-bit unsigned value.
|
||||||
|
*/
|
||||||
|
public static long fromUInt32(int value) {
|
||||||
|
return (long) (value & 0xFFFFFFFFL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values in unsigned 32-bit representation into their
|
||||||
|
* actual values. That is, all return values of this function will be
|
||||||
|
* positive.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The unsigned 32-bit values to convert.
|
||||||
|
* @return The values of the given 64-bit unsigned values.
|
||||||
|
*/
|
||||||
|
public static long[] fromUInt32(int[] values) {
|
||||||
|
long[] tmp = new long[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.fromUInt32(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value to an unsigned 64-bit unsigned integer. This
|
||||||
|
* ignores the high 64-bits of the input.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The value to convert.
|
||||||
|
* @return The value encoded as an 64-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static long toUInt64(BigInteger value) {
|
||||||
|
return value.longValue();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values to unsigned 64-bit unsigned integers. This
|
||||||
|
* ignores the high 64-bits of the input.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The values to convert.
|
||||||
|
* @return The values encoded as an 64-bit unsigned integer.
|
||||||
|
*/
|
||||||
|
public static long[] toUInt64(BigInteger[] values) {
|
||||||
|
long[] tmp = new long[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.toUInt64(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given value in unsigned 64-bit representation into its actual
|
||||||
|
* value. That is, all return values of this function will be positive.
|
||||||
|
*
|
||||||
|
* @param value
|
||||||
|
* The unsigned 64-bit value to convert.
|
||||||
|
* @return The value of the given 64-bit unsigned value.
|
||||||
|
*/
|
||||||
|
public static BigInteger fromUInt64(long value) {
|
||||||
|
return BigInteger.valueOf(value).and(
|
||||||
|
BigInteger.ONE.shiftLeft(64).subtract(BigInteger.ONE));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the given values in unsigned 64-bit representation into their
|
||||||
|
* actual values. That is, all return values of this function will be
|
||||||
|
* positive.
|
||||||
|
*
|
||||||
|
* @param values
|
||||||
|
* The unsigned 64-bit values to convert.
|
||||||
|
* @return The values of the given 64-bit unsigned values.
|
||||||
|
*/
|
||||||
|
public static BigInteger[] fromUInt64(long[] values) {
|
||||||
|
BigInteger[] tmp = new BigInteger[values.length];
|
||||||
|
for (int i = 0; i < tmp.length; i++) {
|
||||||
|
tmp[i] = Primitive.fromUInt64(values[i]);
|
||||||
|
}
|
||||||
|
return tmp;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,203 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.primitives;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The ROS time primitive.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class Time extends TimeBase<Time> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The primitive type.
|
||||||
|
*/
|
||||||
|
public static final String TYPE = "time";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time with a default of 0.
|
||||||
|
*/
|
||||||
|
public Time() {
|
||||||
|
super(Time.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time with the given seconds and nanoseconds values.
|
||||||
|
*
|
||||||
|
* @param secs
|
||||||
|
* The seconds value of this time.
|
||||||
|
* @param nsecs
|
||||||
|
* The nanoseconds value of this time.
|
||||||
|
*/
|
||||||
|
public Time(int secs, int nsecs) {
|
||||||
|
super(secs, nsecs, Time.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time with the given time in seconds (and partial seconds).
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The time in seconds.
|
||||||
|
*/
|
||||||
|
public Time(double sec) {
|
||||||
|
super(sec, Time.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time with the given time in nanoseconds.
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The time in nanoseconds.
|
||||||
|
*/
|
||||||
|
public Time(long nano) {
|
||||||
|
super(nano, Time.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given Time to this Time and return a new Time with that value.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
* The Time to add.
|
||||||
|
* @return A new Time with the new value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Time add(Time t) {
|
||||||
|
return new Time(this.toSec() + t.toSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract the given Time from this Time and return a new Time with that
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
* The Time to subtract.
|
||||||
|
* @return A new Time with the new value.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Time subtract(Time t) {
|
||||||
|
return new Time(this.toSec() - t.toSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if this Time is valid. A time is valid if it is non-zero.
|
||||||
|
*
|
||||||
|
* @return If this Time is valid.
|
||||||
|
*/
|
||||||
|
public boolean isValid() {
|
||||||
|
return !this.isZero();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Crate a new Java Date object based on this message.
|
||||||
|
*
|
||||||
|
* @return A new Java Date object based on this message.
|
||||||
|
*/
|
||||||
|
public Date toDate() {
|
||||||
|
Calendar c = Calendar.getInstance();
|
||||||
|
c.setTimeInMillis((long) (this.toSec() * (double) TimeBase.SECS_TO_MILLI));
|
||||||
|
return c.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sleep until the given time.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
* The time to sleep until.
|
||||||
|
* @return If the sleep was successful.
|
||||||
|
*/
|
||||||
|
public static boolean sleepUntil(Time t) {
|
||||||
|
// use a duration to sleep with
|
||||||
|
return Duration.fromSec(t.subtract(Time.now()).toSec()).sleep();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this Time.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Time clone() {
|
||||||
|
return new Time(this.secs, this.nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time message based on the current system time. Note that
|
||||||
|
* this might not match the current ROS time.
|
||||||
|
*
|
||||||
|
* @return The new Time message.
|
||||||
|
*/
|
||||||
|
public static Time now() {
|
||||||
|
return Time.fromSec(((double) System.currentTimeMillis())
|
||||||
|
* TimeBase.MILLI_TO_SECS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time message based on the given seconds.
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The time in seconds.
|
||||||
|
*
|
||||||
|
* @return The new Time primitive.
|
||||||
|
*/
|
||||||
|
public static Time fromSec(double sec) {
|
||||||
|
return new Time(sec);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time message based on the given nanoseconds.
|
||||||
|
*
|
||||||
|
* @param nano
|
||||||
|
* The time in nanoseconds.
|
||||||
|
*
|
||||||
|
* @return The new Time primitive.
|
||||||
|
*/
|
||||||
|
public static Time fromNano(long nano) {
|
||||||
|
return new Time(nano);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time from the given Java Data object.
|
||||||
|
*
|
||||||
|
* @param date
|
||||||
|
* The Date to create a Time from.
|
||||||
|
* @return The resulting Time primitive.
|
||||||
|
*/
|
||||||
|
public static Time fromDate(Date date) {
|
||||||
|
return Time.fromSec(((double) date.getTime()) * TimeBase.MILLI_TO_SECS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time based on the given JSON string. Any missing values will
|
||||||
|
* be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON string to parse.
|
||||||
|
* @return A Time message based on the given JSON string.
|
||||||
|
*/
|
||||||
|
public static Time fromJsonString(String jsonString) {
|
||||||
|
// convert to a JSON object
|
||||||
|
return Time.fromJsonObject(Json.createReader(
|
||||||
|
new StringReader(jsonString)).readObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Time based on the given JSON object. Any missing values will
|
||||||
|
* be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object to parse.
|
||||||
|
* @return A Time message based on the given JSON object.
|
||||||
|
*/
|
||||||
|
public static Time fromJsonObject(JsonObject jsonObject) {
|
||||||
|
// check the fields
|
||||||
|
int secs = jsonObject.containsKey(Time.FIELD_SECS) ? jsonObject
|
||||||
|
.getInt(Time.FIELD_SECS) : 0;
|
||||||
|
int nsecs = jsonObject.containsKey(Time.FIELD_NSECS) ? jsonObject
|
||||||
|
.getInt(Time.FIELD_NSECS) : 0;
|
||||||
|
return new Time(secs, nsecs);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,202 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.primitives;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The TimeBase class is an abstract implementation of common time/duration
|
||||||
|
* primitive functions for ROS time and duration primitives. Since these
|
||||||
|
* primitives are serialized like messages, they are immutable.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* The type of TimeBase used in add and subtract.
|
||||||
|
*/
|
||||||
|
public abstract class TimeBase<T extends Primitive> extends Primitive implements
|
||||||
|
Comparable<TimeBase<T>> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the seconds field for the Primitive.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_SECS = "secs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The name of the nanoseconds field for the Primitive.
|
||||||
|
*/
|
||||||
|
public static final String FIELD_NSECS = "nsecs";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of milliseconds in a second.
|
||||||
|
*/
|
||||||
|
protected static final long SECS_TO_MILLI = 1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fraction of a second in a millisecond.
|
||||||
|
*/
|
||||||
|
protected static final double MILLI_TO_SECS = 0.001;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of nanoseconds in a second.
|
||||||
|
*/
|
||||||
|
protected static final long SECS_TO_NSECS = 1000000000l;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The fraction of a second in a nanosecond.
|
||||||
|
*/
|
||||||
|
protected static final double NSECS_TO_SECS = 1e-9;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of milliseconds in a second.
|
||||||
|
*/
|
||||||
|
protected static final long MILLI_TO_NSECS = 1000000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of milliseconds in a second.
|
||||||
|
*/
|
||||||
|
protected static final double NSECS_TO_MILLI = 1e-6;
|
||||||
|
|
||||||
|
public final int secs, nsecs;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an empty TimeBase with the given type field.
|
||||||
|
*
|
||||||
|
* @param type
|
||||||
|
* The type of primitive.
|
||||||
|
*/
|
||||||
|
public TimeBase(String type) {
|
||||||
|
this(0, 0, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new TimeBase with the given time in seconds (and partial
|
||||||
|
* seconds).
|
||||||
|
*
|
||||||
|
* @param sec
|
||||||
|
* The time in seconds.
|
||||||
|
* @param type
|
||||||
|
* The type of TimeBase primitive.
|
||||||
|
*/
|
||||||
|
public TimeBase(double sec, String type) {
|
||||||
|
this((long) (sec * TimeBase.SECS_TO_NSECS), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new TimeBase with the given time in nanoseconds.
|
||||||
|
*
|
||||||
|
* @param nano
|
||||||
|
* The time in nanoseconds.
|
||||||
|
* @param type
|
||||||
|
* The type of TimeBase primitive.
|
||||||
|
*/
|
||||||
|
public TimeBase(long nano, String type) {
|
||||||
|
// extract seconds and nanoseconds
|
||||||
|
this((int) (nano / TimeBase.SECS_TO_NSECS),
|
||||||
|
(int) (nano % TimeBase.SECS_TO_NSECS), type);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new TimeBase with the given time in seconds and nanoseconds.
|
||||||
|
*
|
||||||
|
* @param secs
|
||||||
|
* The amount of seconds.
|
||||||
|
* @param nsecs
|
||||||
|
* The amount of additional nanoseconds.
|
||||||
|
* @param type
|
||||||
|
* The type of TimeBase primitive.
|
||||||
|
*/
|
||||||
|
public TimeBase(int secs, int nsecs, String type) {
|
||||||
|
// build the JSON object
|
||||||
|
super(Json.createObjectBuilder().add(Duration.FIELD_SECS, secs)
|
||||||
|
.add(Duration.FIELD_NSECS, nsecs).build(), type);
|
||||||
|
this.secs = secs;
|
||||||
|
this.nsecs = nsecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the seconds value of this TimeBase.
|
||||||
|
*
|
||||||
|
* @return The seconds value of this TimeBase.
|
||||||
|
*/
|
||||||
|
public int getSecs() {
|
||||||
|
return this.secs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the nanoseconds value of this TimeBase.
|
||||||
|
*
|
||||||
|
* @return The nanoseconds value of this TimeBase.
|
||||||
|
*/
|
||||||
|
public int getNsecs() {
|
||||||
|
return this.nsecs;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if the value of this TimeBase is zero.
|
||||||
|
*
|
||||||
|
* @return If the value of this TimeBase is zero.
|
||||||
|
*/
|
||||||
|
public boolean isZero() {
|
||||||
|
return (this.secs + this.nsecs) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this TimeBase to seconds (and partial seconds).
|
||||||
|
*
|
||||||
|
* @return This TimeBase to seconds (and partial seconds).
|
||||||
|
*/
|
||||||
|
public double toSec() {
|
||||||
|
return this.secs + (TimeBase.NSECS_TO_SECS * (double) this.nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert this TimeBase to nanoseconds.
|
||||||
|
*
|
||||||
|
* @return This TimeBase to nanoseconds.
|
||||||
|
*/
|
||||||
|
public long toNSec() {
|
||||||
|
return ((long) (this.secs * TimeBase.SECS_TO_NSECS))
|
||||||
|
+ ((long) this.nsecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compare the given TimeBase object to this one.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
* The TimeBase to compare to.
|
||||||
|
* @return 0 if the values are equal, less than 0 if t is less that this
|
||||||
|
* TimeBase, and greater than 0 otherwise.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int compareTo(TimeBase<T> t) {
|
||||||
|
return Double.compare(this.toSec(), t.toSec());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add the given type to this TimeBase and return a new object with that
|
||||||
|
* value.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
* Add the given type to this TimeBase.
|
||||||
|
* @return A new object with the new value.
|
||||||
|
*/
|
||||||
|
public abstract T add(T t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract the given type to this TimeBase and return a new object with
|
||||||
|
* that value.
|
||||||
|
*
|
||||||
|
* @param t
|
||||||
|
* Subtract the given type to this TimeBase.
|
||||||
|
* @return A new object with the new value.
|
||||||
|
*/
|
||||||
|
public abstract T subtract(T t);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this TimeBase.
|
||||||
|
*
|
||||||
|
* @return A clone of this TimeBase.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public abstract T clone();
|
||||||
|
}
|
@ -0,0 +1,135 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.services;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.JsonWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceRequest objects are used for making a request to a service. These
|
||||||
|
* service requests act as wrappers around JSON objects. Service request data is
|
||||||
|
* immutable.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class ServiceRequest extends JsonWrapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The String representation of an empty service request in JSON.
|
||||||
|
*/
|
||||||
|
public static final String EMPTY_MESSAGE = JsonWrapper.EMPTY_JSON;
|
||||||
|
|
||||||
|
private String serviceRequestType;
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new, empty service request. The type will be set to the empty
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
public ServiceRequest() {
|
||||||
|
this(ServiceRequest.EMPTY_MESSAGE, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceRequest based on the given String representation of a
|
||||||
|
* JSON object. The type will be set to the empty string.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON String to parse.
|
||||||
|
*/
|
||||||
|
public ServiceRequest(String jsonString) {
|
||||||
|
this(jsonString, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceRequest based on the given String representation of a
|
||||||
|
* JSON object.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON String to parse.
|
||||||
|
* @param serviceRequestType
|
||||||
|
* The type of the service request (e.g., "std_srvs/Empty").
|
||||||
|
*/
|
||||||
|
public ServiceRequest(String jsonString, String serviceRequestType) {
|
||||||
|
// parse and pass it to the JSON constructor
|
||||||
|
this(Json.createReader(new StringReader(jsonString)).readObject(),
|
||||||
|
serviceRequestType);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceRequest based on the given JSON object. The type will be
|
||||||
|
* set to the empty string.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object containing the service request data.
|
||||||
|
*/
|
||||||
|
public ServiceRequest(JsonObject jsonObject) {
|
||||||
|
// setup the JSON information
|
||||||
|
this(jsonObject, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceRequest based on the given JSON object.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object containing the service request data.
|
||||||
|
* @param serviceRequestType
|
||||||
|
* The type of the service request (e.g., "std_srvs/Empty").
|
||||||
|
*/
|
||||||
|
public ServiceRequest(JsonObject jsonObject, String serviceRequestType) {
|
||||||
|
// setup the JSON information
|
||||||
|
super(jsonObject);
|
||||||
|
// set the type
|
||||||
|
this.serviceRequestType = serviceRequestType;
|
||||||
|
this.id = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of the service request if one was set.
|
||||||
|
*
|
||||||
|
* @return The type of the service request.
|
||||||
|
*/
|
||||||
|
public String getServiceRequestType() {
|
||||||
|
return this.serviceRequestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the type of the service request.
|
||||||
|
*
|
||||||
|
* @param serviceRequestType
|
||||||
|
* The type of the service request (e.g., "std_srvs/Empty").
|
||||||
|
*/
|
||||||
|
public void setServiceRequestType(String serviceRequestType) {
|
||||||
|
this.serviceRequestType = serviceRequestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ID of the service request.
|
||||||
|
*
|
||||||
|
* @param id
|
||||||
|
* The new ID.
|
||||||
|
*/
|
||||||
|
public void setId(String id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the ID of the service request.
|
||||||
|
*
|
||||||
|
* @return The ID.
|
||||||
|
*/
|
||||||
|
public String getId() {
|
||||||
|
return this.id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this ServiceRequest.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ServiceRequest clone() {
|
||||||
|
return new ServiceRequest(this.toJsonObject(), this.serviceRequestType);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,141 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.services;
|
||||||
|
|
||||||
|
import java.io.StringReader;
|
||||||
|
|
||||||
|
import javax.json.Json;
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.JsonWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ServiceResponse objects are used for making a response to a service. These
|
||||||
|
* service responses act as wrappers around JSON objects. Service response data
|
||||||
|
* is immutable.
|
||||||
|
*
|
||||||
|
* @author Russell Toris - russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class ServiceResponse extends JsonWrapper {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The String representation of an empty service response in JSON.
|
||||||
|
*/
|
||||||
|
public static final String EMPTY_MESSAGE = JsonWrapper.EMPTY_JSON;
|
||||||
|
|
||||||
|
private String serviceResponseType;
|
||||||
|
private final boolean result;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new, empty service response. The type will be set to the empty
|
||||||
|
* string.
|
||||||
|
*/
|
||||||
|
public ServiceResponse() {
|
||||||
|
this(ServiceResponse.EMPTY_MESSAGE, "", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceResponse based on the given String representation of a
|
||||||
|
* JSON object. The type will be set to the empty string.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON String to parse.
|
||||||
|
* @param result
|
||||||
|
* The result flag for the response (i.e., if the service server
|
||||||
|
* returned a success).
|
||||||
|
*/
|
||||||
|
public ServiceResponse(String jsonString, boolean result) {
|
||||||
|
this(jsonString, "", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceResponse based on the given String representation of a
|
||||||
|
* JSON object.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON String to parse.
|
||||||
|
* @param serviceResponseType
|
||||||
|
* The type of the service response (e.g., "std_srvs/Empty").
|
||||||
|
* @param result
|
||||||
|
* The result flag for the response (i.e., if the service server
|
||||||
|
* returned a success).
|
||||||
|
*/
|
||||||
|
public ServiceResponse(String jsonString, String serviceResponseType,
|
||||||
|
boolean result) {
|
||||||
|
// parse and pass it to the JSON constructor
|
||||||
|
this(Json.createReader(new StringReader(jsonString)).readObject(),
|
||||||
|
serviceResponseType, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceResponse based on the given JSON object. The type will be
|
||||||
|
* set to the empty string.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object containing the service response data.
|
||||||
|
* @param result
|
||||||
|
* The result flag for the response (i.e., if the service server
|
||||||
|
* returned a success).
|
||||||
|
*/
|
||||||
|
public ServiceResponse(JsonObject jsonObject, boolean result) {
|
||||||
|
// setup the JSON information
|
||||||
|
this(jsonObject, "", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a ServiceResponse based on the given JSON object.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object containing the service response data.
|
||||||
|
* @param serviceResponseType
|
||||||
|
* The type of the service response (e.g., "std_srvs/Empty").
|
||||||
|
* @param result
|
||||||
|
* The result flag for the response (i.e., if the service server
|
||||||
|
* returned a success).
|
||||||
|
*/
|
||||||
|
public ServiceResponse(JsonObject jsonObject, String serviceResponseType,
|
||||||
|
boolean result) {
|
||||||
|
// setup the JSON information
|
||||||
|
super(jsonObject);
|
||||||
|
// set the type
|
||||||
|
this.serviceResponseType = serviceResponseType;
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the type of the service response if one was set.
|
||||||
|
*
|
||||||
|
* @return The type of the service response.
|
||||||
|
*/
|
||||||
|
public String getServiceResponseType() {
|
||||||
|
return this.serviceResponseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the result flag of this response (i.e., if the service server
|
||||||
|
* returned a success).
|
||||||
|
*
|
||||||
|
* @return The result flag for the response.
|
||||||
|
*/
|
||||||
|
public boolean getResult() {
|
||||||
|
return this.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the type of the service response.
|
||||||
|
*
|
||||||
|
* @param serviceResponseType
|
||||||
|
* The type of the service response (e.g., "std_srvs/Empty").
|
||||||
|
*/
|
||||||
|
public void setServiceResponseType(String serviceResponseType) {
|
||||||
|
this.serviceResponseType = serviceResponseType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this ServiceResponse.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public ServiceResponse clone() {
|
||||||
|
return new ServiceResponse(this.toJsonObject(),
|
||||||
|
this.serviceResponseType, this.result);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,157 @@
|
|||||||
|
package edu.wpi.rail.jrosbridge.services.std;
|
||||||
|
|
||||||
|
import javax.json.JsonObject;
|
||||||
|
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceRequest;
|
||||||
|
import edu.wpi.rail.jrosbridge.services.ServiceResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The std_srvs/Empty service.
|
||||||
|
*
|
||||||
|
* @author Russell Toris -- russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public class Empty {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service type.
|
||||||
|
*/
|
||||||
|
public static final String TYPE = "std_srvs/Empty";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service request for the Empty service.
|
||||||
|
*
|
||||||
|
* @author Russell Toris -- russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public static class Request extends ServiceRequest {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceRequest.
|
||||||
|
*/
|
||||||
|
public Request() {
|
||||||
|
super(ServiceRequest.EMPTY_MESSAGE, Empty.TYPE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this Empty ServiceRequest.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Request clone() {
|
||||||
|
return new Request();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceRequest based on the given JSON string. Any
|
||||||
|
* missing values will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON string to parse.
|
||||||
|
* @return A Empty ServiceRequest based on the given JSON string.
|
||||||
|
*/
|
||||||
|
public static Request fromJsonString(String jsonString) {
|
||||||
|
// convert to a ServiceRequest
|
||||||
|
return Request.fromServiceRequest(new ServiceRequest(
|
||||||
|
jsonString));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceRequest based on the given ServiceRequest.
|
||||||
|
* Any missing values will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param m
|
||||||
|
* The ServiceRequest to parse.
|
||||||
|
* @return A Empty ServiceRequest based on the given Message.
|
||||||
|
*/
|
||||||
|
public static Request fromServiceRequest(ServiceRequest req) {
|
||||||
|
// get it from the JSON object
|
||||||
|
return Request.fromJsonObject(req.toJsonObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceRequest based on the given JSON object. Any
|
||||||
|
* missing values will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object to parse.
|
||||||
|
* @return A Empty ServiceRequest based on the given JSON object.
|
||||||
|
*/
|
||||||
|
public static Request fromJsonObject(JsonObject jsonObject) {
|
||||||
|
return new Request();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The service response for the Empty service.
|
||||||
|
*
|
||||||
|
* @author Russell Toris -- russell.toris@gmail.com
|
||||||
|
* @version April 1, 2014
|
||||||
|
*/
|
||||||
|
public static class Response extends ServiceResponse {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceResponse.
|
||||||
|
*/
|
||||||
|
public Response() {
|
||||||
|
this(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceResponse.
|
||||||
|
*
|
||||||
|
* @param result
|
||||||
|
* The result flag for the response (i.e., if the service
|
||||||
|
* server returned a success).
|
||||||
|
*/
|
||||||
|
public Response(boolean result) {
|
||||||
|
super(ServiceResponse.EMPTY_MESSAGE, Empty.TYPE, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a clone of this Empty ServiceResponse.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Response clone() {
|
||||||
|
return new Response();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceResponse based on the given JSON string.
|
||||||
|
* Any missing values will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonString
|
||||||
|
* The JSON string to parse.
|
||||||
|
* @return A Empty ServiceResponse based on the given JSON string.
|
||||||
|
*/
|
||||||
|
public static Response fromJsonString(String jsonString) {
|
||||||
|
// convert to a ServiceResponse
|
||||||
|
return Response.fromServiceResponse(new ServiceResponse(
|
||||||
|
jsonString, true));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceResponse based on the given
|
||||||
|
* ServiceResponse. Any missing values will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param m
|
||||||
|
* The ServiceResponse to parse.
|
||||||
|
* @return A Empty ServiceResponse based on the given Message.
|
||||||
|
*/
|
||||||
|
public static Response fromServiceResponse(ServiceResponse resp) {
|
||||||
|
// get it from the JSON object
|
||||||
|
return Response.fromJsonObject(resp.toJsonObject());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new Empty ServiceResponse based on the given JSON object.
|
||||||
|
* Any missing values will be set to their defaults.
|
||||||
|
*
|
||||||
|
* @param jsonObject
|
||||||
|
* The JSON object to parse.
|
||||||
|
* @return A Empty ServiceResponse based on the given JSON object.
|
||||||
|
*/
|
||||||
|
public static Response fromJsonObject(JsonObject jsonObject) {
|
||||||
|
return new Response();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,26 @@
|
|||||||
|
Manifest-Version: 1.0
|
||||||
|
Main-Class: com.example.testdemo.ServerApplication
|
||||||
|
Class-Path: log4j-to-slf4j-2.14.1.jar selenium-support-3.141.59.jar jsr3
|
||||||
|
05-1.3.9.jar okhttp-3.14.9.jar spring-boot-starter-json-2.5.4.jar sprin
|
||||||
|
g-web-5.3.9.jar logback-core-1.2.5.jar tomcat-embed-core-9.0.52.jar spr
|
||||||
|
ing-aop-5.3.9.jar animal-sniffer-annotations-1.14.jar error_prone_annot
|
||||||
|
ations-2.1.3.jar selenium-ie-driver-3.141.59.jar jackson-datatype-jdk8-
|
||||||
|
2.12.4.jar jackson-core-2.12.4.jar spring-boot-2.5.4.jar j2objc-annotat
|
||||||
|
ions-1.1.jar tomcat-embed-el-9.0.52.jar guava-25.0-jre.jar spring-expre
|
||||||
|
ssion-5.3.9.jar jul-to-slf4j-1.7.32.jar selenium-java-3.141.59.jar jack
|
||||||
|
son-datatype-jsr310-2.12.4.jar spring-boot-starter-logging-2.5.4.jar sp
|
||||||
|
ring-context-5.3.9.jar logback-classic-1.2.5.jar spring-messaging-5.3.9
|
||||||
|
.jar selenium-opera-driver-3.141.59.jar selenium-chrome-driver-3.141.59
|
||||||
|
.jar selenium-firefox-driver-3.141.59.jar okio-1.14.0.jar checker-compa
|
||||||
|
t-qual-2.0.0.jar spring-boot-starter-tomcat-2.5.4.jar selenium-remote-d
|
||||||
|
river-3.141.59.jar jakarta.annotation-api-1.3.5.jar selenium-api-3.141.
|
||||||
|
59.jar jackson-databind-2.12.4.jar fastjson-1.2.73.jar snakeyaml-1.28.j
|
||||||
|
ar selenium-edge-driver-3.141.59.jar spring-boot-starter-2.5.4.jar spri
|
||||||
|
ng-websocket-5.3.9.jar spring-core-5.3.9.jar byte-buddy-1.10.22.jar jac
|
||||||
|
kson-annotations-2.12.4.jar selenium-safari-driver-3.141.59.jar lombok-
|
||||||
|
1.18.20.jar spring-webmvc-5.3.9.jar spring-beans-5.3.9.jar commons-exec
|
||||||
|
-1.3.jar spring-jcl-5.3.9.jar log4j-api-2.14.1.jar spring-boot-starter-
|
||||||
|
websocket-2.5.4.jar spring-boot-autoconfigure-2.5.4.jar jackson-module-
|
||||||
|
parameter-names-2.12.4.jar slf4j-api-1.7.32.jar tomcat-embed-websocket-
|
||||||
|
9.0.52.jar spring-boot-starter-web-2.5.4.jar
|
||||||
|
|
Loading…
Reference in new issue