blob: 465efa8c615004d5379b22e38b61fb3ee3e336bb [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2018 Agence spatiale canadienne / Canadian Space Agency
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
<<<<<<< HEAD
* Contributors:
* Pierre Allard - initial API and implementation
* Regent L'Archeveque
*
=======
* Contributors:
* Pierre Allard,
* Regent L'Archeveque - initial API and implementation
*
>>>>>>> refs/heads/eclipse_pa
* SPDX-License-Identifier: EPL-1.0
*******************************************************************************/
package org.eclipse.apogy.examples.robotic_arm.ui.composites;
import org.eclipse.apogy.common.emf.ui.composites.TypedElementSimpleUnitsComposite;
import org.eclipse.apogy.examples.robotic_arm.ApogyExamplesRoboticArmPackage;
import org.eclipse.apogy.examples.robotic_arm.MoveSpeedLevel;
import org.eclipse.apogy.examples.robotic_arm.RoboticArm;
import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.UpdateValueStrategy;
import org.eclipse.core.databinding.conversion.Converter;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.emf.databinding.EMFProperties;
import org.eclipse.jface.databinding.swt.WidgetProperties;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class RoboticArmControlComposite extends Composite {
private static final Logger Logger = LoggerFactory.getLogger(RoboticArmControlComposite.class);
private static final String DEGREE_SYM = "\u00b0";
private static final String MOVING_STR = "Moving";
private static final String STOPPED_STR = "Stopped";
private static final String READY_STR = "Ready";
private static final String NOT_READY_STR = "Not Ready";
private DataBindingContext m_bindingContext;
private RoboticArm roboticArm;
private final Text txtInitialized;
private final Text txtMoving;
private final Text txtWristEditValue;
private final Text txtTurretEditValue;
private final Text txtShoulderEditValue;
private final Text txtElbowEditValue;
private final TypedElementSimpleUnitsComposite lblTurretValue;
private final TypedElementSimpleUnitsComposite lblElbowValue;
private final TypedElementSimpleUnitsComposite lblShoulderValue;
private final TypedElementSimpleUnitsComposite lblWristValue;
private final Button btnInitialized;
private final Button btnStow;
private final Button btnMoveTo;
private final Combo cmbSpeedMode;
/**
* Create the parentComposite.
*
* @param parent
* @param style
*/
public RoboticArmControlComposite(Composite parent, int style) {
super(parent, style);
setLayout(new GridLayout(2, false));
this.addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
RoboticArmControlComposite.this.m_bindingContext.dispose();
}
});
Group compositeStatus = new Group(this, SWT.BORDER);
compositeStatus.setText("Status");
compositeStatus.setLayout(new GridLayout(2, true));
this.txtInitialized = new Text(compositeStatus, SWT.CENTER | SWT.NO_FOCUS);
this.txtInitialized.setEditable(false);
this.txtInitialized.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
this.txtMoving = new Text(compositeStatus, SWT.CENTER | SWT.NO_FOCUS);
this.txtMoving.setEditable(false);
this.txtMoving.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
this.txtMoving.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if (RoboticArmControlComposite.this.txtMoving.getText().equals(MOVING_STR) == true) {
RoboticArmControlComposite.this.txtMoving
.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
} else if (RoboticArmControlComposite.this.txtMoving.getText().equals(STOPPED_STR) == true) {
RoboticArmControlComposite.this.txtMoving
.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
}
}
});
this.txtMoving.setText(STOPPED_STR);
Group composite = new Group(this, SWT.BORDER);
composite.setText("High Level Commands");
composite.setLayout(new GridLayout(3, false));
this.btnInitialized = new Button(composite, SWT.NONE);
this.btnInitialized.setText("Initialize");
this.btnInitialized.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (RoboticArmControlComposite.this.roboticArm != null) {
Job initJob = new InitJob();
initJob.schedule();
}
}
});
this.btnInitialized.setLayoutData(new GridData(SWT.LEFT, SWT.CENTER, false, true, 1, 1));
this.btnStow = new Button(composite, SWT.NONE);
this.btnStow.setText("Stow");
this.btnStow.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (RoboticArmControlComposite.this.roboticArm != null) {
Job stowJob = new StowJob();
stowJob.schedule();
}
}
});
this.cmbSpeedMode = new Combo(composite, SWT.READ_ONLY);
this.cmbSpeedMode.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
this.cmbSpeedMode.add(MoveSpeedLevel.SLOW.getLiteral());
this.cmbSpeedMode.add(MoveSpeedLevel.MEDIUM.getLiteral());
this.cmbSpeedMode.add(MoveSpeedLevel.FAST.getLiteral());
this.cmbSpeedMode.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (RoboticArmControlComposite.this.roboticArm != null) {
String newSpeedMode = RoboticArmControlComposite.this.cmbSpeedMode.getText();
MoveSpeedLevel newSpeedLevel = MoveSpeedLevel.get(newSpeedMode);
Job speedJob = new SpeedModeJob(newSpeedLevel);
speedJob.schedule();
}
}
});
Group compositeJoints = new Group(this, SWT.NONE);
compositeJoints.setText("Joints");
compositeJoints.setLayoutData(new GridData(SWT.FILL, SWT.TOP, false, false, 2, 1));
compositeJoints.setLayout(new GridLayout(6, true));
new Label(compositeJoints, SWT.NONE);
Label lblTurret = new Label(compositeJoints, SWT.NONE);
lblTurret.setText("Turret (" + DEGREE_SYM + ")");
lblTurret.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
Label lblShoulder = new Label(compositeJoints, SWT.NONE);
lblShoulder.setText("Shoulder (" + DEGREE_SYM + ")");
lblShoulder.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
Label lblElbow = new Label(compositeJoints, SWT.NONE);
lblElbow.setText("Elbow (" + DEGREE_SYM + ")");
lblElbow.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
Label lblWrist = new Label(compositeJoints, SWT.NONE);
lblWrist.setText("Wrist (" + DEGREE_SYM + ")");
lblWrist.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false, 1, 1));
Label lblNewLabel = new Label(compositeJoints, SWT.NONE);
lblNewLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1));
Label lblActuals = new Label(compositeJoints, SWT.NONE);
lblActuals.setText("Actuals");
lblActuals.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
// lblTurretValue = formToolkit.createLabel(compositeJoints, "0.0", SWT.CENTER);
this.lblTurretValue = new TypedElementSimpleUnitsComposite(compositeJoints, SWT.BORDER, false, true, "N/A");
this.lblTurretValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.lblTurretValue.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
this.lblShoulderValue = new TypedElementSimpleUnitsComposite(compositeJoints, SWT.BORDER, false, true, "N/A");
this.lblShoulderValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.lblShoulderValue.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
this.lblElbowValue = new TypedElementSimpleUnitsComposite(compositeJoints, SWT.BORDER, false, true, "N/A");
this.lblElbowValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.lblElbowValue.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
this.lblWristValue = new TypedElementSimpleUnitsComposite(compositeJoints, SWT.BORDER, false, true, "N/A");
this.lblWristValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.lblWristValue.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
Button btnLoad = new Button(compositeJoints, SWT.NONE);
btnLoad.setText("Load");
btnLoad.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (getRoboticArm() != null) {
RoboticArmControlComposite.this.txtTurretEditValue
.setText(Double.toString(getRoboticArm().getTurretAngle()));
RoboticArmControlComposite.this.txtShoulderEditValue
.setText(Double.toString(getRoboticArm().getShoulderAngle()));
RoboticArmControlComposite.this.txtElbowEditValue
.setText(Double.toString(getRoboticArm().getElbowAngle()));
RoboticArmControlComposite.this.txtWristEditValue
.setText(Double.toString(getRoboticArm().getWristAngle()));
}
}
});
btnLoad.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, true, 1, 1));
Label lblCommanded = new Label(compositeJoints, SWT.NONE);
lblCommanded.setText("Commanded");
lblCommanded.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, false, false, 1, 1));
this.txtTurretEditValue = new Text(compositeJoints, SWT.CENTER);
this.txtTurretEditValue.setText("0.0");
this.txtTurretEditValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.txtTurretEditValue.addVerifyListener(new AngleValueVerifyListener());
this.txtShoulderEditValue = new Text(compositeJoints, SWT.CENTER);
this.txtShoulderEditValue.setText("0.0");
this.txtShoulderEditValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.txtShoulderEditValue.addVerifyListener(new AngleValueVerifyListener());
this.txtElbowEditValue = new Text(compositeJoints, SWT.CENTER);
this.txtElbowEditValue.setText("0.0");
this.txtElbowEditValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1));
this.txtElbowEditValue.addVerifyListener(new AngleValueVerifyListener());
this.txtWristEditValue = new Text(compositeJoints, SWT.CENTER);
this.txtWristEditValue.setText("0.0");
this.txtWristEditValue.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false, 1, 1));
this.txtWristEditValue.addVerifyListener(new AngleValueVerifyListener());
this.btnMoveTo = new Button(compositeJoints, SWT.NONE);
this.btnMoveTo.setText("MoveTo");
this.btnMoveTo.addSelectionListener(new SelectionAdapter() {
@Override
public void widgetSelected(SelectionEvent e) {
if (RoboticArmControlComposite.this.roboticArm != null) {
double turret = Math.toRadians(
Double.parseDouble(RoboticArmControlComposite.this.txtTurretEditValue.getText()));
double shoulder = Math.toRadians(
Double.parseDouble(RoboticArmControlComposite.this.txtShoulderEditValue.getText()));
double elbow = Math
.toRadians(Double.parseDouble(RoboticArmControlComposite.this.txtElbowEditValue.getText()));
double wrist = Math
.toRadians(Double.parseDouble(RoboticArmControlComposite.this.txtWristEditValue.getText()));
Job moveToJob = new MoveToJob(turret, shoulder, elbow, wrist);
moveToJob.schedule();
}
}
});
this.btnMoveTo.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 1, 1));
this.txtInitialized.addModifyListener(new ModifyListener() {
@Override
public void modifyText(ModifyEvent e) {
if (RoboticArmControlComposite.this.txtInitialized.getText().equals(READY_STR) == true) {
RoboticArmControlComposite.this.txtInitialized
.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_GREEN));
RoboticArmControlComposite.this.btnInitialized.setEnabled(false);
RoboticArmControlComposite.this.btnStow.setEnabled(true);
RoboticArmControlComposite.this.btnMoveTo.setEnabled(true);
RoboticArmControlComposite.this.cmbSpeedMode.setEnabled(true);
} else if (RoboticArmControlComposite.this.txtInitialized.getText().equals(NOT_READY_STR) == true) {
RoboticArmControlComposite.this.txtInitialized
.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_RED));
RoboticArmControlComposite.this.btnInitialized.setEnabled(true);
RoboticArmControlComposite.this.btnStow.setEnabled(false);
RoboticArmControlComposite.this.btnMoveTo.setEnabled(false);
RoboticArmControlComposite.this.cmbSpeedMode.setEnabled(false);
}
}
});
this.txtInitialized.setText(NOT_READY_STR);
// Dispose
addDisposeListener(new DisposeListener() {
@Override
public void widgetDisposed(DisposeEvent e) {
if (RoboticArmControlComposite.this.m_bindingContext != null)
RoboticArmControlComposite.this.m_bindingContext.dispose();
}
});
}
public void setRoboticArm(RoboticArm newRoboticArm) {
this.roboticArm = newRoboticArm;
if (this.m_bindingContext != null) {
this.m_bindingContext.dispose();
this.m_bindingContext = null;
}
if (newRoboticArm != null && !isDisposed()) {
this.m_bindingContext = initDataBindings();
}
}
public RoboticArm getRoboticArm() {
return this.roboticArm;
}
private class AngleValueVerifyListener implements VerifyListener {
@Override
public void verifyText(VerifyEvent e) {
String oldText = ((Text) e.widget).getText();
String newText = oldText.substring(0, e.start) + e.text + oldText.substring(e.end);
try {
Double.parseDouble(newText);
} catch (NumberFormatException ex) {
e.text = "";
e.doit = false;
}
}
}
public class InitJob extends Job {
public InitJob() {
super("Robotic Arm - Initialize");
setSystem(true);
}
@Override
public IStatus run(IProgressMonitor arg0) {
try {
RoboticArmControlComposite.this.roboticArm.init();
} catch (Exception ex) {
ex.printStackTrace();
}
return Status.OK_STATUS;
}
}
public class StowJob extends Job {
public StowJob() {
super("Robotic Arm - Stow");
setSystem(true);
}
@Override
protected IStatus run(IProgressMonitor arg0) {
try {
RoboticArmControlComposite.this.roboticArm.stow();
} catch (Exception ex) {
ex.printStackTrace();
}
return Status.OK_STATUS;
}
};
private class SpeedModeJob extends Job {
private final MoveSpeedLevel speedModeLevel;
public SpeedModeJob(MoveSpeedLevel level) {
super("Robotic Arm - Speed Mode Change");
this.speedModeLevel = level;
setSystem(true);
}
@Override
protected IStatus run(IProgressMonitor arg0) {
try {
RoboticArmControlComposite.this.roboticArm.cmdMoveSpeedLevel(this.speedModeLevel);
} catch (Exception ex) {
ex.printStackTrace();
}
return Status.OK_STATUS;
}
}
@SuppressWarnings({ "rawtypes", "unchecked" })
protected DataBindingContext initDataBindings() {
DataBindingContext bindingContext = new DataBindingContext();
// Start binding
this.m_bindingContext = new DataBindingContext();
// Turret Angle.
try {
this.lblTurretValue.setTypedElement(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__TURRET_ANGLE,
getRoboticArm());
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
// Shoulder Angle.
try {
this.lblShoulderValue.setTypedElement(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__SHOULDER_ANGLE,
getRoboticArm());
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
// ELbow Angle.
try {
this.lblElbowValue.setTypedElement(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__ELBOW_ANGLE,
getRoboticArm());
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
// Wrist Angle.
try {
this.lblWristValue.setTypedElement(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__WRIST_ANGLE,
getRoboticArm());
} catch (Throwable t) {
Logger.error(t.getMessage(), t);
}
// Enablement.
IObservableValue<?> observeInitializedValue = EMFProperties
.value(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__INITIALIZED).observe(getRoboticArm());
// Stow Enablement
IObservableValue<?> observeBtnStowEnable = WidgetProperties.enabled().observe(this.btnStow);
bindingContext.bindValue(observeBtnStowEnable, observeInitializedValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy());
// Cmd Speed Enablement
IObservableValue<?> observeCmbSpeedModeEnable = WidgetProperties.enabled().observe(this.cmbSpeedMode);
bindingContext.bindValue(observeCmbSpeedModeEnable, observeInitializedValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy());
// Move to
IObservableValue<?> observeBtnMoveToEnable = WidgetProperties.enabled().observe(this.btnMoveTo);
bindingContext.bindValue(observeBtnMoveToEnable, observeInitializedValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy());
// Moving
IObservableValue<?> observeTextTxtMovingObserveWidget = WidgetProperties.text().observe(this.txtMoving);
IObservableValue roboticArmArmMovingObserveValue = EMFProperties
.value(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__ARM_MOVING).observe(getRoboticArm());
this.m_bindingContext.bindValue(observeTextTxtMovingObserveWidget, roboticArmArmMovingObserveValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(boolean.class, String.class) {
@Override
public Object convert(Object arg0) {
return ((Boolean) arg0).booleanValue() ? MOVING_STR : STOPPED_STR;
}
}));
// Ready Enablement
IObservableValue<?> observeTxtInitializedEnabled = WidgetProperties.enabled().observe(this.txtInitialized);
bindingContext.bindValue(observeTxtInitializedEnabled, observeInitializedValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER), new UpdateValueStrategy());
// Ready
IObservableValue<?> observeTxtInitializedObserveWidget = WidgetProperties.text().observe(this.txtInitialized);
this.m_bindingContext.bindValue(observeTxtInitializedObserveWidget, observeInitializedValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(boolean.class, String.class) {
@Override
public Object convert(Object arg0) {
return ((Boolean) arg0).booleanValue() ? READY_STR : NOT_READY_STR;
}
}));
IObservableValue observeTextCmdMoveSpeedObserveWidget = WidgetProperties.singleSelectionIndex()
.observe(this.cmbSpeedMode);
IObservableValue roboticArmMoveSpeedObserveValue = EMFProperties
.value(ApogyExamplesRoboticArmPackage.Literals.ROBOTIC_ARM__SPEED).observe(getRoboticArm());
this.m_bindingContext.bindValue(observeTextCmdMoveSpeedObserveWidget, roboticArmMoveSpeedObserveValue,
new UpdateValueStrategy(UpdateValueStrategy.POLICY_NEVER),
new UpdateValueStrategy(UpdateValueStrategy.POLICY_UPDATE)
.setConverter(new Converter(MoveSpeedLevel.class, Integer.class) {
@Override
public Object convert(Object obj) {
String literal = ((MoveSpeedLevel) obj).getLiteral();
for (int index = 0; index < RoboticArmControlComposite.this.cmbSpeedMode
.getItemCount(); index++) {
if (literal.equals(
RoboticArmControlComposite.this.cmbSpeedMode.getItems()[index]) == true) {
return new Integer(index);
}
}
return new Integer(-1);
}
}));
return bindingContext;
}
private class MoveToJob extends Job {
private final double turretValue;
private final double shoulderValue;
private final double elbowValue;
private final double wristValue;
public MoveToJob(double turret, double shoulder, double elbow, double wrist) {
super("Robotic Arm - Move To");
this.turretValue = turret;
this.shoulderValue = shoulder;
this.elbowValue = elbow;
this.wristValue = wrist;
setSystem(true);
}
@Override
public IStatus run(IProgressMonitor monitor) {
try {
RoboticArmControlComposite.this.roboticArm.moveTo(this.turretValue, this.shoulderValue, this.elbowValue,
this.wristValue);
} catch (Exception ex) {
ex.printStackTrace();
}
return Status.OK_STATUS;
}
}
}