;; magic.el - a utility for plotting friction functions. ;; ;; Copyright (C) 2003 Sam Varner ;; ;; This file is part of Vamos Automotive Simulator. ;; ;; This program is free software; you can redistribute it and/or modify ;; it under the terms of the GNU General Public License as published by ;; the Free Software Foundation; either version 2 of the License, or ;; (at your option) any later version. ;; ;; This program is distributed in the hope that it will be useful, ;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ;; GNU General Public License for more details. ;; ;; You should have received a copy of the GNU General Public License ;; along with this program; if not, write to the Free Software ;; Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA ;; The function `magic' is for use with car definition files used by ;; Vamos Automotive Simulator . The ;; Gnuplot plotting program is required. ;; ;; Open a file and place the point inside a friction parameter list ;; and call `magic'. Press 'x' to dismiss the Gnuplot window. ;; `magic' uses the values currently in the buffer; you don't need to ;; save the file between edits. Gnuplot is run as a synchonus ;; subprocess. So you need to dismiss the window before you can do ;; anything else in Emacs. (defvar magic-camber 0.0) ;; Camber angle in degrees (defvar magic-Fz 2.0) ;; Normal force in kN (defvar magic-longitudinal-range '(-50 50)) (defvar magic-transverse-range '(-50 50)) (defvar magic-aligning-range '(-50 50)) (defun magic-num (index lst) "Return the INDEXth item in the list LST as a number." (string-to-number (nth index lst))) (defun magic () "Plot the friction function for the parameters at point." (interactive) (save-excursion ;; Find the previous tag and remember its name. (re-search-backward "<\\(.*\\)>") (let ((type (buffer-substring (match-beginning 1) (match-end 1)))) ;; Find and split the coefficients. (re-search-forward "\\[[ \t]*\\(.*\\)[ \t]*\\]") (let* ((param (buffer-substring (match-beginning 1) (match-end 1))) (equation "") (coeff (split-string param "[ \t]*,[ \t]*")) (file "magic-eq")) ; should be a temporary file ;; Write the appropriate equation. (cond ((string= type "longitudinal") (setq equation (magic-write-longitudinal coeff))) ((string= type "transverse") (setq equation (magic-write-transverse coeff))) ((string= type "aligning") (setq equation (magic-write-aligning coeff))) (t (error "Point is not inside find friction parameter tag."))) (and (string= equation "") (error "Could not set equation")) ;; Write the equation to a file and call Gnuplot. (find-file file) (kill-region (point-min) (point-max)) (insert-string equation) (save-buffer) (kill-buffer (current-buffer)) (shell-command (concat "gnuplot -persist " file)))))) (defun magic-write-longitudinal (coeff) "Write the magic formula for longitudinal force." (let* ((Fz magic-Fz) (Fz2 (* magic-Fz magic-Fz)) (C (magic-num 0 coeff)) (D (+ (* (magic-num 1 coeff) Fz2) (* (magic-num 2 coeff) Fz))) (B (* (+ (* (magic-num 3 coeff) Fz2) (* (magic-num 4 coeff) Fz)) (exp (* -1 (magic-num 5 coeff) Fz)) (/ 1 (* C D)))) (E (+ (* (magic-num 6 coeff) Fz2) (* (magic-num 7 coeff) Fz) (magic-num 8 coeff))) (Sh (+ (* (magic-num 9 coeff) Fz) (magic-num 10 coeff)))) (format "plot [x=%f:%f] %f*sin (%f*atan(%f*(1 - %f)*(x + %f) + %f*atan(%f*(x + %f))))" (nth 0 magic-longitudinal-range) (nth 1 magic-longitudinal-range) D C B E Sh E B Sh))) (defun magic-write-transverse (coeff) "Write the magic formula for transverse force." (let* ((Fz magic-Fz) (Fz2 (* magic-Fz magic-Fz)) (C (magic-num 0 coeff)) (D (+ (* (magic-num 1 coeff) Fz2) (* (magic-num 2 coeff) Fz))) (B (* (magic-num 3 coeff) (sin (* 2 (atan (/ Fz (magic-num 4 coeff))))) (- 1 (* (magic-num 5 coeff) (abs magic-camber))) (/ 1 (* C D)))) (E (+ (* (magic-num 6 coeff) Fz) (magic-num 7 coeff))) (Sh (+ (* (magic-num 8 coeff) magic-camber) (* (magic-num 9 coeff) Fz) (magic-num 10 coeff))) (Sv (+ (* (+ (* (magic-num 11 coeff) Fz) (magic-num 12 coeff)) magic-camber Fz) (* (magic-num 13 coeff) Fz) (magic-num 14 coeff)))) (format "plot [x=%f:%f] %f*sin(%f*atan(%f*(1 - %f)*(x + %f) + %f*atan(%f*(x + %f)))) + %f" (nth 0 magic-transverse-range) (nth 1 magic-transverse-range) D C B E Sh E B Sh Sv))) (defun magic-write-aligning (coeff) "Write the magic formula for aligning torque." (let* ((Fz magic-Fz) (Fz2 (* magic-Fz magic-Fz)) (C (magic-num 0 coeff)) (D (+ (* (magic-num 1 coeff) Fz2) (* (magic-num 2 coeff) Fz))) (B (* (+ (* (magic-num 3 coeff) Fz2) (* (magic-num 4 coeff) Fz)) (- 1 (* (magic-num 6 coeff) (abs magic-camber))) (exp (* -1 (magic-num 5 coeff) Fz)) (/ 1 (* C D)))) (E (* (+ (* (magic-num 7 coeff) Fz2) (* (magic-num 8 coeff) Fz) (magic-num 9 coeff)) (- 1 (* (magic-num 10 coeff) (abs magic-camber))))) (Sh (+ (* (magic-num 11 coeff) magic-camber) (* (magic-num 12 coeff) Fz) (magic-num 13 coeff))) (Sv (+ (* (+ (* (magic-num 14 coeff) Fz2) (* (magic-num 15 coeff) Fz)) magic-camber) (* (magic-num 16 coeff) Fz) (magic-num 17 coeff)))) (format "plot [x=%f:%f] %f*sin(%f*atan(%f*(1 - %f)*(x + %f) + %f*atan(%f*(x + %f)))) + %f" (nth 0 magic-aligning-range) (nth 1 magic-aligning-range) D C B E Sh E B Sh Sv)))