Wind estimation

This commit is contained in:
Pascal Brisset
2005-09-12 05:35:43 +00:00
parent a17f4bce86
commit aa60f9350b
6 changed files with 284 additions and 10 deletions
+3 -1
View File
@@ -275,10 +275,12 @@
<message name="SELECTED_REQ" ID="6">
</message>
<message name="WIND_REQ" ID="7">
<message name="WIND_CLEAR" ID="7">
<field name="ac_id" type="string"/>
</message>
<message name="WIND" ID="8">
<field name="ac_id" type="string"/>
<field name="dir" type="float" unit="deg_wind"/>
<field name="speed" type="float" unit="m/s"/>
<field name="mean_aspeed" type="float" unit="m/s"/>
+1 -1
View File
@@ -11,7 +11,7 @@ all : map2d
map2d : map2d.ml
$(OCAMLC) -custom $(INCLUDES) $(LIBS) gtkInit.cmo $< -o $@ #to Check
cat ../../../pprz_src_test.sh > $@
echo 'exec lablgtk2 -I +camlimages ci_core.cma ci_png.cma ci_gif.cma ci_jpeg.cma ci_tiff.cma ci_bmp.cma ci_ppm.cma ci_ps.cma -I $$PAPARAZZI_SRC/sw/lib/ocaml glibivy-ocaml.cma lib-pprz.cma xlib-pprz.cma $$PAPARAZZI_SRC/sw/ground_segment/cockpit/$< $$*' >> $@
echo 'exec lablgtk2 lablgtk.cma -I +camlimages ci_core.cma ci_png.cma ci_gif.cma ci_jpeg.cma ci_tiff.cma ci_bmp.cma ci_ppm.cma ci_ps.cma -I $$PAPARAZZI_SRC/sw/lib/ocaml glibivy-ocaml.cma lib-pprz.cma xlib-pprz.cma $$PAPARAZZI_SRC/sw/ground_segment/cockpit/$< $$*' >> $@
chmod a+x $@
+3 -3
View File
@@ -64,10 +64,10 @@ stereo_demod : ../multimon/multimon.cma stereo_demod.ml ../../lib/ocaml/lib-pprz
@echo 'exec lablgtk2 -I $$PAPARAZZI_SRC/sw/lib/ocaml -I $$PAPARAZZI_SRC/sw/ground_segment/multimon glibivy-ocaml.cma lib-pprz.cma -I $$PAPARAZZI_SRC/sw/ground_segment/tmtc $$PAPARAZZI_SRC/sw/ground_segment/multimon/multimon.cma $$PAPARAZZI_SRC/sw/ground_segment/tmtc/stereo_demod.ml $$*' >> $@
@chmod a+x $@
receive : receive.ml ../../lib/ocaml/lib-pprz.cma
$(OCAMLC) $(INCLUDES) -o $@ lablgtk.cma glibivy-ocaml.cma lib-pprz.cma $^
receive : wind.cmo receive.ml ../../lib/ocaml/lib-pprz.cma
$(OCAMLC) $(INCLUDES) -o $@.out lablgtk.cma glibivy-ocaml.cma lib-pprz.cma $^
@cat ../../../pprz_src_test.sh > $@
@echo 'exec lablgtk2 -I $$PAPARAZZI_SRC/sw/lib/ocaml glibivy-ocaml.cma lib-pprz.cma $$PAPARAZZI_SRC/sw/ground_segment/tmtc/receive.ml $$*' >> $@
@echo 'exec lablgtk2 -I $$PAPARAZZI_SRC/sw/lib/ocaml glibivy-ocaml.cma lib-pprz.cma -I $$PAPARAZZI_SRC/sw/ground_segment/tmtc $$PAPARAZZI_SRC/sw/ground_segment/tmtc/wind.cmo $$PAPARAZZI_SRC/sw/ground_segment/tmtc/receive.ml $$*' >> $@
@chmod a+x $@
+26 -3
View File
@@ -248,7 +248,9 @@ let log_and_parse = fun logging ac_name a msg values ->
a.course <- norm_course ((Deg>>Rad)(fvalue "course" /. 10.));
a.alt <- fvalue "alt" /. 100.;
a.climb <- fvalue "climb" /. 100.;
a.gps_mode <- check_index (ivalue "mode") gps_modes "GPS_MODE"
a.gps_mode <- check_index (ivalue "mode") gps_modes "GPS_MODE";
if a.gspeed > 3. then
Wind.update ac_name a.gspeed a.course
| "DESIRED" ->
a.desired_east <- fvalue "desired_x";
a.desired_north <- fvalue "desired_y";
@@ -416,6 +418,21 @@ let send_horiz_status = fun a ->
| UnknownHorizMode -> ()
let send_wind = fun a ->
let id = a.id in
try
let (wind_cap_deg, wind_polar, mean, stddev, nb_sample) = Wind.get id in
let vs =
["ac_id", Pprz.String id;
"dir", Pprz.Float wind_cap_deg;
"speed", Pprz.Float wind_polar;
"mean_aspeed", Pprz.Float mean;
"stddev", Pprz.Float stddev] in
Ground_Pprz.message_send my_id "WIND" vs
with
exc -> ()
let send_aircraft_msg = fun ac ->
try
let a = Hashtbl.find aircrafts ac in
@@ -473,7 +490,8 @@ let send_aircraft_msg = fun ac ->
send_fbw a;
send_infrared a;
send_svsinfo a;
send_horiz_status a
send_horiz_status a;
send_wind a
with
Not_found -> prerr_endline ac
| x -> prerr_endline (Printexc.to_string x)
@@ -509,11 +527,16 @@ let check_alerts = fun a ->
if a.bat < 9. then send "CATASTROPHIC"
else if a.bat < 10. then send "CRITIC"
else if a.bat < 10.5 then send "WARNING"
let wind_clear = fun _sender vs ->
Wind.clear (Pprz.string_assoc "ac_id" vs)
let register_aircraft = fun name a ->
Hashtbl.add aircrafts name a;
ignore (Glib.Timeout.add aircraft_msg_period (fun () -> send_aircraft_msg name; true));
ignore (Glib.Timeout.add aircraft_alerts_period (fun () -> check_alerts a; true))
ignore (Glib.Timeout.add aircraft_alerts_period (fun () -> check_alerts a; true));
Wind.new_ac name 1000;
ignore(Ground_Pprz.message_bind "WIND_CLEAR" wind_clear)
(** Identifying message from a A/C *)
+249
View File
@@ -0,0 +1,249 @@
(*
* $Id$
*
* Multi aircrafts receiver, logger and broadcaster
*
* Copyright (C) 2004 CENA/ENAC, Pascal Brisset, Antoine Drouin
*
* This file is part of paparazzi.
*
* paparazzi 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, or (at your option)
* any later version.
*
* paparazzi 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 paparazzi; see the file COPYING. If not, write to
* the Free Software Foundation, 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*
*)
(*
*
* Estimate wind by analysing aircrafts trajectories
*
* Author : Nicolas Barnier - barnier@recherche.enac.fr
*
*)
let debug = false
open Printf
let (//) = Filename.concat
let conf_xml = Xml.parse_file (Env.paparazzi_home // "conf" // "conf.xml")
open Geometry_2d
type point_val = {p : pt_2D; f : float}
type triangle = {a: point_val; b: point_val; c: point_val}
let bary t = barycenter [t.a.p; t.b.p; t.c.p]
let init w_init step f =
let pb = vect_add w_init {x2D = step; y2D = 0.}
and pc = vect_add w_init {x2D = 0.; y2D = step} in
{a = {p = w_init; f = f w_init};
b = {p = pb; f = f pb};
c = {p = pc; f = f pc}}
let shift pa fa t = {a = {p = pa; f = fa}; b = t.a; c = t.b}
let shiftpv pf t = shift pf.p pf.f t
let calcnew p b alpha = vect_add_mul_scal alpha b (vect_make b p)
let triangle_sort t =
let abc = [|t.a; t.b; t.c|] in
Array.sort (fun t1 t2 -> compare t2.f t1.f) abc;
{a = abc.(0); b = abc.(1); c = abc.(2)}
let norme2 p = p.x2D *. p.x2D +. p.y2D *. p.y2D
let simplex p fmax step max_iter precision =
let f x = -. (fmax x) in
let rec loop num_iter vs =
if num_iter < max_iter && norme2 (vect_make vs.a.p vs.c.p) > precision then begin
begin if debug then
let pa = cart2polar vs.a.p in
Printf.printf "%f %f %f\n" pa.theta2D pa.r2D (-. vs.a.f) end;
let vb = bary vs in
let vr = calcnew vs.c.p vb (-1.) in
let fvr = f vr in
let new_vs =
if fvr > vs.a.f then
let ve = calcnew vs.c.p vb (-2.) in
let fve = f ve in
if fve > fvr then shift ve fve vs
else shift vr fvr vs
else
let vc = calcnew vs.c.p vb 0.5 in
let fvc = f vc in
if fvc > vs.b.f || fvr > vs.b.f then
let v = if fvr > fvc then {p = vr; f = fvr} else {p = vc; f = fvc} in
if v.f <= vs.b.f then {vs with c = v}
else if v.f > vs.a.f then shiftpv v vs
else {vs with b = v; c = vs.b}
else
let vcb = calcnew vs.b.p vs.a.p 0.5
and vcc = calcnew vs.c.p vs.a.p 0.5 in
triangle_sort {vs with b = {p = vcb; f = f vcb}; c = {p = vcc; f = f vcc}} in
loop (num_iter + 1) new_vs end
else vs.a in
if debug then Printf.printf "%f %f %f\n" p.x2D p.y2D (fmax p);
let vs = init p step f in
let vs = triangle_sort vs in
loop 0 vs
let isotropic_mean wind speeds =
let n = Array.length speeds in
let air_speeds = Array.map (fun speed -> cart2polar (vect_sub speed wind)) speeds in
let weights =
Array.map
(fun air ->
let sum =
Array.fold_left
(fun acc airj ->
acc +. norm_angle_rad (abs_float (air.theta2D -. airj.theta2D)) /. m_pi)
0. air_speeds in
sum /. (float (n-1)))
air_speeds in
let mean = ref 0. in
for i = 0 to n-1 do
mean := !mean +. vect_norm (vect_sub speeds.(i) wind) *. weights.(i) done;
!mean /. float n
let isotropic_wind wind_init speeds precision =
let n = Array.length speeds in
let mean wind =
let air_speeds = Array.map (fun speed -> cart2polar (vect_sub speed wind)) speeds in
let weights =
Array.mapi
(fun i airi ->
let sum = ref 0. in
for j = 0 to n-1 do
if j <> i then
sum := !sum +.
norm_angle_rad (abs_float (airi.theta2D -. air_speeds.(j).theta2D)) /. m_pi
done;
!sum /. (float (n-1)))
air_speeds in
let sum_weights = Array.fold_left (+.) 0. weights in
let mean = ref 0. in
for i = 0 to n-1 do
mean := !mean +. vect_norm (vect_sub speeds.(i) wind) *. weights.(i) done;
(!mean /. sum_weights, sum_weights, weights) in
let nb_calls = ref 0 in
let cost wind =
incr nb_calls;
let (m, sum_weights, weights) = mean wind in
let sum = ref 0. in
for i = 0 to n-1 do
let err = weights.(i) *. (vect_norm (vect_sub speeds.(i) wind) -. m) in
sum := !sum +. err *. err done;
!sum /. sum_weights in
let step = 2. and max_iter = 100 in
let wind = simplex wind_init cost step max_iter precision in
if debug then Printf.printf "nb calls: %d\n" !nb_calls;
let (mean, _, _) = mean wind.p in
(wind.p, mean, wind.f)
(* val wind : Geometry_2d.pt_2D -> Geometry_2d.pt_2D array -> float
-> (Geometry_2d.pt_2Dfloat * float * float) *)
(** [wind wind_init speeds precision] returns the wind and air speed mean and std dev. *)
let wind wind_init speeds precision =
let mean wind =
let sum =
Array.fold_left (fun acc speed -> acc +. vect_norm (vect_sub speed wind)) 0. speeds in
sum /. float (Array.length speeds) in
let nb_calls = ref 0 in
let cost wind =
incr nb_calls;
let m = mean wind in
let sum =
Array.fold_left
(fun acc speed ->
let err = vect_norm (vect_sub speed wind) -. m in
acc +. err *. err)
0. speeds in
sum /. float (Array.length speeds) in
let step = 2. and max_iter = 100 in
let wind = simplex wind_init cost step max_iter precision in
if debug then Printf.printf "nb calls: %d\n" !nb_calls;
(wind.p, mean wind.p, wind.f)
type wind_ac =
{mutable speeds : Geometry_2d.pt_2D array;
mutable index : int;
mutable length : int;
mutable wind_init : Geometry_2d.pt_2D}
let h = Hashtbl.create 17
let create_wind_ac max_nb_sample =
{speeds = Array.create max_nb_sample {x2D=0.; y2D=0.} ; wind_init = null_vector; index = 0; length = 0}
let new_ac = fun id max_nb_sample ->
Hashtbl.add h id (create_wind_ac max_nb_sample)
let clear id =
let wind_ac = Hashtbl.find h id in
wind_ac.index <- 0;
wind_ac.length <- 0;
wind_ac.wind_init <- null_vector
let precision = 1e-3
let update = fun id r course ->
let theta = heading_of_to_angle_rad course in
let speed = polar2cart {r2D = r; theta2D = theta} in
let wind_ac = Hashtbl.find h id in
let i = wind_ac.index in
wind_ac.speeds.(i) <- speed;
let i' = i + 1 in
wind_ac.length <- max wind_ac.length i';
wind_ac.index <- i' mod (Array.length wind_ac.speeds)
let compute = fun compute_wind id ->
try
let wind_ac = Hashtbl.find h id in
let speeds = Array.sub wind_ac.speeds 0 wind_ac.length in
if Array.length speeds >= 3 then begin
let wind_init = wind_ac.wind_init in
let (wind, mean, stddev) = compute_wind wind_init speeds precision in
wind_ac.wind_init <- wind;
let wind_polar = cart2polar wind in
let wind_cap_deg = rad2deg (wind_dir_from_angle_rad wind_polar.theta2D) in
let nb_sample = Array.length speeds in
(wind_cap_deg, wind_polar.r2D, mean, stddev, nb_sample)
end else
failwith (Printf.sprintf "Wind.on_wind_compute: ac %s not enough data\n%!" id)
with Not_found ->
failwith (Printf.sprintf "Wind.on_wind_compute: ac %s unknown\n%!" id)
let get = fun id -> compute wind id
let get_iso = fun id -> compute isotropic_wind id
+2 -2
View File
@@ -56,8 +56,8 @@ let _ =
let world_values = fun () ->
let wind_dir_rad = Latlong.pi /. 2. -. (Deg>>Rad) wind_dir_adj#value in
let wind_east = wind_speed_adj#value *. cos wind_dir_rad
and wind_north = wind_speed_adj#value *. sin wind_dir_rad in
let wind_east = -. wind_speed_adj#value *. cos wind_dir_rad
and wind_north = -. wind_speed_adj#value *. sin wind_dir_rad in
[ "wind_east", Pprz.Float wind_east;
"wind_north", Pprz.Float wind_north;
"ir_contrast", Pprz.Float infrared_contrast_adj#value;