Skip to content

Commit

Permalink
SIH support: add display-only mode for simulation-in-hardware (PX4#101)
Browse files Browse the repository at this point in the history
via -displayonly flag.
  • Loading branch information
romain-chiap authored and bkueng committed Jun 18, 2019
1 parent 883413f commit def7501
Show file tree
Hide file tree
Showing 4 changed files with 153 additions and 14 deletions.
88 changes: 88 additions & 0 deletions src/me/drton/jmavsim/MAVLinkDisplayOnly.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package me.drton.jmavsim;

import me.drton.jmavlib.conversion.RotationConversion;
import me.drton.jmavlib.mavlink.MAVLinkMessage;
import me.drton.jmavlib.mavlink.MAVLinkSchema;
import me.drton.jmavsim.vehicle.AbstractVehicle;

import javax.vecmath.*;
import java.util.Arrays;

/**
* MAVLinkDisplayOnly is MAVLink bridge between AbstractVehicle and autopilot connected via MAVLink.
* MAVLinkDisplayOnly should have the same sysID as the autopilot, but different componentId.
* It reads HIL_STATE_QUATERNION from the MAVLink and displays the vehicle position and attitude.
* @author Romain Chiappinelli
*/
public class MAVLinkDisplayOnly extends MAVLinkHILSystemBase {

private boolean firstMsg=true; // to detect the first MAVLink message
private double lat0; // initial latitude (radians)
private double lon0; // initial longitude (radians)
private double alt0; // initial altitude (meters)
private double lat; // geodetic latitude (radians)
private double lon; // geodetic longitude (radians)
private double alt; // above sea level (meters)
private double [] quat={0.0,0.0,0.0,0.0}; // unit quaternion for attitude representation
private Double [] control = {0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0};
private static final double EARTH_RADIUS=6371000.0; // earth radius in meters

/**
* Create MAVLinkDisplayOnly, MAVLink system that sends nothing to autopilot and passes states from
* autopilot to simulator
*
* @param sysId SysId of simulator should be the same as autopilot
* @param componentId ComponentId of simulator should be different from autopilot
* @param vehicle vehicle to connect
*/
public MAVLinkDisplayOnly(MAVLinkSchema schema, int sysId, int componentId, AbstractVehicle vehicle) {
super(schema, sysId, componentId, vehicle);
}

@Override
public void handleMessage(MAVLinkMessage msg) {
if ("HIL_STATE_QUATERNION".equals(msg.getMsgName())) {

if (firstMsg) {
firstMsg=false;
// we take the first received position as initial position
lat0=Math.toRadians(msg.getDouble("lat")*1e-7);
lon0=Math.toRadians(msg.getDouble("lon")*1e-7);
alt0=msg.getDouble("alt")*1e-3;
}
for (int i = 0; i < 4; ++i) {
quat[i] = ((Number)((Object[])msg.get("attitude_quaternion"))[i]).doubleValue();
}
lat=Math.toRadians(msg.getDouble("lat")*1e-7);
lon=Math.toRadians(msg.getDouble("lon")*1e-7);
alt=msg.getDouble("alt")*1e-3;

Vector3d pos = new Vector3d(EARTH_RADIUS*(lat-lat0),EARTH_RADIUS*(lon-lon0)*Math.cos(lat0),alt0-alt);
double [] euler = RotationConversion.eulerAnglesByQuaternion(quat);
Matrix3d dcm = new Matrix3d(RotationConversion.rotationMatrixByEulerAngles(euler[0],euler[1],euler[2]));

vehicle.setControl(Arrays.asList(control)); // set 0 throttles
vehicle.setPosition(pos); // we want ideally a "local" pos groundtruth
vehicle.setRotation(dcm);
}
}

@Override
public boolean gotHilActuatorControls()
{
return !firstMsg;
}

@Override
public void initMavLink()
{
firstMsg=true;
}

@Override
public void endSim()
{

}

}
16 changes: 7 additions & 9 deletions src/me/drton/jmavsim/MAVLinkHILSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@
* MAVLinkHILSystem is MAVLink bridge between AbstractVehicle and autopilot connected via MAVLink.
* MAVLinkHILSystem should have the same sysID as the autopilot, but different componentId.
*/
public class MAVLinkHILSystem extends MAVLinkSystem {
private Simulator simulator;
private AbstractVehicle vehicle;
public class MAVLinkHILSystem extends MAVLinkHILSystemBase {
// private Simulator simulator;
// private AbstractVehicle vehicle;
private boolean gotHeartBeat = false;
private boolean inited = false;
private boolean stopped = false;
Expand All @@ -38,14 +38,10 @@ public class MAVLinkHILSystem extends MAVLinkSystem {
* @param vehicle vehicle to connect
*/
public MAVLinkHILSystem(MAVLinkSchema schema, int sysId, int componentId, AbstractVehicle vehicle) {
super(schema, sysId, componentId);
this.vehicle = vehicle;
}

public void setSimulator(Simulator simulator) {
this.simulator = simulator;
super(schema, sysId, componentId, vehicle);
}

@Override
public boolean gotHilActuatorControls() {
return gotHilActuatorControls;
}
Expand Down Expand Up @@ -147,6 +143,7 @@ public void handleMessage(MAVLinkMessage msg) {
}
}

@Override
public void initMavLink() {
if (vehicle.getSensors().getGPSStartTime() == -1) {
vehicle.getSensors().setGPSStartTime(simulator.getSimMillis() + 1000);
Expand All @@ -155,6 +152,7 @@ public void initMavLink() {
inited = true;
}

@Override
public void endSim() {
if (!inited) {
return;
Expand Down
38 changes: 38 additions & 0 deletions src/me/drton/jmavsim/MAVLinkHILSystemBase.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package me.drton.jmavsim;

import me.drton.jmavlib.mavlink.MAVLinkSchema;
import me.drton.jmavsim.vehicle.AbstractVehicle;

/**
* MAVLinkHILSystemBase is the superclass of MAVLinkHILSystem and MAVLinkDisplayOnly. It is a bridge between
* AbstractVehicle and autopilot connected via MAVLink.
* MAVLinkHILSystemBase should have the same sysID as the autopilot, but different componentId.
*/
public abstract class MAVLinkHILSystemBase extends MAVLinkSystem {
protected Simulator simulator;
protected AbstractVehicle vehicle;

/**
* Create MAVLinkHILSimulator, MAVLink system that sends simulated sensors to autopilot and passes controls from
* autopilot to simulator
*
* @param sysId SysId of simulator should be the same as autopilot
* @param componentId ComponentId of simulator should be different from autopilot
* @param vehicle vehicle to connect
*/
public MAVLinkHILSystemBase(MAVLinkSchema schema, int sysId, int componentId, AbstractVehicle vehicle) {
super(schema, sysId, componentId);
this.vehicle = vehicle;
}

public void setSimulator(Simulator simulator) {
this.simulator = simulator;
}

public abstract boolean gotHilActuatorControls();

public abstract void initMavLink();

public abstract void endSim();

}
25 changes: 20 additions & 5 deletions src/me/drton/jmavsim/Simulator.java
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ private static enum Port {
public static boolean LOG_TO_STDOUT =
true; // send System.out messages to stdout (console) as well as any custom handlers (see SystemOutHandler)
public static boolean DEBUG_MODE = false;
public static boolean DISPLAY_ONLY = false; // display HIL_STATE_QUATERNION from the autopilot, simulation engine disabled

public static final int DEFAULT_SIM_RATE = 250; // Hz
public static final double DEFAULT_SPEED_FACTOR = 1.0;
Expand Down Expand Up @@ -121,7 +122,7 @@ private static enum Port {
private Visualizer3D visualizer;
private AbstractMulticopter vehicle;
private CameraGimbal2D gimbal;
private MAVLinkHILSystem hilSystem;
private MAVLinkHILSystemBase hilSystem;
private MAVLinkPort autopilotMavLinkPort;
private UDPMavLinkPort udpGCMavLinkPort;
private UDPMavLinkPort udpSDKMavLinkPort;
Expand Down Expand Up @@ -306,7 +307,14 @@ public Simulator() throws IOException, InterruptedException {

// Create MAVLink HIL system
// SysId should be the same as autopilot, ComponentId should be different!
hilSystem = new MAVLinkHILSystem(schema, autopilotSysId, 51, vehicle);
if (DISPLAY_ONLY){
vehicle.setIgnoreGravity(true);
vehicle.setIgnoreWind(true);
hilSystem = new MAVLinkDisplayOnly(schema, autopilotSysId, 51, vehicle);
} else {
hilSystem = new MAVLinkHILSystem(schema, autopilotSysId, 51, vehicle);
visualizer.setHilSystem((MAVLinkHILSystem)hilSystem);
}
hilSystem.setSimulator(this);
//hilSystem.setHeartbeatInterval(0);
connHIL.addNode(hilSystem);
Expand All @@ -323,7 +331,6 @@ public Simulator() throws IOException, InterruptedException {
world.addObject(new ReportUpdater(world, visualizer));

visualizer.addWorldModels();
visualizer.setHilSystem(hilSystem);
visualizer.setVehicleViewObject(vehicle);

// set default view and zoom mode
Expand Down Expand Up @@ -482,7 +489,7 @@ public void run() {
boolean needsToPause = false;
long now;

if (LOCKSTEP_ENABLED) {
if (LOCKSTEP_ENABLED && !DISPLAY_ONLY) {
// In lockstep we run every update with a checkFactor of (e.g. 2).
// This way every second update is just an IO (input/output) run where
// time is not increased.
Expand Down Expand Up @@ -610,6 +617,7 @@ public void advanceTime() {
public final static String RATE_STRING = "-r <Hz>";
public final static String SPEED_FACTOR_STRING = "-f";
public final static String LOCKSTEP_STRING = "-lockstep";
public final static String DISPLAY_ONLY_STRING = "-disponly";
public final static String CMD_STRING =
"java [-Xmx512m] -cp lib/*:out/production/jmavsim.jar me.drton.jmavsim.Simulator";
public final static String CMD_STRING_JAR = "java [-Xmx512m] -jar jmavsim_run.jar";
Expand All @@ -626,7 +634,8 @@ public void advanceTime() {
GUI_MAX_STRING + "] [" +
GUI_VIEW_STRING + "] [" +
REP_STRING + "] [" +
PRINT_INDICATION_STRING + "]";
PRINT_INDICATION_STRING + "] [" +
DISPLAY_ONLY_STRING + "]";

public static void main(String[] args)
throws InterruptedException, IOException {
Expand Down Expand Up @@ -862,6 +871,8 @@ public static void main(String[] args)
System.err.println("-view requires an argument: " + GUI_VIEW_STRING);
return;
}
} else if (arg.equals(DISPLAY_ONLY_STRING)) {
DISPLAY_ONLY = true; // // display HIL_STATE_QUATERNION from the autopilot, simulation engine disabled
} else if (arg.equals("-automag")) {
DO_MAG_FIELD_LOOKUP = true;
} else if (arg.equals("-rep")) {
Expand Down Expand Up @@ -950,6 +961,10 @@ public static void handleHelpFlag() {
System.out.println(PRINT_INDICATION_STRING);
System.out.println(" Monitor (echo) all/selected MAVLink messages to the console.");
System.out.println(" If no MsgIDs are specified, all messages are monitored.");
System.out.println(DISPLAY_ONLY_STRING);
System.out.println(" Disable the simulation engine.");
System.out.println(" Display the autopilot states from HIL_STATE_QUATERNION.");
System.out.println(" Compatible with simulation-in-hardware.");
System.out.println("");
System.out.println("Key commands (in the visualizer window):");
System.out.println("");
Expand Down

0 comments on commit def7501

Please sign in to comment.