Files
paparazzi/sw/tools/gen_flight_plan.ml
T
2013-03-26 00:15:46 +01:00

833 lines
28 KiB
OCaml

(*
* Flight plan preprocessing (from XML to C)
*
* Copyright (C) 2004-2008 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.
*
*)
open Printf
open Latlong
module G2D = Geometry_2d
(* From mapFP.ml to avoid complex linking *)
let georef_of_xml = fun xml ->
let lat0 = Latlong.deg_of_string (ExtXml.attrib xml "lat0")
and lon0 = Latlong.deg_of_string (ExtXml.attrib xml "lon0") in
{ posn_lat = (Deg>>Rad)lat0; posn_long = (Deg>>Rad)lon0 }
let sof = string_of_float
let soi = string_of_int
let check_expressions = ref false
let cm = fun x -> 100. *. x
let parse = fun s ->
let e = Fp_proc.parse_expression s in
if !check_expressions then begin
let unexpected = fun kind x ->
fprintf stderr "Parsing error in '%s': unexpected %s: '%s' \n" s kind x;
exit 1 in
begin
try
Expr_syntax.check_expression e
with
Expr_syntax.Unknown_operator x -> unexpected "operator" x
| Expr_syntax.Unknown_ident x -> unexpected "ident" x
| Expr_syntax.Unknown_function x -> unexpected "function" x
end
end;
Expr_syntax.sprint e
let parsed_attrib = fun xml a ->
parse (ExtXml.attrib xml a)
let gen_label =
let x = ref 0 in
fun p -> incr x; sprintf "%s_%d" p !x
(** Formatting with a margin *)
let margin = ref 0
let step = 2
let right () = margin := !margin + step
let left () = margin := !margin - step
let lprintf = fun f ->
printf "%s" (String.make !margin ' ');
printf f
let float_attrib = fun xml a ->
try
float_of_string (Xml.attrib xml a)
with
Failure "float_of_string" ->
failwith (sprintf "Float expected in attribute '%s' from %s" a (Xml.to_string_fmt xml))
let name_of = fun wp -> ExtXml.attrib wp "name"
let ground_alt = ref 0.
let security_height = ref 0.
let check_altitude = fun a x ->
if a < !ground_alt +. !security_height then begin
fprintf stderr "\nWarning: low altitude (%.0f<%.0f+%.0f) in %s\n\n" a !ground_alt !security_height (Xml.to_string x)
end
(** Computes "x" and "y" attributes if "lat" and "lon" are available *)
let localize_waypoint = fun rel_utm_of_wgs84 waypoint ->
try
let (x, y) =
rel_utm_of_wgs84
(Latlong.make_geo_deg
(Latlong.deg_of_string (Xml.attrib waypoint "lat"))
(Latlong.deg_of_string (Xml.attrib waypoint "lon"))) in
let x = sprintf "%.2f" x and y = sprintf "%.2f" y in
ExtXml.subst_attrib "y" y (ExtXml.subst_attrib "x" x waypoint)
with
Xml.No_attribute "lat" | Xml.No_attribute "lon" ->
waypoint
let print_waypoint = fun default_alt waypoint ->
let (x, y) = (float_attrib waypoint "x", float_attrib waypoint "y")
and alt = try sof (float_attrib waypoint "height" +. !ground_alt) with _ -> default_alt in
let alt = try Xml.attrib waypoint "alt" with _ -> alt in
check_altitude (float_of_string alt) waypoint;
printf " {%.1f, %.1f, %s},\\\n" x y alt
let convert_angle = fun rad -> truncate (1e7 *. (Rad>>Deg)rad)
let print_waypoint_lla = fun utm0 default_alt waypoint ->
let x = float_attrib waypoint "x"
and y = float_attrib waypoint "y"
and alt = try Xml.attrib waypoint "alt" with _ -> default_alt in
let wgs84 = Latlong.of_utm Latlong.WGS84 (Latlong.utm_add utm0 (x, y)) in
printf " {%d, %d, %.0f}, /* 1e7deg, 1e7deg, cm (hmsl=%.2fm) */ \\\n" (convert_angle wgs84.posn_lat) (convert_angle wgs84.posn_long) (100. *. float_of_string alt) (Egm96.of_wgs84 wgs84)
let index_of_blocks = ref []
let get_index_block = fun x ->
try
List.assoc x !index_of_blocks
with
Not_found -> failwith (sprintf "Unknown block: '%s'" x)
let print_exception = fun x ->
let i = get_index_block (ExtXml.attrib x "deroute") in
let c = parsed_attrib x "cond" in
lprintf "if ((nav_block != %d) && %s) { GotoBlock(%d); return; }\n" i c i
let element = fun a b c -> Xml.Element (a, b, c)
let goto l = element "goto" ["name",l] []
let exit_block = element "exit_block" [] []
let home_block = Xml.parse_string "<block name=\"HOME\"><home/></block>"
let stage = ref 0
let output_label l = lprintf "Label(%s)\n" l
let get_index_waypoint = fun x l ->
try
string_of_int (List.assoc x l)
with
Not_found -> failwith (sprintf "Unknown waypoint: %s" x)
let pprz_throttle = fun s ->
begin
try
let g = float_of_string s in
if g < 0. || g > 1. then
failwith "throttle must be > 0 and < 1"
with
Failure "float_of_string" -> () (* No possible check on expression *)
end;
sprintf "9600*(%s)" s
(********************* Vertical control ********************************************)
let output_vmode = fun stage_xml wp last_wp ->
let pitch = try Xml.attrib stage_xml "pitch" with _ -> "0.0" in
if pitch = "auto"
then begin
lprintf "NavVerticalAutoPitchMode(%s);\n" (pprz_throttle (parsed_attrib stage_xml "throttle"))
end else begin
lprintf "NavVerticalAutoThrottleMode(RadOfDeg(%s));\n" (parse pitch);
end;
let vmode = try ExtXml.attrib stage_xml "vmode" with _ -> "alt" in
begin
match vmode with
"climb" ->
lprintf "NavVerticalClimbMode(%s);\n" (parsed_attrib stage_xml "climb")
| "alt" ->
let alt =
try
let a = parsed_attrib stage_xml "alt" in
begin
try
check_altitude (float_of_string a) stage_xml
with
(* Impossible to check the altitude on an expression: *)
Failure "float_of_string" -> ()
end;
a
with _ ->
try
let h = parsed_attrib stage_xml "height" in
begin
try
check_altitude ((float_of_string h) +. !ground_alt) stage_xml
with
(* Impossible to check the altitude on an expression: *)
Failure "float_of_string" -> ()
end;
sprintf "Height(%s)" h
with _ ->
if wp = ""
then failwith "alt or waypoint required in alt vmode"
else sprintf "WaypointAlt(%s)" wp in
lprintf "NavVerticalAltitudeMode(%s, 0.);\n" alt;
| "xyz" -> () (** Handled in Goto3D() *)
| "glide" ->
lprintf "NavGlide(%s, %s);\n" last_wp wp
| "throttle" ->
if (pitch = "auto") then
failwith "auto pich mode not compatible with vmode=throttle";
lprintf "NavVerticalThrottleMode(%s);\n" (pprz_throttle (parsed_attrib stage_xml "throttle"))
| x -> failwith (sprintf "Unknown vmode '%s'" x)
end;
vmode
(****************** Horizontal control *********************************************)
let output_hmode x wp last_wp =
try
let hmode = ExtXml.attrib x "hmode" in
begin
match hmode with
"route" ->
if last_wp = "last_wp" then
fprintf stderr "Warning: Deprecated use of 'route' using last waypoint in %s\n"(Xml.to_string x);
lprintf "NavSegment(%s, %s);\n" last_wp wp
| "direct" -> lprintf "NavGotoWaypoint(%s);\n" wp
| x -> failwith (sprintf "Unknown hmode '%s'" x)
end;
hmode
with
ExtXml.Error _ -> lprintf "NavGotoWaypoint(%s);\n" wp; "direct" (* Default behaviour *)
let rec index_stage = fun x ->
begin
match Xml.tag x with
"for" ->
incr stage; (* Init of i *)
incr stage;
let n = !stage in
let l = List.map index_stage (Xml.children x) in
incr stage; (* To count the loop stage *)
Xml.Element (Xml.tag x, Xml.attribs x@["no", soi n], l)
| "while" ->
incr stage;
let n = !stage in
let l = List.map index_stage (Xml.children x) in
incr stage; (* To count the loop stage *)
Xml.Element (Xml.tag x, Xml.attribs x@["no", soi n], l)
| "return" | "goto" | "deroute" | "exit_block" | "follow" | "call" | "home"
| "heading" | "attitude" | "go" | "stay" | "xyz" | "set" | "circle" ->
incr stage;
Xml.Element (Xml.tag x, Xml.attribs x@["no", soi !stage], Xml.children x)
| "survey_rectangle" | "eight" | "oval"->
incr stage; incr stage;
Xml.Element (Xml.tag x, Xml.attribs x@["no", soi !stage], Xml.children x)
| "exception" ->
x
| s -> failwith (sprintf "Unknown stage: %s\n" s)
end
let inside_function = fun name -> "Inside" ^ String.capitalize name
let rec print_stage = fun index_of_waypoints x ->
let stage () = incr stage;lprintf "Stage(%d)\n" !stage; right () in
begin
match String.lowercase (Xml.tag x) with
"return" ->
stage ();
lprintf "Return()\n";
lprintf "break\n";
| "goto" ->
stage ();
lprintf "Goto(%s)\n" (name_of x)
| "deroute" ->
stage ();
lprintf "GotoBlock(%d);\n" (get_index_block (ExtXml.attrib x "block"));
lprintf "break;\n"
| "exit_block" ->
lprintf "default:\n";
stage ();
lprintf "NextBlock();\n";
lprintf "break;\n"
| "while" ->
let w = gen_label "while" in
let e = gen_label "endwhile" in
output_label w;
stage ();
let c = try parsed_attrib x "cond" with _ -> "TRUE" in
lprintf "if (! (%s)) Goto(%s) else NextStageAndBreak();\n" c e;
List.iter (print_stage index_of_waypoints) (Xml.children x);
print_stage index_of_waypoints (goto w);
output_label e
| "for" ->
let f = gen_label "for" in
let e = gen_label "endfor" in
let v = Expr_syntax.c_var_of_ident (ExtXml.attrib x "var")
and from_ = parsed_attrib x "from"
and to_expr = parsed_attrib x "to" in
let to_var = v ^ "_to" in
lprintf "static int8_t %s;\n" v;
lprintf "static int8_t %s;\n" to_var;
(* init *)
stage ();
lprintf "%s = %s - 1;\n" v from_;
lprintf "%s = %s;\n" to_var to_expr;
left ();
output_label f;
stage ();
lprintf "if (++%s > %s) Goto(%s) else NextStageAndBreak();\n" v to_var e;
List.iter (print_stage index_of_waypoints) (Xml.children x);
print_stage index_of_waypoints (goto f);
output_label e
| "heading" ->
stage ();
let until = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak() else {\n" until;
right ();
lprintf "NavHeading(RadOfDeg(%s));\n" (parsed_attrib x "course");
ignore (output_vmode x "" "");
left (); lprintf "}\n";
lprintf "break;\n"
| "follow" ->
stage ();
let id = ExtXml.attrib x "ac_id"
and d = ExtXml.attrib x "distance"
and h = ExtXml.attrib x "height" in
lprintf "NavFollow(%s, %s, %s);\n" id d h;
lprintf "break;\n"
| "attitude" ->
stage ();
begin
try
let until = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak() else {\n" until;
with ExtXml.Error _ ->
lprintf "{\n"
end;
right ();
lprintf "NavAttitude(RadOfDeg(%s));\n" (parsed_attrib x "roll");
ignore (output_vmode x "" "");
left (); lprintf "}\n";
lprintf "break;\n"
| "go" ->
stage ();
let wp =
try
get_index_waypoint (ExtXml.attrib x "wp") index_of_waypoints
with
ExtXml.Error _ ->
lprintf "waypoints[0].x = %s;\n" (parsed_attrib x "x");
lprintf "waypoints[0].y = %s;\n" (parsed_attrib x "y");
"0"
in
let at = try ExtXml.attrib x "approaching_time" with _ -> "CARROT" in
let last_wp =
try
get_index_waypoint (ExtXml.attrib x "from") index_of_waypoints
with ExtXml.Error _ -> "last_wp" in
if last_wp = "last_wp" then
lprintf "if (NavApproaching(%s,%s)) NextStageAndBreakFrom(%s) else {\n" wp at wp
else
lprintf "if (NavApproachingFrom(%s,%s,%s)) NextStageAndBreakFrom(%s) else {\n" wp last_wp at wp;
right ();
let hmode = output_hmode x wp last_wp in
let vmode = output_vmode x wp last_wp in
if vmode = "glide" && hmode <> "route" then
failwith "glide vmode requires route hmode";
left (); lprintf "}\n";
begin
try
let c = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak();\n" c
with
ExtXml.Error _ -> ()
end;
lprintf "break;\n"
| "stay" ->
stage ();
begin
try
let wp = get_index_waypoint (ExtXml.attrib x "wp") index_of_waypoints in
ignore (output_hmode x wp "");
ignore (output_vmode x wp "");
with
Xml2h.Error _ ->
lprintf "NavGotoXY(last_x, last_y);\n";
ignore(output_vmode x "" "")
end;
begin
try
let c = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak();\n" c
with
ExtXml.Error _ -> ()
end;
lprintf "break;\n"
| "xyz" ->
stage ();
let r = try parsed_attrib x "radius" with _ -> "100" in
lprintf "Goto3D(%s)\n" r;
let x = ExtXml.subst_attrib "vmode" "xyz" x in
ignore (output_vmode x "" ""); (** To handle "pitch" *)
lprintf "break;\n"
| "home" ->
stage ();
lprintf "nav_home();\n";
lprintf "break;\n"
| "circle" ->
stage ();
let wp = get_index_waypoint (ExtXml.attrib x "wp") index_of_waypoints in
let r = parsed_attrib x "radius" in
let _vmode = output_vmode x wp "" in
lprintf "NavCircleWaypoint(%s, %s);\n" wp r;
begin
try
let c = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak();\n" c
with
ExtXml.Error _ -> ()
end;
lprintf "break;\n"
| "eight" ->
stage ();
lprintf "nav_eight_init();\n";
lprintf "NextStageAndBreak();\n";
left ();
stage ();
let center = get_index_waypoint (ExtXml.attrib x "center") index_of_waypoints
and turn_about = get_index_waypoint (ExtXml.attrib x "turn_around") index_of_waypoints in
let r = parsed_attrib x "radius" in
let _vmode = output_vmode x center "" in
lprintf "Eight(%s, %s, %s);\n" center turn_about r;
begin
try
let c = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak();\n" c
with
ExtXml.Error _ -> ()
end;
lprintf "break;\n"
| "oval" ->
stage ();
lprintf "nav_oval_init();\n";
lprintf "NextStageAndBreak();\n";
left ();
stage ();
let p1 = get_index_waypoint (ExtXml.attrib x "p1") index_of_waypoints
and p2 = get_index_waypoint (ExtXml.attrib x "p2") index_of_waypoints in
let r = parsed_attrib x "radius" in
let _vmode = output_vmode x p1 "" in
lprintf "Oval(%s, %s, %s);\n" p1 p2 r;
begin
try
let c = parsed_attrib x "until" in
lprintf "if (%s) NextStageAndBreak();\n" c
with
ExtXml.Error _ -> ()
end;
lprintf "break;\n"
| "set" ->
stage ();
let var = ExtXml.attrib x "var"
and value = parsed_attrib x "value" in
lprintf "%s = %s;\n" var value;
lprintf "NextStageAndBreak();\n";
lprintf "break;\n"
| "call" ->
stage ();
let statement = ExtXml.attrib x "fun" in
lprintf "if (! (%s))\n" statement;
lprintf " NextStageAndBreak();\n";
lprintf "break;\n"
| "survey_rectangle" ->
let grid = parsed_attrib x "grid"
and wp1 = get_index_waypoint (ExtXml.attrib x "wp1") index_of_waypoints
and wp2 = get_index_waypoint (ExtXml.attrib x "wp2") index_of_waypoints
and orientation = ExtXml.attrib_or_default x "orientation" "NS" in
stage ();
if orientation <> "NS" && orientation <> "WE" then
failwith (sprintf "Unknown survey orientation (NS or WE): %s" orientation);
lprintf "NavSurveyRectangleInit(%s, %s, %s, %s);\n" wp1 wp2 grid orientation;
lprintf "NextStageAndBreak();\n";
left ();
stage ();
lprintf "NavSurveyRectangle(%s, %s);\n" wp1 wp2;
lprintf "break;\n"
| _s -> failwith "Unreachable"
end;
left ()
let indexed_stages = fun blocks ->
let lstages = ref [] in
List.iter
(fun b ->
let block_name = name_of b
and block_no = ExtXml.attrib b "no" in
let rec f = fun stage ->
try
let stage_no = Xml.attrib stage "no" in
lstages :=
Xml.Element ("stage", [ "block", block_no;
"block_name", block_name;
"stage", stage_no], [stage]):: !lstages;
if (ExtXml.tag_is stage "for" || ExtXml.tag_is stage "while") then
List.iter f (Xml.children stage)
with Xml.No_attribute "no" ->
assert (ExtXml.tag_is stage "exception")
in
List.iter f (Xml.children b))
blocks;
!lstages
let index_blocks = fun xml ->
let block = ref (-1) in
let indexed_blocks =
List.map
(fun b ->
incr block;
let name = name_of b in
if List.mem_assoc name !index_of_blocks then
failwith (Printf.sprintf "Error in flight plan: Block '%s' defined twice" name);
index_of_blocks := (name, !block) :: !index_of_blocks;
stage := -1;
let indexed_stages = List.map index_stage (Xml.children b) in
Xml.Element (Xml.tag b, Xml.attribs b@["no", soi !block], indexed_stages))
(Xml.children xml) in
Xml.Element (Xml.tag xml, Xml.attribs xml, indexed_blocks)
let print_block = fun index_of_waypoints (b:Xml.xml) block_num ->
let n = name_of b in
(* Block entry *)
lprintf "Block(%d) // %s\n" block_num n;
lprintf "%s; // pre_call\n" (ExtXml.attrib_or_default b "pre_call" "");
let excpts, stages =
List.partition (fun x -> Xml.tag x = "exception") (Xml.children b) in
List.iter print_exception excpts;
lprintf "switch(nav_stage) {\n";
right ();
stage := (-1);
List.iter (print_stage index_of_waypoints) stages;
print_stage index_of_waypoints exit_block;
left ();
lprintf "}\n";
(* Block exit *)
lprintf "%s; // post_call\n" (ExtXml.attrib_or_default b "post_call" "");
lprintf "break;\n\n"
let print_blocks = fun index_of_waypoints bs ->
let block = ref (-1) in
List.iter (fun b -> incr block; print_block index_of_waypoints b !block) bs
let c_suffix =
let r = Str.regexp "^[a-zA-Z0-9_]*$" in
fun s -> Str.string_match r s 0
let define_waypoints_indices = fun wpts ->
let i = ref 0 in
List.iter (fun w ->
let n = name_of w in
if c_suffix n then
Xml2h.define (sprintf "WP_%s" n) (string_of_int !i);
incr i)
wpts
let home = fun waypoints ->
let rec loop i = function
[] -> failwith "Waypoint 'HOME' required"
| w::ws ->
if name_of w = "HOME" then
(float_attrib w "x", float_attrib w "y")
else
loop (i+1) ws in
loop 0 waypoints
let check_distance = fun (hx, hy) max_d wp ->
let x = float_attrib wp "x"
and y = float_attrib wp "y" in
let d = sqrt ((x-.hx)**2. +. (y-.hy)**2.) in
if d > max_d then
fprintf stderr "\nWarning: Waypoint '%s' too far from HOME (%.0f>%.0f)\n\n" (name_of wp) d max_d
(* Check coherence between global ref and waypoints ref *)
(* Returns a patched xml with utm_x0 and utm_y0 set *)
let check_geo_ref = fun wgs84 xml ->
let get_float = fun x -> float_attrib xml x in
let utm0 = utm_of WGS84 wgs84 in
let max_d = min 1000. (get_float "max_dist_from_home") in
let check_zone = fun u ->
if (utm_of WGS84 (of_utm WGS84 u)).utm_zone <> utm0.utm_zone then
prerr_endline "Warning: You are close (less than twice the max distance) to an UTM zone border ! The navigation will not work unless the GPS_USE_LATLONG flag is set and the GPS receiver configured to send the POSLLH message." in
check_zone { utm0 with utm_x = utm0.utm_x +. 2.*.max_d };
check_zone { utm0 with utm_x = utm0.utm_x -. 2.*.max_d };
let wpts = ExtXml.child xml "waypoints" in
let wpts = ExtXml.subst_attrib "utm_x0" (sof utm0.utm_x) wpts in
let wpts = ExtXml.subst_attrib "utm_y0" (sof utm0.utm_y) wpts in
let x = ExtXml.subst_child "waypoints" wpts xml in
x
let dummy_waypoint =
Xml.Element ("waypoint",
["name", "dummy";
"x", "42.";
"y", "42." ],
[])
let print_inside_polygon = fun pts ->
let layers = Geometry_2d.slice_polygon (Array.of_list pts) in
let rec f = fun i j ->
if i = j then
let {G2D.top=yl; left_side=(xg, ag); right_side=(xd, ad)} = layers.(i) in
if xg > xd then begin
lprintf "return FALSE;\n"
end else begin
if ad <> 0. || ag <> 0. then
lprintf "float dy = _y - %.1f;\n" yl;
let dy_times = fun f -> if f = 0. then "" else sprintf "+dy*%f" f in
lprintf "return (%.1f%s<= _x && _x <= %.1f%s);\n" xg (dy_times ag) xd (dy_times ad)
end
else
let ij2 = (i+j) / 2 in
let yl = layers.(ij2).G2D.top in
lprintf "if (_y <= %.1f) {\n" yl;
right (); f i ij2; left ();
lprintf "} else {\n";
right (); f (ij2+1) j; left ();
lprintf "}\n"
in
f 0 (Array.length layers - 1);;
let print_inside_sector = fun (s, pts) ->
lprintf "static inline bool_t %s(float _x, float _y) { \\\n" (inside_function s);
right ();
print_inside_polygon pts;
left ();
lprintf "}\n"
let parse_wpt_sector = fun waypoints xml ->
let sector_name = ExtXml.attrib xml "name" in
let p2D_of = fun x ->
let name = name_of x in
try
let wp = List.find (fun wp -> name_of wp = name) waypoints in
let x = float_attrib wp "x"
and y = float_attrib wp "y" in
{G2D.x2D = x; G2D.y2D = y }
with
Not_found -> failwith (sprintf "Error: corner '%s' of sector '%s' not found" name sector_name)
in
(sector_name, List.map p2D_of (Xml.children xml))
(************************** MAIN ******************************************)
let () =
let xml_file = ref "fligh_plan.xml"
and dump = ref false in
Arg.parse [ ("-check", Arg.Set check_expressions, "Enable expression checking");
("-dump", Arg.Set dump, "Dump compile result") ]
(fun f -> xml_file := f)
"Usage:";
if !xml_file = "" then
failwith (sprintf "Usage: %s <xml-flight-plan-file>" Sys.argv.(0));
try
let xml = ExtXml.parse_file !xml_file in
let wgs84 = georef_of_xml xml in
let xml = check_geo_ref wgs84 xml in
let dir = Filename.dirname !xml_file in
let xml = Fp_proc.process_includes dir xml in
let xml = Fp_proc.process_paths xml in
let xml = Fp_proc.process_relative_waypoints xml in
(* Add a safety last HOME block *)
let blocks = Xml.children (ExtXml.child xml "blocks") @ [home_block] in
let xml = ExtXml.subst_child "blocks" (index_blocks (element "blocks" [] blocks)) xml in
let waypoints = Xml.children (ExtXml.child xml "waypoints")
and blocks = Xml.children (ExtXml.child xml "blocks")
and global_exceptions = try Xml.children (ExtXml.child xml "exceptions") with _ -> [] in
let utm0 = utm_of WGS84 wgs84 in
let rel_utm_of_wgs84 = fun wgs84 ->
let utm = utm_of WGS84 wgs84 in
(utm.utm_x -. utm0.utm_x, utm.utm_y -. utm0.utm_y) in
let waypoints =
List.map (localize_waypoint rel_utm_of_wgs84) waypoints in
let xml = ExtXml.subst_child "waypoints" (element "waypoints" [] waypoints) xml in
if !dump then
let xml_stages = Xml.Element ("stages", [], indexed_stages blocks) in
let dump_xml = Xml.Element ("dump", [], [xml; xml_stages]) in
printf "%s\n" (ExtXml.to_string_fmt dump_xml)
else begin
let h_name = "FLIGHT_PLAN_H" in
printf "/* This file has been generated from %s */\n" !xml_file;
printf "/* Please DO NOT EDIT */\n\n";
printf "#ifndef %s\n" h_name;
Xml2h.define h_name "";
printf "\n";
printf "#include \"std.h\"\n";
printf "#include \"generated/modules.h\"\n";
begin
try
let header = ExtXml.child (ExtXml.child xml "header") "0" in
printf "%s\n" (Xml.pcdata header)
with _ -> ()
end;
let name = ExtXml.attrib xml "name" in
Xml2h.warning ("FLIGHT PLAN: "^name);
Xml2h.define_string "FLIGHT_PLAN_NAME" name;
let get_float = fun x -> float_attrib xml x in
let qfu = try get_float "qfu" with Xml.No_attribute "qfu" -> 0.
and mdfh = get_float "max_dist_from_home"
and alt = ExtXml.attrib xml "alt" in
security_height := get_float "security_height";
ground_alt := get_float "ground_alt";
let home_mode_height = try
max (get_float "home_mode_height") !security_height
with _ -> !security_height in
check_altitude (float_of_string alt) xml;
Xml2h.define "NAV_UTM_EAST0" (sprintf "%.0f" utm0.utm_x);
Xml2h.define "NAV_UTM_NORTH0" (sprintf "%.0f" utm0.utm_y);
Xml2h.define "NAV_UTM_ZONE0" (sprintf "%d" utm0.utm_zone);
Xml2h.define "NAV_LAT0" (sprintf "%d /* 1e7deg */" (convert_angle wgs84.posn_lat));
Xml2h.define "NAV_LON0" (sprintf "%d /* 1e7deg */" (convert_angle wgs84.posn_long));
Xml2h.define "NAV_ALT0" (sprintf "%.0f /* mm above msl */" (1000. *. !ground_alt));
Xml2h.define "NAV_MSL0" (sprintf "%.0f /* mm, EGM96 geoid-height (msl) over ellipsoid */" (1000. *. Egm96.of_wgs84 wgs84));
Xml2h.define "QFU" (sprintf "%.1f" qfu);
let waypoints = dummy_waypoint :: waypoints in
let (hx, hy) = home waypoints in
List.iter (check_distance (hx, hy) mdfh) waypoints;
define_waypoints_indices waypoints;
Xml2h.define "WAYPOINTS" "{ \\";
List.iter (print_waypoint alt) waypoints;
lprintf "};\n";
Xml2h.define "WAYPOINTS_LLA" "{ \\";
List.iter (print_waypoint_lla utm0 alt) waypoints;
lprintf "};\n";
Xml2h.define "NB_WAYPOINT" (string_of_int (List.length waypoints));
Xml2h.define "NB_BLOCK" (string_of_int (List.length blocks));
Xml2h.define "GROUND_ALT" (sof !ground_alt);
Xml2h.define "GROUND_ALT_CM" (sprintf "%.0f" (100.*. !ground_alt));
Xml2h.define "SECURITY_HEIGHT" (sof !security_height);
Xml2h.define "SECURITY_ALT" (sof (!security_height +. !ground_alt));
Xml2h.define "HOME_MODE_HEIGHT" (sof home_mode_height);
Xml2h.define "MAX_DIST_FROM_HOME" (sof mdfh);
let index_of_waypoints =
let i = ref (-1) in
List.map (fun w -> incr i; (name_of w, !i)) waypoints in
let sectors_element = try ExtXml.child xml "sectors" with Not_found -> Xml.Element ("", [], []) in
let sectors = List.filter (fun x -> String.lowercase (Xml.tag x) = "sector") (Xml.children sectors_element) in
let sectors = List.map (parse_wpt_sector waypoints) sectors in
List.iter print_inside_sector sectors;
lprintf "#ifdef NAV_C\n";
lprintf "\nstatic inline void auto_nav(void) {\n";
right ();
List.iter print_exception global_exceptions;
lprintf "switch (nav_block) {\n";
right ();
print_blocks index_of_waypoints blocks;
lprintf "default: break;\n";
left ();
lprintf "}\n";
left ();
lprintf "}\n";
lprintf "#endif // NAV_C\n";
begin
try
let airspace = Xml.attrib xml "airspace" in
lprintf "#define InAirspace(_x, _y) %s(_x, _y)\n" (inside_function airspace)
with
_ -> ()
end;
Xml2h.finish h_name
end
with
Failure x ->
fprintf stderr "%s: %s\n" !xml_file x; exit 1