[chronojump] Initial coder for force sensor realtime graph
- From: Xavier de Blas <xaviblas src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [chronojump] Initial coder for force sensor realtime graph
- Date: Mon, 23 Oct 2017 14:33:44 +0000 (UTC)
commit 5a4ea61ce6f1dba8b77fd82fd0b7609012e57792
Author: Xavier de Blas <xaviblas gmail com>
Date: Mon Oct 23 16:33:15 2017 +0200
Initial coder for force sensor realtime graph
glade/app1.glade | 19 +++++++
src/forceSensor.cs | 78 +++++++++++++++++++++++++++
src/gui/forceSensor.cs | 137 +++++++++++++++++++++++++++++++++++++++++++++++-
3 files changed, 232 insertions(+), 2 deletions(-)
---
diff --git a/glade/app1.glade b/glade/app1.glade
index be3a7a5..9488ca9 100644
--- a/glade/app1.glade
+++ b/glade/app1.glade
@@ -1396,6 +1396,9 @@
<placeholder/>
</child>
<child>
+ <placeholder/>
+ </child>
+ <child>
<widget class="GtkLabel"
id="label_start_selector_jumps">
<property name="visible">True</property>
<property name="can_focus">False</property>
@@ -11129,6 +11132,19 @@ after time</property>
<property name="position">2</property>
</packing>
</child>
+ <child>
+ <widget class="GtkDrawingArea"
id="force_capture_drawingarea">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <signal name="configure_event"
handler="on_force_capture_drawingarea_configure_event" swapped="no"/>
+ <signal name="expose_event"
handler="on_force_capture_drawingarea_expose_event" swapped="no"/>
+ </widget>
+ <packing>
+ <property name="expand">True</property>
+ <property name="fill">True</property>
+ <property name="position">3</property>
+ </packing>
+ </child>
</widget>
<packing>
<property name="expand">True</property>
@@ -21598,6 +21614,9 @@ then click this button.</property>
<child>
<placeholder/>
</child>
+ <child>
+ <placeholder/>
+ </child>
</widget>
<packing>
<property name="expand">False</property>
diff --git a/src/forceSensor.cs b/src/forceSensor.cs
index 8a00c33..ed9463d 100644
--- a/src/forceSensor.cs
+++ b/src/forceSensor.cs
@@ -23,6 +23,84 @@ using System.IO; //for detect OS
using System.Collections.Generic; //List<T>
using Mono.Unix;
+/*
+ * TODO: this class only contains points plot stuff
+ * currently all the code relevant to force sensor actions is on gui/forcesensor.cs
+ * that code should be here and there only the gui stuff
+ */
+public class ForceSensorCapturePoints
+{
+ //ForceCapturePoints stored to be realtime displayed
+ public List<Gdk.Point> Points;
+ public int NumCaptured;
+ public int NumPainted;
+
+ //used to redo all points if change RealWidthG or RealHeightG
+ private List<double> times;
+ private List<double> forces;
+
+ public int RealWidthG = 10000000; //width of graph in microseconds (will be upgraded if needed)
+ public int RealHeightG = 200; //Newtons (will be upgraded if needed)
+
+ private int widthG;
+ private int heightG;
+
+ //initialize
+ public ForceSensorCapturePoints(int widthG, int heightG)
+ {
+ Points = new List<Gdk.Point>();
+ NumCaptured = 0;
+ NumPainted = 0; //-1 means delete screen
+ times = new List<double>();
+ forces = new List<double>();
+
+ this.widthG = widthG;
+ this.heightG = heightG;
+ }
+// int xCount = 10; //just for debugging!!
+
+ public void Add(double time, double force)
+ {
+ times.Add(time);
+ forces.Add(force);
+ Points.Add(new Gdk.Point(
+ Convert.ToInt32(widthG * time / RealWidthG),
+ Convert.ToInt32( (heightG/2) - ( force * heightG / RealHeightG) )
+ ));
+ }
+
+ private Gdk.Point getLastPoint()
+ {
+ return Points[Points.Count -1];
+ }
+
+ public bool OutsideGraph()
+ {
+ Gdk.Point p = getLastPoint();
+ if(p.X > widthG)
+ {
+ RealWidthG *= 2;
+ return true;
+ }
+ if(p.Y > heightG /2)
+ {
+ RealHeightG *= 2;
+ return true;
+ }
+ return false;
+ }
+
+ //reprocess all points with new RealWidthG, RealHeightG
+ public void Redo()
+ {
+ for(int i=0; i < NumCaptured; i ++)
+ Points[i] = new Gdk.Point(
+ Convert.ToInt32(widthG * times[i] / RealWidthG),
+ Convert.ToInt32( (heightG/2) - ( forces[i] * heightG / RealHeightG) )
+ );
+ }
+}
+
public class ForceSensorRFD
{
//if these names change, change FunctionPrint() below
diff --git a/src/gui/forceSensor.cs b/src/gui/forceSensor.cs
index 0badf35..04c7218 100644
--- a/src/gui/forceSensor.cs
+++ b/src/gui/forceSensor.cs
@@ -41,10 +41,13 @@ public partial class ChronoJumpWindow
[Widget] Gtk.Image image_force_sensor_graph;
[Widget] Gtk.SpinButton spin_force_sensor_calibration_kg_value;
[Widget] Gtk.Button button_force_sensor_image_save;
+ [Widget] Gtk.DrawingArea force_capture_drawingarea;
+ Gdk.Pixmap force_capture_pixmap = null;
Thread forceCaptureThread;
static bool forceProcessFinish;
static bool forceProcessCancel;
+ ForceSensorCapturePoints fscPoints;
Thread forceOtherThread; //for messages on: capture, tare, calibrate
static string forceSensorOtherMessage = "";
@@ -69,6 +72,8 @@ public partial class ChronoJumpWindow
SerialPort portFS;
bool portFSOpened;
+ Gdk.GC pen_black_force_capture;
+
//Don't reopen port because arduino makes reset and tare, calibration... is lost
private bool forceSensorConnect()
@@ -303,7 +308,11 @@ public partial class ChronoJumpWindow
forceProcessFinish = false;
forceProcessCancel = false;
forceSensorLast = 0;
-
+
+ pen_black_force_capture = new Gdk.GC(force_capture_drawingarea.GdkWindow);
+ pen_black_force_capture.Foreground = UtilGtk.BLACK;
+ //pen_black_force_capture.SetLineAttributes (2, Gdk.LineStyle.Solid, Gdk.CapStyle.NotLast,
Gdk.JoinStyle.Miter);
+
event_execute_ButtonFinish.Clicked -= new EventHandler(on_finish_clicked);
event_execute_ButtonFinish.Clicked += new EventHandler(on_finish_clicked);
@@ -347,6 +356,13 @@ public partial class ChronoJumpWindow
writer.WriteLine("Time (s);Force(N)");
str = "";
double firstTime = 0;
+ fscPoints = new ForceSensorCapturePoints(
+ force_capture_drawingarea.Allocation.Width,
+ force_capture_drawingarea.Allocation.Height
+ );
+ UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+
+ int count = 0;
while(! forceProcessFinish && ! forceProcessCancel)
{
str = portFS.ReadLine();
@@ -381,6 +397,14 @@ public partial class ChronoJumpWindow
writer.WriteLine(time.ToString() + ";" + force.ToString());
forceSensorLast = force;
+ fscPoints.Add(time, force);
+ fscPoints.NumCaptured = count ++;
+ if(fscPoints.OutsideGraph())
+ {
+ fscPoints.Redo();
+ fscPoints.NumPainted = -1;
+ }
+
//changeSlideIfNeeded(time, force);
}
portFS.WriteLine("end_capture:");
@@ -449,6 +473,7 @@ public partial class ChronoJumpWindow
if(capturingForce == forceStatus.CAPTURING)
{
+ //------------------- vscale -----------------
//A) resize vscale if needed
int upper = Convert.ToInt32(vscale_force_sensor.Adjustment.Upper);
int lower = Convert.ToInt32(vscale_force_sensor.Adjustment.Lower);
@@ -474,13 +499,121 @@ public partial class ChronoJumpWindow
label_force_sensor_value_max.Text = forceSensorLast.ToString();
if(forceSensorLast < Convert.ToDouble(label_force_sensor_value_min.Text))
label_force_sensor_value_min.Text = forceSensorLast.ToString();
+
+
+ //------------------- realtime graph -----------------
+ if(fscPoints.Points == null || force_capture_drawingarea == null)
+ return true;
+
+ //mark meaning screen should be erased
+ if(fscPoints.NumPainted == -1) {
+ UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+ fscPoints.NumPainted = 0;
+ }
+
+ int last = fscPoints.NumCaptured;
+ int toDraw = fscPoints.NumCaptured - fscPoints.NumPainted;
+
+ //LogB.Information("toDraw: " + toDraw.ToString());
+ //fixes crash at the end
+ if(toDraw == 0)
+ return true;
+
+ Gdk.Point [] paintPoints;
+ if(fscPoints.NumPainted > 1)
+ paintPoints = new Gdk.Point[toDraw +1]; // if something has been painted,
connected first point with previous points
+ else
+ paintPoints = new Gdk.Point[toDraw];
+
+ int jStart = 0;
+ if(fscPoints.NumPainted > 1)
+ {
+ // if something has been painted, connected first point with previous points
+ paintPoints[0] = fscPoints.Points[fscPoints.NumPainted];
+ jStart = 1;
+ }
+
+ for(int j=jStart, i = fscPoints.NumPainted +1 ; i <= last ; i ++, j++)
+ {
+ paintPoints[j] = fscPoints.Points[i];
+ LogB.Information("X: " + paintPoints[j].X.ToString() + "; Y: " +
paintPoints[j].Y.ToString());
+ }
+ force_capture_pixmap.DrawLines(pen_black_force_capture, paintPoints);
+ force_capture_drawingarea.QueueDraw(); // -- refresh
+ fscPoints.NumPainted = fscPoints.NumCaptured;
}
Thread.Sleep (25);
-// LogB.Information(" ForceSensor:"+ forceCaptureThread.ThreadState.ToString());
+ //LogB.Information(" ForceSensor:"+ forceCaptureThread.ThreadState.ToString());
return true;
}
+ int force_capture_allocationXOld;
+ bool force_capture_sizeChanged;
+ public void on_force_capture_drawingarea_configure_event(object o, ConfigureEventArgs args)
+ {
+// if(force_capture_drawingarea == null)
+// return;
+
+ Gdk.EventConfigure ev = args.Event;
+ Gdk.Window window = ev.Window;
+
+ Gdk.Rectangle allocation = force_capture_drawingarea.Allocation;
+
+ if(force_capture_pixmap == null || force_capture_sizeChanged ||
+ allocation.Width != force_capture_allocationXOld)
+ {
+ force_capture_pixmap = new Gdk.Pixmap (window, allocation.Width, allocation.Height,
-1);
+
+ if(forceCaptureThread != null) //&& capturingCsharp ==
encoderCaptureProcess.CAPTURING)
+ fscPoints.NumPainted = -1; //mark meaning screen should be erased and start
painting from the beginning
+ else
+ UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+
+ force_capture_sizeChanged = false;
+ }
+
+ force_capture_allocationXOld = allocation.Width;
+ }
+ public void on_force_capture_drawingarea_expose_event(object o, ExposeEventArgs args)
+ {
+// if(force_capture_drawingarea == null)
+// return;
+
+ /* in some mono installations, configure_event is not called, but expose_event yes.
+ * Do here the initialization
+ */
+ //LogB.Debug("EXPOSE");
+
+ Gdk.Rectangle allocation = force_capture_drawingarea.Allocation;
+ if(force_capture_pixmap == null || force_capture_sizeChanged ||
+ allocation.Width != force_capture_allocationXOld) {
+ force_capture_pixmap = new Gdk.Pixmap (force_capture_drawingarea.GdkWindow,
+ allocation.Width, allocation.Height, -1);
+
+ if(forceCaptureThread != null) //&& capturingCsharp ==
encoderCaptureProcess.CAPTURING)
+ fscPoints.NumPainted = -1; //mark meaning screen should be erased and start
painting from the beginning
+ else
+ UtilGtk.ErasePaint(force_capture_drawingarea, force_capture_pixmap);
+
+ force_capture_sizeChanged = false;
+ }
+
+ Gdk.Rectangle area = args.Event.Area;
+
+ //sometimes this is called when paint is finished
+ //don't let this erase win
+ if(force_capture_pixmap != null) {
+ args.Event.Window.DrawDrawable(force_capture_drawingarea.Style.WhiteGC,
force_capture_pixmap,
+ area.X, area.Y,
+ area.X, area.Y,
+ area.Width, area.Height);
+ }
+
+ force_capture_allocationXOld = allocation.Width;
+ }
+
+
private void on_button_force_sensor_graph_clicked (object o, EventArgs args)
{
Gtk.FileChooserDialog filechooser = new Gtk.FileChooserDialog ("Choose file",
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]