Razor 9DOF IMU/Clojure
Something I put together to visualize the data coming from a Razor 9DOF IMU, in case I need it later.
(ns razor.core
(:import (java.awt Color Dimension Font BasicStroke)
(java.awt.event WindowListener)
(javax.swing JFrame JPanel)
(java.text DecimalFormat)
(org.jfree.chart ChartPanel JFreeChart)
(org.jfree.chart.plot CompassPlot)
(org.jfree.data.general DefaultValueDataset)
(org.jfree.chart.plot.dial DialPlot StandardDialFrame
StandardDialScale DialPointer$Pointer
DialValueIndicator DialBackground DialCap)
(java.io BufferedReader InputStreamReader)
(gnu.io SerialPort CommPortIdentifier
SerialPortEventListener SerialPortEvent)))
(defn razor [dev]
(let [state (atom [0 0 0])
id (first
(filter #(= dev (.getName %))
(enumeration-seq (CommPortIdentifier/getPortIdentifiers))))
port (doto (.open id "clojure" 1)
(.setSerialPortParams 57600
SerialPort/DATABITS_8
SerialPort/STOPBITS_1
SerialPort/PARITY_NONE))
stream (.getInputStream port)
reader (BufferedReader. (InputStreamReader. stream))
parser (fn [_ line]
(map read-string (.split (.replaceAll line "!ANG:" "") ",")))
listener (proxy [SerialPortEventListener] []
(serialEvent
[event]
(if (= (.getEventType event) SerialPortEvent/DATA_AVAILABLE)
(while (pos? (.available stream))
(swap! state parser (.readLine reader))))))]
(.addEventListener port listener)
(.notifyOnDataAvailable port true)
[port state]))
(defn dial [name dataset min max]
(let [dial-frame (doto (StandardDialFrame.)
(.setBackgroundPaint Color/LIGHT_GRAY)
(.setStroke (BasicStroke. 2)))
scale (doto (StandardDialScale. min max 300 300 30 4)
(.setMajorTickPaint Color/WHITE)
(.setMinorTickPaint Color/WHITE)
(.setTickLabelPaint Color/WHITE)
(.setTickLabelFont (Font. nil Font/BOLD 15))
(.setTickLabelFormatter (DecimalFormat. "# °"))
(.setTickRadius 0.9)
(.setTickLabelOffset 0.2))
pointer (doto (DialPointer$Pointer. 0)
(.setFillPaint Color/GRAY)
(.setOutlinePaint (Color. 0 true)))
indicator (doto (DialValueIndicator. 0)
(.setFont (Font. nil Font/BOLD 14))
(.setNumberFormat (DecimalFormat. "#.# °"))
(.setRadius 0.85)
(.setPaint Color/WHITE)
(.setOutlinePaint (Color. 0 true))
(.setBackgroundPaint (Color. 0 true)))
plot (doto (DialPlot. dataset)
(.setBackground (DialBackground. Color/DARK_GRAY))
(.setDialFrame dial-frame)
(.setCap (DialCap.))
(.addScale 0 scale)
(.mapDatasetToScale 0 0)
(.addPointer pointer)
(.addLayer indicator))]
(doto (ChartPanel.
(doto (JFreeChart. name JFreeChart/DEFAULT_TITLE_FONT plot false)
(.setBackgroundPaint (Color. 0x999999))))
(.setPreferredSize (Dimension. 300 300)))))
(defn compass [name dataset]
(let [plot (CompassPlot. dataset)]
(doto plot
(.setSeriesNeedle 0 5)
(.setSeriesPaint 0 Color/GRAY)
(.setSeriesOutlinePaint 0 Color/GRAY)
(.setRosePaint Color/DARK_GRAY)
(.setRoseCenterPaint Color/DARK_GRAY)
(.setRoseHighlightPaint Color/WHITE))
(doto (ChartPanel.
(doto (JFreeChart. name JFreeChart/DEFAULT_TITLE_FONT plot false)
(.setBackgroundPaint (Color. 0x999999))))
(.setPreferredSize (Dimension. 300 300)))))
(defn frame [dev]
(let [[port state] (razor dev)
pitch (DefaultValueDataset. 0.0)
yaw (DefaultValueDataset. 0.0)
roll (DefaultValueDataset. 0.0)]
(add-watch state "update-dials"
(fn [k r o n]
(let [[rl ph yw] n]
(.setValue roll (int rl))
(.setValue pitch (int ph))
(.setValue yaw yw))))
(doto (JFrame.)
(.add (doto (JPanel.)
(.setBackground (Color. 0x999999))
(.add (compass "Yaw" yaw))
(.add (dial "Roll" roll -180 180))
(.add (dial "Pitch" pitch -90 90))))
(.addWindowListener (proxy [WindowListener] []
(windowActivated [e])
(windowClosing [e]
(.close port))
(windowDeactivated [e])
(windowDeiconified [e])
(windowIconified [e])
(windowOpened [e])
(windowClosed [e])))
(.setTitle "Razor IMU")
(.pack)
(.setVisible true))))
(frame "/dev/tty.usbserial-A600e1hM")