commit 5d5507bd2880f586feb22f09cacdf8b91ed57328 Author: 王闯 Date: Mon Aug 24 17:26:17 2026 +0800 迁移到dhxdl diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6518716 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +*.aux +*.fdb_latexmk +*.fls +*.log +*.pdf +*.synctex.gz +*.xdv +*.bbl +*.blg +!figs/*.pdf diff --git a/IEEEtran.cls b/IEEEtran.cls new file mode 100644 index 0000000..8e43e7c --- /dev/null +++ b/IEEEtran.cls @@ -0,0 +1,6343 @@ +%% +%% IEEEtran.cls 2015/08/26 version V1.8b +%% +%% This is the IEEEtran LaTeX class for authors of the Institute of +%% Electrical and Electronics Engineers (IEEE) Transactions journals and +%% conferences. +%% +%% Support sites: +%% http://www.michaelshell.org/tex/ieeetran/ +%% http://www.ctan.org/pkg/ieeetran +%% and +%% http://www.ieee.org/ +%% +%% Based on the original 1993 IEEEtran.cls, but with many bug fixes +%% and enhancements (from both JVH and MDS) over the 1996/7 version. +%% +%% +%% Contributors: +%% Gerry Murray (1993), Silvano Balemi (1993), +%% Jon Dixon (1996), Peter N"uchter (1996), +%% Juergen von Hagen (2000), and Michael Shell (2001-2014) +%% +%% +%% Copyright (c) 1993-2000 by Gerry Murray, Silvano Balemi, +%% Jon Dixon, Peter N"uchter, +%% Juergen von Hagen +%% and +%% Copyright (c) 2001-2015 by Michael Shell +%% +%% Current maintainer (V1.3 to V1.8b): Michael Shell +%% See: +%% http://www.michaelshell.org/ +%% for current contact information. +%% +%% Special thanks to Peter Wilson (CUA) and Donald Arseneau +%% for allowing the inclusion of the \@ifmtarg command +%% from their ifmtarg LaTeX package. +%% +%%************************************************************************* +%% Legal Notice: +%% This code is offered as-is without any warranty either expressed or +%% implied; without even the implied warranty of MERCHANTABILITY or +%% FITNESS FOR A PARTICULAR PURPOSE! +%% User assumes all risk. +%% In no event shall the IEEE or any contributor to this code be liable for +%% any damages or losses, including, but not limited to, incidental, +%% consequential, or any other damages, resulting from the use or misuse +%% of any information contained here. +%% +%% All comments are the opinions of their respective authors and are not +%% necessarily endorsed by the IEEE. +%% +%% This work is distributed under the LaTeX Project Public License (LPPL) +%% ( http://www.latex-project.org/ ) version 1.3, and may be freely used, +%% distributed and modified. A copy of the LPPL, version 1.3, is included +%% in the base LaTeX documentation of all distributions of LaTeX released +%% 2003/12/01 or later. +%% Retain all contribution notices and credits. +%% ** Modified files should be clearly indicated as such, including ** +%% ** renaming them and changing author support contact information. ** +%% +%% File list of work: IEEEtran.cls, IEEEtran_HOWTO.pdf, bare_adv.tex, +%% bare_conf.tex, bare_jrnl.tex, bare_conf_compsoc.tex, +%% bare_jrnl_compsoc.tex +%% +%% Major changes to the user interface should be indicated by an +%% increase in the version numbers. If a version is a beta, it will +%% be indicated with a BETA suffix, i.e., 1.4 BETA. +%% Small changes can be indicated by appending letters to the version +%% such as "IEEEtran_v14a.cls". +%% In all cases, \Providesclass, any \typeout messages to the user, +%% \IEEEtransversionmajor and \IEEEtransversionminor must reflect the +%% correct version information. +%% The changes should also be documented via source comments. +%%************************************************************************* +%% +% +% Available class options +% e.g., \documentclass[10pt,conference]{IEEEtran} +% +% *** choose only one from each category *** +% +% 9pt, 10pt, 11pt, 12pt +% Sets normal font size. The default is 10pt. +% +% conference, journal, technote, peerreview, peerreviewca +% determines format mode - conference papers, journal papers, +% correspondence papers (technotes), or peer review papers. The user +% should also select 9pt when using technote. peerreview is like +% journal mode, but provides for a single-column "cover" title page for +% anonymous peer review. The paper title (without the author names) is +% repeated at the top of the page after the cover page. For peer review +% papers, the \IEEEpeerreviewmaketitle command must be executed (will +% automatically be ignored for non-peerreview modes) at the place the +% cover page is to end, usually just after the abstract (keywords are +% not normally used with peer review papers). peerreviewca is like +% peerreview, but allows the author names to be entered and formatted +% as with conference mode so that author affiliation and contact +% information can be easily seen on the cover page. +% The default is journal. +% +% draft, draftcls, draftclsnofoot, final +% determines if paper is formatted as a widely spaced draft (for +% handwritten editor comments) or as a properly typeset final version. +% draftcls restricts draft mode to the class file while all other LaTeX +% packages (i.e., \usepackage{graphicx}) will behave as final - allows +% for a draft paper with visible figures, etc. draftclsnofoot is like +% draftcls, but does not display the date and the word "DRAFT" at the foot +% of the pages. If using one of the draft modes, the user will probably +% also want to select onecolumn. +% The default is final. +% +% letterpaper, a4paper, cspaper +% determines paper size: 8.5in X 11in, 210mm X 297mm or 7.875in X 10.75in. +% Changing the paper size in the standard journal and conference modes +% will not alter the typesetting of the document - only the margins will +% be affected. In particular, documents using the a4paper option will +% have reduced side margins (A4 is narrower than US letter) and a longer +% bottom margin (A4 is longer than US letter). For both cases, the top +% margins will be the same and the text will be horizontally centered. +% For the compsoc conference and draft modes, it is the margins that will +% remain constant, and thus the text area size will vary, with changes in +% the paper size. +% The cspaper option is the special ``trim'' paper size (7.875in x 10.75in) +% used in the actual publication of Computer Society journals. Under +% compsoc journal mode, this option does not alter the typesetting of the +% document. Authors should invoke the cspaper option only if requested to +% do so by the editors of the specific journal they are submitting to. +% For final submission to the IEEE, authors should generally use US letter +% (8.5 X 11in) paper unless otherwise instructed. Note that authors should +% ensure that all post-processing (ps, pdf, etc.) uses the same paper +% specificiation as the .tex document. Problems here are by far the number +% one reason for incorrect margins. IEEEtran will automatically set the +% default paper size under pdflatex (without requiring any change to +% pdftex.cfg), so this issue is more important to dvips users. Fix +% config.ps, config.pdf, or ~/.dvipsrc for dvips, or use the +% dvips -t papersize option instead as needed. For the cspaper option, +% the corresponding dvips paper name is "ieeecs". +% See the testflow documentation +% http://www.ctan.org/tex-archive/macros/latex/contrib/IEEEtran/testflow +% for more details on dvips paper size configuration. +% The default is letterpaper. +% +% oneside, twoside +% determines if layout follows single sided or two sided (duplex) +% printing. The only notable change is with the headings at the top of +% the pages. +% The default is oneside. +% +% onecolumn, twocolumn +% determines if text is organized into one or two columns per page. One +% column mode is usually used only with draft papers. +% The default is twocolumn. +% +% comsoc, compsoc, transmag +% Use the format of the IEEE Communications Society, IEEE Computer Society +% or IEEE Transactions on Magnetics, respectively. +% +% romanappendices +% Use the "Appendix I" convention when numbering appendices. IEEEtran.cls +% now defaults to Alpha "Appendix A" convention - the opposite of what +% v1.6b and earlier did. +% +% captionsoff +% disables the display of the figure/table captions. Some IEEE journals +% request that captions be removed and figures/tables be put on pages +% of their own at the end of an initial paper submission. The endfloat +% package can be used with this class option to achieve this format. +% +% nofonttune +% turns off tuning of the font interword spacing. Maybe useful to those +% not using the standard Times fonts or for those who have already "tuned" +% their fonts. +% The default is to enable IEEEtran to tune font parameters. +% +% +%---------- +% Available CLASSINPUTs provided (all are macros unless otherwise noted): +% \CLASSINPUTbaselinestretch +% \CLASSINPUTinnersidemargin +% \CLASSINPUToutersidemargin +% \CLASSINPUTtoptextmargin +% \CLASSINPUTbottomtextmargin +% +% Available CLASSINFOs provided: +% \ifCLASSINFOpdf (TeX if conditional) +% \CLASSINFOpaperwidth (macro) +% \CLASSINFOpaperheight (macro) +% \CLASSINFOnormalsizebaselineskip (length) +% \CLASSINFOnormalsizeunitybaselineskip (length) +% +% Available CLASSOPTIONs provided: +% all class option flags (TeX if conditionals) unless otherwise noted, +% e.g., \ifCLASSOPTIONcaptionsoff +% point size options provided as a single macro: +% \CLASSOPTIONpt +% which will be defined as 9, 10, 11, or 12 depending on the document's +% normalsize point size. +% also, class option peerreviewca implies the use of class option peerreview +% and classoption draft implies the use of class option draftcls + + + + + +\ProvidesClass{IEEEtran}[2015/08/26 V1.8b by Michael Shell] +\typeout{-- See the "IEEEtran_HOWTO" manual for usage information.} +\typeout{-- http://www.michaelshell.org/tex/ieeetran/} +\NeedsTeXFormat{LaTeX2e} + +% IEEEtran.cls version numbers, provided as of V1.3 +% These values serve as a way a .tex file can +% determine if the new features are provided. +% The version number of this IEEEtrans.cls can be obtained from +% these values. i.e., V1.4 +% KEEP THESE AS INTEGERS! i.e., NO {4a} or anything like that- +% (no need to enumerate "a" minor changes here) +\def\IEEEtransversionmajor{1} +\def\IEEEtransversionminor{8} + + +% hook to allow easy changeover to IEEEtran.cls/tools.sty error reporting +\def\@IEEEclspkgerror{\ClassError{IEEEtran}} + + +% These do nothing, but provide them like in article.cls +\newif\if@restonecol +\newif\if@titlepage + + +% class option conditionals +\newif\ifCLASSOPTIONonecolumn \CLASSOPTIONonecolumnfalse +\newif\ifCLASSOPTIONtwocolumn \CLASSOPTIONtwocolumntrue + +\newif\ifCLASSOPTIONoneside \CLASSOPTIONonesidetrue +\newif\ifCLASSOPTIONtwoside \CLASSOPTIONtwosidefalse + +\newif\ifCLASSOPTIONfinal \CLASSOPTIONfinaltrue +\newif\ifCLASSOPTIONdraft \CLASSOPTIONdraftfalse +\newif\ifCLASSOPTIONdraftcls \CLASSOPTIONdraftclsfalse +\newif\ifCLASSOPTIONdraftclsnofoot \CLASSOPTIONdraftclsnofootfalse + +\newif\ifCLASSOPTIONpeerreview \CLASSOPTIONpeerreviewfalse +\newif\ifCLASSOPTIONpeerreviewca \CLASSOPTIONpeerreviewcafalse + +\newif\ifCLASSOPTIONjournal \CLASSOPTIONjournaltrue +\newif\ifCLASSOPTIONconference \CLASSOPTIONconferencefalse +\newif\ifCLASSOPTIONtechnote \CLASSOPTIONtechnotefalse + +\newif\ifCLASSOPTIONnofonttune \CLASSOPTIONnofonttunefalse + +\newif\ifCLASSOPTIONcaptionsoff \CLASSOPTIONcaptionsofffalse + +\newif\ifCLASSOPTIONcomsoc \CLASSOPTIONcomsocfalse +\newif\ifCLASSOPTIONcompsoc \CLASSOPTIONcompsocfalse +\newif\ifCLASSOPTIONtransmag \CLASSOPTIONtransmagfalse + +\newif\ifCLASSOPTIONromanappendices \CLASSOPTIONromanappendicesfalse + + +% class info conditionals + +% indicates if pdf (via pdflatex) output +\newif\ifCLASSINFOpdf \CLASSINFOpdffalse + + +% V1.6b internal flag to show if using a4paper +\newif\if@IEEEusingAfourpaper \@IEEEusingAfourpaperfalse +% V1.6b internal flag to show if using cspaper +\newif\if@IEEEusingcspaper \@IEEEusingcspaperfalse + + +% IEEEtran class scratch pad registers +% dimen +\newdimen\@IEEEtrantmpdimenA +\newdimen\@IEEEtrantmpdimenB +\newdimen\@IEEEtrantmpdimenC +% count +\newcount\@IEEEtrantmpcountA +\newcount\@IEEEtrantmpcountB +\newcount\@IEEEtrantmpcountC +% token list +\newtoks\@IEEEtrantmptoksA + +% we use \CLASSOPTIONpt so that we can ID the point size (even for 9pt docs) +% as well as LaTeX's \@ptsize to retain some compatability with some +% external packages +\def\@ptsize{0} +% LaTeX does not support 9pt, so we set \@ptsize to 0 - same as that of 10pt +\DeclareOption{9pt}{\def\CLASSOPTIONpt{9}\def\@ptsize{0}} +\DeclareOption{10pt}{\def\CLASSOPTIONpt{10}\def\@ptsize{0}} +\DeclareOption{11pt}{\def\CLASSOPTIONpt{11}\def\@ptsize{1}} +\DeclareOption{12pt}{\def\CLASSOPTIONpt{12}\def\@ptsize{2}} + + + +\DeclareOption{letterpaper}{\setlength{\paperwidth}{8.5in}% + \setlength{\paperheight}{11in}% + \@IEEEusingAfourpaperfalse + \@IEEEusingcspaperfalse + \def\CLASSOPTIONpaper{letter}% + \def\CLASSINFOpaperwidth{8.5in}% + \def\CLASSINFOpaperheight{11in}} + + +\DeclareOption{a4paper}{\setlength{\paperwidth}{210mm}% + \setlength{\paperheight}{297mm}% + \@IEEEusingAfourpapertrue + \@IEEEusingcspaperfalse + \def\CLASSOPTIONpaper{a4}% + \def\CLASSINFOpaperwidth{210mm}% + \def\CLASSINFOpaperheight{297mm}} + +% special paper option for compsoc journals +\DeclareOption{cspaper}{\setlength{\paperwidth}{7.875in}% + \setlength{\paperheight}{10.75in}% + \@IEEEusingcspapertrue + \@IEEEusingAfourpaperfalse + \def\CLASSOPTIONpaper{ieeecs}% + \def\CLASSINFOpaperwidth{7.875in}% + \def\CLASSINFOpaperheight{10.75in}} + +\DeclareOption{oneside}{\@twosidefalse\@mparswitchfalse + \CLASSOPTIONonesidetrue\CLASSOPTIONtwosidefalse} +\DeclareOption{twoside}{\@twosidetrue\@mparswitchtrue + \CLASSOPTIONtwosidetrue\CLASSOPTIONonesidefalse} + +\DeclareOption{onecolumn}{\CLASSOPTIONonecolumntrue\CLASSOPTIONtwocolumnfalse} +\DeclareOption{twocolumn}{\CLASSOPTIONtwocolumntrue\CLASSOPTIONonecolumnfalse} + +% If the user selects draft, then this class AND any packages +% will go into draft mode. +\DeclareOption{draft}{\CLASSOPTIONdrafttrue\CLASSOPTIONdraftclstrue + \CLASSOPTIONdraftclsnofootfalse} +% draftcls is for a draft mode which will not affect any packages +% used by the document. +\DeclareOption{draftcls}{\CLASSOPTIONdraftfalse\CLASSOPTIONdraftclstrue + \CLASSOPTIONdraftclsnofootfalse} +% draftclsnofoot is like draftcls, but without the footer. +\DeclareOption{draftclsnofoot}{\CLASSOPTIONdraftfalse\CLASSOPTIONdraftclstrue + \CLASSOPTIONdraftclsnofoottrue} +\DeclareOption{final}{\CLASSOPTIONdraftfalse\CLASSOPTIONdraftclsfalse + \CLASSOPTIONdraftclsnofootfalse} + +\DeclareOption{journal}{\CLASSOPTIONpeerreviewfalse\CLASSOPTIONpeerreviewcafalse + \CLASSOPTIONjournaltrue\CLASSOPTIONconferencefalse\CLASSOPTIONtechnotefalse} + +\DeclareOption{conference}{\CLASSOPTIONpeerreviewfalse\CLASSOPTIONpeerreviewcafalse + \CLASSOPTIONjournalfalse\CLASSOPTIONconferencetrue\CLASSOPTIONtechnotefalse} + +\DeclareOption{technote}{\CLASSOPTIONpeerreviewfalse\CLASSOPTIONpeerreviewcafalse + \CLASSOPTIONjournalfalse\CLASSOPTIONconferencefalse\CLASSOPTIONtechnotetrue} + +\DeclareOption{peerreview}{\CLASSOPTIONpeerreviewtrue\CLASSOPTIONpeerreviewcafalse + \CLASSOPTIONjournalfalse\CLASSOPTIONconferencefalse\CLASSOPTIONtechnotefalse} + +\DeclareOption{peerreviewca}{\CLASSOPTIONpeerreviewtrue\CLASSOPTIONpeerreviewcatrue + \CLASSOPTIONjournalfalse\CLASSOPTIONconferencefalse\CLASSOPTIONtechnotefalse} + +\DeclareOption{nofonttune}{\CLASSOPTIONnofonttunetrue} + +\DeclareOption{captionsoff}{\CLASSOPTIONcaptionsofftrue} + +\DeclareOption{comsoc}{\CLASSOPTIONcomsoctrue\CLASSOPTIONcompsocfalse\CLASSOPTIONtransmagfalse} + +\DeclareOption{compsoc}{\CLASSOPTIONcomsocfalse\CLASSOPTIONcompsoctrue\CLASSOPTIONtransmagfalse} + +\DeclareOption{transmag}{\CLASSOPTIONtransmagtrue\CLASSOPTIONcomsocfalse\CLASSOPTIONcompsocfalse} + +\DeclareOption{romanappendices}{\CLASSOPTIONromanappendicestrue} + + +% default to US letter paper, 10pt, twocolumn, one sided, final, journal +\ExecuteOptions{letterpaper,10pt,twocolumn,oneside,final,journal} +% overrride these defaults per user requests +\ProcessOptions + + + +%% -- Command Argument Scanning Support Functions -- + +% Sets the category codes for punctuation to their normal values. +% For local use with argument scanning. +\def\IEEEnormalcatcodespunct{\catcode`\!=12 \catcode`\,=12 \catcode`\:=12 +\catcode`\;=12 \catcode`\`=12 \catcode`\'=12 \catcode`\"=12 \catcode`\.=12 +\catcode`\/=12 \catcode`\?=12 \catcode`\*=12 \catcode`\+=12 \catcode`\-=12 +\catcode`\<=12 \catcode`\>=12 \catcode`\(=12 \catcode`\)=12 \catcode`\[=12 +\catcode`\]=12 \catcode`\==12 \catcode`\|=12} +% Sets the category codes for numbers to their normal values. +% For local use with argument scanning. +\def\IEEEnormalcatcodesnum{\catcode`\0=12 \catcode`\1=12 \catcode`\2=12 +\catcode`\3=12 \catcode`\4=12 \catcode`\5=12 \catcode`\6=12 \catcode`\7=12 +\catcode`\8=12 \catcode`\9=12} +% combined action of \IEEEnormalcatcodespunct and \IEEEnormalcatcodesnum +\def\IEEEnormalcatcodes{\IEEEnormalcatcodespunct\IEEEnormalcatcodesnum} + + +% usage: \@IEEEextracttoken*{} +% \@IEEEextracttoken fully expands its argument (which it then stores in +% \@IEEEextracttokenarg) via \edef and then the meaning of the first +% nonbrace (but including the empty group) token found is assigned via \let +% to \@IEEEextractedtoken as well as stored in the macro +% \@IEEEextractedtokenmacro. Tokens that would otherwise be discarded during +% the acquisition of the first are stored in \@IEEEextractedtokensdiscarded, +% however their original relative brace nesting depths are not guaranteed to +% be preserved. +% If the argument is empty, or if a first nonbrace token does not exist (or +% is an empty group), \@IEEEextractedtoken will be \relax and +% \@IEEEextractedtokenmacro and \@IEEEextractedtokensdiscarded will be empty. +% +% For example: +% \@IEEEextracttoken{{{ab}{cd}}{{ef}g}} +% results in: +% +% \@IEEEextracttokenarg ==> a macro containing {{ab}{cd}}{{ef}g} +% \@IEEEextractedtoken ==> the letter a +% \@IEEEextractedtokenmacro ==> a macro containing a +% \@IEEEextractedtokensdiscarded ==> a macro containing bcd{ef}g +% +% the *-star form, \@IEEEextracttoken*, does not expand its argument +% contents during processing. +\def\@IEEEextracttoken{\@ifstar{\let\@IEEEextracttokendef=\def\@@IEEEextracttoken}{\let\@IEEEextracttokendef=\edef\@@IEEEextracttoken}} + +\def\@@IEEEextracttoken#1{\@IEEEextracttokendef\@IEEEextracttokenarg{#1}\relax +\def\@IEEEextractedtokensdiscarded{}\relax % initialize to empty +% if the macro is unchanged after being acquired as a single undelimited argument +% with anything after it being stripped off as a delimited argument +% we know we have one token without any enclosing braces. loop until this is true. +\let\@IEEEextracttokencurgroup\@IEEEextracttokenarg +\loop + % trap case of an empty argument as this would cause a problem with + % \@@@IEEEextracttoken's first (nondelimited) argument acquisition + \ifx\@IEEEextracttokencurgroup\@empty + \def\@IEEEextractedtokenmacro{}\relax + \else + \expandafter\@@@IEEEextracttoken\@IEEEextracttokencurgroup\@IEEEgeneralsequenceDELIMITER\relax + \fi + \ifx\@IEEEextractedtokenmacro\@IEEEextracttokencurgroup + \else + \let\@IEEEextracttokencurgroup=\@IEEEextractedtokenmacro +\repeat +% we can safely do a \let= here because there should be at most one token +% the relax is needed to handle the case of no token found +\expandafter\let\expandafter\@IEEEextractedtoken\@IEEEextractedtokenmacro\relax} + +\def\@@@IEEEextracttoken#1#2\@IEEEgeneralsequenceDELIMITER{\def\@IEEEextractedtokenmacro{#1}\relax +\def\@@IEEEextractedtokensdiscarded{#2}\expandafter\expandafter\expandafter\def\expandafter\expandafter\expandafter +\@IEEEextractedtokensdiscarded\expandafter\expandafter\expandafter +{\expandafter\@@IEEEextractedtokensdiscarded\@IEEEextractedtokensdiscarded}} +%% +%% -- End of Command Argument Scanning Support Functions -- + + + +% Computer Society conditional execution command +\long\def\@IEEEcompsoconly#1{\relax\ifCLASSOPTIONcompsoc\relax#1\relax\fi\relax} +% inverse +\long\def\@IEEEnotcompsoconly#1{\relax\ifCLASSOPTIONcompsoc\else\relax#1\relax\fi\relax} +% compsoc conference +\long\def\@IEEEcompsocconfonly#1{\relax\ifCLASSOPTIONcompsoc\ifCLASSOPTIONconference\relax#1\relax\fi\fi\relax} +% compsoc not conference +\long\def\@IEEEcompsocnotconfonly#1{\relax\ifCLASSOPTIONcompsoc\ifCLASSOPTIONconference\else\relax#1\relax\fi\fi\relax} + + +% comsoc verify that newtxmath, mtpro2, mt11p or mathtime has been loaded +\def\@IEEEcomsocverifymathfont{\typeout{-- Verifying Times compatible math font.}\relax + \@ifpackageloaded{newtxmath}{\typeout{-- newtxmath loaded, OK.}}{\@@IEEEcomsocverifymathfont}} +\def\@@IEEEcomsocverifymathfont{\@ifpackageloaded{mtpro2}{\typeout{-- mtpro2 loaded, OK.}}{\@@@IEEEcomsocverifymathfont}} +\def\@@@IEEEcomsocverifymathfont{\@ifpackageloaded{mt11p}{\typeout{-- mt11p2 loaded, OK.}}{\@@@@IEEEcomsocverifymathfont}} +\def\@@@@IEEEcomsocverifymathfont{\@ifpackageloaded{mathtime}{\typeout{-- mathtime loaded, OK.}}{\@IEEEcomsocenforcemathfont}} + +% comsoc, if a Times math font was not loaded by user, enforce it +\def\@IEEEcomsocenforcemathfont{\typeout{** Times compatible math font not found, forcing.}\relax +\IfFileExists{newtxmath.sty}{\typeout{-- Found newtxmath, loading.}\RequirePackage{newtxmath}}{\@@IEEEcomsocenforcemathfont}} +\def\@@IEEEcomsocenforcemathfont{\IfFileExists{mtpro2.sty}{\typeout{-- Found mtpro2, loading.}\RequirePackage{mtpro2}}{\@@@IEEEcomsocenforcemathfont}} +\def\@@@IEEEcomsocenforcemathfont{\IfFileExists{mt11p.sty}{\typeout{-- Found mt11p, loading.}\RequirePackage{mt11p}}{\@@@@IEEEcomsocenforcemathfont}} +\def\@@@@IEEEcomsocenforcemathfont{\IfFileExists{mathtime.sty}{\typeout{-- Found mathtime, loading.}\RequirePackage{mathtime}}{\@@@@@IEEEcomsocenforcemathfont}} +% if no acceptable Times math font package found, error with newtxmath requirement +\def\@@@@@IEEEcomsocenforcemathfont{\typeout{** No Times compatible math font package found. newtxmath is required.}\RequirePackage{newtxmath}} + + +\ifCLASSOPTIONcomsoc + % ensure that if newtxmath is used, the cmintegrals option is also invoked + \PassOptionsToPackage{cmintegrals}{newtxmath} + % comsoc requires a Times like math font + % ensure this requirement is satisfied at document start + \AtBeginDocument{\@IEEEcomsocverifymathfont} +\fi + + + +% The IEEE uses Times Roman font, so we'll default to Times. +% These three commands make up the entire times.sty package. +\renewcommand{\sfdefault}{phv} +\renewcommand{\rmdefault}{ptm} +\renewcommand{\ttdefault}{pcr} + +% V1.7 compsoc nonconference papers, use Palatino/Palladio as the main text font, +% not Times Roman. +\@IEEEcompsocnotconfonly{\renewcommand{\rmdefault}{ppl}} + +% enable the selected main text font +\normalfont\selectfont + + +\ifCLASSOPTIONcomsoc + \typeout{-- Using IEEE Communications Society mode.} +\fi + +\ifCLASSOPTIONcompsoc + \typeout{-- Using IEEE Computer Society mode.} +\fi + + +% V1.7 conference notice message hook +\def\@IEEEconsolenoticeconference{\typeout{}% +\typeout{** Conference Paper **}% +\typeout{Before submitting the final camera ready copy, remember to:}% +\typeout{}% +\typeout{ 1. Manually equalize the lengths of two columns on the last page}% +\typeout{ of your paper;}% +\typeout{}% +\typeout{ 2. Ensure that any PostScript and/or PDF output post-processing}% +\typeout{ uses only Type 1 fonts and that every step in the generation}% +\typeout{ process uses the appropriate paper size.}% +\typeout{}} + + +% we can send console reminder messages to the user here +\AtEndDocument{\ifCLASSOPTIONconference\@IEEEconsolenoticeconference\fi} + + +% warn about the use of single column other than for draft mode +\ifCLASSOPTIONtwocolumn\else% + \ifCLASSOPTIONdraftcls\else% + \typeout{** ATTENTION: Single column mode is not typically used with IEEE publications.}% + \fi% +\fi + + +% V1.7 improved paper size setting code. +% Set pdfpage and dvips paper sizes. Conditional tests are similar to that +% of ifpdf.sty. Retain within {} to ensure tested macros are never altered, +% even if only effect is to set them to \relax. +% if \pdfoutput is undefined or equal to relax, output a dvips special +{\@ifundefined{pdfoutput}{\AtBeginDvi{\special{papersize=\CLASSINFOpaperwidth,\CLASSINFOpaperheight}}}{% +% pdfoutput is defined and not equal to \relax +% check for pdfpageheight existence just in case someone sets pdfoutput +% under non-pdflatex. If exists, set them regardless of value of \pdfoutput. +\@ifundefined{pdfpageheight}{\relax}{\global\pdfpagewidth\paperwidth +\global\pdfpageheight\paperheight}% +% if using \pdfoutput=0 under pdflatex, send dvips papersize special +\ifcase\pdfoutput +\AtBeginDvi{\special{papersize=\CLASSINFOpaperwidth,\CLASSINFOpaperheight}}% +\else +% we are using pdf output, set CLASSINFOpdf flag +\global\CLASSINFOpdftrue +\fi}} + +% let the user know the selected papersize +\typeout{-- Using \CLASSINFOpaperwidth\space x \CLASSINFOpaperheight\space +(\CLASSOPTIONpaper)\space paper.} + +\ifCLASSINFOpdf +\typeout{-- Using PDF output.} +\else +\typeout{-- Using DVI output.} +\fi + + +% The idea hinted here is for LaTeX to generate markleft{} and markright{} +% automatically for you after you enter \author{}, \journal{}, +% \journaldate{}, journalvol{}, \journalnum{}, etc. +% However, there may be some backward compatibility issues here as +% well as some special applications for IEEEtran.cls and special issues +% that may require the flexible \markleft{}, \markright{} and/or \markboth{}. +% We'll leave this as an open future suggestion. +%\newcommand{\journal}[1]{\def\@journal{#1}} +%\def\@journal{} + + + +% pointsize values +% used with ifx to determine the document's normal size +\def\@IEEEptsizenine{9} +\def\@IEEEptsizeten{10} +\def\@IEEEptsizeeleven{11} +\def\@IEEEptsizetwelve{12} + + + +% FONT DEFINITIONS (No sizexx.clo file needed) +% V1.6 revised font sizes, displayskip values and +% revised normalsize baselineskip to reduce underfull vbox problems +% on the 58pc = 696pt = 9.5in text height we want +% normalsize #lines/column baselineskip (aka leading) +% 9pt 63 11.0476pt (truncated down) +% 10pt 58 12pt (exact) +% 11pt 52 13.3846pt (truncated down) +% 12pt 50 13.92pt (exact) +% + +% we need to store the nominal baselineskip for the given font size +% in case baselinestretch ever changes. +% this is a dimen, so it will not hold stretch or shrink +\newdimen\@IEEEnormalsizeunitybaselineskip +\@IEEEnormalsizeunitybaselineskip\baselineskip + + + +%% ******* WARNING! ******* +%% +%% Authors should not alter font sizes, baselineskip ("leading"), +%% margins or other spacing values in an attempt to squeeze more +%% material on each page. +%% +%% The IEEE's own typesetting software will restore the correct +%% values when re-typesetting/proofing the submitted document, +%% possibly resulting in unexpected article over length charges. +%% +%% ******* WARNING! ******* + + +% 9pt option defaults +\ifx\CLASSOPTIONpt\@IEEEptsizenine +\typeout{-- This is a 9 point document.} +\def\normalsize{\@setfontsize{\normalsize}{9}{11.0476pt}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{11.0476pt} +\normalsize +\abovedisplayskip 1.5ex plus 3pt minus 1pt +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 3pt +\belowdisplayshortskip 1.5ex plus 3pt minus 1pt +\def\small{\@setfontsize{\small}{8.5}{10pt}} +\def\footnotesize{\@setfontsize{\footnotesize}{8}{9pt}} +\def\scriptsize{\@setfontsize{\scriptsize}{7}{8pt}} +\def\tiny{\@setfontsize{\tiny}{5}{6pt}} +% sublargesize is the same as large - 10pt +\def\sublargesize{\@setfontsize{\sublargesize}{10}{12pt}} +\def\large{\@setfontsize{\large}{10}{12pt}} +\def\Large{\@setfontsize{\Large}{12}{14pt}} +\def\LARGE{\@setfontsize{\LARGE}{14}{17pt}} +\def\huge{\@setfontsize{\huge}{17}{20pt}} +\def\Huge{\@setfontsize{\Huge}{20}{24pt}} +\fi +% +% 10pt option defaults +\ifx\CLASSOPTIONpt\@IEEEptsizeten +\typeout{-- This is a 10 point document.} +\def\normalsize{\@setfontsize{\normalsize}{10}{12.00pt}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{12pt} +\normalsize +\abovedisplayskip 1.5ex plus 4pt minus 2pt +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 4pt +\belowdisplayshortskip 1.5ex plus 4pt minus 2pt +\def\small{\@setfontsize{\small}{9}{10pt}} +\def\footnotesize{\@setfontsize{\footnotesize}{8}{9pt}} +\def\scriptsize{\@setfontsize{\scriptsize}{7}{8pt}} +\def\tiny{\@setfontsize{\tiny}{5}{6pt}} +% sublargesize is a tad smaller than large - 11pt +\def\sublargesize{\@setfontsize{\sublargesize}{11}{13.4pt}} +\def\large{\@setfontsize{\large}{12}{14pt}} +\def\Large{\@setfontsize{\Large}{14}{17pt}} +%20230227 \def\LARGE{\@setfontsize{\LARGE}{17}{20pt}} +%20230227 \def\huge{\@setfontsize{\huge}{20}{24pt}} +%20230227 \def\Huge{\@setfontsize{\Huge}{24}{28pt}} +\def\LARGE{\@setfontsize{\LARGE}{18}{20pt}} +\def\huge{\@setfontsize{\huge}{18}{24pt}} +\def\Huge{\@setfontsize{\Huge}{18}{28pt}} +\fi +% +% 11pt option defaults +\ifx\CLASSOPTIONpt\@IEEEptsizeeleven +\typeout{-- This is an 11 point document.} +\def\normalsize{\@setfontsize{\normalsize}{11}{13.3846pt}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{13.3846pt} +\normalsize +\abovedisplayskip 1.5ex plus 5pt minus 3pt +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 5pt +\belowdisplayshortskip 1.5ex plus 5pt minus 3pt +\def\small{\@setfontsize{\small}{10}{12pt}} +\def\footnotesize{\@setfontsize{\footnotesize}{9}{10.5pt}} +\def\scriptsize{\@setfontsize{\scriptsize}{8}{9pt}} +\def\tiny{\@setfontsize{\tiny}{6}{7pt}} +% sublargesize is the same as large - 12pt +\def\sublargesize{\@setfontsize{\sublargesize}{12}{14pt}} +\def\large{\@setfontsize{\large}{12}{14pt}} +\def\Large{\@setfontsize{\Large}{14}{17pt}} +\def\LARGE{\@setfontsize{\LARGE}{17}{20pt}} +\def\huge{\@setfontsize{\huge}{20}{24pt}} +\def\Huge{\@setfontsize{\Huge}{24}{28pt}} +\fi +% +% 12pt option defaults +\ifx\CLASSOPTIONpt\@IEEEptsizetwelve +\typeout{-- This is a 12 point document.} +\def\normalsize{\@setfontsize{\normalsize}{12}{13.92pt}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{13.92pt} +\normalsize +\abovedisplayskip 1.5ex plus 6pt minus 4pt +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 6pt +\belowdisplayshortskip 1.5ex plus 6pt minus 4pt +\def\small{\@setfontsize{\small}{10}{12pt}} +\def\footnotesize{\@setfontsize{\footnotesize}{9}{10.5pt}} +\def\scriptsize{\@setfontsize{\scriptsize}{8}{9pt}} +\def\tiny{\@setfontsize{\tiny}{6}{7pt}} +% sublargesize is the same as large - 14pt +\def\sublargesize{\@setfontsize{\sublargesize}{14}{17pt}} +\def\large{\@setfontsize{\large}{14}{17pt}} +\def\Large{\@setfontsize{\Large}{17}{20pt}} +\def\LARGE{\@setfontsize{\LARGE}{20}{24pt}} +\def\huge{\@setfontsize{\huge}{22}{26pt}} +\def\Huge{\@setfontsize{\Huge}{24}{28pt}} +\fi + + + +% V1.8a compsoc font sizes +% compsoc font sizes use bp "Postscript" point units (1/72in) +% rather than the traditional pt (1/72.27) +\ifCLASSOPTIONcompsoc +% -- compsoc defaults -- +% ** will override some of these values later ** +% 9pt +\ifx\CLASSOPTIONpt\@IEEEptsizenine +\def\normalsize{\@setfontsize{\normalsize}{9bp}{11bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{11bp} +\normalsize +\abovedisplayskip 1.5ex plus 3bp minus 1bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0bp plus 3bp +\belowdisplayshortskip 1.5ex plus 3bp minus 1bp +\def\small{\@setfontsize{\small}{8.5bp}{10bp}} +\def\footnotesize{\@setfontsize{\footnotesize}{8bp}{9bp}} +\def\scriptsize{\@setfontsize{\scriptsize}{7bp}{8bp}} +\def\tiny{\@setfontsize{\tiny}{5bp}{6bp}} +% sublargesize is the same as large - 10bp +\def\sublargesize{\@setfontsize{\sublargesize}{10bp}{12bp}} +\def\large{\@setfontsize{\large}{10bp}{12bp}} +\def\Large{\@setfontsize{\Large}{12bp}{14bp}} +\def\LARGE{\@setfontsize{\LARGE}{14bp}{17bp}} +\def\huge{\@setfontsize{\huge}{17bp}{20bp}} +\def\Huge{\@setfontsize{\Huge}{20bp}{24bp}} +\fi +% +% 10pt +\ifx\CLASSOPTIONpt\@IEEEptsizeten +\def\normalsize{\@setfontsize{\normalsize}{10bp}{12bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{12bp} +\normalsize +\abovedisplayskip 1.5ex plus 4bp minus 2bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 4bp +\belowdisplayshortskip 1.5ex plus 4bp minus 2bp +\def\small{\@setfontsize{\small}{9bp}{10bp}} +\def\footnotesize{\@setfontsize{\footnotesize}{8bp}{9bp}} +\def\scriptsize{\@setfontsize{\scriptsize}{7bp}{8bp}} +\def\tiny{\@setfontsize{\tiny}{5bp}{6bp}} +% sublargesize is a tad smaller than large - 11bp +\def\sublargesize{\@setfontsize{\sublargesize}{11bp}{13.5bp}} +\def\large{\@setfontsize{\large}{12bp}{14bp}} +\def\Large{\@setfontsize{\Large}{14bp}{17bp}} +\def\LARGE{\@setfontsize{\LARGE}{17bp}{20bp}} +\def\huge{\@setfontsize{\huge}{20bp}{24bp}} +\def\Huge{\@setfontsize{\Huge}{24bp}{28bp}} +\fi +% +% 11pt +\ifx\CLASSOPTIONpt\@IEEEptsizeeleven +\def\normalsize{\@setfontsize{\normalsize}{11bp}{13.5bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{13.5bp} +\normalsize +\abovedisplayskip 1.5ex plus 5bp minus 3bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 5bp +\belowdisplayshortskip 1.5ex plus 5bp minus 3bp +\def\small{\@setfontsize{\small}{10bp}{12bp}} +\def\footnotesize{\@setfontsize{\footnotesize}{9bp}{10.5bp}} +\def\scriptsize{\@setfontsize{\scriptsize}{8bp}{9bp}} +\def\tiny{\@setfontsize{\tiny}{6bp}{7bp}} +% sublargesize is the same as large - 12bp +\def\sublargesize{\@setfontsize{\sublargesize}{12bp}{14bp}} +\def\large{\@setfontsize{\large}{12bp}{14bp}} +\def\Large{\@setfontsize{\Large}{14bp}{17bp}} +\def\LARGE{\@setfontsize{\LARGE}{17bp}{20bp}} +\def\huge{\@setfontsize{\huge}{20bp}{24bp}} +\def\Huge{\@setfontsize{\Huge}{24bp}{28bp}} +\fi +% +% 12pt +\ifx\CLASSOPTIONpt\@IEEEptsizetwelve +\def\normalsize{\@setfontsize{\normalsize}{12bp}{14bp}}% +\setlength{\@IEEEnormalsizeunitybaselineskip}{14bp}% +\normalsize +\abovedisplayskip 1.5ex plus 6bp minus 4bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 6bp +\belowdisplayshortskip 1.5ex plus 6bp minus 4bp +\def\small{\@setfontsize{\small}{10bp}{12bp}} +\def\footnotesize{\@setfontsize{\footnotesize}{9bp}{10.5bp}} +\def\scriptsize{\@setfontsize{\scriptsize}{8bp}{9bp}} +\def\tiny{\@setfontsize{\tiny}{6bp}{7bp}} +% sublargesize is the same as large - 14bp +\def\sublargesize{\@setfontsize{\sublargesize}{14bp}{17bp}} +\def\large{\@setfontsize{\large}{14bp}{17bp}} +\def\Large{\@setfontsize{\Large}{17bp}{20bp}} +\def\LARGE{\@setfontsize{\LARGE}{20bp}{24bp}} +\def\huge{\@setfontsize{\huge}{22bp}{26bp}} +\def\Huge{\@setfontsize{\Huge}{24bp}{28bp}} +\fi +% +% -- override defaults: compsoc journals use special normalsizes -- +\ifCLASSOPTIONconference +% +% compsoc conferences +% 9pt +\ifx\CLASSOPTIONpt\@IEEEptsizenine +\def\normalsize{\@setfontsize{\normalsize}{9bp}{10.8bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{10.8bp} +\normalsize +\abovedisplayskip 1.5ex plus 3bp minus 1bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0bp plus 3bp +\belowdisplayshortskip 1.5ex plus 3bp minus 1bp +\fi +% 10pt +\ifx\CLASSOPTIONpt\@IEEEptsizeten +\def\normalsize{\@setfontsize{\normalsize}{10bp}{11.2bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{11.2bp} +\normalsize +\abovedisplayskip 1.5ex plus 4bp minus 2bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 4bp +\belowdisplayshortskip 1.5ex plus 4bp minus 2bp +\fi +% 11pt +\ifx\CLASSOPTIONpt\@IEEEptsizeeleven +\def\normalsize{\@setfontsize{\normalsize}{11bp}{13.2bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{13.2bp} +\normalsize +\abovedisplayskip 1.5ex plus 5bp minus 3bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 5bp +\belowdisplayshortskip 1.5ex plus 5bp minus 3bp +\fi +% 12pt +\ifx\CLASSOPTIONpt\@IEEEptsizetwelve +\def\normalsize{\@setfontsize{\normalsize}{12bp}{14.4bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{14.4bp} +\normalsize +\abovedisplayskip 1.5ex plus 6bp minus 4bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 6bp +\belowdisplayshortskip 1.5ex plus 6bp minus 4bp +\fi +% +% compsoc nonconferences +\else +% 9pt +\ifx\CLASSOPTIONpt\@IEEEptsizenine +\def\normalsize{\@setfontsize{\normalsize}{9bp}{10.8bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{10.8bp} +\normalsize +\abovedisplayskip 1.5ex plus 3bp minus 1bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0bp plus 3bp +\belowdisplayshortskip 1.5ex plus 3bp minus 1bp +\fi +% 10pt +\ifx\CLASSOPTIONpt\@IEEEptsizeten +% the official spec is 9.5bp with 11.4bp leading for 10pt, +% but measurements of proofs suggest upto 11.723bp leading +% here we'll use 11.54bp which gives 61 lines per column +% with the standard compsoc margins +\def\normalsize{\@setfontsize{\normalsize}{9.5bp}{11.54bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{11.54bp} +\normalsize +\abovedisplayskip 1.5ex plus 4bp minus 2bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 4bp +\belowdisplayshortskip 1.5ex plus 4bp minus 2bp +\fi +% 11pt +\ifx\CLASSOPTIONpt\@IEEEptsizeeleven +\def\normalsize{\@setfontsize{\normalsize}{11bp}{13.2bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{13.2bp} +\normalsize +\abovedisplayskip 1.5ex plus 5bp minus 3bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 5bp +\belowdisplayshortskip 1.5ex plus 5bp minus 3bp +\fi +% 12pt +\ifx\CLASSOPTIONpt\@IEEEptsizetwelve +\def\normalsize{\@setfontsize{\normalsize}{12bp}{14.4bp}} +\setlength{\@IEEEnormalsizeunitybaselineskip}{14.4bp} +\normalsize +\abovedisplayskip 1.5ex plus 6bp minus 4bp +\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip 0pt plus 6bp +\belowdisplayshortskip 1.5ex plus 6bp minus 4bp +\fi +\fi\fi + + + + +% V1.6 The Computer Modern Fonts will issue a substitution warning for +% 24pt titles (24.88pt is used instead, but the default and correct +% Times font will scale exactly as needed) increase the substitution +% tolerance to turn off this warning. +% +% V1.8a, the compsoc bp font sizes can also cause bogus font substitution +% warnings with footnote or scriptsize math and the $\bullet$ itemized +% list of \IEEEcompsocitemizethanks. So, increase this to 1.5pt or more. +\def\fontsubfuzz{1.7bp} + + +% warn the user in case they forget to use the 9pt option with +% technote +\ifCLASSOPTIONtechnote% + \ifx\CLASSOPTIONpt\@IEEEptsizenine\else% + \typeout{** ATTENTION: Technotes are normally 9pt documents.}% + \fi% +\fi + + +% V1.7 +% Improved \textunderscore to provide a much better fake _ when used with +% OT1 encoding. Under OT1, detect use of pcr or cmtt \ttfamily and use +% available true _ glyph for those two typewriter fonts. +\def\@IEEEstringptm{ptm} % Times Roman family +\def\@IEEEstringppl{ppl} % Palatino Roman family +\def\@IEEEstringphv{phv} % Helvetica Sans Serif family +\def\@IEEEstringpcr{pcr} % Courier typewriter family +\def\@IEEEstringcmtt{cmtt} % Computer Modern typewriter family +\DeclareTextCommandDefault{\textunderscore}{\leavevmode +\ifx\f@family\@IEEEstringpcr\string_\else +\ifx\f@family\@IEEEstringcmtt\string_\else +\ifx\f@family\@IEEEstringptm\kern 0em\vbox{\hrule\@width 0.5em\@height 0.5pt\kern -0.3ex}\else +\ifx\f@family\@IEEEstringppl\kern 0em\vbox{\hrule\@width 0.5em\@height 0.5pt\kern -0.3ex}\else +\ifx\f@family\@IEEEstringphv\kern -0.03em\vbox{\hrule\@width 0.62em\@height 0.52pt\kern -0.33ex}\kern -0.03em\else +\kern 0.09em\vbox{\hrule\@width 0.6em\@height 0.44pt\kern -0.63pt\kern -0.42ex}\kern 0.09em\fi\fi\fi\fi\fi\relax} + +% set the default \baselinestretch +\def\baselinestretch{1} +\ifCLASSOPTIONdraftcls + \def\baselinestretch{1.5}% default baselinestretch for draft modes +\fi + +% process CLASSINPUT baselinestretch +\ifx\CLASSINPUTbaselinestretch\@IEEEundefined +\else + \edef\baselinestretch{\CLASSINPUTbaselinestretch} % user CLASSINPUT override + \typeout{** ATTENTION: Overriding \string\baselinestretch\space to + \baselinestretch\space via \string\CLASSINPUT.} +\fi + +\small\normalsize % make \baselinestretch take affect + +% store the normalsize baselineskip +\newdimen\CLASSINFOnormalsizebaselineskip +\CLASSINFOnormalsizebaselineskip=\baselineskip\relax +% and the normalsize unity (baselinestretch=1) baselineskip +% we could save a register by giving the user access to +% \@IEEEnormalsizeunitybaselineskip. However, let's protect +% its read only internal status +\newdimen\CLASSINFOnormalsizeunitybaselineskip +\CLASSINFOnormalsizeunitybaselineskip=\@IEEEnormalsizeunitybaselineskip\relax +% store the nominal value of jot +\newdimen\IEEEnormaljot +\IEEEnormaljot=0.25\baselineskip\relax + +% set \jot +\jot=\IEEEnormaljot\relax + + + + +% V1.6, we are now going to fine tune the interword spacing +% The default interword glue for Times under TeX appears to use a +% nominal interword spacing of 25% (relative to the font size, i.e., 1em) +% a maximum of 40% and a minimum of 19%. +% For example, 10pt text uses an interword glue of: +% +% 2.5pt plus 1.49998pt minus 0.59998pt +% +% However, the IEEE allows for a more generous range which reduces the need +% for hyphenation, especially for two column text. Furthermore, the IEEE +% tends to use a little bit more nominal space between the words. +% The IEEE's interword spacing percentages appear to be: +% 35% nominal +% 23% minimum +% 50% maximum +% (They may even be using a tad more for the largest fonts such as 24pt.) +% +% for bold text, the IEEE increases the spacing a little more: +% 37.5% nominal +% 23% minimum +% 55% maximum + +% here are the interword spacing ratios we'll use +% for medium (normal weight) +\def\@IEEEinterspaceratioM{0.35} +\def\@IEEEinterspaceMINratioM{0.23} +\def\@IEEEinterspaceMAXratioM{0.50} + +% for bold +\def\@IEEEinterspaceratioB{0.375} +\def\@IEEEinterspaceMINratioB{0.23} +\def\@IEEEinterspaceMAXratioB{0.55} + + +% compsoc nonconference papers use Palatino, +% tweak settings to better match the proofs +\ifCLASSOPTIONcompsoc +\ifCLASSOPTIONconference\else +% for medium (normal weight) +\def\@IEEEinterspaceratioM{0.28} +\def\@IEEEinterspaceMINratioM{0.21} +\def\@IEEEinterspaceMAXratioM{0.47} +% for bold +\def\@IEEEinterspaceratioB{0.305} +\def\@IEEEinterspaceMINratioB{0.21} +\def\@IEEEinterspaceMAXratioB{0.52} +\fi\fi + + +% command to revise the interword spacing for the current font under TeX: +% \fontdimen2 = nominal interword space +% \fontdimen3 = interword stretch +% \fontdimen4 = interword shrink +% since all changes to the \fontdimen are global, we can enclose these commands +% in braces to confine any font attribute or length changes +\def\@@@IEEEsetfontdimens#1#2#3{{% +\setlength{\@IEEEtrantmpdimenB}{\f@size pt}% grab the font size in pt, could use 1em instead. +\setlength{\@IEEEtrantmpdimenA}{#1\@IEEEtrantmpdimenB}% +\fontdimen2\font=\@IEEEtrantmpdimenA\relax +\addtolength{\@IEEEtrantmpdimenA}{-#2\@IEEEtrantmpdimenB}% +\fontdimen3\font=-\@IEEEtrantmpdimenA\relax +\setlength{\@IEEEtrantmpdimenA}{#1\@IEEEtrantmpdimenB}% +\addtolength{\@IEEEtrantmpdimenA}{-#3\@IEEEtrantmpdimenB}% +\fontdimen4\font=\@IEEEtrantmpdimenA\relax}} + +% revise the interword spacing for each font weight +\def\@@IEEEsetfontdimens{{% +\mdseries +\@@@IEEEsetfontdimens{\@IEEEinterspaceratioM}{\@IEEEinterspaceMAXratioM}{\@IEEEinterspaceMINratioM}% +\bfseries +\@@@IEEEsetfontdimens{\@IEEEinterspaceratioB}{\@IEEEinterspaceMAXratioB}{\@IEEEinterspaceMINratioB}% +}} + +% revise the interword spacing for each font shape +% \slshape is not often used for IEEE work and is not altered here. The \scshape caps are +% already a tad too large in the free LaTeX fonts (as compared to what the IEEE uses) so we +% won't alter these either. +\def\@IEEEsetfontdimens{{% +\normalfont +\@@IEEEsetfontdimens +\normalfont\itshape +\@@IEEEsetfontdimens +}} + +% command to revise the interword spacing for each font size (and shape +% and weight). Only the \rmfamily is done here as \ttfamily uses a +% fixed spacing and \sffamily is not used as the main text of IEEE papers. +\def\@IEEEtunefonts{{\selectfont\rmfamily +\tiny\@IEEEsetfontdimens +\scriptsize\@IEEEsetfontdimens +\footnotesize\@IEEEsetfontdimens +\small\@IEEEsetfontdimens +\normalsize\@IEEEsetfontdimens +\sublargesize\@IEEEsetfontdimens +\large\@IEEEsetfontdimens +\LARGE\@IEEEsetfontdimens +\huge\@IEEEsetfontdimens +\Huge\@IEEEsetfontdimens}} + +% if the nofonttune class option is not given, revise the interword spacing +% now - in case IEEEtran makes any default length measurements, and make +% sure all the default fonts are loaded +\ifCLASSOPTIONnofonttune\else +\@IEEEtunefonts +\fi + +% and again at the start of the document in case the user loaded different fonts +\AtBeginDocument{\ifCLASSOPTIONnofonttune\else\@IEEEtunefonts\fi} + + + + + +% -- V1.8a page setup commands -- + +% The default sample text for calculating margins +% Note that IEEE publications use \scriptsize for headers and footers. +\def\IEEEdefaultsampletext{\normalfont\normalsize gT} +\def\IEEEdefaultheadersampletext{\normalfont\scriptsize T}% IEEE headers default to uppercase +\def\IEEEdefaultfootersampletext{\normalfont\scriptsize gT} + + + +% usage: \IEEEsettextwidth{inner margin}{outer margin} +% Sets \textwidth to allow the specified inner and outer margins +% for the current \paperwidth. +\def\IEEEsettextwidth#1#2{\@IEEEtrantmpdimenA\paperwidth +\@IEEEtrantmpdimenB#1\relax +\advance\@IEEEtrantmpdimenA by -\@IEEEtrantmpdimenB +\@IEEEtrantmpdimenB#2\relax +\advance\@IEEEtrantmpdimenA by -\@IEEEtrantmpdimenB +\textwidth\@IEEEtrantmpdimenA} + + + +% usage: \IEEEsetsidemargin{mode: i, o, c, a}{margin/offset} +% Sets \oddsidemargin and \evensidemargin to yield the specified margin +% of the given mode. +% The available modes are: +% i = inner margin +% o = outer margin +% c = centered, with the given offset +% a = adjust the margins using the given offset +% For the offsets, positive values increase the inner margin. +% \textwidth should be set properly for the given margins before calling this +% function. +\def\IEEEsetsidemargin#1#2{\@IEEEtrantmpdimenA #2\relax +\@IEEEextracttoken{#1}\relax +% check for mode errors +\ifx\@IEEEextractedtokenmacro\@empty + \@IEEEclspkgerror{Empty mode type in \string\IEEEsetsidemargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `i'}{Valid modes for \string\IEEEsetsidemargin\space are: i, o, c and a.}\relax + \let\@IEEEextractedtoken=i\relax + \def\@IEEEextractedtokenmacro{i}\relax +\else + \ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: \string\IEEEsetsidemargin\space mode specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax + \fi +\fi +% handle each mode +\if\@IEEEextractedtoken a\relax + \advance\oddsidemargin by \@IEEEtrantmpdimenA\relax +\else +\if\@IEEEextractedtoken c\relax + \oddsidemargin\paperwidth + \advance\oddsidemargin by -\textwidth + \divide\oddsidemargin by 2\relax + \advance\oddsidemargin by -1in\relax + \advance\oddsidemargin by \@IEEEtrantmpdimenA\relax +\else +\if\@IEEEextractedtoken o\relax + \oddsidemargin\paperwidth + \advance\oddsidemargin by -\textwidth + \advance\oddsidemargin by -\@IEEEtrantmpdimenA + \advance\oddsidemargin by -1in\relax +\else + \if\@IEEEextractedtoken i\relax + \else + \@IEEEclspkgerror{Unknown mode type `\@IEEEextractedtokenmacro' in \string\IEEEsetsidemargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `i'}% + {Valid modes for \string\IEEEsetsidemargin\space are: i, o, c and a.}% + \fi + \oddsidemargin\@IEEEtrantmpdimenA + \advance\oddsidemargin by -1in\relax +\fi\fi\fi +% odd and even side margins both mean "inner" for single sided pages +\evensidemargin\oddsidemargin +% but are mirrors of each other when twosided is in effect +\if@twoside + \evensidemargin\paperwidth + \advance\evensidemargin by -\textwidth + \advance\evensidemargin by -\oddsidemargin + % have to compensate for both the builtin 1in LaTex offset + % and the fact we already subtracted this offset from \oddsidemargin + \advance\evensidemargin -2in\relax +\fi} + + + +% usage: \IEEEsettextheight[sample text]{top text margin}{bottom text margin} +% Sets \textheight based on the specified top margin and bottom margin. +% Takes into consideration \paperheight, \topskip, and (by default) the +% the actual height and depth of the \IEEEdefaultsampletext text. +\def\IEEEsettextheight{\@ifnextchar [{\@IEEEsettextheight}{\@IEEEsettextheight[\IEEEdefaultsampletext]}} +\def\@IEEEsettextheight[#1]#2#3{\textheight\paperheight\relax + \@IEEEtrantmpdimenA #2\relax + \advance \textheight by -\@IEEEtrantmpdimenA% subtract top margin + \@IEEEtrantmpdimenA #3\relax + \advance \textheight by -\@IEEEtrantmpdimenA% subtract bottom margin + \advance \textheight by \topskip% add \topskip + % subtract off everything above the top, and below the bottom, baselines + \settoheight{\@IEEEtrantmpdimenA}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance \textheight by -\@IEEEtrantmpdimenA + \settodepth{\@IEEEtrantmpdimenA}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance \textheight by -\@IEEEtrantmpdimenA} + + + +\newdimen\IEEEquantizedlength +\IEEEquantizedlength 0sp\relax +\newdimen\IEEEquantizedlengthdiff +\IEEEquantizedlengthdiff 0sp\relax +\def\IEEEquantizedlengthint{0} + +% usage: \IEEEquantizelength{mode: d, c, i}{base unit}{length} +% Sets the length \IEEEquantizedlength to be an integer multiple of the given +% (nonzero) base unit such that \IEEEquantizedlength approximates the given +% length. +% \IEEEquantizedlengthdiff is a length equal to the difference between the +% \IEEEquantizedlength and the given length. +% \IEEEquantizedlengthint is a macro containing the integer number of base units +% in \IEEEquantizedlength. +% i.e., \IEEEquantizedlength = \IEEEquantizedlengthint * base unit +% The mode determines how \IEEEquantizedlength is quantized: +% d = always decrease (always round down \IEEEquantizeint) +% c = use the closest match +% i = always increase (always round up \IEEEquantizeint) +% In anycase, if the given length is already quantized, +% \IEEEquantizedlengthdiff will be set to zero. +\def\IEEEquantizelength#1#2#3{\begingroup +% work in isolation so as not to externally disturb the \@IEEEtrantmp +% variables +% load the argument values indirectly via \IEEEquantizedlengthdiff +% in case the user refers to our \@IEEEtrantmpdimenX, \IEEEquantizedlength, +% etc. in the arguments. we also will work with these as counters, +% i.e., in sp units +% A has the base unit +\IEEEquantizedlengthdiff #2\relax\relax\relax\relax +\@IEEEtrantmpcountA\IEEEquantizedlengthdiff +% B has the input length +\IEEEquantizedlengthdiff #3\relax\relax\relax\relax +\@IEEEtrantmpcountB\IEEEquantizedlengthdiff +\@IEEEtrantmpdimenA\the\@IEEEtrantmpcountA sp\relax +\@IEEEtrantmpdimenB\the\@IEEEtrantmpcountB sp\relax +% \@IEEEtrantmpcountC will have the quantized int +% \IEEEquantizedlength will have the quantized length +% \@IEEEtrantmpdimenC will have the quantized diff +% initialize them to zero as this is what will be +% exported if an error occurs +\@IEEEtrantmpcountC 0\relax +\IEEEquantizedlength 0sp\relax +\@IEEEtrantmpdimenC 0sp\relax +% extract mode +\@IEEEextracttoken{#1}\relax +% check for mode errors +\ifx\@IEEEextractedtokenmacro\@empty + \@IEEEclspkgerror{Empty mode type in \string\IEEEquantizelength\space (line \the\inputlineno).\MessageBreak + Defaulting to `d'}{Valid modes for \string\IEEEquantizelength\space are: d, c and i.}\relax + \let\@IEEEextractedtoken=d\relax + \def\@IEEEextractedtokenmacro{d}\relax +\else + \ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: \string\IEEEquantizelength\space mode specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax + \fi +\fi +% check for base unit is zero error +\ifnum\@IEEEtrantmpcountA=0\relax +\@IEEEclspkgerror{Base unit is zero in \string\IEEEquantizelength\space (line \the\inputlineno).\MessageBreak + \string\IEEEquantizedlength\space and \string\IEEEquantizedlengthdiff\space are set to zero}{Division by zero is not allowed.}\relax +\else% base unit is nonzero + % \@IEEEtrantmpcountC carries the number of integer units + % in the quantized length (integer length \ base) + \@IEEEtrantmpcountC\@IEEEtrantmpcountB\relax + \divide\@IEEEtrantmpcountC by \@IEEEtrantmpcountA\relax + % \IEEEquantizedlength has the (rounded down) quantized length + % = base * int + \IEEEquantizedlength\@IEEEtrantmpdimenA\relax + \multiply\IEEEquantizedlength by \@IEEEtrantmpcountC\relax + % \@IEEEtrantmpdimenC has the difference + % = quantized length - length + \@IEEEtrantmpdimenC\IEEEquantizedlength\relax + \advance\@IEEEtrantmpdimenC by -\@IEEEtrantmpdimenB\relax + % trap special case of length being already quantized + % to avoid a roundup under i option + \ifdim\@IEEEtrantmpdimenC=0sp\relax + \else % length not is already quantized + % set dimenA to carry the upper quantized (absolute value) difference: + % quantizedlength + base - length + \advance\@IEEEtrantmpdimenA by \IEEEquantizedlength\relax + \advance\@IEEEtrantmpdimenA by -\@IEEEtrantmpdimenB\relax + % set dimenB to carry the lower quantized (absolute value) difference: + % length - quantizedlength + \advance\@IEEEtrantmpdimenB by -\IEEEquantizedlength\relax + % handle each mode + \if\@IEEEextractedtoken c\relax + % compare upper and lower amounts, select upper if lower > upper + \ifdim\@IEEEtrantmpdimenB>\@IEEEtrantmpdimenA\relax + % use upper + \advance\IEEEquantizedlength by \the\@IEEEtrantmpcountA sp\relax + \advance\@IEEEtrantmpcountC by 1\relax + \@IEEEtrantmpdimenC\@IEEEtrantmpdimenA + \else% <=. uselower + % no need to do anything for lower, use output values already setup + \fi + \else% not mode c + \if\@IEEEextractedtoken i\relax + % always round up under i mode + \advance\IEEEquantizedlength by \the\@IEEEtrantmpcountA sp\relax + \advance\@IEEEtrantmpcountC by 1\relax + \@IEEEtrantmpdimenC\@IEEEtrantmpdimenA + \else + \if\@IEEEextractedtoken d\relax + \else + \@IEEEclspkgerror{Unknown mode type `\@IEEEextractedtokenmacro' in \string\IEEEquantizelength\space (line \the\inputlineno).\MessageBreak + Defaulting to `d'}% + {Valid modes for \string\IEEEquantizelength\space are: d, c, and i.}\relax + \fi % if d + % no need to do anything for d, use output values already setup + \fi\fi % if i, c + \fi % if length is already quantized +\fi% if base unit is zero +% globally assign the results to macros we use here to escape the enclosing +% group without needing to call \global on any of the \@IEEEtrantmp variables. +% \@IEEEtrantmpcountC has the quantized int +% \IEEEquantizedlength has the quantized length +% \@IEEEtrantmpdimenC has the quantized diff +\xdef\@IEEEquantizedlengthintmacro{\the\@IEEEtrantmpcountC}\relax +\@IEEEtrantmpcountC\IEEEquantizedlength\relax +\xdef\@IEEEquantizedlengthmacro{\the\@IEEEtrantmpcountC}\relax +\@IEEEtrantmpcountC\@IEEEtrantmpdimenC\relax +\xdef\@IEEEquantizedlengthdiffmacro{\the\@IEEEtrantmpcountC}\relax +\endgroup +% locally assign the outputs here from the macros +\expandafter\IEEEquantizedlength\@IEEEquantizedlengthmacro sp\relax +\expandafter\IEEEquantizedlengthdiff\@IEEEquantizedlengthdiffmacro sp\relax +\edef\IEEEquantizedlengthint{\@IEEEquantizedlengthintmacro}\relax} + + + +\newdimen\IEEEquantizedtextheightdiff +\IEEEquantizedtextheightdiff 0sp\relax + +% usage: \IEEEquantizetextheight[base unit]{mode: d, c, i} +% Sets \textheight to be an integer multiple of the current \baselineskip +% (or the optionally specified base unit) plus the first (\topskip) line. +% \IEEEquantizedtextheightdiff is a length equal to the difference between +% the new quantized and original \textheight. +% \IEEEquantizedtextheightlpc is a macro containing the integer number of +% lines per column under the quantized \textheight. i.e., +% \textheight = \IEEEquantizedtextheightlpc * \baselineskip + \topskip +% The mode determines how \textheight is quantized: +% d = always decrease (always round down the number of lines per column) +% c = use the closest match +% i = always increase (always round up the number of lines per column) +% In anycase, if \textheight is already quantized, it will remain unchanged, +% and \IEEEquantizedtextheightdiff will be set to zero. +% Depends on: \IEEEquantizelength +\def\IEEEquantizetextheight{\@ifnextchar [{\@IEEEquantizetextheight}{\@IEEEquantizetextheight[\baselineskip]}} +\def\@IEEEquantizetextheight[#1]#2{\begingroup +% use our \IEEEquantizedtextheightdiff as a scratch pad +% we need to subtract off \topskip before quantization +\IEEEquantizedtextheightdiff\textheight +\advance\IEEEquantizedtextheightdiff by -\topskip\relax +\IEEEquantizelength{#2}{#1}{\IEEEquantizedtextheightdiff} +% add back \topskip line +\advance\IEEEquantizedlength by \topskip +\@IEEEtrantmpcountC\IEEEquantizedlengthint\relax +\advance\@IEEEtrantmpcountC by 1\relax +% globally assign the results to macros we use here to escape the enclosing +% group without needing to call \global on any of the \@IEEEtrantmp variables. +\xdef\@IEEEquantizedtextheightlpcmacro{\the\@IEEEtrantmpcountC}\relax +\@IEEEtrantmpcountC\IEEEquantizedlength\relax +\xdef\@IEEEquantizedtextheightmacro{\the\@IEEEtrantmpcountC}\relax +\@IEEEtrantmpcountC\IEEEquantizedlengthdiff\relax +\xdef\@IEEEquantizedtextheightdiffmacro{\the\@IEEEtrantmpcountC}\relax +\endgroup +% locally assign the outputs here from the macros +\textheight\@IEEEquantizedtextheightmacro sp\relax +\IEEEquantizedtextheightdiff\@IEEEquantizedtextheightdiffmacro sp\relax +\edef\IEEEquantizedtextheightlpc{\@IEEEquantizedtextheightlpcmacro}} + + + +% usage: \IEEEsettopmargin[sample text]{mode: t, b, c, a, q}{margin/offset} +% Sets \topmargin based on the specified vertical margin. +% Takes into consideration the base 1in offset, \headheight, \headsep, +% \topskip, and (by default) the the actual height (or, for the bottom, depth) +% of the \IEEEdefaultsampletext text. +% The available modes are: +% t = top margin +% b = bottom margin +% c = vertically centered, with the given offset +% a = adjust the vertical margins using the given offset +% q = adjust the margins using \IEEEquantizedtextheightdiff and the given offset +% For the offsets, positive values increase the top margin. +% \headheight, \headsep, \topskip and \textheight should be set properly for the +% given margins before calling this function. +\def\IEEEsettopmargin{\@ifnextchar [{\@IEEEsettopmargin}{\@IEEEsettopmargin[\IEEEdefaultsampletext]}} +\def\@IEEEsettopmargin[#1]#2#3{\@IEEEtrantmpdimenA #3\relax +\@IEEEextracttoken{#2}\relax +% check for mode errors +\ifx\@IEEEextractedtokenmacro\@empty + \@IEEEclspkgerror{Empty mode type in \string\IEEEsettopmargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `t'}{Valid modes for \string\IEEEsettopmargin\space are: t, b, c, a and q.}\relax + \let\@IEEEextractedtoken=t\relax + \def\@IEEEextractedtokenmacro{t}\relax +\else + \ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: \string\IEEEsettopmargin\space mode specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax + \fi +\fi +% handle each mode +\if\@IEEEextractedtoken a\relax + \advance\topmargin by \@IEEEtrantmpdimenA\relax +\else +\if\@IEEEextractedtoken q\relax + % we need to adjust by half the \IEEEquantizedtextheightdiff value + \@IEEEtrantmpdimenB\IEEEquantizedtextheightdiff\relax + \divide\@IEEEtrantmpdimenB by 2\relax + % a positive \IEEEquantizedtextheightdiff means we need to reduce \topmargin + % because \textheight has been lenghtened + \advance\topmargin by -\@IEEEtrantmpdimenB\relax + \advance\topmargin by \@IEEEtrantmpdimenA\relax +\else +\if\@IEEEextractedtoken c\relax + \topmargin\paperheight + \advance\topmargin by -\textheight + % \textheight includes \topskip, but we should not count topskip whitespace here, backout + \advance \topmargin by \topskip + \settoheight{\@IEEEtrantmpdimenB}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\topmargin by -\@IEEEtrantmpdimenB\relax + \settodepth{\@IEEEtrantmpdimenB}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\topmargin by -\@IEEEtrantmpdimenB\relax + \divide\topmargin by 2\relax + \advance\topmargin by \@IEEEtrantmpdimenA\relax +\else +\if\@IEEEextractedtoken b\relax + \topmargin\paperheight + \advance\topmargin by -\textheight + % \textheight includes \topskip, but we should not count topskip whitespace here, backout + \advance \topmargin by \topskip + \settodepth{\@IEEEtrantmpdimenB}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\topmargin by -\@IEEEtrantmpdimenB\relax + \advance\topmargin by -\@IEEEtrantmpdimenA\relax +\else + \if\@IEEEextractedtoken t\relax + \else + \@IEEEclspkgerror{Unknown mode type `\@IEEEextractedtokenmacro' in \string\IEEEsettopmargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `t'}% + {Valid modes for \string\IEEEsettopmargin\space are: t, b, c, a and q.}\relax + \fi + \topmargin\@IEEEtrantmpdimenA\relax + \settoheight{\@IEEEtrantmpdimenB}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\topmargin by \@IEEEtrantmpdimenB\relax +\fi\fi % if t, b, c +% convert desired top margin into actual \topmargin +% this is not done for the q or a modes because they are only adjustments +\advance \topmargin by -\topskip +\advance \topmargin by -1in +\advance \topmargin by -\headheight +\advance \topmargin by -\headsep +\fi\fi % if q, a +} + + + +% usage: \IEEEsetheadermargin[header sample][text sample]{mode: t, b, c, a}{margin/offset} +% Differentially adjusts \topmargin and \headsep (such that their sum is unchanged) +% based on the specified header margin. +% Takes into consideration the base 1in offset, \headheight, \topskip, and (by default) +% the actual height (or depth) of the \IEEEdefaultheadersampletext and +% \IEEEdefaultsampletext text. +% The available modes are: +% t = top margin (top of the header text to the top of the page) +% b = bottom margin (bottom of the header text to the top of the main text) +% c = vertically centered between the main text and the top of the page, +% with the given offset +% a = adjust the vertical position using the given offset +% For the offsets, positive values move the header downward. +% \headheight, \headsep, \topskip and \topmargin should be set properly before +% calling this function. +\def\IEEEsetheadermargin{\@ifnextchar [{\@IEEEsetheadermargin}{\@IEEEsetheadermargin[\IEEEdefaultheadersampletext]}} +\def\@IEEEsetheadermargin[#1]{\@ifnextchar [{\@@IEEEsetheadermargin[#1]}{\@@IEEEsetheadermargin[#1][\IEEEdefaultsampletext]}} +\def\@@IEEEsetheadermargin[#1][#2]#3#4{\@IEEEtrantmpdimenA #4\relax +\@IEEEextracttoken{#3}\relax +% check for mode errors +\ifx\@IEEEextractedtokenmacro\@empty + \@IEEEclspkgerror{Empty mode type in \string\IEEEsetheadermargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `t'}{Valid modes for \string\IEEEsetheadermargin\space are: t, b, c, and a.}\relax + \let\@IEEEextractedtoken=t\relax + \def\@IEEEextractedtokenmacro{t}\relax +\else + \ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: \string\IEEEsetheadermargin\space mode specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax + \fi +\fi +% handle each mode +\if\@IEEEextractedtoken a\relax + % No need to do anything here and can pass through the adjustment + % value as is. The end adjustment of \topmargin and \headsep will + % do all that is needed +\else +\if\@IEEEextractedtoken c\relax + % get the bottom margin + \@IEEEtrantmpdimenB\headsep\relax + \settodepth{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + \advance\@IEEEtrantmpdimenB by \topskip + \settoheight{\@IEEEtrantmpdimenC}{\begingroup #2\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the actual header bottom margin + % subtract from it the top header margin + \advance\@IEEEtrantmpdimenB -1in\relax % take into consideration the system 1in offset of the top margin + \advance\@IEEEtrantmpdimenB by -\topmargin + \advance\@IEEEtrantmpdimenB by -\headheight + \settoheight{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by \@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the difference between the bottom and top margins + % we need to adjust by half this amount to center the header + \divide\@IEEEtrantmpdimenB by 2\relax + % and add to offset + \advance\@IEEEtrantmpdimenA by \@IEEEtrantmpdimenB +\else +\if\@IEEEextractedtoken b\relax + \@IEEEtrantmpdimenB\headsep\relax + \settodepth{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + \advance\@IEEEtrantmpdimenB by \topskip + \settoheight{\@IEEEtrantmpdimenC}{\begingroup #2\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the actual header bottom margin + % get the difference between the actual and the desired + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenA + \@IEEEtrantmpdimenA\@IEEEtrantmpdimenB +\else + \if\@IEEEextractedtoken t\relax + \else + \@IEEEclspkgerror{Unknown mode type `\@IEEEextractedtokenmacro' in \string\IEEEsetheadermargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `t'}% + {Valid modes for \string\IEEEsetheadermargin\space are: t, b, c and a.}\relax + \fi + \@IEEEtrantmpdimenB 1in\relax % take into consideration the system 1in offset of the top margin + \advance\@IEEEtrantmpdimenB by \topmargin + \advance\@IEEEtrantmpdimenB by \headheight + \settoheight{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the actual header top margin + % get the difference between the desired and the actual + \advance\@IEEEtrantmpdimenA by -\@IEEEtrantmpdimenB +\fi\fi % if t, b, c +\fi % if a +% advance \topmargin by the needed amount and reduce \headsep by the same +% so as not to disturb the location of the main text +\advance\topmargin by \@IEEEtrantmpdimenA\relax +\advance\headsep by -\@IEEEtrantmpdimenA\relax +} + + + +% usage: \IEEEsetfootermargin[footer sample][text sample]{mode: t, b, c, a}{margin/offset} +% Adjusts \footskip based on the specified footer margin. +% Takes into consideration the base 1in offset, \paperheight, \headheight, +% \headsep, \textheight and (by default) the actual height (or depth) of the +% \IEEEdefaultfootersampletext and \IEEEdefaultsampletext text. +% The available modes are: +% t = top margin (top of the footer text to the bottom of the main text) +% b = bottom margin (bottom of the footer text to the bottom of page) +% c = vertically centered between the main text and the bottom of the page, +% with the given offset +% a = adjust the vertical position using the given offset +% For the offsets, positive values move the footer downward. +% \headheight, \headsep, \topskip, \topmargin, and \textheight should be set +% properly before calling this function. +\def\IEEEsetfootermargin{\@ifnextchar [{\@IEEEsetfootermargin}{\@IEEEsetfootermargin[\IEEEdefaultfootersampletext]}} +\def\@IEEEsetfootermargin[#1]{\@ifnextchar [{\@@IEEEsetfootermargin[#1]}{\@@IEEEsetfootermargin[#1][\IEEEdefaultsampletext]}} +\def\@@IEEEsetfootermargin[#1][#2]#3#4{\@IEEEtrantmpdimenA #4\relax +\@IEEEextracttoken{#3}\relax +% check for mode errors +\ifx\@IEEEextractedtokenmacro\@empty + \@IEEEclspkgerror{Empty mode type in \string\IEEEsetfootermargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `t'}{Valid modes for \string\IEEEsetfootermargin\space are: t, b, c, and a.}\relax + \let\@IEEEextractedtoken=t\relax + \def\@IEEEextractedtokenmacro{t}\relax +\else + \ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: \string\IEEEsetfootermargin\space mode specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax + \fi +\fi +% handle each mode +\if\@IEEEextractedtoken a\relax + % No need to do anything here and can pass through the adjustment + % value as is. The end adjustment of \footskip will do all that + % is needed +\else +\if\@IEEEextractedtoken c\relax + % calculate the bottom margin + \@IEEEtrantmpdimenB 1in\relax % system 1in offset + \advance\@IEEEtrantmpdimenB\topmargin\relax + \advance\@IEEEtrantmpdimenB\headheight\relax + \advance\@IEEEtrantmpdimenB\headsep\relax + \advance\@IEEEtrantmpdimenB\textheight\relax + \advance\@IEEEtrantmpdimenB\footskip\relax + \settodepth{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenC by \@IEEEtrantmpdimenB + \@IEEEtrantmpdimenB\paperheight + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the actual footer bottom margin + % now subtract off the footer top margin + \advance\@IEEEtrantmpdimenB -\footskip\relax + \settodepth{\@IEEEtrantmpdimenC}{\begingroup #2\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by \@IEEEtrantmpdimenC + \settoheight{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by \@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the difference between the bottom + % and top footer margins + % our adjustment must be half this value to center the footer + \divide\@IEEEtrantmpdimenB by 2\relax + % add to the offset + \advance\@IEEEtrantmpdimenA by \@IEEEtrantmpdimenB +\else +\if\@IEEEextractedtoken b\relax + % calculate the bottom margin + \@IEEEtrantmpdimenB 1in\relax % system 1in offset + \advance\@IEEEtrantmpdimenB\topmargin\relax + \advance\@IEEEtrantmpdimenB\headheight\relax + \advance\@IEEEtrantmpdimenB\headsep\relax + \advance\@IEEEtrantmpdimenB\textheight\relax + \advance\@IEEEtrantmpdimenB\footskip\relax + \settodepth{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenC by \@IEEEtrantmpdimenB + \@IEEEtrantmpdimenB\paperheight + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the actual footer bottom margin + % get the difference between the actual and the desired + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenA + \@IEEEtrantmpdimenA\@IEEEtrantmpdimenB +\else + \if\@IEEEextractedtoken t\relax + \else + \@IEEEclspkgerror{Unknown mode type `\@IEEEextractedtokenmacro' in \string\IEEEsetfootermargin\space (line \the\inputlineno).\MessageBreak + Defaulting to `t'}% + {Valid modes for \string\IEEEsetfootermargin\space are: t, b, c and a.}\relax + \fi + \@IEEEtrantmpdimenB\footskip\relax + \settodepth{\@IEEEtrantmpdimenC}{\begingroup #2\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + \settoheight{\@IEEEtrantmpdimenC}{\begingroup #1\relax\relax\relax\endgroup}\relax + \advance\@IEEEtrantmpdimenB by -\@IEEEtrantmpdimenC + % at this point \@IEEEtrantmpdimenB has the actual footer top margin + % get the difference between the desired and the actual + \advance\@IEEEtrantmpdimenA by -\@IEEEtrantmpdimenB +\fi\fi % if t, b, c +\fi % if a +% advance \footskip by the needed amount +\advance\footskip by \@IEEEtrantmpdimenA\relax +} + +% -- End V1.8a page setup commands -- + + + + + +% V1.6 +% LaTeX is a little to quick to use hyphenations +% So, we increase the penalty for their use and raise +% the badness level that triggers an underfull hbox +% warning. The author may still have to tweak things, +% but the appearance will be much better "right out +% of the box" than that under V1.5 and prior. +% TeX default is 50 +\hyphenpenalty=750 +\ifCLASSOPTIONcompsoc +\hyphenpenalty 500 +\fi +% If we didn't adjust the interword spacing, 2200 might be better. +% The TeX default is 1000 +\hbadness=1350 +% The IEEE does not use extra spacing after punctuation +\frenchspacing + +% V1.7 increase this a tad to discourage equation breaks +\binoppenalty=1000 % default 700 +\relpenalty=800 % default 500 + +% v1.8a increase these to discourage widows and orphans +\clubpenalty=1000 % default 150 +\widowpenalty=1000 % default 150 +\displaywidowpenalty=1000 % default 50 + + +% margin note stuff +\marginparsep 10pt +\marginparwidth 20pt +\marginparpush 25pt + + +% if things get too close, go ahead and let them touch +\lineskip 0pt +\normallineskip 0pt +\lineskiplimit 0pt +\normallineskiplimit 0pt + +% The distance from the lower edge of the text body to the +% footline +\footskip 0.4in + +% normally zero, should be relative to font height. +% put in a little rubber to help stop some bad breaks (underfull vboxes) +\parskip 0ex plus 0.2ex minus 0.1ex + +\parindent 1.0em +\ifCLASSOPTIONcompsoc + \parindent 1.5em +\fi + +\headheight 12pt +\headsep 18pt +% use the normal font baselineskip +% so that \topskip is unaffected by changes in \baselinestretch +\topskip=\@IEEEnormalsizeunitybaselineskip + + +% V1.8 \maxdepth defaults to 4pt, but should be font size dependent +\maxdepth=0.5\@IEEEnormalsizeunitybaselineskip +\textheight 58pc % 9.63in, 696pt + +% set the default top margin to 58pt +% which results in a \topmargin of -49.59pt for 10pt documents +\IEEEsettopmargin{t}{58pt} +% tweak textheight to a perfect integer number of lines/column. +% standard is: 9pt/63 lpc; 10pt/58 lpc; 11pt/52 lpc; 12pt/50 lpc +\IEEEquantizetextheight{c} +% tweak top margin so that the error is shared equally at the top and bottom +\IEEEsettopmargin{q}{0sp} + + +\columnsep 1pc +\textwidth 43pc % 2 x 21pc + 1pc = 43pc + +% set the default side margins to center the text +\IEEEsetsidemargin{c}{0pt} + + +% adjust margins for default conference mode +\ifCLASSOPTIONconference + \textheight 9.25in % The standard for conferences (668.4975pt) + \IEEEsettopmargin{t}{0.75in} + % tweak textheight to a perfect integer number of lines/page. + % standard is: 9pt/61 lpc; 10pt/56 lpc; 11pt/50 lpc; 12pt/48 lpc + \IEEEquantizetextheight{c} + % tweak top margin so that the error is shared equally at the top and bottom + \IEEEsettopmargin{q}{0sp} +\fi + + +% compsoc text sizes, margins and spacings +\ifCLASSOPTIONcompsoc + \columnsep 12bp + % CS specs for \textwdith are 6.875in + % \textwidth 6.875in + % however, measurements from proofs show they are using 3.5in columns + \textwidth 7in + \advance\textwidth by \columnsep + % set the side margins to center the text + \IEEEsetsidemargin{c}{0pt} + % top/bottom margins to center + % could just set \textheight to 9.75in for all the different paper sizes + % and then quantize, but we'll do it the long way here to allow for easy + % future per-paper size adjustments + \IEEEsettextheight{0.625in}{0.625in}% 11in - 2 * 0.625in = 9.75in is the standard text height for compsoc journals + \IEEEsettopmargin{t}{0.625in} + \if@IEEEusingcspaper + \IEEEsettextheight{0.5in}{0.5in}% 10.75in - 2 * 0.5in = 9.75in + \IEEEsettopmargin{t}{0.5in} + \fi + \if@IEEEusingAfourpaper + \IEEEsettextheight{24.675mm}{24.675mm}% 297mm - 2 * 24.675mm = 247.650mm (9.75in) + \IEEEsettopmargin{t}{24.675mm} + \fi + % tweak textheight to a perfect integer number of lines/page. + % standard is: 9pt/65 lpc; 10pt/61 lpc; 11pt/53 lpc; 12pt/49 lpc + \IEEEquantizetextheight{c} + % tweak top margin so that the error is shared equally at the top and bottom + \IEEEsettopmargin{q}{0sp} + +% compsoc conference + \ifCLASSOPTIONconference + % compsoc conference use a larger value for columnsep + \columnsep 0.25in + \IEEEsettextwidth{0.75in}{0.75in} + % set the side margins to center the text (0.75in for letterpaper) + \IEEEsetsidemargin{c}{0pt} + % compsoc conferences want 1in top and bottom margin + \IEEEsettextheight{1in}{1in} + \IEEEsettopmargin{t}{1in} + % tweak textheight to a perfect integer number of lines/page. + % standard is: 9pt/58 lpc; 10pt/53 lpc; 11pt/48 lpc; 12pt/46 lpc + \IEEEquantizetextheight{c} + % tweak top margin so that the error is shared equally at the top and bottom + \IEEEsettopmargin{q}{0sp} + \fi +\fi + + + +% draft mode settings override that of all other modes +% provides a nice 1in margin all around the paper and extra +% space between the lines for editor's comments +\ifCLASSOPTIONdraftcls + % we want 1in side margins regardless of paper type + \IEEEsettextwidth{1in}{1in} + \IEEEsetsidemargin{c}{0pt} + % want 1in top and bottom margins + \IEEEsettextheight{1in}{1in} + \IEEEsettopmargin{t}{1in} + % digitize textheight to be an integer number of lines. + % this may cause the top and bottom margins to be off a tad + \IEEEquantizetextheight{c} + % tweak top margin so that the error is shared equally at the top and bottom + \IEEEsettopmargin{q}{0sp} +\fi + + + +% process CLASSINPUT inner/outer margin +% if inner margin defined, but outer margin not, set outer to inner. +\ifx\CLASSINPUTinnersidemargin\@IEEEundefined +\else + \ifx\CLASSINPUToutersidemargin\@IEEEundefined + \edef\CLASSINPUToutersidemargin{\CLASSINPUTinnersidemargin} + \fi +\fi + +\ifx\CLASSINPUToutersidemargin\@IEEEundefined +\else + % if outer margin defined, but inner margin not, set inner to outer. + \ifx\CLASSINPUTinnersidemargin\@IEEEundefined + \edef\CLASSINPUTinnersidemargin{\CLASSINPUToutersidemargin} + \fi + \IEEEsettextwidth{\CLASSINPUTinnersidemargin}{\CLASSINPUToutersidemargin} + \IEEEsetsidemargin{i}{\CLASSINPUTinnersidemargin} + \typeout{** ATTENTION: Overriding inner side margin to \CLASSINPUTinnersidemargin\space and + outer side margin to \CLASSINPUToutersidemargin\space via \string\CLASSINPUT.} +\fi + + + +% process CLASSINPUT top/bottom text margin +% if toptext margin defined, but bottomtext margin not, set bottomtext to toptext margin +\ifx\CLASSINPUTtoptextmargin\@IEEEundefined +\else + \ifx\CLASSINPUTbottomtextmargin\@IEEEundefined + \edef\CLASSINPUTbottomtextmargin{\CLASSINPUTtoptextmargin} + \fi +\fi + +\ifx\CLASSINPUTbottomtextmargin\@IEEEundefined +\else + % if bottomtext margin defined, but toptext margin not, set toptext to bottomtext margin + \ifx\CLASSINPUTtoptextmargin\@IEEEundefined + \edef\CLASSINPUTtoptextmargin{\CLASSINPUTbottomtextmargin} + \fi + \IEEEsettextheight{\CLASSINPUTtoptextmargin}{\CLASSINPUTbottomtextmargin} + \IEEEsettopmargin{t}{\CLASSINPUTtoptextmargin} + \typeout{** ATTENTION: Overriding top text margin to \CLASSINPUTtoptextmargin\space and + bottom text margin to \CLASSINPUTbottomtextmargin\space via \string\CLASSINPUT.} +\fi + + + +% default to center header and footer text in the margins +\IEEEsetheadermargin{c}{0pt} +\IEEEsetfootermargin{c}{0pt} + +% adjust header and footer positions for compsoc journals +\ifCLASSOPTIONcompsoc + \ifCLASSOPTIONjournal + \IEEEsetheadermargin{b}{\@IEEEnormalsizeunitybaselineskip} + \IEEEsetfootermargin{t}{\@IEEEnormalsizeunitybaselineskip} + \fi +\fi + + +% V1.8a display lines per column info message on user's console +\def\IEEEdisplayinfolinespercolumn{\@IEEEtrantmpdimenA=\textheight +% topskip represents only one line even if > baselineskip +\advance\@IEEEtrantmpdimenA by -1\topskip +\@IEEEtrantmpcountA=\@IEEEtrantmpdimenA +\@IEEEtrantmpcountB=\@IEEEtrantmpdimenA +\divide\@IEEEtrantmpcountB by \baselineskip +% need to add one line to include topskip (first) line +\advance\@IEEEtrantmpcountB by 1 +% save lines per column value as text +\edef\@IEEEnumlinespercolumninfotxt{\the\@IEEEtrantmpcountB} +% backout topskip advance to allow direct \@IEEEtrantmpcountA comparison +\advance\@IEEEtrantmpcountB by -1 +% restore value as text height (without topskip) rather than just as number of lines +\multiply\@IEEEtrantmpcountB by \baselineskip +% is the column height an integer number of lines per column? +\ifnum\@IEEEtrantmpcountA=\@IEEEtrantmpcountB +\edef\@IEEEnumlinespercolumnexactinfotxt{exact} +\else +\@IEEEtrantmpdimenA\@IEEEtrantmpcountA sp\relax +\advance\@IEEEtrantmpdimenA by -\@IEEEtrantmpcountB sp\relax +\edef\@IEEEnumlinespercolumnexactinfotxt{approximate, difference = \the\@IEEEtrantmpdimenA} +\fi +\typeout{-- Lines per column: \@IEEEnumlinespercolumninfotxt\space (\@IEEEnumlinespercolumnexactinfotxt).}} +% delay execution till start of document to allow for user changes +\AtBeginDocument{\IEEEdisplayinfolinespercolumn} + + + +% LIST SPACING CONTROLS + +% Controls the amount of EXTRA spacing +% above and below \trivlist +% Both \list and IED lists override this. +% However, \trivlist will use this as will most +% things built from \trivlist like the \center +% environment. +\topsep 0.5\baselineskip + +% Controls the additional spacing around lists preceded +% or followed by blank lines. the IEEE does not increase +% spacing before or after paragraphs so it is set to zero. +% \z@ is the same as zero, but faster. +\partopsep \z@ + +% Controls the spacing between paragraphs in lists. +% The IEEE does not increase spacing before or after paragraphs +% so this is also zero. +% With IEEEtran.cls, global changes to +% this value DO affect lists (but not IED lists). +\parsep \z@ + +% Controls the extra spacing between list items. +% The IEEE does not put extra spacing between items. +% With IEEEtran.cls, global changes to this value DO affect +% lists (but not IED lists). +\itemsep \z@ + +% \itemindent is the amount to indent the FIRST line of a list +% item. It is auto set to zero within the \list environment. To alter +% it, you have to do so when you call the \list. +% However, the IEEE uses this for the theorem environment +% There is an alternative value for this near \leftmargini below +\itemindent -1em + +% \leftmargin, the spacing from the left margin of the main text to +% the left of the main body of a list item is set by \list. +% Hence this statement does nothing for lists. +% But, quote and verse do use it for indention. +\leftmargin 2em + +% we retain this stuff from the older IEEEtran.cls so that \list +% will work the same way as before. However, itemize, enumerate and +% description (IED) could care less about what these are as they +% all are overridden. +\leftmargini 2em +%\itemindent 2em % Alternative values: sometimes used. +%\leftmargini 0em +\leftmarginii 1em +\leftmarginiii 1.5em +\leftmarginiv 1.5em +\leftmarginv 1.0em +\leftmarginvi 1.0em +\labelsep 0.5em +\labelwidth \z@ + + +% The old IEEEtran.cls behavior of \list is retained. +% However, the new V1.3 IED list environments override all the +% @list stuff (\@listX is called within \list for the +% appropriate level just before the user's list_decl is called). +% \topsep is now 2pt as the IEEE puts a little extra space around +% lists - used by those non-IED macros that depend on \list. +% Note that \parsep and \itemsep are not redefined as in +% the sizexx.clo \@listX (which article.cls uses) so global changes +% of these values DO affect \list +% +\def\@listi{\leftmargin\leftmargini \topsep 2pt plus 1pt minus 1pt} +\let\@listI\@listi +\def\@listii{\leftmargin\leftmarginii\labelwidth\leftmarginii% + \advance\labelwidth-\labelsep \topsep 2pt} +\def\@listiii{\leftmargin\leftmarginiii\labelwidth\leftmarginiii% + \advance\labelwidth-\labelsep \topsep 2pt} +\def\@listiv{\leftmargin\leftmarginiv\labelwidth\leftmarginiv% + \advance\labelwidth-\labelsep \topsep 2pt} +\def\@listv{\leftmargin\leftmarginv\labelwidth\leftmarginv% + \advance\labelwidth-\labelsep \topsep 2pt} +\def\@listvi{\leftmargin\leftmarginvi\labelwidth\leftmarginvi% + \advance\labelwidth-\labelsep \topsep 2pt} + + +% The IEEE uses 5) not 5. +\def\labelenumi{\theenumi)} \def\theenumi{\arabic{enumi}} + +% The IEEE uses a) not (a) +\def\labelenumii{\theenumii)} \def\theenumii{\alph{enumii}} + +% The IEEE uses iii) not iii. +\def\labelenumiii{\theenumiii)} \def\theenumiii{\roman{enumiii}} + +% The IEEE uses A) not A. +\def\labelenumiv{\theenumiv)} \def\theenumiv{\Alph{enumiv}} + +% exactly the same as in article.cls +\def\p@enumii{\theenumi} +\def\p@enumiii{\theenumi(\theenumii)} +\def\p@enumiv{\p@enumiii\theenumiii} + +% itemized list label styles +\def\labelitemi{$\scriptstyle\bullet$} +\def\labelitemii{\textbf{--}} +\def\labelitemiii{$\ast$} +\def\labelitemiv{$\cdot$} + + + +% **** V1.3 ENHANCEMENTS **** +% Itemize, Enumerate and Description (IED) List Controls +% *************************** +% +% +% The IEEE seems to use at least two different values by +% which ITEMIZED list labels are indented to the right +% For The Journal of Lightwave Technology (JLT) and The Journal +% on Selected Areas in Communications (JSAC), they tend to use +% an indention equal to \parindent. For Transactions on Communications +% they tend to indent ITEMIZED lists a little more--- 1.3\parindent. +% We'll provide both values here for you so that you can choose +% which one you like in your document using a command such as: +% setlength{\IEEEilabelindent}{\IEEEilabelindentB} +\newdimen\IEEEilabelindentA +\IEEEilabelindentA \parindent + +\newdimen\IEEEilabelindentB +\IEEEilabelindentB 1.3\parindent +% However, we'll default to using \parindent +% which makes more sense to me +\newdimen\IEEEilabelindent +\IEEEilabelindent \IEEEilabelindentA + + +% This controls the default amount the enumerated list labels +% are indented to the right. +% Normally, this is the same as the paragraph indention +\newdimen\IEEEelabelindent +\IEEEelabelindent \parindent + +% This controls the default amount the description list labels +% are indented to the right. +% Normally, this is the same as the paragraph indention +\newdimen\IEEEdlabelindent +\IEEEdlabelindent \parindent + +% This is the value actually used within the IED lists. +% The IED environments automatically set its value to +% one of the three values above, so global changes do +% not have any effect +\newdimen\IEEElabelindent +\IEEElabelindent \parindent + +% The actual amount labels will be indented is +% \IEEElabelindent multiplied by the factor below +% corresponding to the level of nesting depth +% This provides a means by which the user can +% alter the effective \IEEElabelindent for deeper +% levels +% There may not be such a thing as correct "standard IEEE" +% values. What the IEEE actually does may depend on the specific +% circumstances. +% The first list level almost always has full indention. +% The second levels I've seen have only 75% of the normal indentation +% Three level or greater nestings are very rare. I am guessing +% that they don't use any indentation. +\def\IEEElabelindentfactori{1.0} % almost always one +\def\IEEElabelindentfactorii{0.75} % 0.0 or 1.0 may be used in some cases +\def\IEEElabelindentfactoriii{0.0} % 0.75? 0.5? 0.0? +\def\IEEElabelindentfactoriv{0.0} +\def\IEEElabelindentfactorv{0.0} +\def\IEEElabelindentfactorvi{0.0} + +% value actually used within IED lists, it is auto +% set to one of the 6 values above +% global changes here have no effect +\def\IEEElabelindentfactor{1.0} + +% This controls the default spacing between the end of the IED +% list labels and the list text, when normal text is used for +% the labels. +% compsoc uses a larger value here, but we'll set that later +% in the class so that this code block area can be extracted +% as-is for IEEEtrantools.sty +\newdimen\IEEEiednormlabelsep +\IEEEiednormlabelsep 0.6em + +% This controls the default spacing between the end of the IED +% list labels and the list text, when math symbols are used for +% the labels (nomenclature lists). The IEEE usually increases the +% spacing in these cases +\newdimen\IEEEiedmathlabelsep +\IEEEiedmathlabelsep 1.2em + +% This controls the extra vertical separation put above and +% below each IED list. the IEEE usually puts a little extra spacing +% around each list. However, this spacing is barely noticeable. +% compsoc uses a larger value here, but we'll set that later +% in the class so that this code block area can be extracted +% as-is for IEEEtrantools.sty +\newskip\IEEEiedtopsep +\IEEEiedtopsep 2pt plus 1pt minus 1pt + + +% This command is executed within each IED list environment +% at the beginning of the list. You can use this to set the +% parameters for some/all your IED list(s) without disturbing +% global parameters that affect things other than lists. +% i.e., renewcommand{\IEEEiedlistdecl}{\setlength{\labelsep}{5em}} +% will alter the \labelsep for the next list(s) until +% \IEEEiedlistdecl is redefined. +\def\IEEEiedlistdecl{\relax} + +% This command provides an easy way to set \leftmargin based +% on the \labelwidth, \labelsep and the argument \IEEElabelindent +% Usage: \IEEEcalcleftmargin{width-to-indent-the-label} +% output is in the \leftmargin variable, i.e., effectively: +% \leftmargin = argument + \labelwidth + \labelsep +% Note controlled spacing here, shield end of lines with % +\def\IEEEcalcleftmargin#1{\setlength{\leftmargin}{#1}% +\addtolength{\leftmargin}{\labelwidth}% +\addtolength{\leftmargin}{\labelsep}} + +% This command provides an easy way to set \labelwidth to the +% width of the given text. It is the same as +% \settowidth{\labelwidth}{label-text} +% and useful as a shorter alternative. +% Typically used to set \labelwidth to be the width +% of the longest label in the list +\def\IEEEsetlabelwidth#1{\settowidth{\labelwidth}{#1}} + +% When this command is executed, IED lists will use the +% IEEEiedmathlabelsep label separation rather than the normal +% spacing. To have an effect, this command must be executed via +% the \IEEEiedlistdecl or within the option of the IED list +% environments. +\def\IEEEusemathlabelsep{\setlength{\labelsep}{\IEEEiedmathlabelsep}} + +% A flag which controls whether the IED lists automatically +% calculate \leftmargin from \IEEElabelindent, \labelwidth and \labelsep +% Useful if you want to specify your own \leftmargin +% This flag must be set (\IEEEnocalcleftmargintrue or \IEEEnocalcleftmarginfalse) +% via the \IEEEiedlistdecl or within the option of the IED list +% environments to have an effect. +\newif\ifIEEEnocalcleftmargin +\IEEEnocalcleftmarginfalse + +% A flag which controls whether \IEEElabelindent is multiplied by +% the \IEEElabelindentfactor for each list level. +% This flag must be set via the \IEEEiedlistdecl or within the option +% of the IED list environments to have an effect. +\newif\ifIEEEnolabelindentfactor +\IEEEnolabelindentfactorfalse + + +% internal variable to indicate type of IED label +% justification +% 0 - left; 1 - center; 2 - right +\def\@IEEEiedjustify{0} + + +% commands to allow the user to control IED +% label justifications. Use these commands within +% the IED environment option or in the \IEEEiedlistdecl +% Note that changing the normal list justifications +% is nonstandard and the IEEE may not like it if you do so! +% I include these commands as they may be helpful to +% those who are using these enhanced list controls for +% other non-IEEE related LaTeX work. +% itemize and enumerate automatically default to right +% justification, description defaults to left. +\def\IEEEiedlabeljustifyl{\def\@IEEEiedjustify{0}}%left +\def\IEEEiedlabeljustifyc{\def\@IEEEiedjustify{1}}%center +\def\IEEEiedlabeljustifyr{\def\@IEEEiedjustify{2}}%right + + + + +% commands to save to and restore from the list parameter copies +% this allows us to set all the list parameters within +% the list_decl and prevent \list (and its \@list) +% from overriding any of our parameters +% V1.6 use \edefs instead of dimen's to conserve dimen registers +% Note controlled spacing here, shield end of lines with % +\def\@IEEEsavelistparams{\edef\@IEEEiedtopsep{\the\topsep}% +\edef\@IEEEiedlabelwidth{\the\labelwidth}% +\edef\@IEEEiedlabelsep{\the\labelsep}% +\edef\@IEEEiedleftmargin{\the\leftmargin}% +\edef\@IEEEiedpartopsep{\the\partopsep}% +\edef\@IEEEiedparsep{\the\parsep}% +\edef\@IEEEieditemsep{\the\itemsep}% +\edef\@IEEEiedrightmargin{\the\rightmargin}% +\edef\@IEEEiedlistparindent{\the\listparindent}% +\edef\@IEEEieditemindent{\the\itemindent}} + +% Note controlled spacing here +\def\@IEEErestorelistparams{\topsep\@IEEEiedtopsep\relax% +\labelwidth\@IEEEiedlabelwidth\relax% +\labelsep\@IEEEiedlabelsep\relax% +\leftmargin\@IEEEiedleftmargin\relax% +\partopsep\@IEEEiedpartopsep\relax% +\parsep\@IEEEiedparsep\relax% +\itemsep\@IEEEieditemsep\relax% +\rightmargin\@IEEEiedrightmargin\relax% +\listparindent\@IEEEiedlistparindent\relax% +\itemindent\@IEEEieditemindent\relax} + + +% v1.6b provide original LaTeX IED list environments +% note that latex.ltx defines \itemize and \enumerate, but not \description +% which must be created by the base classes +% save original LaTeX itemize and enumerate +\let\LaTeXitemize\itemize +\let\endLaTeXitemize\enditemize +\let\LaTeXenumerate\enumerate +\let\endLaTeXenumerate\endenumerate + +% provide original LaTeX description environment from article.cls +\newenvironment{LaTeXdescription} + {\list{}{\labelwidth\z@ \itemindent-\leftmargin + \let\makelabel\descriptionlabel}} + {\endlist} +\newcommand*\descriptionlabel[1]{\hspace\labelsep + \normalfont\bfseries #1} + + +% override LaTeX's default IED lists +\def\itemize{\@IEEEitemize} +\def\enditemize{\@endIEEEitemize} +\def\enumerate{\@IEEEenumerate} +\def\endenumerate{\@endIEEEenumerate} +\def\description{\@IEEEdescription} +\def\enddescription{\@endIEEEdescription} + +% provide the user with aliases - may help those using packages that +% override itemize, enumerate, or description +\def\IEEEitemize{\@IEEEitemize} +\def\endIEEEitemize{\@endIEEEitemize} +\def\IEEEenumerate{\@IEEEenumerate} +\def\endIEEEenumerate{\@endIEEEenumerate} +\def\IEEEdescription{\@IEEEdescription} +\def\endIEEEdescription{\@endIEEEdescription} + + +% V1.6 we want to keep the IEEEtran IED list definitions as our own internal +% commands so they are protected against redefinition +\def\@IEEEitemize{\@ifnextchar[{\@@IEEEitemize}{\@@IEEEitemize[\relax]}} +\def\@IEEEenumerate{\@ifnextchar[{\@@IEEEenumerate}{\@@IEEEenumerate[\relax]}} +\def\@IEEEdescription{\@ifnextchar[{\@@IEEEdescription}{\@@IEEEdescription[\relax]}} +\def\@endIEEEitemize{\endlist} +\def\@endIEEEenumerate{\endlist} +\def\@endIEEEdescription{\endlist} + + +% DO NOT ALLOW BLANK LINES TO BE IN THESE IED ENVIRONMENTS +% AS THIS WILL FORCE NEW PARAGRAPHS AFTER THE IED LISTS +% IEEEtran itemized list MDS 1/2001 +% Note controlled spacing here, shield end of lines with % +\def\@@IEEEitemize[#1]{% + \ifnum\@itemdepth>3\relax\@toodeep\else% + \ifnum\@listdepth>5\relax\@toodeep\else% + \advance\@itemdepth\@ne% + \edef\@itemitem{labelitem\romannumeral\the\@itemdepth}% + % get the IEEElabelindentfactor for this level + \advance\@listdepth\@ne% we need to know what the level WILL be + \edef\IEEElabelindentfactor{\csname IEEElabelindentfactor\romannumeral\the\@listdepth\endcsname}% + \advance\@listdepth-\@ne% undo our increment + \def\@IEEEiedjustify{2}% right justified labels are default + % set other defaults + \IEEEnocalcleftmarginfalse% + \IEEEnolabelindentfactorfalse% + \topsep\IEEEiedtopsep% + \IEEElabelindent\IEEEilabelindent% + \labelsep\IEEEiednormlabelsep% + \partopsep 0ex% + \parsep 0ex% + \itemsep 0ex% + \rightmargin 0em% + \listparindent 0em% + \itemindent 0em% + % calculate the label width + % the user can override this later if + % they specified a \labelwidth + \settowidth{\labelwidth}{\csname labelitem\romannumeral\the\@itemdepth\endcsname}% + \@IEEEsavelistparams% save our list parameters + \list{\csname\@itemitem\endcsname}{% + \@IEEErestorelistparams% override any list{} changes + % to our globals + \let\makelabel\@IEEEiedmakelabel% v1.6b setup \makelabel + \IEEEiedlistdecl% let user alter parameters + #1\relax% + % If the user has requested not to use the + % IEEElabelindent factor, don't revise \IEEElabelindent + \ifIEEEnolabelindentfactor\relax% + \else\IEEElabelindent=\IEEElabelindentfactor\IEEElabelindent% + \fi% + % Unless the user has requested otherwise, + % calculate our left margin based + % on \IEEElabelindent, \labelwidth and + % \labelsep + \ifIEEEnocalcleftmargin\relax% + \else\IEEEcalcleftmargin{\IEEElabelindent}% + \fi}\fi\fi}% + + +% DO NOT ALLOW BLANK LINES TO BE IN THESE IED ENVIRONMENTS +% AS THIS WILL FORCE NEW PARAGRAPHS AFTER THE IED LISTS +% IEEEtran enumerate list MDS 1/2001 +% Note controlled spacing here, shield end of lines with % +\def\@@IEEEenumerate[#1]{% + \ifnum\@enumdepth>3\relax\@toodeep\else% + \ifnum\@listdepth>5\relax\@toodeep\else% + \advance\@enumdepth\@ne% + \edef\@enumctr{enum\romannumeral\the\@enumdepth}% + % get the IEEElabelindentfactor for this level + \advance\@listdepth\@ne% we need to know what the level WILL be + \edef\IEEElabelindentfactor{\csname IEEElabelindentfactor\romannumeral\the\@listdepth\endcsname}% + \advance\@listdepth-\@ne% undo our increment + \def\@IEEEiedjustify{2}% right justified labels are default + % set other defaults + \IEEEnocalcleftmarginfalse% + \IEEEnolabelindentfactorfalse% + \topsep\IEEEiedtopsep% + \IEEElabelindent\IEEEelabelindent% + \labelsep\IEEEiednormlabelsep% + \partopsep 0ex% + \parsep 0ex% + \itemsep 0ex% + \rightmargin 0em% + \listparindent 0em% + \itemindent 0em% + % calculate the label width + % We'll set it to the width suitable for all labels using + % normalfont 1) to 9) + % The user can override this later + \settowidth{\labelwidth}{9)}% + \@IEEEsavelistparams% save our list parameters + \list{\csname label\@enumctr\endcsname}{\usecounter{\@enumctr}% + \@IEEErestorelistparams% override any list{} changes + % to our globals + \let\makelabel\@IEEEiedmakelabel% v1.6b setup \makelabel + \IEEEiedlistdecl% let user alter parameters + #1\relax% + % If the user has requested not to use the + % IEEElabelindent factor, don't revise \IEEElabelindent + \ifIEEEnolabelindentfactor\relax% + \else\IEEElabelindent=\IEEElabelindentfactor\IEEElabelindent% + \fi% + % Unless the user has requested otherwise, + % calculate our left margin based + % on \IEEElabelindent, \labelwidth and + % \labelsep + \ifIEEEnocalcleftmargin\relax% + \else\IEEEcalcleftmargin{\IEEElabelindent}% + \fi}\fi\fi}% + + +% DO NOT ALLOW BLANK LINES TO BE IN THESE IED ENVIRONMENTS +% AS THIS WILL FORCE NEW PARAGRAPHS AFTER THE IED LISTS +% IEEEtran description list MDS 1/2001 +% Note controlled spacing here, shield end of lines with % +\def\@@IEEEdescription[#1]{% + \ifnum\@listdepth>5\relax\@toodeep\else% + % get the IEEElabelindentfactor for this level + \advance\@listdepth\@ne% we need to know what the level WILL be + \edef\IEEElabelindentfactor{\csname IEEElabelindentfactor\romannumeral\the\@listdepth\endcsname}% + \advance\@listdepth-\@ne% undo our increment + \def\@IEEEiedjustify{0}% left justified labels are default + % set other defaults + \IEEEnocalcleftmarginfalse% + \IEEEnolabelindentfactorfalse% + \topsep\IEEEiedtopsep% + \IEEElabelindent\IEEEdlabelindent% + % assume normal labelsep + \labelsep\IEEEiednormlabelsep% + \partopsep 0ex% + \parsep 0ex% + \itemsep 0ex% + \rightmargin 0em% + \listparindent 0em% + \itemindent 0em% + % Bogus label width in case the user forgets + % to set it. + % TIP: If you want to see what a variable's width is you + % can use the TeX command \showthe\width-variable to + % display it on the screen during compilation + % (This might be helpful to know when you need to find out + % which label is the widest) + \settowidth{\labelwidth}{Hello}% + \@IEEEsavelistparams% save our list parameters + \list{}{\@IEEErestorelistparams% override any list{} changes + % to our globals + \let\makelabel\@IEEEiedmakelabel% v1.6b setup \makelabel + \IEEEiedlistdecl% let user alter parameters + #1\relax% + % If the user has requested not to use the + % labelindent factor, don't revise \IEEElabelindent + \ifIEEEnolabelindentfactor\relax% + \else\IEEElabelindent=\IEEElabelindentfactor\IEEElabelindent% + \fi% + % Unless the user has requested otherwise, + % calculate our left margin based + % on \IEEElabelindent, \labelwidth and + % \labelsep + \ifIEEEnocalcleftmargin\relax% + \else\IEEEcalcleftmargin{\IEEElabelindent}\relax% + \fi}\fi} + +% v1.6b we use one makelabel that does justification as needed. +\def\@IEEEiedmakelabel#1{\relax\if\@IEEEiedjustify 0\relax +\makebox[\labelwidth][l]{\normalfont #1}\else +\if\@IEEEiedjustify 1\relax +\makebox[\labelwidth][c]{\normalfont #1}\else +\makebox[\labelwidth][r]{\normalfont #1}\fi\fi} + + +% compsoc uses a larger value for the normal labelsep +% and also extra spacing above and below each list +\ifCLASSOPTIONcompsoc + \IEEEiednormlabelsep 1.2em + \IEEEiedtopsep 6pt plus 3pt minus 3pt +\fi + + +% VERSE and QUOTE +% V1.7 define environments with newenvironment +\newenvironment{verse}{\let\\=\@centercr + \list{}{\itemsep\z@ \itemindent -1.5em \listparindent \itemindent + \rightmargin\leftmargin\advance\leftmargin 1.5em}\item\relax} + {\endlist} +\newenvironment{quotation}{\list{}{\listparindent 1.5em \itemindent\listparindent + \rightmargin\leftmargin \parsep 0pt plus 1pt}\item\relax} + {\endlist} +\newenvironment{quote}{\list{}{\rightmargin\leftmargin}\item\relax} + {\endlist} + + +% \titlepage +% provided only for backward compatibility. \maketitle is the correct +% way to create the title page. +\def\titlepage{\@restonecolfalse\if@twocolumn\@restonecoltrue\onecolumn + \else \newpage \fi \thispagestyle{empty}\c@page\z@} +\def\endtitlepage{\if@restonecol\twocolumn \else \newpage \fi} + +% standard values from article.cls +\arraycolsep 5pt +\arrayrulewidth .4pt +\doublerulesep 2pt + +\tabcolsep 6pt +\tabbingsep 0.5em + + +%% FOOTNOTES +% +%\skip\footins 10pt plus 4pt minus 2pt +% V1.6 respond to changes in font size +% space added above the footnotes (if present) +\skip\footins 0.9\baselineskip plus 0.4\baselineskip minus 0.2\baselineskip + +% V1.6, we need to make \footnotesep responsive to changes +% in \baselineskip or strange spacings will result when in +% draft mode. Here is a little LaTeX secret - \footnotesep +% determines the height of an invisible strut that is placed +% *above* the baseline of footnotes after the first. Since +% LaTeX considers the space for characters to be 0.7\baselineskip +% above the baseline and 0.3\baselineskip below it, we need to +% use 0.7\baselineskip as a \footnotesep to maintain equal spacing +% between all the lines of the footnotes. The IEEE often uses a tad +% more, so use 0.8\baselineskip. This slightly larger value also helps +% the text to clear the footnote marks. Note that \thanks in IEEEtran +% uses its own value of \footnotesep which is set in \maketitle. +{\footnotesize +\global\footnotesep 0.8\baselineskip} + + +\skip\@mpfootins = \skip\footins +\fboxsep = 3pt +\fboxrule = .4pt +% V1.6 use 1em, then use LaTeX2e's \@makefnmark +% Note that the IEEE normally *left* aligns the footnote marks, so we don't need +% box resizing tricks here. +\long\def\@makefntext#1{\parindent 1em\indent\hbox{\@makefnmark}#1}% V1.6 use 1em +% V1.7 compsoc does not use superscipts for footnote marks +\ifCLASSOPTIONcompsoc +\def\@IEEEcompsocmakefnmark{\hbox{\normalfont\@thefnmark.\ }} +\long\def\@makefntext#1{\parindent 1em\indent\hbox{\@IEEEcompsocmakefnmark}#1} +\fi + +% The IEEE does not use footnote rules +\def\footnoterule{} + +% V1.7 for compsoc, the IEEE uses a footnote rule only for \thanks. We devise a "one-shot" +% system to implement this. +\newif\if@IEEEenableoneshotfootnoterule +\@IEEEenableoneshotfootnoterulefalse +\ifCLASSOPTIONcompsoc +\def\footnoterule{\relax\if@IEEEenableoneshotfootnoterule +\kern-5pt +\hbox to \columnwidth{\hfill\vrule width 0.5\columnwidth height 0.4pt\hfill} +\kern4.6pt +\global\@IEEEenableoneshotfootnoterulefalse +\else +\relax +\fi} +\fi + +% V1.6 do not allow LaTeX to break a footnote across multiple pages +\interfootnotelinepenalty=10000 + +% V1.6 discourage breaks within equations +% Note that amsmath normally sets this to 10000, +% but LaTeX2e normally uses 100. +\interdisplaylinepenalty=2500 + +% default allows section depth up to /paragraph +\setcounter{secnumdepth}{4} + +% technotes do not allow /paragraph +\ifCLASSOPTIONtechnote + \setcounter{secnumdepth}{3} +\fi +% neither do compsoc conferences +\@IEEEcompsocconfonly{\setcounter{secnumdepth}{3}} + + +\newcounter{section} +\newcounter{subsection}[section] +\newcounter{subsubsection}[subsection] +\newcounter{paragraph}[subsubsection] + +% used only by IEEEtran's IEEEeqnarray as other packages may +% have their own, different, implementations +\newcounter{IEEEsubequation}[equation] + +% as shown when called by user from \ref, \label and in table of contents +\def\theequation{\arabic{equation}} % 1 +\def\theIEEEsubequation{\theequation\alph{IEEEsubequation}} % 1a (used only by IEEEtran's IEEEeqnarray) +\ifCLASSOPTIONcompsoc +% compsoc is all arabic +\def\thesection{\arabic{section}} +\def\thesubsection{\thesection.\arabic{subsection}} +\def\thesubsubsection{\thesubsection.\arabic{subsubsection}} +\def\theparagraph{\thesubsubsection.\arabic{paragraph}} +\else +\def\thesection{\Roman{section}} % I +% V1.7, \mbox prevents breaks around - +\def\thesubsection{\mbox{\thesection-\Alph{subsection}}} % I-A +% V1.7 use I-A1 format used by the IEEE rather than I-A.1 +\def\thesubsubsection{\thesubsection\arabic{subsubsection}} % I-A1 +\def\theparagraph{\thesubsubsection\alph{paragraph}} % I-A1a +\fi + +% From Heiko Oberdiek. Because of the \mbox in \thesubsection, we need to +% tell hyperref to disable the \mbox command when making PDF bookmarks. +% This done already with hyperref.sty version 6.74o and later, but +% it will not hurt to do it here again for users of older versions. +\@ifundefined{pdfstringdefPreHook}{\let\pdfstringdefPreHook\@empty}{}% +\g@addto@macro\pdfstringdefPreHook{\let\mbox\relax} + + +% Main text forms (how shown in main text headings) +% V1.6, using \thesection in \thesectiondis allows changes +% in the former to automatically appear in the latter +\ifCLASSOPTIONcompsoc + \ifCLASSOPTIONconference% compsoc conference + \def\thesectiondis{\thesection.} + \def\thesubsectiondis{\thesectiondis\arabic{subsection}.} + \def\thesubsubsectiondis{\thesubsectiondis\arabic{subsubsection}.} + \def\theparagraphdis{\thesubsubsectiondis\arabic{paragraph}.} + \else% compsoc not conferencs + \def\thesectiondis{\thesection} + \def\thesubsectiondis{\thesectiondis.\arabic{subsection}} + \def\thesubsubsectiondis{\thesubsectiondis.\arabic{subsubsection}} + \def\theparagraphdis{\thesubsubsectiondis.\arabic{paragraph}} + \fi +\else% not compsoc + \def\thesectiondis{\thesection.} % I. + \def\thesubsectiondis{\Alph{subsection}.} % B. + \def\thesubsubsectiondis{\arabic{subsubsection})} % 3) + \def\theparagraphdis{\alph{paragraph})} % d) +\fi + +% just like LaTeX2e's \@eqnnum +\def\theequationdis{{\normalfont \normalcolor (\theequation)}}% (1) +% IEEEsubequation used only by IEEEtran's IEEEeqnarray +\def\theIEEEsubequationdis{{\normalfont \normalcolor (\theIEEEsubequation)}}% (1a) +% redirect LaTeX2e's equation number display and all that depend on +% it, through IEEEtran's \theequationdis +\def\@eqnnum{\theequationdis} + + + +% V1.7 provide string macros as article.cls does +\def\contentsname{Contents} +\def\listfigurename{List of Figures} +\def\listtablename{List of Tables} +\def\refname{References} +\def\indexname{Index} +\def\figurename{Fig.} +\def\tablename{TABLE} +\@IEEEcompsocconfonly{\def\figurename{Figure}} +\def\partname{Part} +\def\appendixname{Appendix} +\def\abstractname{Abstract} +% IEEE specific names +\def\IEEEkeywordsname{Index Terms} +\def\IEEEproofname{Proof} + + +% LIST OF FIGURES AND TABLES AND TABLE OF CONTENTS +% +\def\@pnumwidth{1.55em} +\def\@tocrmarg{2.55em} +\def\@dotsep{4.5} +\setcounter{tocdepth}{3} + +% adjusted some spacings here so that section numbers will not easily +% collide with the section titles. +% VIII; VIII-A; and VIII-A.1 are usually the worst offenders. +% MDS 1/2001 +\def\tableofcontents{\section*{\contentsname}\@starttoc{toc}} +\def\l@section#1#2{\addpenalty{\@secpenalty}\addvspace{1.0em plus 1pt}% + \@tempdima 2.75em \begingroup \parindent \z@ \rightskip \@pnumwidth% + \parfillskip-\@pnumwidth {\bfseries\leavevmode #1}\hfil\hbox to\@pnumwidth{\hss #2}\par% + \endgroup} +% argument format #1:level, #2:labelindent,#3:labelsep +\def\l@subsection{\@dottedtocline{2}{2.75em}{3.75em}} +\def\l@subsubsection{\@dottedtocline{3}{6.5em}{4.5em}} +% must provide \l@ defs for ALL sublevels EVEN if tocdepth +% is such as they will not appear in the table of contents +% these defs are how TOC knows what level these things are! +\def\l@paragraph{\@dottedtocline{4}{6.5em}{5.5em}} +\def\l@subparagraph{\@dottedtocline{5}{6.5em}{6.5em}} +\def\listoffigures{\section*{\listfigurename}\@starttoc{lof}} +\def\l@figure{\@dottedtocline{1}{0em}{2.75em}} +\def\listoftables{\section*{\listtablename}\@starttoc{lot}} +\let\l@table\l@figure + + +% Definitions for floats +% +% Normal Floats +% V1.8 floatsep et al. revised down by 0.15\baselineskip +% to account for the sideeffects of \topskip compensation +\floatsep 0.85\baselineskip plus 0.2\baselineskip minus 0.2\baselineskip +\textfloatsep 1.55\baselineskip plus 0.2\baselineskip minus 0.4\baselineskip +\@fptop 0pt plus 1fil +\@fpsep 0.75\baselineskip plus 2fil +\@fpbot 0pt plus 1fil +\def\topfraction{0.9} +\def\bottomfraction{0.4} +\def\floatpagefraction{0.8} +% V1.7, let top floats approach 90% of page +\def\textfraction{0.1} + +% Double Column Floats +\dblfloatsep 0.85\baselineskip plus 0.2\baselineskip minus 0.2\baselineskip + +\dbltextfloatsep 1.55\baselineskip plus 0.2\baselineskip minus 0.4\baselineskip +% Note that it would be nice if the rubber here actually worked in LaTeX2e. +% There is a long standing limitation in LaTeX, first discovered (to the best +% of my knowledge) by Alan Jeffrey in 1992. LaTeX ignores the stretchable +% portion of \dbltextfloatsep, and as a result, double column figures can and +% do result in an non-integer number of lines in the main text columns with +% underfull vbox errors as a consequence. A post to comp.text.tex +% by Donald Arseneau confirms that this had not yet been fixed in 1998. +% IEEEtran V1.6 will fix this problem for you in the titles, but it doesn't +% protect you from other double floats. Happy vspace'ing. + +\@dblfptop 0pt plus 1fil +\@dblfpsep 0.75\baselineskip plus 2fil +\@dblfpbot 0pt plus 1fil +\def\dbltopfraction{0.8} +\def\dblfloatpagefraction{0.8} +\setcounter{dbltopnumber}{4} + +\intextsep 0.85\baselineskip plus 0.2\baselineskip minus 0.2\baselineskip +\setcounter{topnumber}{2} +\setcounter{bottomnumber}{2} +\setcounter{totalnumber}{4} + + + +% article class provides these, we should too. +\newlength\abovecaptionskip +\newlength\belowcaptionskip +% but only \abovecaptionskip is used above figure captions and *below* table +% captions +\setlength\abovecaptionskip{0.5\baselineskip} +% compsoc journals are a little more generous +\ifCLASSOPTIONcompsoc\ifCLASSOPTIONjournal + \setlength\abovecaptionskip{0.75\baselineskip} +\fi\fi +\setlength\belowcaptionskip{0pt} +% V1.6 create hooks in case the caption spacing ever needs to be +% overridden by a user +\def\@IEEEfigurecaptionsepspace{\vskip\abovecaptionskip\relax}% +\def\@IEEEtablecaptionsepspace{\vskip\abovecaptionskip\relax}% + + +% 1.6b revise caption system so that \@makecaption uses two arguments +% as with LaTeX2e. Otherwise, there will be problems when using hyperref. +\def\@IEEEtablestring{table} + + +% V1.8 compensate for \topskip so top of top figures align with tops of the first lines of main text +% here we calculate a space equal to the amount \topskip exceeds the main text height +% we hook in at \@floatboxreset +\def\@IEEEfiguretopskipspace{\ifdim\prevdepth=-1000pt\relax +\setlength{\@IEEEtrantmpdimenA}{1\topskip}\relax +\addtolength{\@IEEEtrantmpdimenA}{-0.7\@IEEEnormalsizeunitybaselineskip}\relax +\vspace*{\@IEEEtrantmpdimenA}\fi} +% V1.8 compensate for \topskip at the top of top tables so caption text is on main text baseline +% use a strut set on the caption baseline within \@makecaption +\def\@IEEEtabletopskipstrut{\ifdim\prevdepth=-1000pt\rule{0pt}{\topskip}\fi} +% the \ifdim\prevdepth checks are always expected to be true for IEEE style float caption ordering +% because top of figure content and top of captions in tables is the first thing on the vertical +% list of these floats +% thanks to Donald Arseneau for his 2000/11/11 post "Re: caption hacking" with info on this topic. + + +\ifCLASSOPTIONcompsoc +% V1.7 compsoc \@makecaption +\ifCLASSOPTIONconference% compsoc conference +\long\def\@makecaption#1#2{% +% test if is a for a figure or table +\ifx\@captype\@IEEEtablestring% +% if a table, do table caption +\footnotesize\bgroup\par\centering\@IEEEtabletopskipstrut{\normalfont\footnotesize {#1.}\nobreakspace\scshape #2}\par\addvspace{0.5\baselineskip}\egroup% +\@IEEEtablecaptionsepspace +% if not a table, format it as a figure +\else +\@IEEEfigurecaptionsepspace +\setbox\@tempboxa\hbox{\normalfont\footnotesize {#1.}\nobreakspace #2}% +\ifdim \wd\@tempboxa >\hsize% +% if caption is longer than a line, let it wrap around +\setbox\@tempboxa\hbox{\normalfont\footnotesize {#1.}\nobreakspace}% +\parbox[t]{\hsize}{\normalfont\footnotesize \noindent\unhbox\@tempboxa#2}% +% if caption is shorter than a line, center +\else% +\hbox to\hsize{\normalfont\footnotesize\hfil\box\@tempboxa\hfil}% +\fi\fi} +% +\else% nonconference compsoc +\long\def\@makecaption#1#2{% +% test if is a for a figure or table +\ifx\@captype\@IEEEtablestring% +% if a table, do table caption +\footnotesize\bgroup\par\centering\@IEEEtabletopskipstrut{\normalfont\sffamily\footnotesize #1}\\{\normalfont\sffamily\footnotesize #2}\par\addvspace{0.5\baselineskip}\egroup% +\@IEEEtablecaptionsepspace +% if not a table, format it as a figure +\else +\@IEEEfigurecaptionsepspace +\setbox\@tempboxa\hbox{\normalfont\sffamily\footnotesize {#1.}\nobreakspace #2}% +\ifdim \wd\@tempboxa >\hsize% +% if caption is longer than a line, let it wrap around +\setbox\@tempboxa\hbox{\normalfont\sffamily\footnotesize {#1.}\nobreakspace}% +\parbox[t]{\hsize}{\normalfont\sffamily\footnotesize \noindent\unhbox\@tempboxa#2}% +% if caption is shorter than a line, left justify +\else% +\hbox to\hsize{\normalfont\sffamily\footnotesize\box\@tempboxa\hfil}% +\fi\fi} +\fi +% +\else% traditional noncompsoc \@makecaption +\long\def\@makecaption#1#2{% +% test if is a for a figure or table +\ifx\@captype\@IEEEtablestring% +% if a table, do table caption +\footnotesize\bgroup\par\centering\@IEEEtabletopskipstrut{\normalfont\footnotesize #1}\\{\normalfont\footnotesize\scshape #2}\par\addvspace{0.5\baselineskip}\egroup% +\@IEEEtablecaptionsepspace +% if not a table, format it as a figure +\else +\@IEEEfigurecaptionsepspace +% 3/2001 use footnotesize, not small; use two nonbreaking spaces, not one +\setbox\@tempboxa\hbox{\normalfont\footnotesize {#1.}\nobreakspace\nobreakspace #2}% +\ifdim \wd\@tempboxa >\hsize% +% if caption is longer than a line, let it wrap around +\setbox\@tempboxa\hbox{\normalfont\footnotesize {#1.}\nobreakspace\nobreakspace}% +\parbox[t]{\hsize}{\normalfont\footnotesize\noindent\unhbox\@tempboxa#2}% +% if caption is shorter than a line, center if conference, left justify otherwise +\else% +\ifCLASSOPTIONconference \hbox to\hsize{\normalfont\footnotesize\hfil\box\@tempboxa\hfil}% +\else \hbox to\hsize{\normalfont\footnotesize\box\@tempboxa\hfil}% +\fi\fi\fi} +\fi + + + +% V1.7 disable captions class option, do so in a way that retains operation of \label +% within \caption +\ifCLASSOPTIONcaptionsoff +\long\def\@makecaption#1#2{\vspace*{2em}\footnotesize\bgroup\par\addvspace{0.5\baselineskip}\centering{\footnotesize #1}\par\addvspace{0.5\baselineskip}\egroup% +\let\@IEEEtemporiglabeldefsave\label +\let\@IEEEtemplabelargsave\relax +\def\label##1{\gdef\@IEEEtemplabelargsave{##1}}% +\setbox\@tempboxa\hbox{#2}% +\let\label\@IEEEtemporiglabeldefsave +\ifx\@IEEEtemplabelargsave\relax\else\label{\@IEEEtemplabelargsave}\fi} +\fi + + +% V1.7 define end environments with \def not \let so as to work OK with +% preview-latex +\newcounter{figure} +\def\thefigure{\@arabic\c@figure} +\def\fps@figure{tbp} +\def\ftype@figure{1} +\def\ext@figure{lof} +\def\fnum@figure{\figurename\nobreakspace\thefigure} +% V1.8 within figures add \@IEEEfiguretopskipspace compensation to LaTeX2e's \@floatboxreset +\def\figure{\def\@floatboxreset{\reset@font\normalsize\@setminipage\@IEEEfiguretopskipspace}\@float{figure}} +\def\endfigure{\end@float} +% V1.8 also add \@IEEEfiguretopskipspace compensation to \figure* +\@namedef{figure*}{\def\@floatboxreset{\reset@font\normalsize\@setminipage\@IEEEfiguretopskipspace}\@dblfloat{figure}} +\@namedef{endfigure*}{\end@dblfloat} + +\newcounter{table} +\ifCLASSOPTIONcompsoc +\def\thetable{\arabic{table}} +\else +\def\thetable{\@Roman\c@table} +\fi +\def\fps@table{tbp} +\def\ftype@table{2} +\def\ext@table{lot} +\def\fnum@table{\tablename\nobreakspace\thetable} +% V1.6 The IEEE uses 8pt text for tables +% within tables alter LaTeX2e's \@floatboxreset to use \footnotesize +\def\table{\def\@floatboxreset{\reset@font\footnotesize\@setminipage}\@float{table}} +\def\endtable{\end@float} +% v1.6b double column tables need to default to footnotesize as well. +\@namedef{table*}{\def\@floatboxreset{\reset@font\footnotesize\@setminipage}\@dblfloat{table}} +\@namedef{endtable*}{\end@dblfloat} + + + + +%% -- Command Argument Scanning Support Functions -- +%% V1.8a + +% usage: \@IEEEstripouterbraces*{} +% \@IEEEstripouterbraces fully expands its argument (which it then stores +% in \@IEEEstripouterbracesarg) via \edef, then removes any outer enclosing +% braces, and finally stores the result in the macro +% \@IEEEstrippedouterbraces. +% +% For example: +% \@IEEEstripouterbraces{{{{ab}c}}} +% results in: +% +% \@IEEEstripouterbracesarg ==> a macro containing {{{ab}c}} +% \@IEEEstrippedouterbraces ==> a macro containing {ab}c +% +% the *-star form,\@IEEEstripouterbraces*, does not expand the argument +% contents during processing +\def\@IEEEstripouterbraces{\@ifstar{\let\@IEEEstripouterbracesdef=\def\@@IEEEstripouterbraces}{\let\@IEEEstripouterbracesdef=\edef\@@IEEEstripouterbraces}} + +\def\@@IEEEstripouterbraces#1{\@IEEEstripouterbracesdef\@IEEEstripouterbracesarg{#1}\relax +% If the macro is unchanged after being acquired as a single delimited +% argument, we know we have one sequence of tokens without any enclosing +% braces. Loop until this is true. +\loop + \expandafter\@@@IEEEstripouterbraces\@IEEEstripouterbracesarg\@IEEEgeneralsequenceDELIMITER +\ifx\@IEEEstrippedouterbraces\@IEEEstripouterbracesarg +\else + \let\@IEEEstripouterbracesarg\@IEEEstrippedouterbraces +\repeat} + +\def\@@@IEEEstripouterbraces#1\@IEEEgeneralsequenceDELIMITER{\def\@IEEEstrippedouterbraces{#1}} + + + +% usage: \@IEEEextractgroup*{} +% \@IEEEextractgroup fully expands its argument (which it then stores in +% \@IEEEextractgrouparg) via \edef and then assigns the first "brace group" +% of tokens to the macro \@IEEEextractedgroup. +% The remaining groups, if any, are stored in the macro +% \@IEEEextractedgroupremain. If the argument does not contain the requisite +% groups, the respective macros will be defined to be empty. +% There is an asymmetry in that \@IEEEextractedgroup is stripped of its first +% outer grouping while \@IEEEextractedgroupremain retains even the outer +% grouping (if present) that originally identified it as a group. +% +% For example: +% \@IEEEextractgroup{{{ab}}{c{de}}} +% results in: +% +% \@IEEEextractgrouparg ==> a macro containing {{ab}}{c{de}} +% \@IEEEextractedgroup ==> a macro containing {ab} +% \@IEEEextractedgroupremain ==> a macro containing {c{de}} +% +% The *-star form, \@IEEEextractgroup*, does not expand its argument +% contents during processing. +\def\@IEEEextractgroup{\@ifstar{\let\@IEEEextractgroupdef=\def\@@IEEEextractgroup}{\let\@IEEEextractgroupdef=\edef\@@IEEEextractgroup}} + +\def\@@IEEEextractgroup#1{\@IEEEextractgroupdef\@IEEEextractgrouparg{#1}\relax +% trap the case of an empty extracted group as this would cause problems with +% \@IEEEextractgroupremain's argument acquisition +\ifx\@IEEEextractgrouparg\@empty + \def\@IEEEextractedgroup{}\relax + \def\@IEEEextractedgroupremain{}\relax +\else + % We have to use some dirty tricks here. We want to insert {} around + % whatever remains after the first group so that TeX's argument scanner + % will preserve any originally enclosing braces as well as provide an + % empty argument to acquire even if there isn't a second group. + % In this first of two dirty tricks, we put a } at the end of the structure + % we are going to extract from. The \ifnum0=`{\fi keeps TeX happy to allow + % what would otherwise be an unbalanced macro definition for + % \@@IEEEextractgroup to be acceptable to it. + \ifnum0=`{\fi\expandafter\@IEEEextractgroupremain\@IEEEextractgrouparg}\relax +\fi} + +% In the second part of the dirty tricks, we insert a leading { right after +% the first group is acquired, but before the remainder is. Again, the +% \ifnum0=`}\fi keeps TeX happy during definition time, but will disappear +% during run time. +\def\@IEEEextractgroupremain#1{\def\@IEEEextractedgroup{#1}\expandafter\@@IEEEextractgroupremain\expandafter{\ifnum0=`}\fi} + +\def\@@IEEEextractgroupremain#1{\def\@IEEEextractedgroupremain{#1}} + + + +% \@IEEEextracttoken relocated at top because margin setting commands rely on it + + + +% usage: \@IEEEextracttokengroups*{} +% \@IEEEextracttokengroups fully expands its argument (which it then stores +% in \@IEEEextracttokengroupsarg) and then assigns the first "brace group" of +% tokens (with the outermost braces removed) to the macro +% \@IEEEextractedfirstgroup. +% The meaning of the first nonbrace (but including the empty group) token +% within this first group is assigned via \let to \@IEEEextractedfirsttoken +% as well as stored in the macro \@IEEEextractedfirsttokenmacro. If a first +% nonbrace token does not exist (or is an empty group), these will be \relax +% and empty, respectively. Tokens that would otherwise be discarded during +% the acquisition of the first token in the first group are stored in +% \@IEEEextractedfirsttokensdiscarded, however their original relative brace +% nesting depths are not guaranteed to be preserved. +% The first group within this first group is stored in the macro +% \@IEEEextractedfirstfirstgroup. +% Likewise for the next group after the first: \@IEEEextractednextgroup, +% \@IEEEextractednextfirstgroup, \@IEEEextractednextgroupfirsttoken, +% \@IEEEextractednextgroupfirsttokenmacro, and +% \@IEEEextractednextfirsttokensdiscarded. +% All tokens/groups after the first group, including any enclosing braces, +% are stored in the macro \@IEEEextractedafterfirstgroupremain which will +% be empty if none exist. +% +% For example: +% \@IEEEextracttokengroups{{{ab}{cd}}{{ef}g}} +% will result in: +% +% \@IEEEextracttokengroupsarg ==> a macro containing {{ab}{cd}}{{ef}g} +% \@IEEEextractedfirstgroup ==> a macro containing {ab}{cd} +% \@IEEEextractedafterfirstgroupremain ==> a macro containing {{ef}g} +% \@IEEEextractedfirsttoken ==> the letter a +% \@IEEEextractedfirsttokenmacro ==> a macro containing a +% \@IEEEextractedfirsttokensdiscarded ==> a macro containing bcd +% \@IEEEextractedfirstfirstgroup ==> a macro containing ab +% \@IEEEextractednextgroup ==> a macro containing {ef}g +% \@IEEEextractednextfirsttoken ==> the letter e +% \@IEEEextractednextfirsttokenmacro ==> a macro containing e +% \@IEEEextractednextfirsttokensdiscarded ==> a macro containing fg +% \@IEEEextractednextfirstgroup ==> a macro containing ef +% +% If given an empty argument, \@IEEEextractedfirsttoken and +% \@IEEEextractednextfirsttoken will be set to \relax +% and all the macros will be empty. +% the *-star form, \@IEEEextracttokengroups*, does not expand its argument +% contents during processing. +% +% Depends on: \@IEEEextractgroup, \@IEEEextracttoken +\def\@IEEEextracttokengroups{\@ifstar{\let\@IEEEextracttokengroupsdef=\def\@@IEEEextracttokengroups}{\let\@IEEEextracttokengroupsdef=\edef\@@IEEEextracttokengroups}} +\def\@@IEEEextracttokengroups#1{\@IEEEextracttokengroupsdef\@IEEEextracttokengroupsarg{#1}\relax +% begin extraction, these functions are safe with empty arguments +% first group +\expandafter\@IEEEextractgroup\expandafter*\expandafter{\@IEEEextracttokengroupsarg}\relax +\let\@IEEEextractedfirstgroup\@IEEEextractedgroup +\let\@IEEEextractedafterfirstgroupremain\@IEEEextractedgroupremain +\expandafter\@IEEEextracttoken\expandafter*\expandafter{\@IEEEextractedfirstgroup}\relax +\let\@IEEEextractedfirsttoken\@IEEEextractedtoken +\let\@IEEEextractedfirsttokenmacro\@IEEEextractedtokenmacro +\let\@IEEEextractedfirsttokensdiscarded\@IEEEextractedtokensdiscarded +% first first group +\expandafter\@IEEEextractgroup\expandafter*\expandafter{\@IEEEextractedfirstgroup}\relax +\let\@IEEEextractedfirstfirstgroup\@IEEEextractedgroup +% next group +\expandafter\@IEEEextractgroup\expandafter*\expandafter{\@IEEEextractedafterfirstgroupremain}\relax +\let\@IEEEextractednextgroup\@IEEEextractedgroup +\expandafter\@IEEEextracttoken\expandafter*\expandafter{\@IEEEextractednextgroup}\relax +\let\@IEEEextractednextfirsttoken\@IEEEextractedtoken +\let\@IEEEextractednextfirsttokenmacro\@IEEEextractedtokenmacro +\let\@IEEEextractednextfirsttokensdiscarded\@IEEEextractedtokensdiscarded +% next first group +\expandafter\@IEEEextractgroup\expandafter*\expandafter{\@IEEEextractednextgroup}\relax +\let\@IEEEextractednextfirstgroup\@IEEEextractedgroup} + + +%% -- End of Command Argument Scanning Support Functions -- + + + + +%% +%% START OF IEEEeqnarray DEFINITIONS +%% +%% Inspired by the concepts, examples, and previous works of LaTeX +%% coders and developers such as Donald Arseneau, Fred Bartlett, +%% David Carlisle, Tony Liu, Frank Mittelbach, Piet van Oostrum, +%% Roland Winkler and Mark Wooding. +%% I don't make the claim that my work here is even near their calibre. ;) + + +\newif\if@IEEEeqnarrayboxnojot% flag to indicate if the environment was called as the star form +\@IEEEeqnarrayboxnojotfalse + +\newif\if@advanceIEEEeqncolcnt% tracks if the environment should advance the col counter +% allows a way to make an \IEEEeqnarraybox that can be used within an \IEEEeqnarray +% used by IEEEeqnarraymulticol so that it can work properly in both +\@advanceIEEEeqncolcnttrue + +\newcount\@IEEEeqnnumcols % tracks how many IEEEeqnarray cols are defined +\newcount\@IEEEeqncolcnt % tracks how many IEEEeqnarray cols the user actually used + + +% The default math style used by the columns +\def\IEEEeqnarraymathstyle{\displaystyle} +% The default text style used by the columns +% default to using the current font +\def\IEEEeqnarraytextstyle{\relax} + +% like the iedlistdecl but for \IEEEeqnarray +\def\IEEEeqnarraydecl{\relax} +\def\IEEEeqnarrayboxdecl{\relax} + + + +% V1.8 flags to indicate that equation numbering is to persist +\newif\if@IEEEeqnumpersist% +\@IEEEeqnumpersistfalse +\newif\if@IEEEsubeqnumpersist% +\@IEEEsubeqnumpersistfalse +% +% V1.8 flags to indicate if (sub)equation number of last line was preadvanced +\newif\if@IEEEeqnumpreadv% +\@IEEEeqnumpreadvfalse +\newif\if@IEEEsubeqnumpreadv% +\@IEEEsubeqnumpreadvfalse + +\newcount\@IEEEsubeqnnumrollback% saves previous value of IEEEsubequation number in case we need to restore it + +% \yesnumber is the opposite of \nonumber +% a novel concept with the same def as the equationarray package +% However, we give IEEE versions too since some LaTeX packages such as +% the MDWtools mathenv.sty redefine \nonumber to something else. +% This command is intended for use in non-IEEEeqnarray math environments +\providecommand{\yesnumber}{\global\@eqnswtrue} + + +% IEEEyes/nonumber +% V1.8 add persistant * forms +% These commands can alter the type of equation an IEEEeqnarray line is. +\def\IEEEyesnumber{\@ifstar{\global\@IEEEeqnumpersisttrue\global\@IEEEsubeqnumpersistfalse\@IEEEyesnumber}{\@IEEEyesnumber}} + +\def\@IEEEyesnumber{\global\@eqnswtrue +\if@IEEEeqnarrayISinner% alter counters and label only inside an IEEEeqnarray +\ifnum\c@IEEEsubequation>0\relax + \stepcounter{equation}\setcounter{IEEEsubequation}{0}\gdef\@currentlabel{\p@equation\theequation}\relax + \gdef\@currentHref{\@IEEEtheHrefequation}% setup hyperref label +\fi +% even if we reached this eqn num via a preadv, it is legit now +\global\@IEEEeqnumpreadvfalse\global\@IEEEsubeqnumpreadvfalse +\fi} + +\def\IEEEnonumber{\@ifstar{\global\@IEEEeqnumpersistfalse\global\@IEEEsubeqnumpersistfalse\global\@eqnswfalse}{\global\@eqnswfalse}} + + +\def\IEEEyessubnumber{\@ifstar{\global\@IEEEsubeqnumpersisttrue\@IEEEyessubnumber}{\@IEEEyessubnumber}} +% +\def\@IEEEyessubnumber{\if@IEEEeqnarrayISinner% alter counters and label only inside an IEEEeqnarray + \ifnum\c@IEEEsubequation>0\relax% if it already is a subequation, we are good to go as-is + \else% if we are a regular equation we have to watch out for two cases + \if@IEEEeqnumpreadv% if this equation is the result of a preadvance, backout and bump the sub eqnnum + \global\advance\c@equation\m@ne\global\c@IEEEsubequation=\@IEEEsubeqnnumrollback\addtocounter{IEEEsubequation}{1}\relax + \else% non-preadvanced equations just need initialization of their sub eqnnum + \setcounter{IEEEsubequation}{1}\relax + \fi + \fi% fi already is subequation + \gdef\@currentlabel{\p@IEEEsubequation\theIEEEsubequation}\relax + \gdef\@currentHref{\@IEEEtheHrefsubequation}% setup hyperref label + \global\@IEEEeqnumpreadvfalse\global\@IEEEsubeqnumpreadvfalse% no longer a preadv anymore + \global\@eqnswtrue +\fi} + + +\def\IEEEnosubnumber{\@ifstar{\global\@IEEEsubeqnumpersistfalse\@IEEEnosubnumber}{\@IEEEnosubnumber}} +% +\def\@IEEEnosubnumber{\if@IEEEeqnarrayISinner% alter counters and label only inside an IEEEeqnarray + \if@eqnsw % we do nothing unless we know we will display because we play with the counters here + % if it currently is a subequation, bump up to the next equation number and turn off the subequation + \ifnum\c@IEEEsubequation>0\relax\addtocounter{equation}{1}\setcounter{IEEEsubequation}{0}\relax + \fi + \global\@IEEEeqnumpreadvfalse\global\@IEEEsubeqnumpreadvfalse% no longer a preadv anymore + \gdef\@currentlabel{\p@equation\theequation}\relax + \gdef\@currentHref{\@IEEEtheHrefequation}% setup hyperref label + \fi +\fi} + + + +% allows users to "push away" equations that get too close to the equation numbers +\def\IEEEeqnarraynumspace{\hphantom{\ifnum\c@IEEEsubequation>0\relax\theIEEEsubequationdis\else\theequationdis\fi}} + +% provides a way to span multiple columns within IEEEeqnarray environments +% will consider \if@advanceIEEEeqncolcnt before globally advancing the +% column counter - so as to work within \IEEEeqnarraybox +% usage: \IEEEeqnarraymulticol{number cols. to span}{col type}{cell text} +\long\def\IEEEeqnarraymulticol#1#2#3{\multispan{#1}\relax +% check if column is defined for the precolumn definition +% We have to be careful here because TeX scans for & even within an \iffalse +% where it does not expand macros. So, if we used only one \ifx and a #3 +% appeared in the false branch and the user inserted another alignment +% structure that uses & in the \IEEEeqnarraymulticol{}, TeX will not see that +% there is an inner alignment in the false branch yet still will see any & +% there and will think that they apply to the outer alignment resulting in an +% incomplete \ifx error. +% So, here we use separate checks for the pre and post parts in order to keep +% the #3 outside of all conditionals. +\relax\expandafter\ifx\csname @IEEEeqnarraycolDEF#2\endcsname\@IEEEeqnarraycolisdefined\relax +\csname @IEEEeqnarraycolPRE#2\endcsname +\else% if not, error and use default type +\@IEEEclspkgerror{Invalid column type "#2" in \string\IEEEeqnarraymulticol.\MessageBreak +Using a default centering column instead}% +{You must define IEEEeqnarray column types before use.}% +\csname @IEEEeqnarraycolPRE@IEEEdefault\endcsname +\fi +% The ten \relax are to help prevent misleading error messages in case a user +% accidently inserted a macro that tries to acquire additional arguments. +#3\relax\relax\relax\relax\relax\relax\relax\relax\relax\relax +% check if column is defined for the postcolumn definition +\expandafter\ifx\csname @IEEEeqnarraycolDEF#2\endcsname\@IEEEeqnarraycolisdefined\relax +\csname @IEEEeqnarraycolPOST#2\endcsname +\else% if not, use the default type +\csname @IEEEeqnarraycolPOST@IEEEdefault\endcsname +\fi +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by #1\relax\fi} + +% like \omit, but maintains track of the column counter for \IEEEeqnarray +\def\IEEEeqnarrayomit{\omit\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by 1\relax\fi} + + +% provides a way to define a letter referenced column type +% usage: \IEEEeqnarraydefcol{col. type letter/name}{pre insertion text}{post insertion text} +\def\IEEEeqnarraydefcol#1#2#3{\expandafter\def\csname @IEEEeqnarraycolPRE#1\endcsname{#2}% +\expandafter\def\csname @IEEEeqnarraycolPOST#1\endcsname{#3}% +\expandafter\def\csname @IEEEeqnarraycolDEF#1\endcsname{1}} + + +% provides a way to define a numerically referenced inter-column glue types +% usage: \IEEEeqnarraydefcolsep{col. glue number}{glue definition} +\def\IEEEeqnarraydefcolsep#1#2{\expandafter\def\csname @IEEEeqnarraycolSEP\romannumeral #1\endcsname{#2}% +\expandafter\def\csname @IEEEeqnarraycolSEPDEF\romannumeral #1\endcsname{1}} + + +\def\@IEEEeqnarraycolisdefined{1}% just a macro for 1, used for checking undefined column types + + +% expands and appends the given argument to the \@IEEEtrantmptoksA token list +% used to build up the \halign preamble +\def\@IEEEappendtoksA#1{\edef\@@IEEEappendtoksA{\@IEEEtrantmptoksA={\the\@IEEEtrantmptoksA #1}}% +\@@IEEEappendtoksA} + +% also appends to \@IEEEtrantmptoksA, but does not expand the argument +% uses \toks8 as a scratchpad register +\def\@IEEEappendNOEXPANDtoksA#1{\toks8={#1}% +\edef\@@IEEEappendNOEXPANDtoksA{\@IEEEtrantmptoksA={\the\@IEEEtrantmptoksA\the\toks8}}% +\@@IEEEappendNOEXPANDtoksA} + +% define some common column types for the user +% math +\IEEEeqnarraydefcol{l}{$\IEEEeqnarraymathstyle}{$\hfil} +\IEEEeqnarraydefcol{c}{\hfil$\IEEEeqnarraymathstyle}{$\hfil} +\IEEEeqnarraydefcol{r}{\hfil$\IEEEeqnarraymathstyle}{$} +\IEEEeqnarraydefcol{L}{$\IEEEeqnarraymathstyle{}}{{}$\hfil} +\IEEEeqnarraydefcol{C}{\hfil$\IEEEeqnarraymathstyle{}}{{}$\hfil} +\IEEEeqnarraydefcol{R}{\hfil$\IEEEeqnarraymathstyle{}}{{}$} +% text +\IEEEeqnarraydefcol{s}{\IEEEeqnarraytextstyle}{\hfil} +\IEEEeqnarraydefcol{t}{\hfil\IEEEeqnarraytextstyle}{\hfil} +\IEEEeqnarraydefcol{u}{\hfil\IEEEeqnarraytextstyle}{} + +% vertical rules +\IEEEeqnarraydefcol{v}{}{\vrule width\arrayrulewidth} +\IEEEeqnarraydefcol{vv}{\vrule width\arrayrulewidth\hfil}{\hfil\vrule width\arrayrulewidth} +\IEEEeqnarraydefcol{V}{}{\vrule width\arrayrulewidth\hskip\doublerulesep\vrule width\arrayrulewidth} +\IEEEeqnarraydefcol{VV}{\vrule width\arrayrulewidth\hskip\doublerulesep\vrule width\arrayrulewidth\hfil}% +{\hfil\vrule width\arrayrulewidth\hskip\doublerulesep\vrule width\arrayrulewidth} + +% horizontal rules +\IEEEeqnarraydefcol{h}{}{\leaders\hrule height\arrayrulewidth\hfil} +\IEEEeqnarraydefcol{H}{}{\leaders\vbox{\hrule width\arrayrulewidth\vskip\doublerulesep\hrule width\arrayrulewidth}\hfil} + +% plain +\IEEEeqnarraydefcol{x}{}{} +\IEEEeqnarraydefcol{X}{$}{$} + +% the default column type to use in the event a column type is not defined +\IEEEeqnarraydefcol{@IEEEdefault}{\hfil$\IEEEeqnarraymathstyle}{$\hfil} + + +% a zero tabskip (used for "-" col types) +\def\@IEEEeqnarraycolSEPzero{0pt plus 0pt minus 0pt} +% a centering tabskip (used for "+" col types) +\def\@IEEEeqnarraycolSEPcenter{1000pt plus 0pt minus 1000pt} + +% top level default tabskip glues for the start, end, and inter-column +% may be reset within environments not always at the top level, e.g., \IEEEeqnarraybox +\edef\@IEEEeqnarraycolSEPdefaultstart{\@IEEEeqnarraycolSEPcenter}% default start glue +\edef\@IEEEeqnarraycolSEPdefaultend{\@IEEEeqnarraycolSEPcenter}% default end glue +\edef\@IEEEeqnarraycolSEPdefaultmid{\@IEEEeqnarraycolSEPzero}% default inter-column glue + + + +% creates a vertical rule that extends from the bottom to the top a a cell +% Provided in case other packages redefine \vline some other way. +% usage: \IEEEeqnarrayvrule[rule thickness] +% If no argument is provided, \arrayrulewidth will be used for the rule thickness. +\newcommand\IEEEeqnarrayvrule[1][\arrayrulewidth]{\vrule\@width#1\relax} + +% creates a blank separator row +% usage: \IEEEeqnarrayseprow[separation length][font size commands] +% default is \IEEEeqnarrayseprow[0.25\normalbaselineskip][\relax] +% blank arguments inherit the default values +% uses \skip5 as a scratch register - calls \@IEEEeqnarraystrutsize which uses more scratch registers +\def\IEEEeqnarrayseprow{\relax\@ifnextchar[{\@IEEEeqnarrayseprow}{\@IEEEeqnarrayseprow[0.25\normalbaselineskip]}} +\def\@IEEEeqnarrayseprow[#1]{\relax\@ifnextchar[{\@@IEEEeqnarrayseprow[#1]}{\@@IEEEeqnarrayseprow[#1][\relax]}} +\def\@@IEEEeqnarrayseprow[#1][#2]{\def\@IEEEeqnarrayseprowARGONE{#1}% +\ifx\@IEEEeqnarrayseprowARGONE\@empty% +% get the skip value, based on the font commands +% use skip5 because \IEEEeqnarraystrutsize uses \skip0, \skip2, \skip3 +% assign within a bogus box to confine the font changes +{\setbox0=\hbox{#2\relax\global\skip5=0.25\normalbaselineskip}}% +\else% +{\setbox0=\hbox{#2\relax\global\skip5=#1}}% +\fi% +\@IEEEeqnarrayhoptolastcolumn\IEEEeqnarraystrutsize{\skip5}{0pt}[\relax]\relax} + +% creates a blank separator row, but omits all the column templates +% usage: \IEEEeqnarrayseprowcut[separation length][font size commands] +% default is \IEEEeqnarrayseprowcut[0.25\normalbaselineskip][\relax] +% blank arguments inherit the default values +% uses \skip5 as a scratch register - calls \@IEEEeqnarraystrutsize which uses more scratch registers +\def\IEEEeqnarrayseprowcut{\multispan{\@IEEEeqnnumcols}\relax% span all the cols +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by \@IEEEeqnnumcols\relax\fi% +\@ifnextchar[{\@IEEEeqnarrayseprowcut}{\@IEEEeqnarrayseprowcut[0.25\normalbaselineskip]}} +\def\@IEEEeqnarrayseprowcut[#1]{\relax\@ifnextchar[{\@@IEEEeqnarrayseprowcut[#1]}{\@@IEEEeqnarrayseprowcut[#1][\relax]}} +\def\@@IEEEeqnarrayseprowcut[#1][#2]{\def\@IEEEeqnarrayseprowARGONE{#1}% +\ifx\@IEEEeqnarrayseprowARGONE\@empty% +% get the skip value, based on the font commands +% use skip5 because \IEEEeqnarraystrutsize uses \skip0, \skip2, \skip3 +% assign within a bogus box to confine the font changes +{\setbox0=\hbox{#2\relax\global\skip5=0.25\normalbaselineskip}}% +\else% +{\setbox0=\hbox{#2\relax\global\skip5=#1}}% +\fi% +\IEEEeqnarraystrutsize{\skip5}{0pt}[\relax]\relax} + + + +% draws a single rule across all the columns optional +% argument determines the rule width, \arrayrulewidth is the default +% updates column counter as needed and turns off struts +% usage: \IEEEeqnarrayrulerow[rule line thickness] +\def\IEEEeqnarrayrulerow{\multispan{\@IEEEeqnnumcols}\relax% span all the cols +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by \@IEEEeqnnumcols\relax\fi% +\@ifnextchar[{\@IEEEeqnarrayrulerow}{\@IEEEeqnarrayrulerow[\arrayrulewidth]}} +\def\@IEEEeqnarrayrulerow[#1]{\leaders\hrule height#1\hfil\relax% put in our rule +% turn off any struts +\IEEEeqnarraystrutsize{0pt}{0pt}[\relax]\relax} + + +% draws a double rule by using a single rule row, a separator row, and then +% another single rule row +% first optional argument determines the rule thicknesses, \arrayrulewidth is the default +% second optional argument determines the rule spacing, \doublerulesep is the default +% usage: \IEEEeqnarraydblrulerow[rule line thickness][rule spacing] +\def\IEEEeqnarraydblrulerow{\multispan{\@IEEEeqnnumcols}\relax% span all the cols +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by \@IEEEeqnnumcols\relax\fi% +\@ifnextchar[{\@IEEEeqnarraydblrulerow}{\@IEEEeqnarraydblrulerow[\arrayrulewidth]}} +\def\@IEEEeqnarraydblrulerow[#1]{\relax\@ifnextchar[{\@@IEEEeqnarraydblrulerow[#1]}% +{\@@IEEEeqnarraydblrulerow[#1][\doublerulesep]}} +\def\@@IEEEeqnarraydblrulerow[#1][#2]{\def\@IEEEeqnarraydblrulerowARG{#1}% +% we allow the user to say \IEEEeqnarraydblrulerow[][] +\ifx\@IEEEeqnarraydblrulerowARG\@empty% +\@IEEEeqnarrayrulerow[\arrayrulewidth]% +\else% +\@IEEEeqnarrayrulerow[#1]\relax% +\fi% +\def\@IEEEeqnarraydblrulerowARG{#2}% +\ifx\@IEEEeqnarraydblrulerowARG\@empty% +\\\IEEEeqnarrayseprow[\doublerulesep][\relax]% +\else% +\\\IEEEeqnarrayseprow[#2][\relax]% +\fi% +\\\multispan{\@IEEEeqnnumcols}% +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by \@IEEEeqnnumcols\relax\fi% +\def\@IEEEeqnarraydblrulerowARG{#1}% +\ifx\@IEEEeqnarraydblrulerowARG\@empty% +\@IEEEeqnarrayrulerow[\arrayrulewidth]% +\else% +\@IEEEeqnarrayrulerow[#1]% +\fi% +} + +% draws a double rule by using a single rule row, a separator (cutting) row, and then +% another single rule row +% first optional argument determines the rule thicknesses, \arrayrulewidth is the default +% second optional argument determines the rule spacing, \doublerulesep is the default +% usage: \IEEEeqnarraydblrulerow[rule line thickness][rule spacing] +\def\IEEEeqnarraydblrulerowcut{\multispan{\@IEEEeqnnumcols}\relax% span all the cols +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by \@IEEEeqnnumcols\relax\fi% +\@ifnextchar[{\@IEEEeqnarraydblrulerowcut}{\@IEEEeqnarraydblrulerowcut[\arrayrulewidth]}} +\def\@IEEEeqnarraydblrulerowcut[#1]{\relax\@ifnextchar[{\@@IEEEeqnarraydblrulerowcut[#1]}% +{\@@IEEEeqnarraydblrulerowcut[#1][\doublerulesep]}} +\def\@@IEEEeqnarraydblrulerowcut[#1][#2]{\def\@IEEEeqnarraydblrulerowARG{#1}% +% we allow the user to say \IEEEeqnarraydblrulerow[][] +\ifx\@IEEEeqnarraydblrulerowARG\@empty% +\@IEEEeqnarrayrulerow[\arrayrulewidth]% +\else% +\@IEEEeqnarrayrulerow[#1]% +\fi% +\def\@IEEEeqnarraydblrulerowARG{#2}% +\ifx\@IEEEeqnarraydblrulerowARG\@empty% +\\\IEEEeqnarrayseprowcut[\doublerulesep][\relax]% +\else% +\\\IEEEeqnarrayseprowcut[#2][\relax]% +\fi% +\\\multispan{\@IEEEeqnnumcols}% +% advance column counter only if the IEEEeqnarray environment wants it +\if@advanceIEEEeqncolcnt\global\advance\@IEEEeqncolcnt by \@IEEEeqnnumcols\relax\fi% +\def\@IEEEeqnarraydblrulerowARG{#1}% +\ifx\@IEEEeqnarraydblrulerowARG\@empty% +\@IEEEeqnarrayrulerow[\arrayrulewidth]% +\else% +\@IEEEeqnarrayrulerow[#1]% +\fi% +} + + + +% inserts a full row's worth of &'s +% relies on \@IEEEeqnnumcols to provide the correct number of columns +% uses \@IEEEtrantmptoksA, \count0 as scratch registers +\def\@IEEEeqnarrayhoptolastcolumn{\@IEEEtrantmptoksA={}\count0=1\relax% +\loop% add cols if the user did not use them all +\ifnum\count0<\@IEEEeqnnumcols\relax% +\@IEEEappendtoksA{&}% +\advance\count0 by 1\relax% update the col count +\repeat% +\the\@IEEEtrantmptoksA%execute the &'s +} + + + +\newif\if@IEEEeqnarrayISinner % flag to indicate if we are within the lines +\@IEEEeqnarrayISinnerfalse % of an IEEEeqnarray - after the IEEEeqnarraydecl + +\edef\@IEEEeqnarrayTHEstrutheight{0pt} % height and depth of IEEEeqnarray struts +\edef\@IEEEeqnarrayTHEstrutdepth{0pt} + +\edef\@IEEEeqnarrayTHEmasterstrutheight{0pt} % default height and depth of +\edef\@IEEEeqnarrayTHEmasterstrutdepth{0pt} % struts within an IEEEeqnarray + +\edef\@IEEEeqnarrayTHEmasterstrutHSAVE{0pt} % saved master strut height +\edef\@IEEEeqnarrayTHEmasterstrutDSAVE{0pt} % and depth + +\newif\if@IEEEeqnarrayusemasterstrut % flag to indicate that the master strut value +\@IEEEeqnarrayusemasterstruttrue % is to be used + + + +% saves the strut height and depth of the master strut +\def\@IEEEeqnarraymasterstrutsave{\relax% +\expandafter\skip0=\@IEEEeqnarrayTHEmasterstrutheight\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEmasterstrutdepth\relax% +% remove stretchability +\dimen0\skip0\relax% +\dimen2\skip2\relax% +% save values +\edef\@IEEEeqnarrayTHEmasterstrutHSAVE{\the\dimen0}% +\edef\@IEEEeqnarrayTHEmasterstrutDSAVE{\the\dimen2}} + +% restores the strut height and depth of the master strut +\def\@IEEEeqnarraymasterstrutrestore{\relax% +\expandafter\skip0=\@IEEEeqnarrayTHEmasterstrutHSAVE\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEmasterstrutDSAVE\relax% +% remove stretchability +\dimen0\skip0\relax% +\dimen2\skip2\relax% +% restore values +\edef\@IEEEeqnarrayTHEmasterstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEmasterstrutdepth{\the\dimen2}} + + +% globally restores the strut height and depth to the +% master values and sets the master strut flag to true +\def\@IEEEeqnarraystrutreset{\relax% +\expandafter\skip0=\@IEEEeqnarrayTHEmasterstrutheight\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEmasterstrutdepth\relax% +% remove stretchability +\dimen0\skip0\relax% +\dimen2\skip2\relax% +% restore values +\xdef\@IEEEeqnarrayTHEstrutheight{\the\dimen0}% +\xdef\@IEEEeqnarrayTHEstrutdepth{\the\dimen2}% +\global\@IEEEeqnarrayusemasterstruttrue} + + +% if the master strut is not to be used, make the current +% values of \@IEEEeqnarrayTHEstrutheight, \@IEEEeqnarrayTHEstrutdepth +% and the use master strut flag, global +% this allows user strut commands issued in the last column to be carried +% into the isolation/strut column +\def\@IEEEeqnarrayglobalizestrutstatus{\relax% +\if@IEEEeqnarrayusemasterstrut\else% +\xdef\@IEEEeqnarrayTHEstrutheight{\@IEEEeqnarrayTHEstrutheight}% +\xdef\@IEEEeqnarrayTHEstrutdepth{\@IEEEeqnarrayTHEstrutdepth}% +\global\@IEEEeqnarrayusemasterstrutfalse% +\fi} + + + +% usage: \IEEEeqnarraystrutsize{height}{depth}[font size commands] +% If called outside the lines of an IEEEeqnarray, sets the height +% and depth of both the master and local struts. If called inside +% an IEEEeqnarray line, sets the height and depth of the local strut +% only and sets the flag to indicate the use of the local strut +% values. If the height or depth is left blank, 0.7\normalbaselineskip +% and 0.3\normalbaselineskip will be used, respectively. +% The optional argument can be used to evaluate the lengths under +% a different font size and styles. If none is specified, the current +% font is used. +% uses scratch registers \skip0, \skip2, \skip3, \dimen0, \dimen2 +\def\IEEEeqnarraystrutsize#1#2{\relax\@ifnextchar[{\@IEEEeqnarraystrutsize{#1}{#2}}{\@IEEEeqnarraystrutsize{#1}{#2}[\relax]}} +\def\@IEEEeqnarraystrutsize#1#2[#3]{\def\@IEEEeqnarraystrutsizeARG{#1}% +\ifx\@IEEEeqnarraystrutsizeARG\@empty% +{\setbox0=\hbox{#3\relax\global\skip3=0.7\normalbaselineskip}}% +\skip0=\skip3\relax% +\else% arg one present +{\setbox0=\hbox{#3\relax\global\skip3=#1\relax}}% +\skip0=\skip3\relax% +\fi% if null arg +\def\@IEEEeqnarraystrutsizeARG{#2}% +\ifx\@IEEEeqnarraystrutsizeARG\@empty% +{\setbox0=\hbox{#3\relax\global\skip3=0.3\normalbaselineskip}}% +\skip2=\skip3\relax% +\else% arg two present +{\setbox0=\hbox{#3\relax\global\skip3=#2\relax}}% +\skip2=\skip3\relax% +\fi% if null arg +% remove stretchability, just to be safe +\dimen0\skip0\relax% +\dimen2\skip2\relax% +% dimen0 = height, dimen2 = depth +\if@IEEEeqnarrayISinner% inner does not touch master strut size +\edef\@IEEEeqnarrayTHEstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEstrutdepth{\the\dimen2}% +\@IEEEeqnarrayusemasterstrutfalse% do not use master +\else% outer, have to set master strut too +\edef\@IEEEeqnarrayTHEmasterstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEmasterstrutdepth{\the\dimen2}% +\edef\@IEEEeqnarrayTHEstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEstrutdepth{\the\dimen2}% +\@IEEEeqnarrayusemasterstruttrue% use master strut +\fi} + + +% usage: \IEEEeqnarraystrutsizeadd{added height}{added depth}[font size commands] +% If called outside the lines of an IEEEeqnarray, adds the given height +% and depth to both the master and local struts. +% If called inside an IEEEeqnarray line, adds the given height and depth +% to the local strut only and sets the flag to indicate the use +% of the local strut values. +% In both cases, if a height or depth is left blank, 0pt is used instead. +% The optional argument can be used to evaluate the lengths under +% a different font size and styles. If none is specified, the current +% font is used. +% uses scratch registers \skip0, \skip2, \skip3, \dimen0, \dimen2 +\def\IEEEeqnarraystrutsizeadd#1#2{\relax\@ifnextchar[{\@IEEEeqnarraystrutsizeadd{#1}{#2}}{\@IEEEeqnarraystrutsizeadd{#1}{#2}[\relax]}} +\def\@IEEEeqnarraystrutsizeadd#1#2[#3]{\def\@IEEEeqnarraystrutsizearg{#1}% +\ifx\@IEEEeqnarraystrutsizearg\@empty% +\skip0=0pt\relax% +\else% arg one present +{\setbox0=\hbox{#3\relax\global\skip3=#1}}% +\skip0=\skip3\relax% +\fi% if null arg +\def\@IEEEeqnarraystrutsizearg{#2}% +\ifx\@IEEEeqnarraystrutsizearg\@empty% +\skip2=0pt\relax% +\else% arg two present +{\setbox0=\hbox{#3\relax\global\skip3=#2}}% +\skip2=\skip3\relax% +\fi% if null arg +% remove stretchability, just to be safe +\dimen0\skip0\relax% +\dimen2\skip2\relax% +% dimen0 = height, dimen2 = depth +\if@IEEEeqnarrayISinner% inner does not touch master strut size +% get local strut size +\expandafter\skip0=\@IEEEeqnarrayTHEstrutheight\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEstrutdepth\relax% +% add it to the user supplied values +\advance\dimen0 by \skip0\relax% +\advance\dimen2 by \skip2\relax% +% update the local strut size +\edef\@IEEEeqnarrayTHEstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEstrutdepth{\the\dimen2}% +\@IEEEeqnarrayusemasterstrutfalse% do not use master +\else% outer, have to set master strut too +% get master strut size +\expandafter\skip0=\@IEEEeqnarrayTHEmasterstrutheight\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEmasterstrutdepth\relax% +% add it to the user supplied values +\advance\dimen0 by \skip0\relax% +\advance\dimen2 by \skip2\relax% +% update the local and master strut sizes +\edef\@IEEEeqnarrayTHEmasterstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEmasterstrutdepth{\the\dimen2}% +\edef\@IEEEeqnarrayTHEstrutheight{\the\dimen0}% +\edef\@IEEEeqnarrayTHEstrutdepth{\the\dimen2}% +\@IEEEeqnarrayusemasterstruttrue% use master strut +\fi} + + +% allow user a way to see the struts +\newif\ifIEEEvisiblestruts +\IEEEvisiblestrutsfalse + +% inserts an invisible strut using the master or local strut values +% uses scratch registers \skip0, \skip2, \dimen0, \dimen2 +\def\@IEEEeqnarrayinsertstrut{\relax% +\if@IEEEeqnarrayusemasterstrut +% get master strut size +\expandafter\skip0=\@IEEEeqnarrayTHEmasterstrutheight\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEmasterstrutdepth\relax% +\else% +% get local strut size +\expandafter\skip0=\@IEEEeqnarrayTHEstrutheight\relax% +\expandafter\skip2=\@IEEEeqnarrayTHEstrutdepth\relax% +\fi% +% remove stretchability, probably not needed +\dimen0\skip0\relax% +\dimen2\skip2\relax% +% dimen0 = height, dimen2 = depth +% allow user to see struts if desired +\ifIEEEvisiblestruts% +\vrule width0.2pt height\dimen0 depth\dimen2\relax% +\else% +\vrule width0pt height\dimen0 depth\dimen2\relax\fi} + + +% creates an invisible strut, useable even outside \IEEEeqnarray +% if \IEEEvisiblestrutstrue, the strut will be visible and 0.2pt wide. +% usage: \IEEEstrut[height][depth][font size commands] +% default is \IEEEstrut[0.7\normalbaselineskip][0.3\normalbaselineskip][\relax] +% blank arguments inherit the default values +% uses \dimen0, \dimen2, \skip0, \skip2 +\def\IEEEstrut{\relax\@ifnextchar[{\@IEEEstrut}{\@IEEEstrut[0.7\normalbaselineskip]}} +\def\@IEEEstrut[#1]{\relax\@ifnextchar[{\@@IEEEstrut[#1]}{\@@IEEEstrut[#1][0.3\normalbaselineskip]}} +\def\@@IEEEstrut[#1][#2]{\relax\@ifnextchar[{\@@@IEEEstrut[#1][#2]}{\@@@IEEEstrut[#1][#2][\relax]}} +\def\@@@IEEEstrut[#1][#2][#3]{\mbox{#3\relax% +\def\@IEEEstrutARG{#1}% +\ifx\@IEEEstrutARG\@empty% +\skip0=0.7\normalbaselineskip\relax% +\else% +\skip0=#1\relax% +\fi% +\def\@IEEEstrutARG{#2}% +\ifx\@IEEEstrutARG\@empty% +\skip2=0.3\normalbaselineskip\relax% +\else% +\skip2=#2\relax% +\fi% +% remove stretchability, probably not needed +\dimen0\skip0\relax% +\dimen2\skip2\relax% +\ifIEEEvisiblestruts% +\vrule width0.2pt height\dimen0 depth\dimen2\relax% +\else% +\vrule width0.0pt height\dimen0 depth\dimen2\relax\fi}} + + +% enables strut mode by setting a default strut size and then zeroing the +% \baselineskip, \lineskip, \lineskiplimit and \jot +\def\IEEEeqnarraystrutmode{\IEEEeqnarraystrutsize{0.7\normalbaselineskip}{0.3\normalbaselineskip}[\relax]% +\baselineskip=0pt\lineskip=0pt\lineskiplimit=0pt\jot=0pt} + + +% equation and subequation forms to use to setup hyperref's \@currentHref +\def\@IEEEtheHrefequation{equation.\theHequation} +\def\@IEEEtheHrefsubequation{equation.\theHequation\alph{IEEEsubequation}} + + +\def\IEEEeqnarray{\@IEEEeqnumpersisttrue\@IEEEsubeqnumpersistfalse\@IEEEeqnarray} +\def\endIEEEeqnarray{\end@IEEEeqnarray} + +\@namedef{IEEEeqnarray*}{\@IEEEeqnumpersistfalse\@IEEEsubeqnumpersistfalse\@IEEEeqnarray} +\@namedef{endIEEEeqnarray*}{\end@IEEEeqnarray} + + +% \IEEEeqnarray is an enhanced \eqnarray. +% The star form defaults to not putting equation numbers at the end of each row. +% usage: \IEEEeqnarray[decl]{cols} +\def\@IEEEeqnarray{\relax\@ifnextchar[{\@@IEEEeqnarray}{\@@IEEEeqnarray[\relax]}} +% We have to be careful here to normalize catcodes just before acquiring the +% cols as that specification may contain punctuation which could be subject +% to document catcode changes. +\def\@@IEEEeqnarray[#1]{\begingroup\IEEEnormalcatcodes\@@@IEEEeqnarray[#1]} +\def\@@@IEEEeqnarray[#1]#2{\endgroup + % default to showing the equation number or not based on whether or not + % the star form was involked + \if@IEEEeqnumpersist\global\@eqnswtrue + \else% not the star form + \global\@eqnswfalse + \fi% if star form + % provide a basic hyperref \theHequation if this has not already been setup (hyperref not loaded, or no section counter) + \@ifundefined{theHequation}{\def\theHequation{\arabic{equation}}}{}\relax + % provide dummy hyperref commands in case hyperref is not loaded + \providecommand{\Hy@raisedlink}[1]{}\relax + \providecommand{\hyper@anchorstart}[1]{}\relax + \providecommand{\hyper@anchorend}{}\relax + \providecommand{\@currentHref}{}\relax + \@IEEEeqnumpreadvfalse% reset eqnpreadv flag + \@IEEEsubeqnumpreadvfalse% reset subeqnpreadv flag + \@IEEEeqnarrayISinnerfalse% not yet within the lines of the halign + \@IEEEeqnarraystrutsize{0pt}{0pt}[\relax]% turn off struts by default + \@IEEEeqnarrayusemasterstruttrue% use master strut till user asks otherwise + \IEEEvisiblestrutsfalse% diagnostic mode defaults to off + % no extra space unless the user specifically requests it + \lineskip=0pt\relax + \lineskiplimit=0pt\relax + \baselineskip=\normalbaselineskip\relax% + \jot=\IEEEnormaljot\relax% + \mathsurround\z@\relax% no extra spacing around math + \@advanceIEEEeqncolcnttrue% advance the col counter for each col the user uses, + % used in \IEEEeqnarraymulticol and in the preamble build + %V1.8 Here we preadvance to the next equation number. + % If the user later wants a continued subequation, we can roll back. + \global\@IEEEsubeqnnumrollback=\c@IEEEsubequation% + \stepcounter{equation}\@IEEEeqnumpreadvtrue% advance equation counter before first line + \setcounter{IEEEsubequation}{0}% no subequation yet + \let\@IEEEcurrentlabelsave\@currentlabel% save current label as we later change it globally + \let\@IEEEcurrentHrefsave\@currentHref% save current href label as we later change it globally + \def\@currentlabel{\p@equation\theequation}% redefine the ref label + \def\@currentHref{\@IEEEtheHrefequation}% setup hyperref label + \IEEEeqnarraydecl\relax% allow a way for the user to make global overrides + #1\relax% allow user to override defaults + \let\\\@IEEEeqnarraycr% replace newline with one that can put in eqn. numbers + \global\@IEEEeqncolcnt\z@% col. count = 0 for first line + \@IEEEbuildpreamble{#2}\relax% build the preamble and put it into \@IEEEtrantmptoksA + % put in the column for the equation number + \ifnum\@IEEEeqnnumcols>0\relax\@IEEEappendtoksA{&}\fi% col separator for those after the first + \toks0={##}% + % advance the \@IEEEeqncolcnt for the isolation col, this helps with error checking + \@IEEEappendtoksA{\global\advance\@IEEEeqncolcnt by 1\relax}% + % add the isolation column + \@IEEEappendtoksA{\tabskip\z@skip\bgroup\the\toks0\egroup}% + % advance the \@IEEEeqncolcnt for the equation number col, this helps with error checking + \@IEEEappendtoksA{&\global\advance\@IEEEeqncolcnt by 1\relax}% + % add the equation number col to the preamble + \@IEEEappendtoksA{\tabskip\z@skip\hb@xt@\z@\bgroup\hss\the\toks0\egroup}% + % note \@IEEEeqnnumcols does not count the equation col or isolation col + % set the starting tabskip glue as determined by the preamble build + \tabskip=\@IEEEBPstartglue\relax + % begin the display alignment + \@IEEEeqnarrayISinnertrue% commands are now within the lines + $$\everycr{}\halign to\displaywidth\bgroup + % "exspand" the preamble + \span\the\@IEEEtrantmptoksA\cr} + +% enter isolation/strut column (or the next column if the user did not use +% every column), record the strut status, complete the columns, do the strut if needed, +% restore counters (to backout any equation setup for a next line that was never used) +% to their correct values and exit +\def\end@IEEEeqnarray{\@IEEEeqnarrayglobalizestrutstatus&\@@IEEEeqnarraycr\egroup +\if@IEEEsubeqnumpreadv\global\advance\c@IEEEsubequation\m@ne\fi +\if@IEEEeqnumpreadv\global\advance\c@equation\m@ne\global\c@IEEEsubequation=\@IEEEsubeqnnumrollback\fi +\global\let\@currentlabel\@IEEEcurrentlabelsave% restore current label +\global\let\@currentHref\@IEEEcurrentHrefsave% restore current href label +$$\@ignoretrue} + + +% IEEEeqnarray uses a modifed \\ instead of the plain \cr to +% end rows. This allows for things like \\*[vskip amount] +% These "cr" macros are modified versions of those for LaTeX2e's eqnarray +% the {\ifnum0=`} braces must be kept away from the last column to avoid +% altering spacing of its math, so we use & to advance to the next column +% as there is an isolation/strut column after the user's columns +\def\@IEEEeqnarraycr{\@IEEEeqnarrayglobalizestrutstatus&% save strut status and advance to next column + {\ifnum0=`}\fi + \@ifstar{% + \global\@eqpen\@M\@IEEEeqnarrayYCR + }{% + \global\@eqpen\interdisplaylinepenalty \@IEEEeqnarrayYCR + }% +} + +\def\@IEEEeqnarrayYCR{\@testopt\@IEEEeqnarrayXCR\z@skip} + +\def\@IEEEeqnarrayXCR[#1]{% + \ifnum0=`{\fi}% + \@@IEEEeqnarraycr + \noalign{\penalty\@eqpen\vskip\jot\vskip #1\relax}}% + +\def\@@IEEEeqnarraycr{\@IEEEtrantmptoksA={}% clear token register + \advance\@IEEEeqncolcnt by -1\relax% adjust col count because of the isolation column + \ifnum\@IEEEeqncolcnt>\@IEEEeqnnumcols\relax + \@IEEEclspkgerror{Too many columns within the IEEEeqnarray\MessageBreak + environment}% + {Use fewer \string &'s or put more columns in the IEEEeqnarray column\MessageBreak + specifications.}\relax% + \else + \loop% add cols if the user did not use them all + \ifnum\@IEEEeqncolcnt<\@IEEEeqnnumcols\relax + \@IEEEappendtoksA{&}% + \advance\@IEEEeqncolcnt by 1\relax% update the col count + \repeat + % this number of &'s will take us the the isolation column + \fi + % execute the &'s + \the\@IEEEtrantmptoksA% + % handle the strut/isolation column + \@IEEEeqnarrayinsertstrut% do the strut if needed + \@IEEEeqnarraystrutreset% reset the strut system for next line or IEEEeqnarray + &% and enter the equation number column + \if@eqnsw% only if we display something + \Hy@raisedlink{\hyper@anchorstart{\@currentHref}}% start a hyperref anchor + \global\@IEEEeqnumpreadvfalse\relax% displaying an equation number means + \global\@IEEEsubeqnumpreadvfalse\relax% the equation counters point to valid equations + % V1.8 Here we setup the counters, currentlabel and status for what would be the *next* + % equation line as would be the case under the current settings. However, there are two problems. + % One problem is that there might not ever be a next line. The second problem is that the user + % may later alter the meaning of a line with commands such as \IEEEyessubnumber. So, to handle + % these cases we have to record the current values of the (sub)equation counters and revert back + % to them if the next line is changed or never comes. The \if@IEEEeqnumpreadv, \if@IEEEsubeqnumpreadv + % and \@IEEEsubeqnnumrollback stuff tracks this. + % The logic to handle all this is surprisingly complex, but a nice feature of the approach here is + % that the equation counters and labels remain valid for what the line would be unless a + % \IEEEyessubnumber et al. later changes it. So, any hyperref links are always correct. + \ifnum\c@IEEEsubequation>0\relax% handle subequation + \theIEEEsubequationdis\relax + \if@IEEEsubeqnumpersist% setup for default type of next line + \stepcounter{IEEEsubequation}\global\@IEEEsubeqnumpreadvtrue\relax + \gdef\@currentlabel{\p@IEEEsubequation\theIEEEsubequation}\relax + \gdef\@currentHref{\@IEEEtheHrefsubequation}% setup hyperref label + \else + % if no subeqnum persist, go ahead and setup for a new equation number + \global\@IEEEsubeqnnumrollback=\c@IEEEsubequation + \stepcounter{equation}\global\@IEEEeqnumpreadvtrue\relax + \setcounter{IEEEsubequation}{0}\gdef\@currentlabel{\p@equation\theequation}\relax + \gdef\@currentHref{\@IEEEtheHrefequation}% setup hyperref label + \fi + \else% display a standard equation number + \theequationdis\relax + \setcounter{IEEEsubequation}{0}\relax% not really needed + \if@IEEEsubeqnumpersist% setup for default type of next line + % subequations that follow plain equations carry the same equation number e.g, 5, 5a rather than 5, 6a + \stepcounter{IEEEsubequation}\global\@IEEEsubeqnumpreadvtrue\relax + \gdef\@currentlabel{\p@IEEEsubequation\theIEEEsubequation}\relax + \gdef\@currentHref{\@IEEEtheHrefsubequation}% setup hyperref label + \else + % if no subeqnum persist, go ahead and setup for a new equation number + \global\@IEEEsubeqnnumrollback=\c@IEEEsubequation + \stepcounter{equation}\global\@IEEEeqnumpreadvtrue\relax + \setcounter{IEEEsubequation}{0}\gdef\@currentlabel{\p@equation\theequation}\relax + \gdef\@currentHref{\@IEEEtheHrefequation}% setup hyperref label + \fi + \fi% + \Hy@raisedlink{\hyper@anchorend}% end hyperref anchor + \fi% fi only if we display something + % reset the flags to indicate the default preferences of the display of equation numbers + \if@IEEEeqnumpersist\global\@eqnswtrue\else\global\@eqnswfalse\fi + \if@IEEEsubeqnumpersist\global\@eqnswtrue\fi% ditto for the subequation flag + % reset the number of columns the user actually used + \global\@IEEEeqncolcnt\z@\relax + % the real end of the line + \cr} + + + + + +% \IEEEeqnarraybox is like \IEEEeqnarray except the box form puts everything +% inside a vtop, vbox, or vcenter box depending on the letter in the second +% optional argument (t,b,c). Vbox is the default. Unlike \IEEEeqnarray, +% equation numbers are not displayed and \IEEEeqnarraybox can be nested. +% \IEEEeqnarrayboxm is for math mode (like \array) and does not put the vbox +% within an hbox. +% \IEEEeqnarrayboxt is for text mode (like \tabular) and puts the vbox within +% a \hbox{$ $} construct. +% \IEEEeqnarraybox will auto detect whether to use \IEEEeqnarrayboxm or +% \IEEEeqnarrayboxt depending on the math mode. +% The third optional argument specifies the width this box is to be set to - +% natural width is the default. +% The * forms do not add \jot line spacing +% usage: \IEEEeqnarraybox[decl][pos][width]{cols} +\def\IEEEeqnarrayboxm{\@IEEEeqnarrayboxnojotfalse\@IEEEeqnarrayboxHBOXSWfalse\@IEEEeqnarraybox} +\def\endIEEEeqnarrayboxm{\end@IEEEeqnarraybox} +\@namedef{IEEEeqnarrayboxm*}{\@IEEEeqnarrayboxnojottrue\@IEEEeqnarrayboxHBOXSWfalse\@IEEEeqnarraybox} +\@namedef{endIEEEeqnarrayboxm*}{\end@IEEEeqnarraybox} + +\def\IEEEeqnarrayboxt{\@IEEEeqnarrayboxnojotfalse\@IEEEeqnarrayboxHBOXSWtrue\@IEEEeqnarraybox} +\def\endIEEEeqnarrayboxt{\end@IEEEeqnarraybox} +\@namedef{IEEEeqnarrayboxt*}{\@IEEEeqnarrayboxnojottrue\@IEEEeqnarrayboxHBOXSWtrue\@IEEEeqnarraybox} +\@namedef{endIEEEeqnarrayboxt*}{\end@IEEEeqnarraybox} + +\def\IEEEeqnarraybox{\@IEEEeqnarrayboxnojotfalse\ifmmode\@IEEEeqnarrayboxHBOXSWfalse\else\@IEEEeqnarrayboxHBOXSWtrue\fi% +\@IEEEeqnarraybox} +\def\endIEEEeqnarraybox{\end@IEEEeqnarraybox} + +\@namedef{IEEEeqnarraybox*}{\@IEEEeqnarrayboxnojottrue\ifmmode\@IEEEeqnarrayboxHBOXSWfalse\else\@IEEEeqnarrayboxHBOXSWtrue\fi% +\@IEEEeqnarraybox} +\@namedef{endIEEEeqnarraybox*}{\end@IEEEeqnarraybox} + +% flag to indicate if the \IEEEeqnarraybox needs to put things into an hbox{$ $} +% for \vcenter in non-math mode +\newif\if@IEEEeqnarrayboxHBOXSW% +\@IEEEeqnarrayboxHBOXSWfalse + +\def\@IEEEeqnarraybox{\relax\@ifnextchar[{\@@IEEEeqnarraybox}{\@@IEEEeqnarraybox[\relax]}} +% We have to be careful here to normalize catcodes just before acquiring the +% cols as that specification may contain punctuation which could be subject +% to document catcode changes. +\def\@@IEEEeqnarraybox[#1]{\relax\begingroup\IEEEnormalcatcodes\@ifnextchar[{\@@@IEEEeqnarraybox[#1]}{\@@@IEEEeqnarraybox[#1][b]}} +\def\@@@IEEEeqnarraybox[#1][#2]{\relax\@ifnextchar[{\@@@@IEEEeqnarraybox[#1][#2]}{\@@@@IEEEeqnarraybox[#1][#2][\relax]}} + +% #1 = decl; #2 = t,b,c; #3 = width, #4 = col specs +\def\@@@@IEEEeqnarraybox[#1][#2][#3]#4{\endgroup\@IEEEeqnarrayISinnerfalse % not yet within the lines of the halign + \@IEEEeqnarraymasterstrutsave% save current master strut values + \@IEEEeqnarraystrutsize{0pt}{0pt}[\relax]% turn off struts by default + \@IEEEeqnarrayusemasterstruttrue% use master strut till user asks otherwise + \IEEEvisiblestrutsfalse% diagnostic mode defaults to off + % no extra space unless the user specifically requests it + \lineskip=0pt\relax% + \lineskiplimit=0pt\relax% + \baselineskip=\normalbaselineskip\relax% + \jot=\IEEEnormaljot\relax% + \mathsurround\z@\relax% no extra spacing around math + % the default end glues are zero for an \IEEEeqnarraybox + \edef\@IEEEeqnarraycolSEPdefaultstart{\@IEEEeqnarraycolSEPzero}% default start glue + \edef\@IEEEeqnarraycolSEPdefaultend{\@IEEEeqnarraycolSEPzero}% default end glue + \edef\@IEEEeqnarraycolSEPdefaultmid{\@IEEEeqnarraycolSEPzero}% default inter-column glue + \@advanceIEEEeqncolcntfalse% do not advance the col counter for each col the user uses, + % used in \IEEEeqnarraymulticol and in the preamble build + \IEEEeqnarrayboxdecl\relax% allow a way for the user to make global overrides + #1\relax% allow user to override defaults + \let\\\@IEEEeqnarrayboxcr% replace newline with one that allows optional spacing + \@IEEEbuildpreamble{#4}\relax% build the preamble and put it into \@IEEEtrantmptoksA + % add an isolation column to the preamble to stop \\'s {} from getting into the last col + \ifnum\@IEEEeqnnumcols>0\relax\@IEEEappendtoksA{&}\fi% col separator for those after the first + \toks0={##}% + % add the isolation column to the preamble + \@IEEEappendtoksA{\tabskip\z@skip\bgroup\the\toks0\egroup}% + % set the starting tabskip glue as determined by the preamble build + \tabskip=\@IEEEBPstartglue\relax + % begin the alignment + \everycr{}% + % use only the very first token to determine the positioning + \@IEEEextracttoken{#2}\relax + \ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: IEEEeqnarraybox position specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax + \fi + % \@IEEEextractedtoken has the first token, the rest are ignored + % if we need to put things into and hbox and go into math mode, do so now + \if@IEEEeqnarrayboxHBOXSW \leavevmode \hbox \bgroup $\fi% + % use the appropriate vbox type + \if\@IEEEextractedtoken t\relax\vtop\else\if\@IEEEextractedtoken c\relax% + \vcenter\else\vbox\fi\fi\bgroup% + \@IEEEeqnarrayISinnertrue% commands are now within the lines + \ifx#3\relax\halign\else\halign to #3\relax\fi% + \bgroup + % "exspand" the preamble + \span\the\@IEEEtrantmptoksA\cr} + +% carry strut status and enter the isolation/strut column, +% exit from math mode if needed, and exit +\def\end@IEEEeqnarraybox{\@IEEEeqnarrayglobalizestrutstatus% carry strut status +&% enter isolation/strut column +\@IEEEeqnarrayinsertstrut% do strut if needed +\@IEEEeqnarraymasterstrutrestore% restore the previous master strut values +% reset the strut system for next IEEEeqnarray +% (sets local strut values back to previous master strut values) +\@IEEEeqnarraystrutreset% +% ensure last line, exit from halign, close vbox +\crcr\egroup\egroup% +% exit from math mode and close hbox if needed +\if@IEEEeqnarrayboxHBOXSW $\egroup\fi} + + + +% IEEEeqnarraybox uses a modifed \\ instead of the plain \cr to +% end rows. This allows for things like \\[vskip amount] +% This "cr" macros are modified versions those for LaTeX2e's eqnarray +% For IEEEeqnarraybox, \\* is the same as \\ +% the {\ifnum0=`} braces must be kept away from the last column to avoid +% altering spacing of its math, so we use & to advance to the isolation/strut column +% carry strut status into isolation/strut column +\def\@IEEEeqnarrayboxcr{\@IEEEeqnarrayglobalizestrutstatus% carry strut status +&% enter isolation/strut column +\@IEEEeqnarrayinsertstrut% do strut if needed +% reset the strut system for next line or IEEEeqnarray +\@IEEEeqnarraystrutreset% +{\ifnum0=`}\fi% +\@ifstar{\@IEEEeqnarrayboxYCR}{\@IEEEeqnarrayboxYCR}} + +% test and setup the optional argument to \\[] +\def\@IEEEeqnarrayboxYCR{\@testopt\@IEEEeqnarrayboxXCR\z@skip} + +% IEEEeqnarraybox does not automatically increase line spacing by \jot +\def\@IEEEeqnarrayboxXCR[#1]{\ifnum0=`{\fi}% +\cr\noalign{\if@IEEEeqnarrayboxnojot\else\vskip\jot\fi\vskip#1\relax}} + + + +% usage: \@IEEEbuildpreamble{column specifiers} +% starts the halign preamble build +% the assembled preamble is put in \@IEEEtrantmptoksA +\def\@IEEEbuildpreamble#1{\@IEEEtrantmptoksA={}% clear token register +\let\@IEEEBPcurtype=u%current column type is not yet known +\let\@IEEEBPprevtype=s%the previous column type was the start +\let\@IEEEBPnexttype=u%next column type is not yet known +% ensure these are valid +\def\@IEEEBPcurglue={0pt plus 0pt minus 0pt}% +\def\@IEEEBPcurcolname{@IEEEdefault}% name of current column definition +% currently acquired numerically referenced glue +% use a name that is easier to remember +\let\@IEEEBPcurnum=\@IEEEtrantmpcountA% +\@IEEEBPcurnum=0% +% tracks number of columns in the preamble +\@IEEEeqnnumcols=0% +% record the default end glues +\edef\@IEEEBPstartglue{\@IEEEeqnarraycolSEPdefaultstart}% +\edef\@IEEEBPendglue{\@IEEEeqnarraycolSEPdefaultend}% +\edef\@IEEEedefMACRO{#1}\relax% fully expand the preamble to support macro containers +% now parse the user's column specifications +% \ignorespaces is used as a delimiter, need at least one trailing \relax because +% \@@IEEEbuildpreamble looks into the future +\expandafter\@@IEEEbuildpreamble\@IEEEedefMACRO\ignorespaces\relax\relax} + + +% usage: \@@IEEEbuildpreamble{current column}{next column} +% parses and builds the halign preamble +\def\@@IEEEbuildpreamble#1#2{\let\@@nextIEEEbuildpreamble=\@@IEEEbuildpreamble% +% use only the very first token to check the end +\@IEEEextracttokengroups{#1}\relax +\ifx\@IEEEextractedfirsttoken\ignorespaces\let\@@nextIEEEbuildpreamble=\@@IEEEfinishpreamble\else% +% identify current and next token type +\@IEEEgetcoltype{#1}{\@IEEEBPcurtype}{1}% current, error on invalid +\@IEEEgetcoltype{#2}{\@IEEEBPnexttype}{0}% next, no error on invalid next +% if curtype is a glue, get the glue def +\if\@IEEEBPcurtype g\@IEEEgetcurglue{#1}{\@IEEEBPcurglue}\fi% +% if curtype is a column, get the column def and set the current column name +\if\@IEEEBPcurtype c\@IEEEgetcurcol{#1}\fi% +% if curtype is a numeral, acquire the user defined glue +\if\@IEEEBPcurtype n\@IEEEprocessNcol{#1}\fi% +% process the acquired glue +\if\@IEEEBPcurtype g\@IEEEprocessGcol\fi% +% process the acquired col +\if\@IEEEBPcurtype c\@IEEEprocessCcol\fi% +% ready prevtype for next col spec. +\let\@IEEEBPprevtype=\@IEEEBPcurtype% +% be sure and put back the future token(s) as a group +\fi\@@nextIEEEbuildpreamble{#2}} + + +% usage: \@@IEEEfinishpreamble{discarded} +% executed just after preamble build is completed +% warn about zero cols, and if prevtype type = u, put in end tabskip glue +% argument is not used +\def\@@IEEEfinishpreamble#1{\ifnum\@IEEEeqnnumcols<1\relax +\@IEEEclspkgerror{No column specifiers declared for IEEEeqnarray}% +{At least one column type must be declared for each IEEEeqnarray.}% +\fi%num cols less than 1 +%if last type undefined, set default end tabskip glue +\if\@IEEEBPprevtype u\@IEEEappendtoksA{\tabskip=\@IEEEBPendglue}\fi} + + +% usage: \@IEEEgetcoltype{col specifier}{\output}{error more} +% Identify and return the column specifier's type code in the given +% \output macro: +% n = number +% g = glue (any other char in catagory 12) +% c = letter +% e = \ignorespaces (end of sequence) +% u = undefined +% error mode: 0 = no error message, 1 = error on invalid char +\def\@IEEEgetcoltype#1#2#3{% +% use only the very first token to determine the type +\@IEEEextracttoken{#1}\relax +% \@IEEEextractedtoken has the first token, the rest are discarded +\let#2=u\relax% assume invalid until know otherwise +\ifx\@IEEEextractedtoken\ignorespaces\let#2=e\else +\ifcat\@IEEEextractedtoken\relax\else% screen out control sequences +\if0\@IEEEextractedtoken\let#2=n\else +\if1\@IEEEextractedtoken\let#2=n\else +\if2\@IEEEextractedtoken\let#2=n\else +\if3\@IEEEextractedtoken\let#2=n\else +\if4\@IEEEextractedtoken\let#2=n\else +\if5\@IEEEextractedtoken\let#2=n\else +\if6\@IEEEextractedtoken\let#2=n\else +\if7\@IEEEextractedtoken\let#2=n\else +\if8\@IEEEextractedtoken\let#2=n\else +\if9\@IEEEextractedtoken\let#2=n\else +\ifcat,\@IEEEextractedtoken\let#2=g\relax +\else\ifcat a\@IEEEextractedtoken\let#2=c\relax\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi +\if#2u\relax +\if0\noexpand#3\relax\else\@IEEEclspkgerror{Invalid character in column specifications}% +{Only letters, numerals and certain other symbols are allowed \MessageBreak +as IEEEeqnarray column specifiers.}\fi\fi} + + +% usage: \@IEEEgetcurcol{col specifier} +% verify the letter referenced column exists +% and return its name in \@IEEEBPcurcolname +% if column specifier is invalid, use the default column @IEEEdefault +\def\@IEEEgetcurcol#1{\expandafter\ifx\csname @IEEEeqnarraycolDEF#1\endcsname\@IEEEeqnarraycolisdefined% +\def\@IEEEBPcurcolname{#1}\else% invalid column name +\@IEEEclspkgerror{Invalid column type "#1" in column specifications.\MessageBreak +Using a default centering column instead}% +{You must define IEEEeqnarray column types before use.}% +\def\@IEEEBPcurcolname{@IEEEdefault}\fi} + + +% usage: \@IEEEgetcurglue{glue specifier}{\output} +% identify the predefined (punctuation) glue value +% and return it in the given output macro +\def\@IEEEgetcurglue#1#2{% +% ! = \! (neg small) -0.16667em (-3/18 em) +% , = \, (small) 0.16667em ( 3/18 em) +% : = \: (med) 0.22222em ( 4/18 em) +% ; = \; (large) 0.27778em ( 5/18 em) +% ' = \quad 1em +% " = \qquad 2em +% . = 0.5\arraycolsep +% / = \arraycolsep +% ? = 2\arraycolsep +% * = 1fil +% + = \@IEEEeqnarraycolSEPcenter +% - = \@IEEEeqnarraycolSEPzero +% Note that all em values are referenced to the math font (textfont2) fontdimen6 +% value for 1em. +% +% use only the very first token to determine the type +\@IEEEextracttoken{#1}\relax +\ifx\@IEEEextractedtokensdiscarded\@empty\else + \typeout{** WARNING: IEEEeqnarray predefined inter-column glue type specifiers after the first in `\@IEEEextracttokenarg' ignored (line \the\inputlineno).}\relax +\fi +% get the math font 1em value +% LaTeX2e's NFSS2 does not preload the fonts, but \IEEEeqnarray needs +% to gain access to the math (\textfont2) font's spacing parameters. +% So we create a bogus box here that uses the math font to ensure +% that \textfont2 is loaded and ready. If this is not done, +% the \textfont2 stuff here may not work. +% Thanks to Bernd Raichle for his 1997 post on this topic. +{\setbox0=\hbox{$\displaystyle\relax$}}% +% fontdimen6 has the width of 1em (a quad). +\@IEEEtrantmpdimenA=\fontdimen6\textfont2\relax% +% identify the glue value based on the first token +% we discard anything after the first +\if!\@IEEEextractedtoken\@IEEEtrantmpdimenA=-0.16667\@IEEEtrantmpdimenA\edef#2{\the\@IEEEtrantmpdimenA}\else +\if,\@IEEEextractedtoken\@IEEEtrantmpdimenA=0.16667\@IEEEtrantmpdimenA\edef#2{\the\@IEEEtrantmpdimenA}\else +\if:\@IEEEextractedtoken\@IEEEtrantmpdimenA=0.22222\@IEEEtrantmpdimenA\edef#2{\the\@IEEEtrantmpdimenA}\else +\if;\@IEEEextractedtoken\@IEEEtrantmpdimenA=0.27778\@IEEEtrantmpdimenA\edef#2{\the\@IEEEtrantmpdimenA}\else +\if'\@IEEEextractedtoken\@IEEEtrantmpdimenA=1\@IEEEtrantmpdimenA\edef#2{\the\@IEEEtrantmpdimenA}\else +\if"\@IEEEextractedtoken\@IEEEtrantmpdimenA=2\@IEEEtrantmpdimenA\edef#2{\the\@IEEEtrantmpdimenA}\else +\if.\@IEEEextractedtoken\@IEEEtrantmpdimenA=0.5\arraycolsep\edef#2{\the\@IEEEtrantmpdimenA}\else +\if/\@IEEEextractedtoken\edef#2{\the\arraycolsep}\else +\if?\@IEEEextractedtoken\@IEEEtrantmpdimenA=2\arraycolsep\edef#2{\the\@IEEEtrantmpdimenA}\else +\if *\@IEEEextractedtoken\edef#2{0pt plus 1fil minus 0pt}\else +\if+\@IEEEextractedtoken\edef#2{\@IEEEeqnarraycolSEPcenter}\else +\if-\@IEEEextractedtoken\edef#2{\@IEEEeqnarraycolSEPzero}\else +\edef#2{\@IEEEeqnarraycolSEPzero}% +\@IEEEclspkgerror{Invalid predefined inter-column glue type "#1" in\MessageBreak +column specifications. Using a default value of\MessageBreak +0pt instead}% +{Only !,:;'"./?*+ and - are valid predefined glue types in the\MessageBreak +IEEEeqnarray column specifications.}\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi\fi} + + +% usage: \@IEEEprocessNcol{digit} +% process a numerical digit from the column specification +% and look up the corresponding user defined glue value +% can transform current type from n to g or a as the user defined glue is acquired +\def\@IEEEprocessNcol#1{\if\@IEEEBPprevtype g% +\@IEEEclspkgerror{Back-to-back inter-column glue specifiers in column\MessageBreak +specifications. Ignoring consecutive glue specifiers\MessageBreak +after the first}% +{You cannot have two or more glue types next to each other\MessageBreak +in the IEEEeqnarray column specifications.}% +\let\@IEEEBPcurtype=a% abort this glue, future digits will be discarded +\@IEEEBPcurnum=0\relax% +\else% if we previously aborted a glue +\if\@IEEEBPprevtype a\@IEEEBPcurnum=0\let\@IEEEBPcurtype=a%maintain digit abortion +\else%acquire this number +% save the previous type before the numerical digits started +\if\@IEEEBPprevtype n\else\let\@IEEEBPprevsavedtype=\@IEEEBPprevtype\fi% +\multiply\@IEEEBPcurnum by 10\relax% +\advance\@IEEEBPcurnum by #1\relax% add in number, \relax is needed to stop TeX's number scan +\if\@IEEEBPnexttype n\else%close acquisition +\expandafter\ifx\csname @IEEEeqnarraycolSEPDEF\expandafter\romannumeral\number\@IEEEBPcurnum\endcsname\@IEEEeqnarraycolisdefined% +\edef\@IEEEBPcurglue{\csname @IEEEeqnarraycolSEP\expandafter\romannumeral\number\@IEEEBPcurnum\endcsname}% +\else%user glue not defined +\@IEEEclspkgerror{Invalid user defined inter-column glue type "\number\@IEEEBPcurnum" in\MessageBreak +column specifications. Using a default value of\MessageBreak +0pt instead}% +{You must define all IEEEeqnarray numerical inter-column glue types via\MessageBreak +\string\IEEEeqnarraydefcolsep \space before they are used in column specifications.}% +\edef\@IEEEBPcurglue{\@IEEEeqnarraycolSEPzero}% +\fi% glue defined or not +\let\@IEEEBPcurtype=g% change the type to reflect the acquired glue +\let\@IEEEBPprevtype=\@IEEEBPprevsavedtype% restore the prev type before this number glue +\@IEEEBPcurnum=0\relax%ready for next acquisition +\fi%close acquisition, get glue +\fi%discard or acquire number +\fi%prevtype glue or not +} + + +% process an acquired glue +% add any acquired column/glue pair to the preamble +\def\@IEEEprocessGcol{\if\@IEEEBPprevtype a\let\@IEEEBPcurtype=a%maintain previous glue abortions +\else +% if this is the start glue, save it, but do nothing else +% as this is not used in the preamble, but before +\if\@IEEEBPprevtype s\edef\@IEEEBPstartglue{\@IEEEBPcurglue}% +\else%not the start glue +\if\@IEEEBPprevtype g%ignore if back to back glues +\@IEEEclspkgerror{Back-to-back inter-column glue specifiers in column\MessageBreak +specifications. Ignoring consecutive glue specifiers\MessageBreak +after the first}% +{You cannot have two or more glue types next to each other\MessageBreak +in the IEEEeqnarray column specifications.}% +\let\@IEEEBPcurtype=a% abort this glue +\else% not a back to back glue +\if\@IEEEBPprevtype c\relax% if the previoustype was a col, add column/glue pair to preamble +\ifnum\@IEEEeqnnumcols>0\relax\@IEEEappendtoksA{&}\fi +\toks0={##}% +% make preamble advance col counter if this environment needs this +\if@advanceIEEEeqncolcnt\@IEEEappendtoksA{\global\advance\@IEEEeqncolcnt by 1\relax}\fi +% insert the column defintion into the preamble, being careful not to expand +% the column definition +\@IEEEappendtoksA{\tabskip=\@IEEEBPcurglue}% +\@IEEEappendNOEXPANDtoksA{\begingroup\csname @IEEEeqnarraycolPRE}% +\@IEEEappendtoksA{\@IEEEBPcurcolname}% +\@IEEEappendNOEXPANDtoksA{\endcsname}% +\@IEEEappendtoksA{\the\toks0}% +\@IEEEappendNOEXPANDtoksA{\relax\relax\relax\relax\relax% +\relax\relax\relax\relax\relax\csname @IEEEeqnarraycolPOST}% +\@IEEEappendtoksA{\@IEEEBPcurcolname}% +\@IEEEappendNOEXPANDtoksA{\endcsname\relax\relax\relax\relax\relax% +\relax\relax\relax\relax\relax\endgroup}% +\advance\@IEEEeqnnumcols by 1\relax%one more column in the preamble +\else% error: non-start glue with no pending column +\@IEEEclspkgerror{Inter-column glue specifier without a prior column\MessageBreak +type in the column specifications. Ignoring this glue\MessageBreak +specifier}% +{Except for the first and last positions, glue can be placed only\MessageBreak +between column types.}% +\let\@IEEEBPcurtype=a% abort this glue +\fi% previous was a column +\fi% back-to-back glues +\fi% is start column glue +\fi% prev type not a +} + + +% process an acquired letter referenced column and, if necessary, add it to the preamble +\def\@IEEEprocessCcol{\if\@IEEEBPnexttype g\else +\if\@IEEEBPnexttype n\else +% we have a column followed by something other than a glue (or numeral glue) +% so we must add this column to the preamble now +\ifnum\@IEEEeqnnumcols>0\relax\@IEEEappendtoksA{&}\fi%col separator for those after the first +\if\@IEEEBPnexttype e\@IEEEappendtoksA{\tabskip=\@IEEEBPendglue\relax}\else%put in end glue +\@IEEEappendtoksA{\tabskip=\@IEEEeqnarraycolSEPdefaultmid\relax}\fi% or default mid glue +\toks0={##}% +% make preamble advance col counter if this environment needs this +\if@advanceIEEEeqncolcnt\@IEEEappendtoksA{\global\advance\@IEEEeqncolcnt by 1\relax}\fi +% insert the column definition into the preamble, being careful not to expand +% the column definition +\@IEEEappendNOEXPANDtoksA{\begingroup\csname @IEEEeqnarraycolPRE}% +\@IEEEappendtoksA{\@IEEEBPcurcolname}% +\@IEEEappendNOEXPANDtoksA{\endcsname}% +\@IEEEappendtoksA{\the\toks0}% +\@IEEEappendNOEXPANDtoksA{\relax\relax\relax\relax\relax% +\relax\relax\relax\relax\relax\csname @IEEEeqnarraycolPOST}% +\@IEEEappendtoksA{\@IEEEBPcurcolname}% +\@IEEEappendNOEXPANDtoksA{\endcsname\relax\relax\relax\relax\relax% +\relax\relax\relax\relax\relax\endgroup}% +\advance\@IEEEeqnnumcols by 1\relax%one more column in the preamble +\fi%next type not numeral +\fi%next type not glue +} + + +%% +%% END OF IEEEeqnarray DEFINITIONS +%% + + + + + +% set up the running headers and footers +% +% header and footer font and size specifications +\def\@IEEEheaderstyle{\normalfont\scriptsize} +\def\@IEEEfooterstyle{\normalfont\scriptsize} +% +% compsoc uses sans-serif headers and footers +\ifCLASSOPTIONcompsoc + \def\@IEEEheaderstyle{\normalfont\sffamily\scriptsize} + \def\@IEEEfooterstyle{\normalfont\sffamily\scriptsize} +\fi + + +% standard page style, ps@headings +\def\ps@headings{% default to standard twoside headers, no footers +% will change later if the mode requires otherwise +\def\@oddhead{\hbox{}\@IEEEheaderstyle\rightmark\hfil\thepage}\relax +\def\@evenhead{\@IEEEheaderstyle\thepage\hfil\leftmark\hbox{}}\relax +\let\@oddfoot\@empty +\let\@evenfoot\@empty +\ifCLASSOPTIONtechnote + % technote twoside + \def\@oddhead{\hbox{}\@IEEEheaderstyle\leftmark\hfil\thepage}\relax + \def\@evenhead{\@IEEEheaderstyle\thepage\hfil\leftmark\hbox{}}\relax +\fi +\ifCLASSOPTIONdraftcls + % draft footers + \def\@oddfoot{\@IEEEfooterstyle\@date\hfil DRAFT}\relax + \def\@evenfoot{\@IEEEfooterstyle DRAFT\hfil\@date}\relax +\fi +% oneside +\if@twoside\else + % standard one side headers + \def\@oddhead{\hbox{}\@IEEEheaderstyle\leftmark\hfil\thepage}\relax + \let\@evenhead\@empty + \ifCLASSOPTIONdraftcls + % oneside draft footers + \def\@oddfoot{\@IEEEfooterstyle\@date\hfil DRAFT}\relax + \let\@evenfoot\@empty + \fi +\fi +% turn off headers for conferences +\ifCLASSOPTIONconference + \let\@oddhead\@empty + \let\@evenhead\@empty +\fi +% turn off footers for draftclsnofoot +\ifCLASSOPTIONdraftclsnofoot + \let\@oddfoot\@empty + \let\@evenfoot\@empty +\fi} + + +% title page style, ps@IEEEtitlepagestyle +\def\ps@IEEEtitlepagestyle{% default title page headers, no footers +\def\@oddhead{\hbox{}\@IEEEheaderstyle\leftmark\hfil\thepage}\relax +\def\@evenhead{\@IEEEheaderstyle\thepage\hfil\leftmark\hbox{}}\relax +\let\@oddfoot\@empty +\let\@evenfoot\@empty +% will change later if the mode requires otherwise +\ifCLASSOPTIONdraftcls + % draft footers + \ifCLASSOPTIONdraftclsnofoot\else + % but only if not draftclsnofoot + \def\@oddfoot{\@IEEEfooterstyle\@date\hfil DRAFT}\relax + \def\@evenfoot{\@IEEEfooterstyle DRAFT\hfil\@date}\relax + \fi +\else + % all nondraft mode footers + \if@IEEEusingpubid + % for title pages that are using a pubid + % do not repeat pubid on the title page if using a peer review cover page + \ifCLASSOPTIONpeerreview\else + % for noncompsoc papers, the pubid uses footnotesize and + % is at the same vertical position as where the last baseline would normally be + \def\@oddfoot{\hbox{}\hss\@IEEEfooterstyle\footnotesize\raisebox{\footskip}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \def\@evenfoot{\hbox{}\hss\@IEEEfooterstyle\footnotesize\raisebox{\footskip}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \ifCLASSOPTIONcompsoc + % for compsoc papers, the pubid is at the same vertical position as the normal footer + \def\@oddfoot{\hbox{}\hss\@IEEEfooterstyle\raisebox{0pt}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \def\@evenfoot{\hbox{}\hss\@IEEEfooterstyle\raisebox{0pt}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \fi + \fi + \fi +\fi +% turn off headers for conferences +\ifCLASSOPTIONconference + \let\@oddhead\@empty + \let\@evenhead\@empty +\fi} + + +% peer review cover page style, ps@IEEEpeerreviewcoverpagestyle +\def\ps@IEEEpeerreviewcoverpagestyle{% default peer review cover no headers, no footers +\let\@oddhead\@empty +\let\@evenhead\@empty +\let\@oddfoot\@empty +\let\@evenfoot\@empty +% will change later if the mode requires otherwise +\ifCLASSOPTIONdraftcls + % draft footers + \ifCLASSOPTIONdraftclsnofoot\else + % but only if not draftclsnofoot + \def\@oddfoot{\@IEEEfooterstyle\@date\hfil DRAFT}\relax + \def\@evenfoot{\@IEEEfooterstyle DRAFT\hfil\@date}\relax + \fi +\else + % all nondraft mode footers + \if@IEEEusingpubid + % for peer review cover pages that are using a pubid + % for noncompsoc papers, the pubid uses footnotesize and + % is at the same vertical position as where the last baseline would normally be + \def\@oddfoot{\hbox{}\hss\@IEEEfooterstyle\footnotesize\raisebox{\footskip}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \def\@evenfoot{\hbox{}\hss\@IEEEfooterstyle\footnotesize\raisebox{\footskip}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \ifCLASSOPTIONcompsoc + % for compsoc papers, the pubid is at the same vertical position as the normal footer + \def\@oddfoot{\hbox{}\hss\@IEEEfooterstyle\raisebox{0pt}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \def\@evenfoot{\hbox{}\hss\@IEEEfooterstyle\raisebox{0pt}[0pt][0pt]{\@IEEEpubid}\hss\hbox{}}\relax + \fi + \fi +\fi} + + + +%% Defines the command for putting the header. +%% Note that all the text is forced into uppercase, if you have some text +%% that needs to be in lower case, for instance et. al., then either manually +%% set \leftmark and \rightmark or use \MakeLowercase{et. al.} within the +%% arguments to \markboth. +%% V1.7b add \protect to work with Babel +\def\markboth#1#2{\def\leftmark{\MakeUppercase{\protect#1}}% +\def\rightmark{\MakeUppercase{\protect#2}}} + +\def\today{\ifcase\month\or + January\or February\or March\or April\or May\or June\or + July\or August\or September\or October\or November\or December\fi + \space\number\day, \number\year} + + + + +%% CITATION AND BIBLIOGRAPHY COMMANDS +%% +%% V1.6 no longer supports the older, nonstandard \shortcite and \citename setup stuff +% +% +% Modify Latex2e \@citex to separate citations with "], [" +\def\@citex[#1]#2{% + \let\@citea\@empty + \@cite{\@for\@citeb:=#2\do + {\@citea\def\@citea{], [}% + \edef\@citeb{\expandafter\@firstofone\@citeb\@empty}% + \if@filesw\immediate\write\@auxout{\string\citation{\@citeb}}\fi + \@ifundefined{b@\@citeb}{\mbox{\reset@font\bfseries ?}% + \G@refundefinedtrue + \@latex@warning + {Citation `\@citeb' on page \thepage \space undefined}}% + {\hbox{\csname b@\@citeb\endcsname}}}}{#1}} + +% V1.6 we create hooks for the optional use of Donald Arseneau's +% cite.sty package. cite.sty is "smart" and will notice that the +% following format controls are already defined and will not +% redefine them. The result will be the proper sorting of the +% citation numbers and auto detection of 3 or more entry "ranges" - +% all in IEEE style: [1], [2], [5]--[7], [12] +% This also allows for an optional note, i.e., \cite[mynote]{..}. +% If the \cite with note has more than one reference, the note will +% be applied to the last of the listed references. It is generally +% desired that if a note is given, only one reference is listed in +% that \cite. +% Thanks to Mr. Arseneau for providing the required format arguments +% to produce the IEEE style. +\def\citepunct{], [} +\def\citedash{]--[} + +% V1.7 default to using same font for urls made by url.sty +\AtBeginDocument{\csname url@samestyle\endcsname} + +% V1.6 class files should always provide these +\def\newblock{\hskip .11em\@plus.33em\@minus.07em} +\let\@openbib@code\@empty +% V1.8b article.cls is now providing these too +% we do not use \@mkboth, nor alter the page style +\newenvironment{theindex} + {\if@twocolumn + \@restonecolfalse + \else + \@restonecoltrue + \fi + \twocolumn[\section*{\indexname}]% + \parindent\z@ + \parskip\z@ \@plus .3\p@\relax + \columnseprule \z@ + \columnsep 35\p@ + \let\item\@idxitem} + {\if@restonecol\onecolumn\else\clearpage\fi} +\newcommand\@idxitem{\par\hangindent 40\p@} +\newcommand\subitem{\@idxitem \hspace*{20\p@}} +\newcommand\subsubitem{\@idxitem \hspace*{30\p@}} +\newcommand\indexspace{\par \vskip 10\p@ \@plus5\p@ \@minus3\p@\relax} + + + +% Provide support for the control entries of IEEEtran.bst V1.00 and later. +% V1.7 optional argument allows for a different aux file to be specified in +% order to handle multiple bibliographies. For example, with multibib.sty: +% \newcites{sec}{Secondary Literature} +% \bstctlcite[@auxoutsec]{BSTcontrolhak} +\def\bstctlcite{\@ifnextchar[{\@bstctlcite}{\@bstctlcite[@auxout]}} +\def\@bstctlcite[#1]#2{\@bsphack + \@for\@citeb:=#2\do{% + \edef\@citeb{\expandafter\@firstofone\@citeb}% + \if@filesw\immediate\write\csname #1\endcsname{\string\citation{\@citeb}}\fi}% + \@esphack} + +% \IEEEnoauxwrite{} allows for citations that do not add to or affect +% the order of the existing citation list. Can be useful for \cite +% within \thanks{}. +\DeclareRobustCommand{\IEEEnoauxwrite}[1]{\relax +\if@filesw +\@fileswfalse +#1\relax\relax\relax\relax\relax +\@fileswtrue +\else +#1\relax\relax\relax\relax\relax +\fi} + +% V1.6 provide a way for a user to execute a command just before +% a given reference number - used to insert a \newpage to balance +% the columns on the last page +\edef\@IEEEtriggerrefnum{0} % the default of zero means that + % the command is not executed +\def\@IEEEtriggercmd{\newpage} + +% allow the user to alter the triggered command +\long\def\IEEEtriggercmd#1{\long\def\@IEEEtriggercmd{#1}} + +% allow user a way to specify the reference number just before the +% command is executed +\def\IEEEtriggeratref#1{\@IEEEtrantmpcountA=#1% +\edef\@IEEEtriggerrefnum{\the\@IEEEtrantmpcountA}}% + +% trigger command at the given reference +\def\@IEEEbibitemprefix{\@IEEEtrantmpcountA=\@IEEEtriggerrefnum\relax% +\advance\@IEEEtrantmpcountA by -1\relax% +\ifnum\c@enumiv=\@IEEEtrantmpcountA\relax\@IEEEtriggercmd\relax\fi} + + +\def\@biblabel#1{[#1]} + +% compsoc journals and conferences left align the reference numbers +\@IEEEcompsoconly{\def\@biblabel#1{[#1]\hfill}} + +% controls bib item spacing +\def\IEEEbibitemsep{0pt plus .5pt} + +\@IEEEcompsocconfonly{\def\IEEEbibitemsep{0.5\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip}} + + +\def\thebibliography#1{\section*{\refname}% + \addcontentsline{toc}{section}{\refname}% + % V1.6 add some rubber space here and provide a command trigger + \footnotesize\vskip 0.3\baselineskip plus 0.1\baselineskip minus 0.1\baselineskip% + \list{\@biblabel{\@arabic\c@enumiv}}% + {\settowidth\labelwidth{\@biblabel{#1}}% + \leftmargin\labelwidth + \advance\leftmargin\labelsep\relax + \itemsep \IEEEbibitemsep\relax + \usecounter{enumiv}% + \let\p@enumiv\@empty + \renewcommand\theenumiv{\@arabic\c@enumiv}}% + \let\@IEEElatexbibitem\bibitem% + \def\bibitem{\@IEEEbibitemprefix\@IEEElatexbibitem}% +\def\newblock{\hskip .11em plus .33em minus .07em}% +% originally: +% \sloppy\clubpenalty4000\widowpenalty4000% +% by adding the \interlinepenalty here, we make it more +% difficult, but not impossible, for LaTeX to break within a reference. +% The IEEE almost never breaks a reference (but they do it more often with +% technotes). You may get an underfull vbox warning around the bibliography, +% but the final result will be much more like what the IEEE will publish. +% MDS 11/2000 +\ifCLASSOPTIONtechnote\sloppy\clubpenalty4000\widowpenalty4000\interlinepenalty100% +\else\sloppy\clubpenalty4000\widowpenalty4000\interlinepenalty500\fi% + \sfcode`\.=1000\relax} +\let\endthebibliography=\endlist + + + + +% TITLE PAGE COMMANDS +% +% +% \IEEEmembership is used to produce the sublargesize italic font used to indicate author +% IEEE membership. compsoc uses a large size sans slant font +\def\IEEEmembership#1{{\@IEEEnotcompsoconly{\sublargesize}\normalfont\@IEEEcompsoconly{\sffamily}\textit{#1}}} + + +% \IEEEauthorrefmark{} produces a footnote type symbol to indicate author affiliation. +% When given an argument of 1 to 9, \IEEEauthorrefmark{} follows the standard LaTeX footnote +% symbol sequence convention. However, for arguments 10 and above, \IEEEauthorrefmark{} +% reverts to using lower case roman numerals, so it cannot overflow. Do note that you +% cannot use \footnotemark[] in place of \IEEEauthorrefmark{} within \author as the footnote +% symbols will have been turned off to prevent \thanks from creating footnote marks. +% \IEEEauthorrefmark{} produces a symbol that appears to LaTeX as having zero vertical +% height - this allows for a more compact line packing, but the user must ensure that +% the interline spacing is large enough to prevent \IEEEauthorrefmark{} from colliding +% with the text above. +% V1.7 make this a robust command +% V1.8 transmag uses an arabic author affiliation symbol +\ifCLASSOPTIONtransmag +\DeclareRobustCommand*{\IEEEauthorrefmark}[1]{\raisebox{0pt}[0pt][0pt]{\textsuperscript{\footnotesize #1}}} +\else +\DeclareRobustCommand*{\IEEEauthorrefmark}[1]{\raisebox{0pt}[0pt][0pt]{\textsuperscript{\footnotesize\ensuremath{\ifcase#1\or *\or \dagger\or \ddagger\or% + \mathsection\or \mathparagraph\or \|\or **\or \dagger\dagger% + \or \ddagger\ddagger \else\textsuperscript{\expandafter\romannumeral#1}\fi}}}} +\fi + + +% FONT CONTROLS AND SPACINGS FOR CONFERENCE MODE AUTHOR NAME AND AFFILIATION BLOCKS +% +% The default font styles for the author name and affiliation blocks (confmode) +\def\@IEEEauthorblockNstyle{\normalfont\@IEEEcompsocnotconfonly{\sffamily}\sublargesize} +\def\@IEEEauthorblockAstyle{\normalfont\@IEEEcompsocnotconfonly{\sffamily}\@IEEEcompsocconfonly{\itshape}\normalsize} +% The default if the user does not use an author block +\def\@IEEEauthordefaulttextstyle{\normalfont\@IEEEcompsocnotconfonly{\sffamily}\sublargesize} + +% adjustment spacing from title (or special paper notice) to author name blocks (confmode) +% can be negative +\def\@IEEEauthorblockconfadjspace{-0.25em} +% compsoc conferences need more space here +\@IEEEcompsocconfonly{\def\@IEEEauthorblockconfadjspace{0.75\@IEEEnormalsizeunitybaselineskip}} + +% spacing between name and affiliation blocks (confmode) +% This can be negative. +% The IEEE doesn't want any added spacing here, but I will leave these +% controls in place in case they ever change their mind. +% Personally, I like 0.75ex. +%\def\@IEEEauthorblockNtopspace{0.75ex} +%\def\@IEEEauthorblockAtopspace{0.75ex} +\def\@IEEEauthorblockNtopspace{0.0ex} +\def\@IEEEauthorblockAtopspace{0.0ex} +\ifCLASSOPTIONtransmag +% transmag uses one line of space above first affiliation block +\def\@IEEEauthorblockAtopspace{1\@IEEEnormalsizeunitybaselineskip} +\fi + +% baseline spacing within name and affiliation blocks (confmode) +% must be positive, spacings below certain values will make +% the position of line of text sensitive to the contents of the +% line above it i.e., whether or not the prior line has descenders, +% subscripts, etc. For this reason it is a good idea to keep +% these above 2.6ex +\def\@IEEEauthorblockNinterlinespace{2.6ex} +\def\@IEEEauthorblockAinterlinespace{2.75ex} + +% This tracks the required strut size. +% See the \@IEEEauthorhalign command for the actual default value used. +\def\@IEEEauthorblockXinterlinespace{2.7ex} + +% variables to retain font size and style across groups +% values given here have no effect as they will be overwritten later +\gdef\@IEEESAVESTATEfontsize{10} +\gdef\@IEEESAVESTATEfontbaselineskip{12} +\gdef\@IEEESAVESTATEfontencoding{OT1} +\gdef\@IEEESAVESTATEfontfamily{ptm} +\gdef\@IEEESAVESTATEfontseries{m} +\gdef\@IEEESAVESTATEfontshape{n} + +% saves the current font attributes +\def\@IEEEcurfontSAVE{\global\let\@IEEESAVESTATEfontsize\f@size% +\global\let\@IEEESAVESTATEfontbaselineskip\f@baselineskip% +\global\let\@IEEESAVESTATEfontencoding\f@encoding% +\global\let\@IEEESAVESTATEfontfamily\f@family% +\global\let\@IEEESAVESTATEfontseries\f@series% +\global\let\@IEEESAVESTATEfontshape\f@shape} + +% restores the saved font attributes +\def\@IEEEcurfontRESTORE{\fontsize{\@IEEESAVESTATEfontsize}{\@IEEESAVESTATEfontbaselineskip}% +\fontencoding{\@IEEESAVESTATEfontencoding}% +\fontfamily{\@IEEESAVESTATEfontfamily}% +\fontseries{\@IEEESAVESTATEfontseries}% +\fontshape{\@IEEESAVESTATEfontshape}% +\selectfont} + + +% variable to indicate if the current block is the first block in the column +\newif\if@IEEEprevauthorblockincol \@IEEEprevauthorblockincolfalse + + +% the command places a strut with height and depth = \@IEEEauthorblockXinterlinespace +% we use this technique to have complete manual control over the spacing of the lines +% within the halign environment. +% We set the below baseline portion at 30%, the above +% baseline portion at 70% of the total length. +% Responds to changes in the document's \baselinestretch +\def\@IEEEauthorstrutrule{\@IEEEtrantmpdimenA\@IEEEauthorblockXinterlinespace% +\@IEEEtrantmpdimenA=\baselinestretch\@IEEEtrantmpdimenA% +\rule[-0.3\@IEEEtrantmpdimenA]{0pt}{\@IEEEtrantmpdimenA}} + + +% blocks to hold the authors' names and affilations. +% Makes formatting easy for conferences +% +% use real definitions in conference mode +% name block +\def\IEEEauthorblockN#1{\relax\@IEEEauthorblockNstyle% set the default text style +\gdef\@IEEEauthorblockXinterlinespace{0pt}% disable strut for spacer row +% the \expandafter hides the \cr in conditional tex, see the array.sty docs +% for details, probably not needed here as the \cr is in a macro +% do a spacer row if needed +\if@IEEEprevauthorblockincol\expandafter\@IEEEauthorblockNtopspaceline\fi +\global\@IEEEprevauthorblockincoltrue% we now have a block in this column +%restore the correct strut value +\gdef\@IEEEauthorblockXinterlinespace{\@IEEEauthorblockNinterlinespace}% +% input the author names +#1% +% end the row if the user did not already +\crcr} +% spacer row for names +\def\@IEEEauthorblockNtopspaceline{\cr\noalign{\vskip\@IEEEauthorblockNtopspace}} +% +% affiliation block +\def\IEEEauthorblockA#1{\relax\@IEEEauthorblockAstyle% set the default text style +\gdef\@IEEEauthorblockXinterlinespace{0pt}%disable strut for spacer row +% the \expandafter hides the \cr in conditional tex, see the array.sty docs +% for details, probably not needed here as the \cr is in a macro +% do a spacer row if needed +\if@IEEEprevauthorblockincol\expandafter\@IEEEauthorblockAtopspaceline\fi +\global\@IEEEprevauthorblockincoltrue% we now have a block in this column +%restore the correct strut value +\gdef\@IEEEauthorblockXinterlinespace{\@IEEEauthorblockAinterlinespace}% +% input the author affiliations +#1% +% end the row if the user did not already +\crcr +% V1.8 transmag does not use any additional affiliation spacing after the first author +\ifCLASSOPTIONtransmag\gdef\@IEEEauthorblockAtopspace{0pt}\fi} + +% spacer row for affiliations +\def\@IEEEauthorblockAtopspaceline{\cr\noalign{\vskip\@IEEEauthorblockAtopspace}} + + +% allow papers to compile even if author blocks are used in modes other +% than conference or peerreviewca. For such cases, we provide dummy blocks. +\ifCLASSOPTIONconference +\else + \ifCLASSOPTIONpeerreviewca\else + % not conference, peerreviewca or transmag mode + \ifCLASSOPTIONtransmag\else + \def\IEEEauthorblockN#1{#1}% + \def\IEEEauthorblockA#1{#1}% + \fi + \fi +\fi + + + +% we provide our own halign so as not to have to depend on tabular +\def\@IEEEauthorhalign{\@IEEEauthordefaulttextstyle% default text style + \lineskip=0pt\relax% disable line spacing + \lineskiplimit=0pt\relax% + \baselineskip=0pt\relax% + \@IEEEcurfontSAVE% save the current font + \mathsurround\z@\relax% no extra spacing around math + \let\\\@IEEEauthorhaligncr% replace newline with halign friendly one + \tabskip=0pt\relax% no column spacing + \everycr{}% ensure no problems here + \@IEEEprevauthorblockincolfalse% no author blocks yet + \def\@IEEEauthorblockXinterlinespace{2.7ex}% default interline space + \vtop\bgroup%vtop box + \halign\bgroup&\relax\hfil\@IEEEcurfontRESTORE\relax ##\relax + \hfil\@IEEEcurfontSAVE\@IEEEauthorstrutrule\cr} + +% ensure last line, exit from halign, close vbox +\def\end@IEEEauthorhalign{\crcr\egroup\egroup} + +% handle bogus star form +\def\@IEEEauthorhaligncr{{\ifnum0=`}\fi\@ifstar{\@@IEEEauthorhaligncr}{\@@IEEEauthorhaligncr}} + +% test and setup the optional argument to \\[] +\def\@@IEEEauthorhaligncr{\@testopt\@@@IEEEauthorhaligncr\z@skip} + +% end the line and do the optional spacer +\def\@@@IEEEauthorhaligncr[#1]{\ifnum0=`{\fi}\cr\noalign{\vskip#1\relax}} + + + +% flag to prevent multiple \and warning messages +\newif\if@IEEEWARNand +\@IEEEWARNandtrue + +% if in conference or peerreviewca modes, we support the use of \and as \author is a +% tabular environment, otherwise we warn the user that \and is invalid +% outside of conference or peerreviewca modes. +\def\and{\relax} % provide a bogus \and that we will then override + +\renewcommand{\and}[1][\relax]{\if@IEEEWARNand\typeout{** WARNING: \noexpand\and is valid only + when in conference or peerreviewca}\typeout{modes (line \the\inputlineno).}\fi\global\@IEEEWARNandfalse} + +\ifCLASSOPTIONconference% +\renewcommand{\and}[1][\hfill]{\end{@IEEEauthorhalign}#1\begin{@IEEEauthorhalign}}% +\fi +\ifCLASSOPTIONpeerreviewca +\renewcommand{\and}[1][\hfill]{\end{@IEEEauthorhalign}#1\begin{@IEEEauthorhalign}}% +\fi +% V1.8 transmag uses conference author format +\ifCLASSOPTIONtransmag +\renewcommand{\and}[1][\hfill]{\end{@IEEEauthorhalign}#1\begin{@IEEEauthorhalign}}% +\fi + +% page clearing command +% based on LaTeX2e's \cleardoublepage, but allows different page styles +% for the inserted blank pages +\def\@IEEEcleardoublepage#1{\clearpage\if@twoside\ifodd\c@page\else +\hbox{}\thispagestyle{#1}\newpage\if@twocolumn\hbox{}\thispagestyle{#1}\newpage\fi\fi\fi} + +% V1.8b hooks to allow adjustment of space above title +\def\IEEEtitletopspace{0.5\baselineskip} +% an added extra amount to allow for adjustment/offset +\def\IEEEtitletopspaceextra{0pt} + +% user command to invoke the title page +\def\maketitle{\par% + \begingroup% + \normalfont% + \def\thefootnote{}% the \thanks{} mark type is empty + \def\footnotemark{}% and kill space from \thanks within author + \let\@makefnmark\relax% V1.7, must *really* kill footnotemark to remove all \textsuperscript spacing as well. + \footnotesize% equal spacing between thanks lines + \footnotesep 0.7\baselineskip%see global setting of \footnotesep for more info + % V1.7 disable \thanks note indention for compsoc + \@IEEEcompsoconly{\long\def\@makefntext##1{\parindent 1em\noindent\hbox{\@makefnmark}##1}}% + \normalsize% + \ifCLASSOPTIONpeerreview + \newpage\global\@topnum\z@ \@maketitle\@IEEEstatictitlevskip\@IEEEaftertitletext% + \thispagestyle{IEEEpeerreviewcoverpagestyle}\@thanks% + \else + \if@twocolumn% + \ifCLASSOPTIONtechnote% + \newpage\global\@topnum\z@ \@maketitle\@IEEEstatictitlevskip\@IEEEaftertitletext% + \else + \twocolumn[{\IEEEquantizevspace{\@maketitle}[\IEEEquantizedisabletitlecmds]{0pt}[-\topskip]{\baselineskip}{\@IEEENORMtitlevspace}{\@IEEEMINtitlevspace}\@IEEEaftertitletext}]% + \fi + \else + \newpage\global\@topnum\z@ \@maketitle\@IEEEstatictitlevskip\@IEEEaftertitletext% + \fi + \thispagestyle{IEEEtitlepagestyle}\@thanks% + \fi + % pullup page for pubid if used. + \if@IEEEusingpubid + \enlargethispage{-\@IEEEpubidpullup}% + \fi + \endgroup + \setcounter{footnote}{0}\let\maketitle\relax\let\@maketitle\relax + \gdef\@thanks{}% + % v1.6b do not clear these as we will need the title again for peer review papers + % \gdef\@author{}\gdef\@title{}% + \let\thanks\relax} + + +% V1.8 parbox to format \@IEEEtitleabstractindextext +\long\def\@IEEEtitleabstractindextextbox#1{\parbox{1\textwidth}{#1}} +% V1.8 compsoc is partial width +\ifCLASSOPTIONcompsoc +% comparison with proofs suggests it's in the range of 92.1-92.3% +\long\def\@IEEEtitleabstractindextextbox#1{\parbox{0.922\textwidth}{\@IEEEcompsocnotconfonly{\rightskip\@flushglue\leftskip\z@skip}#1}} +\fi + +% formats the Title, authors names, affiliations and special paper notice +% THIS IS A CONTROLLED SPACING COMMAND! Do not allow blank lines or unintentional +% spaces to enter the definition - use % at the end of each line +\def\@maketitle{\newpage +\bgroup\par\vskip\IEEEtitletopspace\vskip\IEEEtitletopspaceextra\centering% +\ifCLASSOPTIONtechnote% technotes, V1.8a abstract and index terms are not treated differently for compsoc technotes + {\bfseries\large\@IEEEcompsoconly{\Large\sffamily}\@title\par}\vskip 1.3em{\lineskip .5em\@IEEEcompsoconly{\large\sffamily}\@author + \@IEEEspecialpapernotice\par}\relax +\else% not a technote + \vskip0.2em{\Huge\ifCLASSOPTIONtransmag\bfseries\LARGE\fi\@IEEEcompsoconly{\sffamily}\@IEEEcompsocconfonly{\normalfont\normalsize\vskip 2\@IEEEnormalsizeunitybaselineskip + \bfseries\Large}\@IEEEcompsocnotconfonly{\vskip 0.75\@IEEEnormalsizeunitybaselineskip}\@title\par}\relax + \@IEEEcompsocnotconfonly{\vskip 0.5\@IEEEnormalsizeunitybaselineskip}\vskip1.0em\par% + % V1.6 handle \author differently if in conference mode + \ifCLASSOPTIONconference% + {\@IEEEspecialpapernotice\mbox{}\vskip\@IEEEauthorblockconfadjspace% + \mbox{}\hfill\begin{@IEEEauthorhalign}\@author\end{@IEEEauthorhalign}\hfill\mbox{}\par}\relax + \else% peerreviewca, peerreview or journal + \ifCLASSOPTIONpeerreviewca + % peerreviewca handles author names just like conference mode + {\@IEEEcompsoconly{\sffamily}\@IEEEspecialpapernotice\mbox{}\vskip\@IEEEauthorblockconfadjspace% + \mbox{}\hfill\begin{@IEEEauthorhalign}\@author\end{@IEEEauthorhalign}\hfill\mbox{}\par + {\@IEEEcompsoconly{\vskip 1.5em\relax + \@IEEEtitleabstractindextextbox{\@IEEEtitleabstractindextext}\par\noindent\hfill + \IEEEcompsocdiamondline\hfill\hbox{}\par}}}\relax + \else% journal, peerreview or transmag + \ifCLASSOPTIONtransmag + % transmag also handles author names just like conference mode + % it also uses \@IEEEtitleabstractindextex, but with one line less + % space above, and one more below + {\@IEEEspecialpapernotice\mbox{}\vskip\@IEEEauthorblockconfadjspace% + \mbox{}\hfill\begin{@IEEEauthorhalign}\@author\end{@IEEEauthorhalign}\hfill\mbox{}\par + {\vspace{0.5\baselineskip}\relax\@IEEEtitleabstractindextextbox{\@IEEEtitleabstractindextext}\vspace{-1\baselineskip}\par}}\relax + \else% journal or peerreview + {\lineskip.5em\@IEEEcompsoconly{\sffamily}\sublargesize\@author\@IEEEspecialpapernotice\par + {\@IEEEcompsoconly{\vskip 1.5em\relax + \@IEEEtitleabstractindextextbox{\@IEEEtitleabstractindextext}\par\noindent\hfill + \IEEEcompsocdiamondline\hfill\hbox{}\par}}}\relax + \fi + \fi + \fi +\fi\par\addvspace{0.5\baselineskip}\egroup} + + +% V1.7 Computer Society "diamond line" which follows index terms for nonconference papers +% V1.8a full width diamond line for single column use +\def\@IEEEcompsocdiamondlinei{\vrule depth 0pt height 0.5pt width 4cm\nobreak\hspace{7.5pt}\nobreak +\raisebox{-3.5pt}{\fontfamily{pzd}\fontencoding{U}\fontseries{m}\fontshape{n}\fontsize{11}{12}\selectfont\char70}\nobreak +\hspace{7.5pt}\nobreak\vrule depth 0pt height 0.5pt width 4cm\relax} +% V1.8a narrower width diamond line for double column use +\def\@IEEEcompsocdiamondlineii{\vrule depth 0pt height 0.5pt width 2.5cm\nobreak\hspace{7.5pt}\nobreak +\raisebox{-3.5pt}{\fontfamily{pzd}\fontencoding{U}\fontseries{m}\fontshape{n}\fontsize{11}{12}\selectfont\char70}\nobreak +\hspace{7.5pt}\nobreak\vrule depth 0pt height 0.5pt width 2.5cm\relax} +% V1.8a bare core without rules to base a last resort on for very narrow linewidths +\def\@IEEEcompsocdiamondlineiii{\mbox{}\nobreak\hspace{7.5pt}\nobreak +\raisebox{-3.5pt}{\fontfamily{pzd}\fontencoding{U}\fontseries{m}\fontshape{n}\fontsize{11}{12}\selectfont\char70}\nobreak +\hspace{7.5pt}\nobreak\mbox{}\relax} + +% V1.8a allow \IEEEcompsocdiamondline to adjust for different linewidths. +% Use \@IEEEcompsocdiamondlinei if its width is less than 0.66\linewidth (0.487 nominal for single column) +% if not, fall back to \@IEEEcompsocdiamondlineii if its width is less than 0.75\linewidth (0.659 nominal for double column) +% if all else fails, try to make a custom diamondline based on the abnormally narrow linewidth +\def\IEEEcompsocdiamondline{\settowidth{\@IEEEtrantmpdimenA}{\@IEEEcompsocdiamondlinei}\relax +\ifdim\@IEEEtrantmpdimenA<0.66\linewidth\relax\@IEEEcompsocdiamondlinei\relax +\else +\settowidth{\@IEEEtrantmpdimenA}{\@IEEEcompsocdiamondlineii}\relax +\ifdim\@IEEEtrantmpdimenA<0.75\linewidth\relax\@IEEEcompsocdiamondlineii\relax +\else +\settowidth{\@IEEEtrantmpdimenA}{\@IEEEcompsocdiamondlineiii}\relax +\@IEEEtrantmpdimenB=\linewidth\relax +\addtolength{\@IEEEtrantmpdimenB}{-1\@IEEEtrantmpdimenA}\relax +\vrule depth 0pt height 0.5pt width 0.33\@IEEEtrantmpdimenB\@IEEEcompsocdiamondlineiii\vrule depth 0pt height 0.5pt width 0.33\@IEEEtrantmpdimenB\relax +\fi\fi} + + +% V1.7 standard LateX2e \thanks, but with \itshape under compsoc. Also make it a \long\def +% We also need to trigger the one-shot footnote rule +\def\@IEEEtriggeroneshotfootnoterule{\global\@IEEEenableoneshotfootnoteruletrue} + + +\long\def\thanks#1{\footnotemark + \protected@xdef\@thanks{\@thanks + \protect\footnotetext[\the\c@footnote]{\@IEEEcompsoconly{\itshape + \protect\@IEEEtriggeroneshotfootnoterule\relax}\ignorespaces#1}}} +\let\@thanks\@empty + + +% V1.7 allow \author to contain \par's. This is needed to allow \thanks to contain \par. +\long\def\author#1{\gdef\@author{#1}} + + +% in addition to setting up IEEEitemize, we need to remove a baselineskip space above and +% below it because \list's \pars introduce blank lines because of the footnote struts. +\def\@IEEEsetupcompsocitemizelist{\def\labelitemi{$\bullet$}% +\setlength{\IEEElabelindent}{0pt}\setlength{\labelsep}{1.2em}\setlength{\parskip}{0pt}% +\setlength{\partopsep}{0pt}\setlength{\topsep}{0.5\baselineskip}\vspace{-1\baselineskip}\relax} + + +% flag for fake non-compsoc \IEEEcompsocthanksitem - prevents line break on very first item +\newif\if@IEEEbreakcompsocthanksitem \@IEEEbreakcompsocthanksitemfalse + +\ifCLASSOPTIONcompsoc +% V1.7 compsoc bullet item \thanks +% also, we need to redefine this to destroy the argument in \IEEEquantizevspace +\long\def\IEEEcompsocitemizethanks#1{\relax\@IEEEbreakcompsocthanksitemfalse\footnotemark + \protected@xdef\@thanks{\@thanks + \protect\footnotetext[\the\c@footnote]{\itshape\protect\@IEEEtriggeroneshotfootnoterule + {\let\IEEEiedlistdecl\relax\protect\begin{IEEEitemize}[\protect\@IEEEsetupcompsocitemizelist]\ignorespaces#1\relax + \protect\end{IEEEitemize}}\protect\vspace{-1\baselineskip}}}} +\DeclareRobustCommand*{\IEEEcompsocthanksitem}{\item} +\else +% non-compsoc, allow for dual compilation via rerouting to normal \thanks +\long\def\IEEEcompsocitemizethanks#1{\thanks{#1}} +% redirect to "pseudo-par" \hfil\break\indent after swallowing [] from \IEEEcompsocthanksitem[] +\DeclareRobustCommand{\IEEEcompsocthanksitem}{\@ifnextchar [{\@IEEEthanksswallowoptionalarg}% +{\@IEEEthanksswallowoptionalarg[\relax]}} +% be sure and break only after first item, be sure and ignore spaces after optional argument +\def\@IEEEthanksswallowoptionalarg[#1]{\relax\if@IEEEbreakcompsocthanksitem\hfil\break +\indent\fi\@IEEEbreakcompsocthanksitemtrue\ignorespaces} +\fi + + +% V1.6b define the \IEEEpeerreviewmaketitle as needed +\ifCLASSOPTIONpeerreview +\def\IEEEpeerreviewmaketitle{\@IEEEcleardoublepage{empty}% +\ifCLASSOPTIONtwocolumn +\twocolumn[{\IEEEquantizevspace{\@IEEEpeerreviewmaketitle}[\IEEEquantizedisabletitlecmds]{0pt}[-\topskip]{\baselineskip}{\@IEEENORMtitlevspace}{\@IEEEMINtitlevspace}}] +\else +\newpage\@IEEEpeerreviewmaketitle\@IEEEstatictitlevskip +\fi +\thispagestyle{IEEEtitlepagestyle}} +\else +% \IEEEpeerreviewmaketitle does nothing if peer review option has not been selected +\def\IEEEpeerreviewmaketitle{\relax} +\fi + +% peerreview formats the repeated title like the title in journal papers. +\def\@IEEEpeerreviewmaketitle{\bgroup\par\addvspace{0.5\baselineskip}\centering\@IEEEcompsoconly{\sffamily}% +\normalfont\normalsize\vskip0.2em{\Huge\@title\par}\vskip1.0em\par +\par\addvspace{0.5\baselineskip}\egroup} + + + +% V1.6 +% this is a static rubber spacer between the title/authors and the main text +% used for single column text, or when the title appears in the first column +% of two column text (technotes). +\def\@IEEEstatictitlevskip{{\normalfont\normalsize +% adjust spacing to next text +% v1.6b handle peer review papers +\ifCLASSOPTIONpeerreview +% for peer review papers, the same value is used for both title pages +% regardless of the other paper modes + \vskip 1\baselineskip plus 0.375\baselineskip minus 0.1875\baselineskip +\else + \ifCLASSOPTIONconference% conference + \vskip 1\baselineskip plus 0.375\baselineskip minus 0.1875\baselineskip% + \else% + \ifCLASSOPTIONtechnote% technote + \vskip 1\baselineskip plus 0.375\baselineskip minus 0.1875\baselineskip% + \else% journal uses more space + \vskip 2.5\baselineskip plus 0.75\baselineskip minus 0.375\baselineskip% + \fi + \fi +\fi}} + + +% set the nominal and minimum values for the quantized title spacer +% the quantization algorithm will not allow the spacer size to +% become less than \@IEEEMINtitlevspace - instead it will be lengthened +% default to journal values +\def\@IEEENORMtitlevspace{2.5\baselineskip} +\def\@IEEEMINtitlevspace{2\baselineskip} +% conferences and technotes need tighter spacing +\ifCLASSOPTIONconference% conference + \def\@IEEENORMtitlevspace{1\baselineskip} + \def\@IEEEMINtitlevspace{0.75\baselineskip} +\fi +\ifCLASSOPTIONtechnote% technote + \def\@IEEENORMtitlevspace{1\baselineskip} + \def\@IEEEMINtitlevspace{0.75\baselineskip} +\fi + + +% V1.8a +\def\IEEEquantizevspace{\begingroup\@ifstar{\@IEEEquantizevspacestarformtrue\@IEEEquantizevspace}{\@IEEEquantizevspacestarformfalse\@IEEEquantizevspace}} +% \IEEEquantizevspace[output dimen register]{object}[object decl] +% {top baselineskip} +% [offset][prevdepth][lineskip limit][lineskip] +% {unit height}{nominal vspace}{minimum vspace} +% +% Calculates and creates the vspace needed to make the combined height with +% the given object an integer multiple of the given unit height. This command +% is more general than the older \@IEEEdynamictitlevspace it replaces. +% +% The star form has no effect at present, but is reserved for future use. +% +% If the optional argument [output dimen register] is given, the calculated +% vspace height is stored in the given output dimen (or skip) register +% and no other action is taken, otherwise the object followed by a vspace* +% of the appropriate height is evaluated/output. +% +% The optional object decl (declarations) is code that is evaluated just +% before the object's height is evaluated. Its intented purpose is to allow +% for the alteration or disabling of code within the object during internal +% height evaluation (e.g., \long\def\thanks#1{\relax} ). +% This special code is not invoked if/when the object is rendered at the end. +% +% The nominal vspace is the target value of the added vspace and the minimum +% vspace is the lower allowed limit. The vspacer will be the value that achieves +% integral overall height, in terms of the given unit height, that is closest +% to the nominal vspace and that is not less than the specified minimum vspace. +% +% The line spacing algorithm of TeX is somewhat involved and requires special +% care with regard to the first line of a vertical list (which is indicated +% when \prevdepth is -1000pt or less). top baselineskip specifies the +% baselineskip or topskip used prior to the object. If the height of the +% first line of the object is greater than the given top baselineskip, then +% the top baselineskip is subtracted from the height of the first line and +% that difference is considered along with the rest of the object height +% (because the object will be shifted down by an amount = +% top line height - top baselineskip). Otherwise, the height of the first line +% of the object is ignored as far as the calculations are concerned. +% This algorithm is adequate for objects that appear at the top of a page +% (e.g., titles) where \topskip spacing is used. +% +% However, as explained on page 78 of the TeXbook, interline spacing is more +% complex when \baselineskip is being used (indicated by \prevdepth > +% -1000pt). The four optional parameters offset, prevdepth, lineskip limit and +% lineskip are assumed to be equal to be 0pt, \prevdepth, \lineskiplimit and +% \lineskip, respectively, if they are omitted. +% +% The prevdepth is the depth of the line before the object, the lineskip limit +% specifies how close the top of the object can come to the bottom of the +% previous line before \baselineskip is ignored and \lineskip is inserted +% between the object and the line above it. Lineskip does not come into +% play unless the first line of the object is high enough to "get too close" +% (as specified by lineskiplimit) to the line before it. The the prevdepth, +% lineskip limit, and lineskip optional parameters are not needed for the +% first object/line on a page (i.e., prevdepth <= -1000pt) where the simplier +% \topskip spacing rules are in effect. +% +% Offset is a manual adjustment that is added to the height calculations of +% object irrespective of the value of \prevdepth. It is useful when the top +% baselineskip will result in a noninteger unit height object placement even +% if the object itself has integral height. e.g., a footnotesize baselineskip +% is used before the object, thus an offset of, say -3pt, can be given as a +% correction. + +% Common combinations of these parameters include: +% +% top baselineskip: (and default values for offset, prevdepth, etc.) +% \topskip % for objects that appear at the top of a page +% \maxdimen % always ignore the height of the top line +% 0pt % always consider any positive height of the top line +% +% for objects to appear inline in normal text: +% top baselineskip = \baselineskip +% +% set prevdepth = -1000pt and top baselineskip = 0pt to consider the +% overall height of the object without any other external skip +% consideration + +\newif\if@IEEEquantizevspacestarform % flag to indicate star form +\newif\if@IEEEquantizevspaceuseoutdimenreg % flag to indicate output dimen register is to be used +% Use our own private registers because the object could contain a +% structure that uses the existing tmp scratch pad registers +\newdimen\@IEEEquantizeheightA +\newdimen\@IEEEquantizeheightB +\newdimen\@IEEEquantizeheightC +\newdimen\@IEEEquantizeprevdepth % need to save this early as can change +\newcount\@IEEEquantizemultiple +\newbox\@IEEEquantizeboxA + + +\def\@IEEEquantizevspace{\@ifnextchar [{\@IEEEquantizevspaceuseoutdimenregtrue\@@IEEEquantizevspace}{\@IEEEquantizevspaceuseoutdimenregfalse\@@IEEEquantizevspace[]}} + + +\long\def\@@IEEEquantizevspace[#1]#2{\relax +% acquire and store +% #1 optional output dimen register +% #2 object +\edef\@IEEEquantizeoutdimenreg{#1}\relax +% allow for object specifications that contain parameters +\@IEEEtrantmptoksA={#2}\relax +\long\edef\@IEEEquantizeobject{\the\@IEEEtrantmptoksA}\relax +\@ifnextchar [{\@@@IEEEquantizevspace}{\@@@IEEEquantizevspace[\relax]}} + +\long\def\@@@IEEEquantizevspace[#1]#2{\relax +% acquire and store +% [#1] optional object decl, is \relax if not given by user +% #2 top baselineskip +% allow for object decl specifications that have parameters +\@IEEEtrantmptoksA={#1}\relax +\long\edef\@IEEEquantizeobjectdecl{\the\@IEEEtrantmptoksA}\relax +\edef\@IEEEquantizetopbaselineskip{#2}\ivIEEEquantizevspace} + +% acquire optional argument set and store +% [offset][prevdepth][lineskip limit][lineskip] +\def\ivIEEEquantizevspace{\@ifnextchar [{\@vIEEEquantizevspace}{\@vIEEEquantizevspace[0pt]}} +\def\@vIEEEquantizevspace[#1]{\edef\@IEEEquantizeoffset{#1}\@ifnextchar [{\@viIEEEquantizevspace}{\@viIEEEquantizevspace[\prevdepth]}} +\def\@viIEEEquantizevspace[#1]{\@IEEEquantizeprevdepth=#1\relax\@ifnextchar [{\@viiIEEEquantizevspace}{\@viiIEEEquantizevspace[\lineskiplimit]}} +\def\@viiIEEEquantizevspace[#1]{\edef\@IEEEquantizelineskiplimit{#1}\@ifnextchar [{\@viiiIEEEquantizevspace}{\@viiiIEEEquantizevspace[\lineskip]}} +\def\@viiiIEEEquantizevspace[#1]{\edef\@IEEEquantizelineskip{#1}\@ixIEEEquantizevspace} + +% main routine +\def\@ixIEEEquantizevspace#1#2#3{\relax +\edef\@IEEEquantizeunitheight{#1}\relax +\edef\@IEEEquantizenomvspace{#2}\relax +\edef\@IEEEquantizeminvspace{#3}\relax +% \@IEEEquantizeoutdimenreg +% \@IEEEquantizeobject +% \@IEEEquantizeobjectdecl +% \@IEEEquantizetopbaselineskip +% \@IEEEquantizeoffset +% \@IEEEquantizeprevdepth +% \@IEEEquantizelineskiplimit +% \@IEEEquantizelineskip +% \@IEEEquantizeunitheight +% \@IEEEquantizenomvspace +% \@IEEEquantizeminvspace +% get overall height of object +\setbox\@IEEEquantizeboxA\vbox{\begingroup\@IEEEquantizeobjectdecl\@IEEEquantizeobject\relax\endgroup}\relax +\@IEEEquantizeheightA\ht\@IEEEquantizeboxA\relax +% get height of first line of object +\setbox\@IEEEquantizeboxA\vtop{\begingroup\@IEEEquantizeobjectdecl\@IEEEquantizeobject\relax\endgroup}\relax +\@IEEEquantizeheightB\ht\@IEEEquantizeboxA\relax +\ifdim\@IEEEquantizeprevdepth>-1000pt\relax % prevdepth > -1000pf means full baselineskip\lineskip rules in effect +% lineskip spacing rule takes effect if height of top line > baselineskip - prevdepth - lineskiplimit, +% otherwise the baselineskip rule is in effect and the height of the first line does not matter at all. +\@IEEEquantizeheightC=\@IEEEquantizetopbaselineskip\relax +\advance\@IEEEquantizeheightC-\@IEEEquantizeprevdepth\relax +\advance\@IEEEquantizeheightC-\@IEEEquantizelineskiplimit\relax % this works even though \@IEEEquantizelineskiplimit is a macro because TeX allows --10pt notation +\ifdim\@IEEEquantizeheightB>\@IEEEquantizeheightC\relax +% lineskip spacing rule is in effect i.e., the object is going to be shifted down relative to the +% baselineskip set position by its top line height (already a part of the total height) + prevdepth + lineskip - baselineskip +\advance\@IEEEquantizeheightA\@IEEEquantizeprevdepth\relax +\advance\@IEEEquantizeheightA\@IEEEquantizelineskip\relax +\advance\@IEEEquantizeheightA-\@IEEEquantizetopbaselineskip\relax +\else +% height of first line <= \@IEEEquantizetopbaselineskip - \@IEEEquantizeprevdepth - \@IEEEquantizelineskiplimit +% standard baselineskip rules are in effect, so don't consider height of first line +\advance\@IEEEquantizeheightA-\@IEEEquantizeheightB\relax +\fi +% +\else % prevdepth <= -1000pt, simplier \topskip type rules in effect +\ifdim\@IEEEquantizeheightB>\@IEEEquantizetopbaselineskip +% height of top line (already included in the total height) in excess of +% baselineskip is the amount it will be downshifted +\advance\@IEEEquantizeheightA-\@IEEEquantizetopbaselineskip\relax +\else +% height of first line is irrelevant, remove it +\advance\@IEEEquantizeheightA-\@IEEEquantizeheightB\relax +\fi +\fi % prevdepth <= -1000pt +% +% adjust height for any manual offset +\advance\@IEEEquantizeheightA\@IEEEquantizeoffset\relax +% add in nominal spacer +\advance\@IEEEquantizeheightA\@IEEEquantizenomvspace\relax +% check for nonzero unitheight +\@IEEEquantizeheightB=\@IEEEquantizeunitheight\relax +\ifnum\@IEEEquantizeheightB=0\relax +\@IEEEclspkgerror{IEEEquantizevspace unit height cannot be zero. Assuming 10pt.}% +{Division by zero is not allowed.} +\@IEEEquantizeheightB=10pt\relax +\fi +% get integer number of lines +\@IEEEquantizemultiple=\@IEEEquantizeheightA\relax +\divide\@IEEEquantizemultiple\@IEEEquantizeheightB\relax +% set A to contain the excess height over the \@IEEEquantizemultiple of lines +% A = height - multiple*unitheight +\@IEEEquantizeheightC\@IEEEquantizeheightB\relax +\multiply\@IEEEquantizeheightC\@IEEEquantizemultiple\relax +\advance\@IEEEquantizeheightA-\@IEEEquantizeheightC\relax +% set B to contain the height short of \@IEEEquantizemultiple+1 of lines +% B = unitheight - A +\advance\@IEEEquantizeheightB-\@IEEEquantizeheightA\relax +% choose A or B based on which is closer +\@IEEEquantizeheightC\@IEEEquantizenomvspace\relax +\ifdim\@IEEEquantizeheightA<\@IEEEquantizeheightB\relax +% C = nomvspace - A, go with lower +\advance\@IEEEquantizeheightC-\@IEEEquantizeheightA\relax +\else +% C = nomvspace + B, go with upper +\advance\@IEEEquantizeheightC\@IEEEquantizeheightB\relax +\fi +% if violate lower bound, use next integer bound +\ifdim\@IEEEquantizeheightC<\@IEEEquantizeminvspace\relax +% A + B = unitheight +\advance\@IEEEquantizeheightC\@IEEEquantizeheightA\relax +\advance\@IEEEquantizeheightC\@IEEEquantizeheightB\relax +\fi +% export object and spacer outside of group +\global\let\@IEEEquantizeobjectout\@IEEEquantizeobject\relax +\global\@IEEEquantizeheightC\@IEEEquantizeheightC\relax +\endgroup +\if@IEEEquantizevspaceuseoutdimenreg +\@IEEEquantizeoutdimenreg=\@IEEEquantizeheightC\relax +\else +\@IEEEquantizeobjectout\relax +\vskip\@IEEEquantizeheightC\relax +\fi} + + +% user command to disable all global assignments, possible use within object decl +\def\IEEEquantizedisableglobal{\let\global\relax +\let\gdef\def +\let\xdef\edef} +% user command to allow for the disabling of \thanks and other commands, possible use within object decl +\def\IEEEquantizedisabletitlecmds{\long\def\thanks##1{\relax}\relax +\long\def\IEEEcompsocitemizethanks##1{\relax}\def\newpage{\relax}} + + + + + +% V1.6 +% we allow the user access to the last part of the title area +% useful in emergencies such as when a different spacing is needed +% This text is NOT compensated for in the dynamic sizer. +\let\@IEEEaftertitletext=\relax +\long\def\IEEEaftertitletext#1{\def\@IEEEaftertitletext{#1}} + + +% V1.7 provide a way for users to enter abstract and keywords +% into the onecolumn title are. This text is compensated for +% in the dynamic sizer. +\let\@IEEEtitleabstractindextext=\relax +\long\def\IEEEtitleabstractindextext#1{\def\@IEEEtitleabstractindextext{#1}} + +% V1.7 provide a way for users to get the \@IEEEtitleabstractindextext if +% not in compsoc or transmag journal mode - this way abstract and keywords +% can still be placed in their conventional position if not in those modes. +\def\IEEEdisplaynontitleabstractindextext{% +% display for all conference formats +\ifCLASSOPTIONconference\@IEEEtitleabstractindextext\relax +\else% non-conferences + % V1.8a display for all technotes + \ifCLASSOPTIONtechnote\@IEEEtitleabstractindextext\relax + % V1.8a add diamond line after abstract and index terms for compsoc technotes + \@IEEEcompsoconly{\noindent\hfill\IEEEcompsocdiamondline\hfill\hbox{}\par}\relax + \else % non-conferences and non-technotes + \ifCLASSOPTIONcompsoc% display if not compsoc and not transmag + \else + \ifCLASSOPTIONtransmag + \else% not compsoc journal nor transmag journal + \@IEEEtitleabstractindextext\relax + \fi + \fi + \fi +\fi} + + +% command to allow alteration of baselinestretch, but only if the current +% baselineskip is unity. Used to tweak the compsoc abstract and keywords line spacing. +\def\@IEEEtweakunitybaselinestretch#1{{\def\baselinestretch{1}\selectfont +\global\@tempskipa\baselineskip}\ifnum\@tempskipa=\baselineskip% +\def\baselinestretch{#1}\selectfont\fi\relax} + + +% abstract and keywords are in \small, except +% for 9pt docs in which they are in \footnotesize +% Because 9pt docs use an 8pt footnotesize, \small +% becomes a rather awkward 8.5pt +\def\@IEEEabskeysecsize{\small} +\ifx\CLASSOPTIONpt\@IEEEptsizenine + \def\@IEEEabskeysecsize{\footnotesize} +\fi + +% compsoc journals use \footnotesize, compsoc conferences use normalsize +\@IEEEcompsoconly{\def\@IEEEabskeysecsize{\footnotesize}} +\@IEEEcompsocconfonly{\def\@IEEEabskeysecsize{\small}} + + +% V1.6 have abstract and keywords strip leading spaces, pars and newlines +% so that spacing is more tightly controlled. +\def\abstract{\normalfont + \if@twocolumn + \@IEEEabskeysecsize\bfseries\textit{\abstractname}---\relax + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\vspace{-1.78ex}\@IEEEabskeysecsize\textbf{\abstractname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize + \fi\@IEEEgobbleleadPARNLSP} +% V1.6 The IEEE wants only 1 pica from end of abstract to introduction heading when in +% conference mode (the heading already has this much above it) +\def\endabstract{\relax\ifCLASSOPTIONconference\vspace{0ex}\else\vspace{1.34ex}\fi\par\if@twocolumn\else\endquotation\fi + \normalfont\normalsize} + +\def\IEEEkeywords{\normalfont + \if@twocolumn + \@IEEEabskeysecsize\bfseries\textit{\IEEEkeywordsname}---\relax + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\@IEEEabskeysecsize\textbf{\IEEEkeywordsname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize + \fi\@IEEEgobbleleadPARNLSP} +\def\endIEEEkeywords{\relax\ifCLASSOPTIONtechnote\vspace{1.34ex}\else\vspace{0.67ex}\fi + \par\if@twocolumn\else\endquotation\fi% + \normalfont\normalsize} + +% V1.7 compsoc keywords index terms +\ifCLASSOPTIONcompsoc + \ifCLASSOPTIONconference% compsoc conference +\def\abstract{\normalfont\@IEEEtweakunitybaselinestretch{1.15}\bfseries + \if@twocolumn + \@IEEEabskeysecsize\noindent\textit{\abstractname}---\relax + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\vspace{-1.78ex}\@IEEEabskeysecsize\textbf{\abstractname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize% + \fi\@IEEEgobbleleadPARNLSP} +\def\IEEEkeywords{\normalfont\@IEEEtweakunitybaselinestretch{1.15}\bfseries + \if@twocolumn + \@IEEEabskeysecsize\vskip 0.5\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip\noindent + \textit{\IEEEkeywordsname}---\relax + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\@IEEEabskeysecsize\textbf{\IEEEkeywordsname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize% + \fi\@IEEEgobbleleadPARNLSP} + \else% compsoc not conference +\def\abstract{\normalfont\@IEEEtweakunitybaselinestretch{1.15}\sffamily + \if@twocolumn + \@IEEEabskeysecsize\noindent\textbf{\abstractname}---\relax + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\vspace{-1.78ex}\@IEEEabskeysecsize\textbf{\abstractname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize% + \fi\@IEEEgobbleleadPARNLSP} +\def\IEEEkeywords{\normalfont\@IEEEtweakunitybaselinestretch{1.15}\sffamily + \if@twocolumn + \@IEEEabskeysecsize\vskip 0.5\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip\noindent + \textbf{\IEEEkeywordsname}---\relax + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\@IEEEabskeysecsize\textbf{\IEEEkeywordsname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize% + \fi\@IEEEgobbleleadPARNLSP} + \fi +\fi + +% V1.8 transmag keywords index terms +% no abstract name, use indentation +\ifCLASSOPTIONtransmag +\def\abstract{\normalfont\parindent 1em\relax + \if@twocolumn + \@IEEEabskeysecsize\bfseries\indent + \else + \bgroup\par\addvspace{0.5\baselineskip}\centering\vspace{-1.78ex}\@IEEEabskeysecsize + \textbf{\abstractname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize + \fi\@IEEEgobbleleadPARNLSP} + +\def\IEEEkeywords{\normalfont\parindent 1em\relax + \if@twocolumn + \@IEEEabskeysecsize\vspace{1\baselineskip}\bfseries\indent\textit{\IEEEkeywordsname}---\relax + \else + \bgroup\par\vspace{1\baselineskip}\centering\@IEEEabskeysecsize + \textbf{\IEEEkeywordsname}\par\addvspace{0.5\baselineskip}\egroup\quotation\@IEEEabskeysecsize + \fi\@IEEEgobbleleadPARNLSP} +\fi + + + +% gobbles all leading \, \\ and \par, upon finding first token that +% is not a \ , \\ or a \par, it ceases and returns that token +% +% used to strip leading \, \\ and \par from the input +% so that such things in the beginning of an environment will not +% affect the formatting of the text +\long\def\@IEEEgobbleleadPARNLSP#1{\let\@IEEEswallowthistoken=0% +\let\@IEEEgobbleleadPARNLSPtoken#1% +\let\@IEEEgobbleleadPARtoken=\par% +\let\@IEEEgobbleleadNLtoken=\\% +\let\@IEEEgobbleleadSPtoken=\ % +\def\@IEEEgobbleleadSPMACRO{\ }% +\ifx\@IEEEgobbleleadPARNLSPtoken\@IEEEgobbleleadPARtoken% +\let\@IEEEswallowthistoken=1% +\fi% +\ifx\@IEEEgobbleleadPARNLSPtoken\@IEEEgobbleleadNLtoken% +\let\@IEEEswallowthistoken=1% +\fi% +\ifx\@IEEEgobbleleadPARNLSPtoken\@IEEEgobbleleadSPtoken% +\let\@IEEEswallowthistoken=1% +\fi% +% a control space will come in as a macro +% when it is the last one on a line +\ifx\@IEEEgobbleleadPARNLSPtoken\@IEEEgobbleleadSPMACRO% +\let\@IEEEswallowthistoken=1% +\fi% +% if we have to swallow this token, do so and taste the next one +% else spit it out and stop gobbling +\ifx\@IEEEswallowthistoken 1\let\@IEEEnextgobbleleadPARNLSP=\@IEEEgobbleleadPARNLSP\else% +\let\@IEEEnextgobbleleadPARNLSP=#1\fi% +\@IEEEnextgobbleleadPARNLSP}% + + + + +% TITLING OF SECTIONS +\def\@IEEEsectpunct{:\ \,} % Punctuation after run-in section heading (headings which are + % part of the paragraphs), need little bit more than a single space + % spacing from section number to title +% compsoc conferences use regular period/space punctuation +\ifCLASSOPTIONcompsoc +\ifCLASSOPTIONconference +\def\@IEEEsectpunct{.\ } +\fi\fi + + +\def\@seccntformat#1{\csname the#1dis\endcsname\hskip 0.5em\relax} + +\ifCLASSOPTIONcompsoc +% compsoc journals need extra spacing +\ifCLASSOPTIONconference\else +\def\@seccntformat#1{\csname the#1dis\endcsname\hskip 1em\relax} +\fi\fi + +%v1.7 put {} after #6 to allow for some types of user font control +%and use \@@par rather than \par +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c@secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + % load section label and spacer into \@svsec + \protected@edef\@svsec{\@seccntformat{#1}\relax}% + \fi% + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@% tempskipa determines whether is treated as a high + \begingroup #6{\relax% or low level heading + \noindent % subsections are NOT indented + % print top level headings. \@svsec is label, #8 is heading title + % The IEEE does not block indent the section title text, it flows like normal + {\hskip #3\relax\@svsec}{\interlinepenalty \@M #8\@@par}}% + \endgroup + \addcontentsline{toc}{#1}{\ifnum #2>\c@secnumdepth\relax\else + \protect\numberline{\csname the#1\endcsname}\fi#7}% + \else % printout low level headings + % svsechd seems to swallow the trailing space, protect it with \mbox{} + % got rid of sectionmark stuff + \def\@svsechd{#6{\hskip #3\relax\@svsec #8\@IEEEsectpunct\mbox{}}% + \addcontentsline{toc}{#1}{\ifnum #2>\c@secnumdepth\relax\else + \protect\numberline{\csname the#1\endcsname}\fi#7}}% + \fi%skip down + \@xsect{#5}} + + +% section* handler +%v1.7 put {} after #4 to allow for some types of user font control +%and use \@@par rather than \par +\def\@ssect#1#2#3#4#5{\@tempskipa #3\relax + \ifdim \@tempskipa>\z@ + %\begingroup #4\@hangfrom{\hskip #1}{\interlinepenalty \@M #5\par}\endgroup + % The IEEE does not block indent the section title text, it flows like normal + \begingroup \noindent #4{\relax{\hskip #1}{\interlinepenalty \@M #5\@@par}}\endgroup + % svsechd swallows the trailing space, protect it with \mbox{} + \else \def\@svsechd{#4{\hskip #1\relax #5\@IEEEsectpunct\mbox{}}}\fi + \@xsect{#3}} + + +%% SECTION heading spacing and font +%% +% arguments are: #1 - sectiontype name +% (for \@sect) #2 - section level +% #3 - section heading indent +% #4 - top separation (absolute value used, neg indicates not to indent main text) +% If negative, make stretch parts negative too! +% #5 - (absolute value used) positive: bottom separation after heading, +% negative: amount to indent main text after heading +% Both #4 and #5 negative means to indent main text and use negative top separation +% #6 - font control +% You've got to have \normalfont\normalsize in the font specs below to prevent +% trouble when you do something like: +% \section{Note}{\ttfamily TT-TEXT} is known to ... +% The IEEE sometimes REALLY stretches the area before a section +% heading by up to about 0.5in. However, it may not be a good +% idea to let LaTeX have quite this much rubber. +\ifCLASSOPTIONconference% +% The IEEE wants section heading spacing to decrease for conference mode +\def\section{\@startsection{section}{1}{\z@}{1.5ex plus 1.5ex minus 0.5ex}% +{0.7ex plus 1ex minus 0ex}{\normalfont\normalsize\centering\scshape}}% +\def\subsection{\@startsection{subsection}{2}{\z@}{1.5ex plus 1.5ex minus 0.5ex}% +{0.7ex plus .5ex minus 0ex}{\normalfont\normalsize\itshape}}% +\else % for journals +\def\section{\@startsection{section}{1}{\z@}{3.0ex plus 1.5ex minus 1.5ex}% V1.6 3.0ex from 3.5ex +{0.7ex plus 1ex minus 0ex}{\normalfont\normalsize\centering\scshape}}% +\def\subsection{\@startsection{subsection}{2}{\z@}{3.5ex plus 1.5ex minus 1.5ex}% +{0.7ex plus .5ex minus 0ex}{\normalfont\normalsize\itshape}}% +\fi + +% for both journals and conferences +% decided to put in a little rubber above the section, might help somebody +\def\subsubsection{\@startsection{subsubsection}{3}{\parindent}{0ex plus 0.1ex minus 0.1ex}% +{0ex}{\normalfont\normalsize\itshape}}% +\def\paragraph{\@startsection{paragraph}{4}{2\parindent}{0ex plus 0.1ex minus 0.1ex}% +{0ex}{\normalfont\normalsize\itshape}}% + + +% compsoc +\ifCLASSOPTIONcompsoc +\ifCLASSOPTIONconference +% compsoc conference +\def\section{\@startsection{section}{1}{\z@}{1\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip}% +{1\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip}{\normalfont\large\bfseries}}% +\def\subsection{\@startsection{subsection}{2}{\z@}{1\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip}% +{1\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip}{\normalfont\sublargesize\bfseries}}% +\def\subsubsection{\@startsection{subsubsection}{3}{\z@}{1\baselineskip plus 0.25\baselineskip minus 0.25\baselineskip}% +{0ex}{\normalfont\normalsize\bfseries}}% +\def\paragraph{\@startsection{paragraph}{4}{2\parindent}{0ex plus 0.1ex minus 0.1ex}% +{0ex}{\normalfont\normalsize}}% +\else% compsoc journals +% use negative top separation as compsoc journals do not indent paragraphs after section titles +\def\section{\@startsection{section}{1}{\z@}{-3.5ex plus -2ex minus -1.5ex}% +{0.7ex plus 1ex minus 0ex}{\normalfont\sublargesize\sffamily\bfseries\scshape}}% +% Note that subsection and smaller may not be correct for the Computer Society, +% I have to look up an example. +\def\subsection{\@startsection{subsection}{2}{\z@}{-3.5ex plus -1.5ex minus -1.5ex}% +{0.7ex plus .5ex minus 0ex}{\normalfont\normalsize\sffamily\bfseries}}% +\def\subsubsection{\@startsection{subsubsection}{3}{\z@}{-2.5ex plus -1ex minus -1ex}% +{0.5ex plus 0.5ex minus 0ex}{\normalfont\normalsize\sffamily\itshape}}% +\def\paragraph{\@startsection{paragraph}{4}{2\parindent}{-0ex plus -0.1ex minus -0.1ex}% +{0ex}{\normalfont\normalsize}}% +\fi\fi + +% transmag +\ifCLASSOPTIONtransmag +\def\subsection{\@startsection{subsection}{2}{0.75\parindent}{3.5ex plus 1.5ex minus 1.5ex}% +{0.7ex plus .5ex minus 0ex}{\normalfont\normalsize\itshape}}% +\def\subsubsection{\@startsection{subsubsection}{3}{1.25\parindent}{0.1ex plus 0.1ex minus 0.1ex}% +{0.1ex}{\normalfont\normalsize\itshape}}% +\fi + + +% V1.8a provide for a raised line Introduction section for use with Computer +% Society papers. We have to remove any spacing glue after the section +% heading and then remove the blank line for the new paragraph after it. +% LaTeX's section handler alters \everypar and we need to propogate those +% changes outside of the \parbox lest there be spacing problems at the top +% of the next section. +\def\IEEEraisesectionheading#1{\noindent\raisebox{1.5\baselineskip}[0pt][0pt]{\parbox[b]{\columnwidth}{#1\unskip\global\everypar=\everypar}}\vspace{-1\baselineskip}\vspace{-\parskip}\par} + + + +%% ENVIRONMENTS +% "box" symbols at end of proofs +\def\IEEEQEDclosed{\mbox{\rule[0pt]{1.3ex}{1.3ex}}} % for a filled box +% V1.6 some journals use an open box instead that will just fit around a closed one +\def\IEEEQEDopen{{\setlength{\fboxsep}{0pt}\setlength{\fboxrule}{0.2pt}\fbox{\rule[0pt]{0pt}{1.3ex}\rule[0pt]{1.3ex}{0pt}}}} +\ifCLASSOPTIONcompsoc +\def\IEEEQED{\IEEEQEDopen} % default to open for compsoc +\else +\def\IEEEQED{\IEEEQEDclosed} % otherwise default to closed +\fi + +%V1.8 flag to indicate if QED symbol is to be shown +\newif\if@IEEEQEDshow \@IEEEQEDshowtrue +\def\IEEEproofindentspace{2\parindent}% V1.8 allow user to change indentation amount if desired +% v1.7 name change to avoid namespace collision with amsthm. Also add support +% for an optional argument. +\def\IEEEproof{\@ifnextchar[{\@IEEEproof}{\@IEEEproof[\IEEEproofname]}} +\def\@IEEEproof[#1]{\@IEEEQEDshowtrue\par\noindent\hspace{\IEEEproofindentspace}{\itshape #1: }} +\def\endIEEEproof{\if@IEEEQEDshow\hspace*{\fill}\nobreakspace\IEEEQED\fi\par} +% qedhere for equation environments, similar to AMS \qedhere +\def\IEEEQEDhereeqn{\global\@IEEEQEDshowfalse\eqno\let\eqno\relax\let\leqno\relax + \let\veqno\relax\hbox{\IEEEQED}} +% IEEE style qedhere for IEEEeqnarray and other environments +\def\IEEEQEDhere{\global\@IEEEQEDshowfalse\IEEEQED} +% command to disable QED at end of IEEEproof +\def\IEEEQEDoff{\global\@IEEEQEDshowfalse} + + +%\itemindent is set to \z@ by list, so define new temporary variable +\newdimen\@IEEEtmpitemindent + +\ifCLASSOPTIONcompsoc +% V1.8a compsoc uses bold theorem titles, a period instead of a colon, vertical spacing, and hanging indentation +% V1.8 allow long theorem names to break across lines. +% Thanks to Miquel Payaro for reporting this. +\def\@begintheorem#1#2{\@IEEEtmpitemindent\itemindent\relax + \topsep 0.2\@IEEEnormalsizeunitybaselineskip plus 0.26\@IEEEnormalsizeunitybaselineskip minus 0.05\@IEEEnormalsizeunitybaselineskip + \rmfamily\trivlist\hangindent\parindent% + \item[]\textit{\bfseries\noindent #1\ #2.} \itemindent\@IEEEtmpitemindent\relax} +\def\@opargbegintheorem#1#2#3{\@IEEEtmpitemindent\itemindent\relax +\topsep 0.2\@IEEEnormalsizeunitybaselineskip plus 0.26\@IEEEnormalsizeunitybaselineskip minus 0.05\@IEEEnormalsizeunitybaselineskip +\rmfamily\trivlist\hangindent\parindent% +% V1.6 The IEEE is back to using () around theorem names which are also in italics +% Thanks to Christian Peel for reporting this. + \item[]\textit{\bfseries\noindent #1\ #2\ (#3).} \itemindent\@IEEEtmpitemindent\relax} +% V1.7 remove bogus \unskip that caused equations in theorems to collide with +% lines below. +\def\@endtheorem{\endtrivlist\vskip 0.25\@IEEEnormalsizeunitybaselineskip plus 0.26\@IEEEnormalsizeunitybaselineskip minus 0.05\@IEEEnormalsizeunitybaselineskip} +\else +% +% noncompsoc +% +% V1.8 allow long theorem names to break across lines. +% Thanks to Miquel Payaro for reporting this. +\def\@begintheorem#1#2{\@IEEEtmpitemindent\itemindent\relax\topsep 0pt\rmfamily\trivlist% + \item[]\textit{\indent #1\ #2:} \itemindent\@IEEEtmpitemindent\relax} +\def\@opargbegintheorem#1#2#3{\@IEEEtmpitemindent\itemindent\relax\topsep 0pt\rmfamily \trivlist% +% V1.6 The IEEE is back to using () around theorem names which are also in italics +% Thanks to Christian Peel for reporting this. + \item[]\textit{\indent #1\ #2\ (#3):} \itemindent\@IEEEtmpitemindent\relax} +% V1.7 remove bogus \unskip that caused equations in theorems to collide with +% lines below. +\def\@endtheorem{\endtrivlist} +\fi + + + +% V1.6 +% display command for the section the theorem is in - so that \thesection +% is not used as this will be in Roman numerals when we want arabic. +% LaTeX2e uses \def\@thmcounter#1{\noexpand\arabic{#1}} for the theorem number +% (second part) display and \def\@thmcountersep{.} as a separator. +% V1.7 intercept calls to the section counter and reroute to \@IEEEthmcounterinsection +% to allow \appendix(ices} to override as needed. +% +% special handler for sections, allows appendix(ices) to override +\gdef\@IEEEthmcounterinsection#1{\arabic{#1}} +% string macro +\edef\@IEEEstringsection{section} + +% redefine the #1#2[#3] form of newtheorem to use a hook to \@IEEEthmcounterinsection +% if section in_counter is used +\def\@xnthm#1#2[#3]{% + \expandafter\@ifdefinable\csname #1\endcsname + {\@definecounter{#1}\@newctr{#1}[#3]% + \edef\@IEEEstringtmp{#3} + \ifx\@IEEEstringtmp\@IEEEstringsection + \expandafter\xdef\csname the#1\endcsname{% + \noexpand\@IEEEthmcounterinsection{#3}\@thmcountersep + \@thmcounter{#1}}% + \else + \expandafter\xdef\csname the#1\endcsname{% + \expandafter\noexpand\csname the#3\endcsname \@thmcountersep + \@thmcounter{#1}}% + \fi + \global\@namedef{#1}{\@thm{#1}{#2}}% + \global\@namedef{end#1}{\@endtheorem}}} + + + +%% SET UP THE DEFAULT PAGESTYLE +\pagestyle{headings} +\pagenumbering{arabic} + +% normally the page counter starts at 1 +\setcounter{page}{1} +% however, for peerreview the cover sheet is page 0 or page -1 +% (for duplex printing) +\ifCLASSOPTIONpeerreview + \if@twoside + \setcounter{page}{-1} + \else + \setcounter{page}{0} + \fi +\fi + +% standard book class behavior - let bottom line float up and down as +% needed when single sided +\ifCLASSOPTIONtwoside\else\raggedbottom\fi +% if two column - turn on twocolumn, allow word spacings to stretch more and +% enforce a rigid position for the last lines +\ifCLASSOPTIONtwocolumn +% the peer review option delays invoking twocolumn + \ifCLASSOPTIONpeerreview\else + \twocolumn + \fi +\sloppy +\flushbottom +\fi + + + + +% \APPENDIX and \APPENDICES definitions + +% This is the \@ifmtarg command from the LaTeX ifmtarg package +% by Peter Wilson (CUA) and Donald Arseneau +% \@ifmtarg is used to determine if an argument to a command +% is present or not. +% For instance: +% \@ifmtarg{#1}{\typeout{empty}}{\typeout{has something}} +% \@ifmtarg is used with our redefined \section command if +% \appendices is invoked. +% The command \section will behave slightly differently depending +% on whether the user specifies a title: +% \section{My appendix title} +% or not: +% \section{} +% This way, we can eliminate the blank lines where the title +% would be, and the unneeded : after Appendix in the table of +% contents +\begingroup +\catcode`\Q=3 +\long\gdef\@ifmtarg#1{\@xifmtarg#1QQ\@secondoftwo\@firstoftwo\@nil} +\long\gdef\@xifmtarg#1#2Q#3#4#5\@nil{#4} +\endgroup +% end of \@ifmtarg defs + + +% V1.7 +% command that allows the one time saving of the original definition +% of section to \@IEEEappendixsavesection for \appendix or \appendices +% we don't save \section here as it may be redefined later by other +% packages (hyperref.sty, etc.) +\def\@IEEEsaveoriginalsectiononce{\let\@IEEEappendixsavesection\section +\let\@IEEEsaveoriginalsectiononce\relax} + +% neat trick to grab and process the argument from \section{argument} +% we process differently if the user invoked \section{} with no +% argument (title) +% note we reroute the call to the old \section* +\def\@IEEEprocessthesectionargument#1{% +\@ifmtarg{#1}{% +\@IEEEappendixsavesection*{\appendixname\nobreakspace\thesectiondis}% +\addcontentsline{toc}{section}{\appendixname\nobreakspace\thesection}}{% +\@IEEEappendixsavesection*{\appendixname\nobreakspace\thesectiondis\\* #1}% +\addcontentsline{toc}{section}{\appendixname\nobreakspace\thesection: #1}}} + +% we use this if the user calls \section{} after +% \appendix-- which has no meaning. So, we ignore the +% command and its argument. Then, warn the user. +\def\@IEEEdestroythesectionargument#1{\typeout{** WARNING: Ignoring useless +\protect\section\space in Appendix (line \the\inputlineno).}} + + +% remember \thesection forms will be displayed in \ref calls +% and in the Table of Contents. +% The \sectiondis form is used in the actual heading itself + +% appendix command for one single appendix +% normally has no heading. However, if you want a +% heading, you can do so via the optional argument: +% \appendix[Optional Heading] +\def\appendix{\relax} +\renewcommand{\appendix}[1][]{\@IEEEsaveoriginalsectiononce\par + % v1.6 keep hyperref's identifiers unique + \gdef\theHsection{Appendix.A}% + % v1.6 adjust hyperref's string name for the section + \xdef\Hy@chapapp{appendix}% + \setcounter{section}{0}% + \setcounter{subsection}{0}% + \setcounter{subsubsection}{0}% + \setcounter{paragraph}{0}% + \gdef\thesection{A}% + \gdef\thesectiondis{}% + \gdef\thesubsection{\Alph{subsection}}% + \gdef\@IEEEthmcounterinsection##1{A} + \refstepcounter{section}% update the \ref counter + \@ifmtarg{#1}{\@IEEEappendixsavesection*{\appendixname}% + \addcontentsline{toc}{section}{\appendixname}}{% + \@IEEEappendixsavesection*{\appendixname\nobreakspace\\* #1}% + \addcontentsline{toc}{section}{\appendixname: #1}}% + % redefine \section command for appendix + % leave \section* as is + \def\section{\@ifstar{\@IEEEappendixsavesection*}{% + \@IEEEdestroythesectionargument}}% throw out the argument + % of the normal form +} + + + +% appendices command for multiple appendices +% user then calls \section with an argument (possibly empty) to +% declare the individual appendices +\def\appendices{\@IEEEsaveoriginalsectiononce\par + % v1.6 keep hyperref's identifiers unique + \gdef\theHsection{Appendix.\Alph{section}}% + % v1.6 adjust hyperref's string name for the section + \xdef\Hy@chapapp{appendix}% + \setcounter{section}{-1}% we want \refstepcounter to use section 0 + \setcounter{subsection}{0}% + \setcounter{subsubsection}{0}% + \setcounter{paragraph}{0}% + \ifCLASSOPTIONromanappendices% + \gdef\thesection{\Roman{section}}% + \gdef\thesectiondis{\Roman{section}}% + \@IEEEcompsocconfonly{\gdef\thesectiondis{\Roman{section}.}}% + \gdef\@IEEEthmcounterinsection##1{A\arabic{##1}} + \else% + \gdef\thesection{\Alph{section}}% + \gdef\thesectiondis{\Alph{section}}% + \@IEEEcompsocconfonly{\gdef\thesectiondis{\Alph{section}.}}% + \gdef\@IEEEthmcounterinsection##1{\Alph{##1}} + \fi% + \refstepcounter{section}% update the \ref counter + \setcounter{section}{0}% NEXT \section will be the FIRST appendix + % redefine \section command for appendices + % leave \section* as is + \def\section{\@ifstar{\@IEEEappendixsavesection*}{% process the *-form + \refstepcounter{section}% or is a new section so, + \@IEEEprocessthesectionargument}}% process the argument + % of the normal form +} + + + +% V1.7 compoc uses nonbold drop cap and small caps word style +\ifCLASSOPTIONcompsoc + \def\IEEEPARstartFONTSTYLE{\mdseries} + \def\IEEEPARstartWORDFONTSTYLE{\scshape} + \def\IEEEPARstartWORDCAPSTYLE{\relax} +\fi +% +% +% \IEEEPARstart +% Definition for the big two line drop cap letter at the beginning of the +% first paragraph of journal papers. The first argument is the first letter +% of the first word, the second argument is the remaining letters of the +% first word which will be rendered in upper case. +% In V1.6 this has been completely rewritten to: +% +% 1. no longer have problems when the user begins an environment +% within the paragraph that uses \IEEEPARstart. +% 2. auto-detect and use the current font family +% 3. revise handling of the space at the end of the first word so that +% interword glue will now work as normal. +% 4. produce correctly aligned edges for the (two) indented lines. +% +% We generalize things via control macros - playing with these is fun too. +% +% V1.7 added more control macros to make it easy for IEEEtrantools.sty users +% to change the font style. +% +% the number of lines that are indented to clear it +% may need to increase if using decenders +\providecommand{\IEEEPARstartDROPLINES}{2} +% minimum number of lines left on a page to allow a \@IEEEPARstart +% Does not take into consideration rubber shrink, so it tends to +% be overly cautious +\providecommand{\IEEEPARstartMINPAGELINES}{2} +% V1.7 the height of the drop cap is adjusted to match the height of this text +% in the current font (when \IEEEPARstart is called). +\providecommand{\IEEEPARstartHEIGHTTEXT}{T} +% the depth the letter is lowered below the baseline +% the height (and size) of the letter is determined by the sum +% of this value and the height of the \IEEEPARstartHEIGHTTEXT in the current +% font. It is a good idea to set this value in terms of the baselineskip +% so that it can respond to changes therein. +\providecommand{\IEEEPARstartDROPDEPTH}{1.1\baselineskip} +% V1.7 the font the drop cap will be rendered in, +% can take zero or one argument. +\providecommand{\IEEEPARstartFONTSTYLE}{\bfseries} +% V1.7 any additional, non-font related commands needed to modify +% the drop cap letter, can take zero or one argument. +\providecommand{\IEEEPARstartCAPSTYLE}{\MakeUppercase} +% V1.7 the font that will be used to render the rest of the word, +% can take zero or one argument. +\providecommand{\IEEEPARstartWORDFONTSTYLE}{\relax} +% V1.7 any additional, non-font related commands needed to modify +% the rest of the word, can take zero or one argument. +\providecommand{\IEEEPARstartWORDCAPSTYLE}{\MakeUppercase} +% This is the horizontal separation distance from the drop letter to the main text. +% Lengths that depend on the font (e.g., ex, em, etc.) will be referenced +% to the font that is active when \IEEEPARstart is called. +\providecommand{\IEEEPARstartSEP}{0.15em} +% V1.7 horizontal offset applied to the left of the drop cap. +\providecommand{\IEEEPARstartHOFFSET}{0em} +% V1.7 Italic correction command applied at the end of the drop cap. +\providecommand{\IEEEPARstartITLCORRECT}{\/} + +% width of the letter output, set globally. Can be used in \IEEEPARstartSEP +% or \IEEEPARstartHOFFSET, but not the height lengths. +\newdimen\IEEEPARstartletwidth +\IEEEPARstartletwidth 0pt\relax + +% definition of \IEEEPARstart +% THIS IS A CONTROLLED SPACING AREA, DO NOT ALLOW SPACES WITHIN THESE LINES +% +% The token \@IEEEPARstartfont will be globally defined after the first use +% of \IEEEPARstart and will be a font command which creates the big letter +% The first argument is the first letter of the first word and the second +% argument is the rest of the first word(s). +\def\IEEEPARstart#1#2{\par{% +% if this page does not have enough space, break it and lets start +% on a new one +\@IEEEtranneedspace{\IEEEPARstartMINPAGELINES\baselineskip}{\relax}% +% V1.7 move this up here in case user uses \textbf for \IEEEPARstartFONTSTYLE +% which uses command \leavevmode which causes an unwanted \indent to be issued +\noindent +% calculate the desired height of the big letter +% it extends from the top of \IEEEPARstartHEIGHTTEXT in the current font +% down to \IEEEPARstartDROPDEPTH below the current baseline +\settoheight{\@IEEEtrantmpdimenA}{\IEEEPARstartHEIGHTTEXT}% +\addtolength{\@IEEEtrantmpdimenA}{\IEEEPARstartDROPDEPTH}% +% extract the name of the current font in bold +% and place it in \@IEEEPARstartFONTNAME +\def\@IEEEPARstartGETFIRSTWORD##1 ##2\relax{##1}% +{\IEEEPARstartFONTSTYLE{\selectfont\edef\@IEEEPARstartFONTNAMESPACE{\fontname\font\space}% +\xdef\@IEEEPARstartFONTNAME{\expandafter\@IEEEPARstartGETFIRSTWORD\@IEEEPARstartFONTNAMESPACE\relax}}}% +% define a font based on this name with a point size equal to the desired +% height of the drop letter +\font\@IEEEPARstartsubfont\@IEEEPARstartFONTNAME\space at \@IEEEtrantmpdimenA\relax% +% save this value as a counter (integer) value (sp points) +\@IEEEtrantmpcountA=\@IEEEtrantmpdimenA% +% now get the height of the actual letter produced by this font size +\settoheight{\@IEEEtrantmpdimenB}{\@IEEEPARstartsubfont\IEEEPARstartCAPSTYLE{#1}}% +% If something bogus happens like the first argument is empty or the +% current font is strange, do not allow a zero height. +\ifdim\@IEEEtrantmpdimenB=0pt\relax% +\typeout{** WARNING: IEEEPARstart drop letter has zero height! (line \the\inputlineno)}% +\typeout{ Forcing the drop letter font size to 10pt.}% +\@IEEEtrantmpdimenB=10pt% +\fi% +% and store it as a counter +\@IEEEtrantmpcountB=\@IEEEtrantmpdimenB% +% Since a font size doesn't exactly correspond to the height of the capital +% letters in that font, the actual height of the letter, \@IEEEtrantmpcountB, +% will be less than that desired, \@IEEEtrantmpcountA +% we need to raise the font size, \@IEEEtrantmpdimenA +% by \@IEEEtrantmpcountA / \@IEEEtrantmpcountB +% But, TeX doesn't have floating point division, so we have to use integer +% division. Hence the use of the counters. +% We need to reduce the denominator so that the loss of the remainder will +% have minimal affect on the accuracy of the result +\divide\@IEEEtrantmpcountB by 200% +\divide\@IEEEtrantmpcountA by \@IEEEtrantmpcountB% +% Then reequalize things when we use TeX's ability to multiply by +% floating point values +\@IEEEtrantmpdimenB=0.005\@IEEEtrantmpdimenA% +\multiply\@IEEEtrantmpdimenB by \@IEEEtrantmpcountA% +% \@IEEEPARstartfont is globaly set to the calculated font of the big letter +% We need to carry this out of the local calculation area to to create the +% big letter. +\global\font\@IEEEPARstartfont\@IEEEPARstartFONTNAME\space at \@IEEEtrantmpdimenB% +% Now set \@IEEEtrantmpdimenA to the width of the big letter +% We need to carry this out of the local calculation area to set the +% hanging indent +\settowidth{\global\@IEEEtrantmpdimenA}{\@IEEEPARstartfont +\IEEEPARstartCAPSTYLE{#1\IEEEPARstartITLCORRECT}}}% +% end of the isolated calculation environment +\global\IEEEPARstartletwidth\@IEEEtrantmpdimenA\relax% +% add in the extra clearance we want +\advance\@IEEEtrantmpdimenA by \IEEEPARstartSEP\relax% +% add in the optional offset +\advance\@IEEEtrantmpdimenA by \IEEEPARstartHOFFSET\relax% +% V1.7 don't allow negative offsets to produce negative hanging indents +\@IEEEtrantmpdimenB\@IEEEtrantmpdimenA +\ifnum\@IEEEtrantmpdimenB < 0 \@IEEEtrantmpdimenB 0pt\fi +% \@IEEEtrantmpdimenA has the width of the big letter plus the +% separation space and \@IEEEPARstartfont is the font we need to use +% Now, we make the letter and issue the hanging indent command +% The letter is placed in a box of zero width and height so that other +% text won't be displaced by it. +\hangindent\@IEEEtrantmpdimenB\hangafter=-\IEEEPARstartDROPLINES% +\makebox[0pt][l]{\hspace{-\@IEEEtrantmpdimenA}% +\raisebox{-\IEEEPARstartDROPDEPTH}[0pt][0pt]{\hspace{\IEEEPARstartHOFFSET}% +\@IEEEPARstartfont\IEEEPARstartCAPSTYLE{#1\IEEEPARstartITLCORRECT}% +\hspace{\IEEEPARstartSEP}}}% +{\IEEEPARstartWORDFONTSTYLE{\IEEEPARstartWORDCAPSTYLE{\selectfont#2}}}} + + + + +% determines if the space remaining on a given page is equal to or greater +% than the specified space of argument one +% if not, execute argument two (only if the remaining space is greater than zero) +% and issue a \newpage +% +% example: \@IEEEtranneedspace{2in}{\vfill} +% +% Does not take into consideration rubber shrinkage, so it tends to +% be overly cautious +% Based on an example posted by Donald Arseneau +% Note this macro uses \@IEEEtrantmpdimenB internally for calculations, +% so DO NOT PASS \@IEEEtrantmpdimenB to this routine +% if you need a dimen register, import with \@IEEEtrantmpdimenA instead +\def\@IEEEtranneedspace#1#2{\penalty-100\begingroup%shield temp variable +\@IEEEtrantmpdimenB\pagegoal\advance\@IEEEtrantmpdimenB-\pagetotal% space left +\ifdim #1>\@IEEEtrantmpdimenB\relax% not enough space left +\ifdim\@IEEEtrantmpdimenB>\z@\relax #2\fi% +\newpage% +\fi\endgroup} + + + +% IEEEbiography ENVIRONMENT +% Allows user to enter biography leaving place for picture (adapts to font size) +% As of V1.5, a new optional argument allows you to have a real graphic! +% V1.5 and later also fixes the "colliding biographies" which could happen when a +% biography's text was shorter than the space for the photo. +% MDS 7/2001 +% V1.6 prevent multiple biographies from making multiple TOC entries +\newif\if@IEEEbiographyTOCentrynotmade +\global\@IEEEbiographyTOCentrynotmadetrue + +% biography counter so hyperref can jump directly to the biographies +% and not just the previous section +\newcounter{IEEEbiography} +\setcounter{IEEEbiography}{0} + +% photo area size +\def\@IEEEBIOphotowidth{1.0in} % width of the biography photo area +\def\@IEEEBIOphotodepth{1.25in} % depth (height) of the biography photo area +% area cleared for photo +\def\@IEEEBIOhangwidth{1.14in} % width cleared for the biography photo area +\def\@IEEEBIOhangdepth{1.25in} % depth cleared for the biography photo area + % actual depth will be a multiple of + % \baselineskip, rounded up +\def\@IEEEBIOskipN{4\baselineskip}% nominal value of the vskip above the biography + +\newenvironment{IEEEbiography}[2][]{\normalfont\@IEEEcompsoconly{\sffamily}\footnotesize% +\unitlength 1in\parskip=0pt\par\parindent 1em\interlinepenalty500% +% we need enough space to support the hanging indent +% the nominal value of the spacer +% and one extra line for good measure +\@IEEEtrantmpdimenA=\@IEEEBIOhangdepth% +\advance\@IEEEtrantmpdimenA by \@IEEEBIOskipN% +\advance\@IEEEtrantmpdimenA by 1\baselineskip% +% if this page does not have enough space, break it and lets start +% with a new one +\@IEEEtranneedspace{\@IEEEtrantmpdimenA}{\relax}% +% nominal spacer can strech, not shrink use 1fil so user can out stretch with \vfill +\vskip \@IEEEBIOskipN plus 1fil minus 0\baselineskip% +% the default box for where the photo goes +\def\@IEEEtempbiographybox{{\setlength{\fboxsep}{0pt}\framebox{% +\begin{minipage}[b][\@IEEEBIOphotodepth][c]{\@IEEEBIOphotowidth}\centering PLACE\\ PHOTO\\ HERE \end{minipage}}}}% +% +% detect if the optional argument was supplied, this requires the +% \@ifmtarg command as defined in the appendix section above +% and if so, override the default box with what they want +\@ifmtarg{#1}{\relax}{\def\@IEEEtempbiographybox{\mbox{\begin{minipage}[b][\@IEEEBIOphotodepth][c]{\@IEEEBIOphotowidth}% +\centering% +#1% +\end{minipage}}}}% end if optional argument supplied +% Make an entry into the table of contents only if we have not done so before +\if@IEEEbiographyTOCentrynotmade% +% link labels to the biography counter so hyperref will jump +% to the biography, not the previous section +\setcounter{IEEEbiography}{-1}% +\refstepcounter{IEEEbiography}% +\addcontentsline{toc}{section}{Biographies}% +\global\@IEEEbiographyTOCentrynotmadefalse% +\fi% +% one more biography +\refstepcounter{IEEEbiography}% +% Make an entry for this name into the table of contents +\addcontentsline{toc}{subsection}{#2}% +% V1.6 properly handle if a new paragraph should occur while the +% hanging indent is still active. Do this by redefining \par so +% that it will not start a new paragraph. (But it will appear to the +% user as if it did.) Also, strip any leading pars, newlines, or spaces. +\let\@IEEEBIOORGparCMD=\par% save the original \par command +\edef\par{\hfil\break\indent}% the new \par will not be a "real" \par +\settoheight{\@IEEEtrantmpdimenA}{\@IEEEtempbiographybox}% get height of biography box +\@IEEEtrantmpdimenB=\@IEEEBIOhangdepth% +\@IEEEtrantmpcountA=\@IEEEtrantmpdimenB% countA has the hang depth +\divide\@IEEEtrantmpcountA by \baselineskip% calculates lines needed to produce the hang depth +\advance\@IEEEtrantmpcountA by 1% ensure we overestimate +% set the hanging indent +\hangindent\@IEEEBIOhangwidth% +\hangafter-\@IEEEtrantmpcountA% +% reference the top of the photo area to the top of a capital T +\settoheight{\@IEEEtrantmpdimenB}{\mbox{T}}% +% set the photo box, give it zero width and height so as not to disturb anything +\noindent\makebox[0pt][l]{\hspace{-\@IEEEBIOhangwidth}\raisebox{\@IEEEtrantmpdimenB}[0pt][0pt]{% +\raisebox{-\@IEEEBIOphotodepth}[0pt][0pt]{\@IEEEtempbiographybox}}}% +% now place the author name and begin the bio text +\noindent\textbf{#2\ }\@IEEEgobbleleadPARNLSP}{\relax\let\par=\@IEEEBIOORGparCMD\par% +% 7/2001 V1.5 detect when the biography text is shorter than the photo area +% and pad the unused area - preventing a collision from the next biography entry +% MDS +\ifnum \prevgraf <\@IEEEtrantmpcountA\relax% detect when the biography text is shorter than the photo + \advance\@IEEEtrantmpcountA by -\prevgraf% calculate how many lines we need to pad + \advance\@IEEEtrantmpcountA by -1\relax% we compensate for the fact that we indented an extra line + \@IEEEtrantmpdimenA=\baselineskip% calculate the length of the padding + \multiply\@IEEEtrantmpdimenA by \@IEEEtrantmpcountA% + \noindent\rule{0pt}{\@IEEEtrantmpdimenA}% insert an invisible support strut +\fi% +\par\normalfont} + + + +% V1.6 +% added biography without a photo environment +\newenvironment{IEEEbiographynophoto}[1]{% +% Make an entry into the table of contents only if we have not done so before +\if@IEEEbiographyTOCentrynotmade% +% link labels to the biography counter so hyperref will jump +% to the biography, not the previous section +\setcounter{IEEEbiography}{-1}% +\refstepcounter{IEEEbiography}% +\addcontentsline{toc}{section}{Biographies}% +\global\@IEEEbiographyTOCentrynotmadefalse% +\fi% +% one more biography +\refstepcounter{IEEEbiography}% +% Make an entry for this name into the table of contents +\addcontentsline{toc}{subsection}{#1}% +\normalfont\@IEEEcompsoconly{\sffamily}\footnotesize\interlinepenalty500% +\vskip 4\baselineskip plus 1fil minus 0\baselineskip% +\parskip=0pt\par% +\noindent\textbf{#1\ }\@IEEEgobbleleadPARNLSP}{\relax\par\normalfont} + + +% provide the user with some old font commands +% got this from article.cls +\DeclareOldFontCommand{\rm}{\normalfont\rmfamily}{\mathrm} +\DeclareOldFontCommand{\sf}{\normalfont\sffamily}{\mathsf} +\DeclareOldFontCommand{\tt}{\normalfont\ttfamily}{\mathtt} +\DeclareOldFontCommand{\bf}{\normalfont\bfseries}{\mathbf} +\DeclareOldFontCommand{\it}{\normalfont\itshape}{\mathit} +\DeclareOldFontCommand{\sl}{\normalfont\slshape}{\@nomath\sl} +\DeclareOldFontCommand{\sc}{\normalfont\scshape}{\@nomath\sc} +\DeclareRobustCommand*\cal{\@fontswitch\relax\mathcal} +\DeclareRobustCommand*\mit{\@fontswitch\relax\mathnormal} + + +% SPECIAL PAPER NOTICE COMMANDS +% +% holds the special notice text +\def\@IEEEspecialpapernotice{\relax} + +% for special papers, like invited papers, the user can do: +% \IEEEspecialpapernotice{(Invited Paper)} before \maketitle +\def\IEEEspecialpapernotice#1{\ifCLASSOPTIONconference% +\def\@IEEEspecialpapernotice{{\sublargesize\textit{#1}\vspace*{1em}}}% +\else% +\def\@IEEEspecialpapernotice{{\\*[1.5ex]\sublargesize\textit{#1}}\vspace*{-2ex}}% +\fi} + + + + +% PUBLISHER ID COMMANDS +% to insert a publisher's ID footer +% V1.6 \IEEEpubid has been changed so that the change in page size and style +% occurs in \maketitle. \IEEEpubid must now be issued prior to \maketitle +% use \IEEEpubidadjcol as before - in the second column of the title page +% These changes allow \maketitle to take the reduced page height into +% consideration when dynamically setting the space between the author +% names and the maintext. +% +% the amount the main text is pulled up to make room for the +% publisher's ID footer +% The IEEE uses about 1.3\baselineskip for journals, +% dynamic title spacing will clean up the fraction +\def\@IEEEpubidpullup{1.3\baselineskip} +\ifCLASSOPTIONtechnote +% for technotes it must be an integer of baselineskip as there can be no +% dynamic title spacing for two column mode technotes (the title is in the +% in first column) and we should maintain an integer number of lines in the +% second column +% There are some examples (such as older issues of "Transactions on +% Information Theory") in which the IEEE really pulls the text off the ID for +% technotes - about 0.55in (or 4\baselineskip). We'll use 2\baselineskip +% and call it even. +\def\@IEEEpubidpullup{2\baselineskip} +\fi + +% V1.7 compsoc does not use a pullup +\ifCLASSOPTIONcompsoc +\def\@IEEEpubidpullup{0pt} +\fi + +% holds the ID text +\def\@IEEEpubid{\relax} + +% flag so \maketitle can tell if \IEEEpubid was called +\newif\if@IEEEusingpubid +\global\@IEEEusingpubidfalse +% issue this command in the page to have the ID at the bottom +% V1.6 use before \maketitle +\def\IEEEpubid#1{\def\@IEEEpubid{#1}\global\@IEEEusingpubidtrue} + + +% command which will pull up (shorten) the column it is executed in +% to make room for the publisher ID. Place in the second column of +% the title page when using \IEEEpubid +% Is smart enough not to do anything when in single column text or +% if the user hasn't called \IEEEpubid +% currently needed in for the second column of a page with the +% publisher ID. If not needed in future releases, please provide this +% command and define it as \relax for backward compatibility +% v1.6b do not allow command to operate if the peer review option has been +% selected because \IEEEpubidadjcol will not be on the cover page. +% V1.7 do nothing if compsoc +\def\IEEEpubidadjcol{\ifCLASSOPTIONcompsoc\else\ifCLASSOPTIONpeerreview\else +\if@twocolumn\if@IEEEusingpubid\enlargethispage{-\@IEEEpubidpullup}\fi\fi\fi\fi} + +% Special thanks to Peter Wilson, Daniel Luecking, and the other +% gurus at comp.text.tex, for helping me to understand how best to +% implement the IEEEpubid command in LaTeX. + + + +%% Lockout some commands under various conditions + +% general purpose bit bucket +\newsavebox{\@IEEEtranrubishbin} + +% flags to prevent multiple warning messages +\newif\if@IEEEWARNthanks +\newif\if@IEEEWARNIEEEPARstart +\newif\if@IEEEWARNIEEEbiography +\newif\if@IEEEWARNIEEEbiographynophoto +\newif\if@IEEEWARNIEEEpubid +\newif\if@IEEEWARNIEEEpubidadjcol +\newif\if@IEEEWARNIEEEmembership +\newif\if@IEEEWARNIEEEaftertitletext +\@IEEEWARNthankstrue +\@IEEEWARNIEEEPARstarttrue +\@IEEEWARNIEEEbiographytrue +\@IEEEWARNIEEEbiographynophototrue +\@IEEEWARNIEEEpubidtrue +\@IEEEWARNIEEEpubidadjcoltrue +\@IEEEWARNIEEEmembershiptrue +\@IEEEWARNIEEEaftertitletexttrue + + +%% Lockout some commands when in various modes, but allow them to be restored if needed +%% +% save commands which might be locked out +% so that the user can later restore them if needed +\let\@IEEESAVECMDthanks\thanks +\let\@IEEESAVECMDIEEEPARstart\IEEEPARstart +\let\@IEEESAVECMDIEEEbiography\IEEEbiography +\let\@IEEESAVECMDendIEEEbiography\endIEEEbiography +\let\@IEEESAVECMDIEEEbiographynophoto\IEEEbiographynophoto +\let\@IEEESAVECMDendIEEEbiographynophoto\endIEEEbiographynophoto +\let\@IEEESAVECMDIEEEpubid\IEEEpubid +\let\@IEEESAVECMDIEEEpubidadjcol\IEEEpubidadjcol +\let\@IEEESAVECMDIEEEmembership\IEEEmembership +\let\@IEEESAVECMDIEEEaftertitletext\IEEEaftertitletext + + +% disable \IEEEPARstart when in draft mode +% This may have originally been done because the pre-V1.6 drop letter +% algorithm had problems with a non-unity baselinestretch +% At any rate, it seems too formal to have a drop letter in a draft +% paper. +\ifCLASSOPTIONdraftcls +\def\IEEEPARstart#1#2{#1#2\if@IEEEWARNIEEEPARstart\typeout{** ATTENTION: \noexpand\IEEEPARstart + is disabled in draft mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEPARstartfalse} +\fi +% and for technotes +\ifCLASSOPTIONtechnote +\def\IEEEPARstart#1#2{#1#2\if@IEEEWARNIEEEPARstart\typeout{** WARNING: \noexpand\IEEEPARstart + is locked out for technotes (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEPARstartfalse} +\fi + + +% lockout unneeded commands when in conference mode +\ifCLASSOPTIONconference +% when locked out, \thanks, \IEEEbiography, \IEEEbiographynophoto, \IEEEpubid, +% \IEEEmembership and \IEEEaftertitletext will all swallow their given text. +% \IEEEPARstart will output a normal character instead +% warn the user about these commands only once to prevent the console screen +% from filling up with redundant messages +\def\thanks#1{\if@IEEEWARNthanks\typeout{** WARNING: \noexpand\thanks + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNthanksfalse} +\def\IEEEPARstart#1#2{#1#2\if@IEEEWARNIEEEPARstart\typeout{** WARNING: \noexpand\IEEEPARstart + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEPARstartfalse} + + +% LaTeX treats environments and commands with optional arguments differently. +% the actual ("internal") command is stored as \\commandname +% (accessed via \csname\string\commandname\endcsname ) +% the "external" command \commandname is a macro with code to determine +% whether or not the optional argument is presented and to provide the +% default if it is absent. So, in order to save and restore such a command +% we would have to save and restore \\commandname as well. But, if LaTeX +% ever changes the way it names the internal names, the trick would break. +% Instead let us just define a new environment so that the internal +% name can be left undisturbed. +\newenvironment{@IEEEbogusbiography}[2][]{\if@IEEEWARNIEEEbiography\typeout{** WARNING: \noexpand\IEEEbiography + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEbiographyfalse% +\setbox\@IEEEtranrubishbin\vbox\bgroup}{\egroup\relax} +% and make biography point to our bogus biography +\let\IEEEbiography=\@IEEEbogusbiography +\let\endIEEEbiography=\end@IEEEbogusbiography + +\renewenvironment{IEEEbiographynophoto}[1]{\if@IEEEWARNIEEEbiographynophoto\typeout{** WARNING: \noexpand\IEEEbiographynophoto + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEbiographynophotofalse% +\setbox\@IEEEtranrubishbin\vbox\bgroup}{\egroup\relax} + +\def\IEEEpubid#1{\if@IEEEWARNIEEEpubid\typeout{** WARNING: \noexpand\IEEEpubid + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEpubidfalse} +\def\IEEEpubidadjcol{\if@IEEEWARNIEEEpubidadjcol\typeout{** WARNING: \noexpand\IEEEpubidadjcol + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEpubidadjcolfalse} +\def\IEEEmembership#1{\if@IEEEWARNIEEEmembership\typeout{** WARNING: \noexpand\IEEEmembership + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEmembershipfalse} +\def\IEEEaftertitletext#1{\if@IEEEWARNIEEEaftertitletext\typeout{** WARNING: \noexpand\IEEEaftertitletext + is locked out when in conference mode (line \the\inputlineno).}\fi\global\@IEEEWARNIEEEaftertitletextfalse} +\fi + + +% provide a way to restore the commands that are locked out +\def\IEEEoverridecommandlockouts{% +\typeout{** ATTENTION: Overriding command lockouts (line \the\inputlineno).}% +\let\thanks\@IEEESAVECMDthanks% +\let\IEEEPARstart\@IEEESAVECMDIEEEPARstart% +\let\IEEEbiography\@IEEESAVECMDIEEEbiography% +\let\endIEEEbiography\@IEEESAVECMDendIEEEbiography% +\let\IEEEbiographynophoto\@IEEESAVECMDIEEEbiographynophoto% +\let\endIEEEbiographynophoto\@IEEESAVECMDendIEEEbiographynophoto% +\let\IEEEpubid\@IEEESAVECMDIEEEpubid% +\let\IEEEpubidadjcol\@IEEESAVECMDIEEEpubidadjcol% +\let\IEEEmembership\@IEEESAVECMDIEEEmembership% +\let\IEEEaftertitletext\@IEEESAVECMDIEEEaftertitletext} + + + +% need a backslash character for typeout output +{\catcode`\|=0 \catcode`\\=12 +|xdef|@IEEEbackslash{\}} + + +% hook to allow easy disabling of all legacy warnings +\def\@IEEElegacywarn#1#2{\typeout{** ATTENTION: \@IEEEbackslash #1 is deprecated (line \the\inputlineno). +Use \@IEEEbackslash #2 instead.}} + + +% provide some legacy IEEEtran commands +\def\IEEEcompsoctitleabstractindextext{\@IEEElegacywarn{IEEEcompsoctitleabstractindextext}{IEEEtitleabstractindextext}\IEEEtitleabstractindextext} +\def\IEEEdisplaynotcompsoctitleabstractindextext{\@IEEElegacywarn{IEEEdisplaynotcompsoctitleabstractindextext}{IEEEdisplaynontitleabstractindextext}\IEEEdisplaynontitleabstractindextext} +% provide some legacy IEEEtran environments + + +% V1.8a no more support for these legacy commands +%\def\authorblockA{\@IEEElegacywarn{authorblockA}{IEEEauthorblockA}\IEEEauthorblockA} +%\def\authorblockN{\@IEEElegacywarn{authorblockN}{IEEEauthorblockN}\IEEEauthorblockN} +%\def\authorrefmark{\@IEEElegacywarn{authorrefmark}{IEEEauthorrefmark}\IEEEauthorrefmark} +%\def\PARstart{\@IEEElegacywarn{PARstart}{IEEEPARstart}\IEEEPARstart} +%\def\pubid{\@IEEElegacywarn{pubid}{IEEEpubid}\IEEEpubid} +%\def\pubidadjcol{\@IEEElegacywarn{pubidadjcol}{IEEEpubidadjcol}\IEEEpubidadjcol} +%\def\specialpapernotice{\@IEEElegacywarn{specialpapernotice}{IEEEspecialpapernotice}\IEEEspecialpapernotice} +% and environments +%\def\keywords{\@IEEElegacywarn{keywords}{IEEEkeywords}\IEEEkeywords} +%\def\endkeywords{\endIEEEkeywords} +% V1.8 no more support for legacy IED list commands +%\let\labelindent\IEEElabelindent +%\def\calcleftmargin{\@IEEElegacywarn{calcleftmargin}{IEEEcalcleftmargin}\IEEEcalcleftmargin} +%\def\setlabelwidth{\@IEEElegacywarn{setlabelwidth}{IEEEsetlabelwidth}\IEEEsetlabelwidth} +%\def\usemathlabelsep{\@IEEElegacywarn{usemathlabelsep}{IEEEusemathlabelsep}\IEEEusemathlabelsep} +%\def\iedlabeljustifyc{\@IEEElegacywarn{iedlabeljustifyc}{IEEEiedlabeljustifyc}\IEEEiedlabeljustifyc} +%\def\iedlabeljustifyl{\@IEEElegacywarn{iedlabeljustifyl}{IEEEiedlabeljustifyl}\IEEEiedlabeljustifyl} +%\def\iedlabeljustifyr{\@IEEElegacywarn{iedlabeljustifyr}{IEEEiedlabeljustifyr}\IEEEiedlabeljustifyr} +% V1.8 no more support for QED and proof stuff +%\def\QED{\@IEEElegacywarn{QED}{IEEEQED}\IEEEQED} +%\def\QEDclosed{\@IEEElegacywarn{QEDclosed}{IEEEQEDclosed}\IEEEQEDclosed} +%\def\QEDopen{\@IEEElegacywarn{QEDopen}{IEEEQEDopen}\IEEEQEDopen} +%\AtBeginDocument{\def\proof{\@IEEElegacywarn{proof}{IEEEproof}\IEEEproof}\def\endproof{\endIEEEproof}} +% V1.8 no longer support biography or biographynophoto +%\def\biography{\@IEEElegacywarn{biography}{IEEEbiography}\IEEEbiography} +%\def\biographynophoto{\@IEEElegacywarn{biographynophoto}{IEEEbiographynophoto}\IEEEbiographynophoto} +%\def\endbiography{\endIEEEbiography} +%\def\endbiographynophoto{\endIEEEbiographynophoto} +% V1.7 and later no longer supports \overrideIEEEmargins +%\def\overrideIEEEmargins{% +%\typeout{** WARNING: \string\overrideIEEEmargins \space no longer supported (line \the\inputlineno).}% +%\typeout{** Use the \string\CLASSINPUTinnersidemargin, \string\CLASSINPUToutersidemargin \space controls instead.}} + +\endinput + +%%%%%%%%%%%%%%%%%%%%%%%%%%%%% End of IEEEtran.cls %%%%%%%%%%%%%%%%%%%%%%%%%%%% +% That's all folks! + diff --git a/README.md b/README.md new file mode 100644 index 0000000..0bdb08b --- /dev/null +++ b/README.md @@ -0,0 +1,11 @@ +# MotionPlan + +main.tex是文本 + +输入下述命令,就能编译tex文件了 +`sudo apt install texlive-full` + +在vsocde里搜索*LaTex Workshop*插件,就能编辑和查看了,甚至还可以使用git来管理版本。 + +这不比word方便? + diff --git a/REVISION_PLAN.md b/REVISION_PLAN.md new file mode 100644 index 0000000..361299d --- /dev/null +++ b/REVISION_PLAN.md @@ -0,0 +1,506 @@ +# TVT 投稿修改计划 + +目标期刊:IEEE Transactions on Vehicular Technology +当前状态:理论四章 + 两附录已完成(中文注释 2.39 万字,97 个公式,PDF 5 页);实验章、结论、摘要为空 +制定日期:2026-08-21 + +--- + +## 阶段划分与依据 + +分四个阶段,顺序不可交换: + +1. **P0 冻结公式** — 后续所有文字都建立在公式之上,公式未定则文字可能作废 +2. **P1 结构瘦身** — 只做不需要逐句权衡的机械迁移,趁写作记忆新鲜时做 +3. **P2 补齐实验** — 带篇幅预算写,避免写完再砍 +4. **P3 包装与收尾** — 新颖性表述、文献、图、润色 + +篇幅预算(IEEEtran 双栏,目标 12 页内): + +| 部分 | 页数 | 当前中文字数 | 目标降幅 | +|---|---|---|---| +| I Introduction + Related Work | 1.5 | 3239 | -15% | +| II Problem Formulation | 2.0 | 5759 | -30% | +| III IGF | 1.5 | 5139 | -40% | +| IV Search | 1.0 | 3718 | -35% | +| V Optimization | 1.5 | 4716 | -35% | +| VI Experiments | 3.0 | 0 | 新写,上限约 5000 字 | +| VII Conclusion | 0.4 | 0 | 新写 | +| Appendix(正文内保留) | 0.6 | 1163 | -50%(其余入补充材料) | + +--- + +## P0 冻结公式(先做,不写正文文字) + +**状态:P0 全部 9 项已完成**(2026-08-24)。main.tex 与 supplement.tex 均编译通过、无未定义引用。 +标记约定:`[x]` 已改入正文;`[~]` 公式与论述已就位,实测数值待 P2 填入。 + +### P0-1 交互项引入时序权重 ★核心 + +**问题**:`J_Psi`(main.tex:248)是全弧长上的无权重对称二重积分,不是 `T_wait` 的单调代理。 +`T_wait` 对冲突位置高度不对称——冲突在装载位附近则空载车几乎要等满载车跑完全程, +冲突在入口附近则几乎不用等。当前核积分对两者计费相同。 +更关键的是:场地单出入口(main.tex:45)+ 装载位共享位姿(main.tex:337)使 +**两个端点区域的重叠都是结构性不可消除的**,而 `J_Psi` 数值恰被这两块支配, +优化器把力气花在改不动的地方。 + +**改法**:按驶离路径的剩余弧长加权 + +``` +J_Psi = (w_Psi / v_0) ∫_{Γ_park} ∫_{Γ_exit} φ(s_exit) · K(d_ε; ρ_Psi, m_Psi) ds_exit ds_park +φ(s_exit) = (s_exit^total − s_exit) / v_0 +``` + +物理含义直接是"该处重叠所诱导的等待时长"。 + +**连带收益**:非对称性从此有物理来源,不再依赖 main.tex:286 那段 +"交互项天然对称 → 非对称只能塞进 J_U → 但 w_U^exit/w_U^park 与位移分配无解析对应关系" +的辩解。该段从"辩解"改写为"设计"。 + +**影响范围**: +- [x] 改 main.tex:248-253(eq:cost_interaction) +- [x] 改 main.tex:266-268(二重积分性质说明——对称性论述需重写,现在是加权对称) +- [x] 重写 main.tex:286-293(非对称加权那一整段) +- [x] 改 main.tex:795-803(Psi_exit 交互场定义,加 φ) +- [x] 改 main.tex:846-856(eq:joint_psi_discrete 离散形式) +- [x] 检查 main.tex:129-136 的代理论证链条是否因此闭合(应当闭合) +- [x] 注意:φ 依赖 s_exit^total = (M_exit−1)·Δs_exit,是决策变量。 + 按 P0-4 的处理方式一并冻结为粗解常值,或说明其梯度贡献。 + +### P0-2 虚拟道路中线剥离装载位支路 ★核心 + +**问题**:两处直接矛盾—— +- main.tex:363 称装载位变更时引导场**无需重建**(理由:场地边界未变) +- main.tex:394 中线是在骨架图上用 A* 连接**入口点、装载点、离开点**得到 + +装载点一变,`Λ_center` 就变,两条引导线随之变,场必须重建。审稿人一眼可见。 + +**改法**:中线只在**入口—出口主通道**上提取,不含装载位支路; +装载位以支路形式在搜索阶段由边界条件(eq:cons_boundary)承担。 +这样场对装载位变更确实不变,main.tex:363 的主张才站得住。 + +**影响范围**: +- [x] 改 main.tex:394(中线提取的 A* 连接端点) +- [x] 改 main.tex:363(第一阶段框架论述) +- [x] 检查 main.tex:588("两条路径独立并行搜索"的论证是否仍成立——应仍成立) +- [x] 检查 main.tex:723("越靠近停靠点路径越应从主路径分叉"——与新设定更一致了) + +### P0-3 拓扑一致性:给出定义与度量 + +**问题**:Challenge 2 通篇讲"拓扑稳定",但"拓扑"全文无定义,也无任何保证或度量。 +`U` 只是软代价,Hybrid A* 完全可能在装载位挪到中线另一侧时翻边。 +三个贡献中这一条目前论证最弱。 + +**改法**: +- [x] 在 II 章给出形式化定义:路径相对 `Λ_center` 的带符号横向偏移在共享通道段内保持同号 +- [~] 在实验章给出跨装载位序列的**拓扑一致率**指标(见 P2-2) +- [x] 明确说明这是软先验下的经验性质,不声称硬保证(避免被追问反证) + +### P0-4 J_Psi 的量纲与正文声明不符 + +**问题**:main.tex:810 称"`J_Psi` 与 `J_U` 同为势能沿路径的弧长积分除以 v_0, +故 `w_Psi` 与 `w_U` 具有相同量纲与可比的物理含义"。 +但 `Ψ_exit = ∫ K ds` 本身带长度单位(K 无量纲),`J_Psi` 因此比 `J_U` 多一个长度量纲, +`w_Psi` 与 `w_U^•` 不可比。 + +**改法**:择一 +- (a) 交互核除以一个特征长度(如 `ρ_Psi` 或 `L_v`)使 `Ψ` 无量纲 +- (b) 保留现状但删掉"同量纲可比"的声明,明确 `w_Psi` 单独标定 + +推荐 (a),与全文"统一折算为等效耗时"的口径一致。 +注意 P0-1 引入 φ(单位:秒)后量纲再变一次,两处需一并算清。 + +- [x] 定下处理方式并改 main.tex:805-810 +- [x] 同步改 Nomenclature 表(main.tex:220 的 w 说明) + +### P0-5 J_ℓ 的存在理由与实际公式不符 + +**问题**:main.tex:278 用弹性带经典论证说明 `J_ℓ` 是 `J_κ` 的必要配重 +("若无长度项,优化器将持续外扩弯道以降低 J_κ")。 +但离散化后(main.tex:828)`M_•` 由粗解固定、`Δs_•` 是唯一长度自由度, +且被 main.tex:750 的信赖域锁在 `±Δ_slide/(M_•−1)` 内。于是 +`J_ℓ = [(M_park−1)Δs_park + (M_exit−1)Δs_exit]/v_0` 只是两个标量的线性函数, +总变动不超过 `2Δ_slide/v_0`。路径长度已被参数化钉死,弹性带论证在此不成立。 + +**连带**: +- main.tex:162 称"自由终端最优控制问题",实际是准固定长度 +- main.tex:756 称信赖域取等的外循环"实际触发极少",但粗解长度若偏大 5–10%, + 单次求解修不回来,与"极少触发"是张力关系 + +**改法:已定 —— 采用 (b)** +保留现有参数化(`M_•` 固定、`Δs_•` 为唯一长度自由度), +把 `J_ℓ` 的作用重新表述为"在固定配置点数下抑制步长膨胀",删掉弹性带论证。 + +理由:改动局部,不触碰 P0-1 刚定下的稀疏结构;代价是需要用实测数据支撑 +"信赖域够宽"这一前提(见下方 checklist 第 4 项)。 + +- [x] 改 main.tex:278:删掉弹性带外扩论证(含 `∫κ²ds = Δθ/R` 那句), + 改为"在 `M_•` 固定的参数化下,`J_ℓ` 抑制 `Δs_•` 膨胀, + 与 `J_κ` 共同确定弯道的展开程度" +- [x] 保留 main.tex:278 末尾对 quinlan 弹性带文献的引用,但改为"同类做法"的弱引用, + 不再作为本文 `J_ℓ` 的论证依据 +- [~] 实验中给出 `Δ_slide` 取值与外循环触发率实测(P2-2), + 用以支撑"信赖域不构成实质限制" +- [x] 改 main.tex:162 的"自由终端"表述 +- [~] main.tex:756 的"触发极少"改为待实测(P2-2 报告) + +### P0-6 避碰约束的表述强度 + +**问题**:main.tex:779 称 eq:cons_collision "被**完全替换**为线性不等式组"。 +实际只在配置点上成立,配置点之间车辆仍可切角。矿卡 `L_v` 十几米、`Δs≈1m` 且伴随转向, +切入量不可忽略。 + +**改法:已定 —— 走廊内缩余量,不加中点约束** + +余量的解析形式:两个配置点之间车辆绕瞬心转过 `Δθ = Δs/R`, +车体某顶点到瞬心距离为 `ρ_c` 时,其轨迹弦的最大矢高(sagitta)为 + +``` +Δ_cut = max_r ρ_c^(r) · (1 − cos(Δs·κ_max / 2)), +ρ_c^(r) = ‖ [a_r, b_r]^T − [0, R_min]^T ‖ +``` + +即取四个顶点中离瞬心最远者。走廊生成时统一内缩 `Δ_cut` 即可覆盖点间切角。 + +按矿卡尺度实算(`R_min=12m`、`L_v=12m`、`B_v=3m`,最远顶点 `ρ_c≈17.7m`): + +| `Δs` | 最大切入量 | +|---|---| +| 0.5 m | 0.4 cm | +| 1.0 m | 1.6 cm | +| 1.5 m | 3.5 cm | +| 2.0 m | 6.3 cm | +| 3.0 m | 14.1 cm | + +**结论:在 `Δs ≤ 1.5m` 时切入量 ≤ 3.5cm,一次性内缩即可覆盖,中点约束确无必要。** +这也反过来给 `Δs` 定了上界——`Δs = 3m` 时 14cm 已接近矿区常用安全余量的量级, +故配置步长不宜再放大。此项同时为 P2 的 `Δs` 取值提供依据。 + +- [x] 改 main.tex:779:措辞从"完全替换"改为 + "离散配置点上的**充分条件**,配置点之间的切角由走廊内缩 `Δ_cut` 覆盖" +- [x] 走廊构造中加入内缩步骤(与 `Δ_slide` 的种子延伸是两个独立余量,勿混淆: + `Δ_slide` 处理**纵向**滑移,`Δ_cut` 处理**横向**切角) +- [x] 上式推导 + 数值表入补充材料 S-IV-E(占位已建) +- [~] 正文声明所采用的 `Δs` 及对应 `Δ_cut` 实际值(P2-2 一并报告) + +### P0-7 σ_max 的量纲转换 + +**问题**:物理限制是 `ψ̇`(时间导数),main.tex:328 约束的是弧长导数,相差 `v`。 +以 `v_0` 折算意味着在装载位附近低速段**过度保守**——恰是空间最紧的地方。 + +**改法**: +- [x] 至少显式说明该保守性及其来源 +- [~] 或按分段速度剖面给分段 `σ_max`(更严谨,改动小) + +### P0-8 归一化场值可超出 [0,1] + +**问题**:main.tex:526 自承 `U_e^max` 在凹角处只是估计而非上界, +故 main.tex:580 归一化后 `Û` 可能 > 1。下界安全(`U ≥ −U_g^max` 严格成立,A* 非负性无碍), +但全文把 `U∈[0,1]` 当作"等效减速因子"来解释 `w_U` 的物理含义。 + +**改法**: +- [x] 加一句截断说明(`Û ← min(Û, 1)`),或明确 `Û∈[0,1]` 为典型范围而非严格值域 + +### P0-9 冻结求积权重的理由改写 + +**问题**:main.tex:858 称不冻结会在 Hessian 里形成"两整行稠密结构"。 +但那是 10^4 量级问题里的 2 行,稀疏内点法完全吃得下。理由偏弱,易被质疑。 + +**改法**: +- [x] 改为"实现简化 + 误差有界可忽略"(误差界你已经给了,照这个说更可信), + 删掉把稀疏性当主因的表述 + +--- + +## P1 结构瘦身(与 P0 并行,只做机械迁移) + +已建 `supplement.tex`(S 前缀独立编号,已编译通过)。以下内容迁入,正文只留结论 + 指针。 + +### P1-1 已在 supplement 建好占位,待迁正文原文 + +- [x] **S-I** 引导场上界推导与场强系数标定 ← main.tex:510-533, 566-577 + 正文保留:`U_g^max`/`U_e^max` 表达式、eq:alpha_dominance 标定条件 +- [x] **S-II** 栅格场连续化表示(B 样条 vs 双线性) ← main.tex:560-563 + 正文保留:一句"以张量积三次 B 样条查询,核衰减阶数取 m≥3" +- [x] **S-III** 联立 vs 交替优化论证 ← main.tex:888-896 + 正文保留:一句结论 + 指针 +- [x] **S-IV** 凸走廊构造完整推导 ← main.tex:970-1008(原附录 B 整节) + 正文保留:凸多面体最终形式 + "半空间由局部边界点分布自适应确定" + +### P1-2 元论述段落精简 + +**状态:已完成**(2026-08-24)。14 处压缩全部落地,另加 main.tex:958-959 的 $\tau_{ij}$ 两段合并;三处影响正确性的论述按计划保留。 + +全文 22 处"需要说明/需要强调/需要指出/此处作一点说明"式防御性论述。 +**保留三处**(影响正确性): +- `J_U` 与 `J_Psi` 不重复计费(main.tex:283) +- 与传统 APF 的本质区别(main.tex:564) +- 启发函数不可采纳性(main.tex:725) + +其余压缩到一两句或删除: +- [x] main.tex:172-173, 258(符号约定说明 → 已有 Nomenclature 表,删重复) +- [x] main.tex:319(换挡点曲率可跳变 → 压成半句) +- [x] main.tex:347(装载位共享位姿的解释 → 保留结论,删"可理解为一条更长路径被切分") +- [x] main.tex:445(QCQP 凸性 + OSQP 接口说明 → 压成两句) +- [x] main.tex:511, 526-527(上界前提与凹角例外 → 入 S-I) +- [x] main.tex:575, 577(支配条件的逐点/上界之辨、线性叠加理由 → 入 S-I) +- [x] main.tex:586(归一化标度一致性 → 压成一句) +- [x] main.tex:631-632(状态格仅作判重键 → 压成一句) +- [x] main.tex:667(分辨率完备性 + 碰撞检测细分 → 保留后半,前半压缩) +- [x] main.tex:674(解析段与两点设定的关系 → 压成两句) +- [x] main.tex:701(弧长加权而非节点计数 → 与 main.tex:812 重复,合并保留一处) +- [x] main.tex:786(两阶段两种解耦机制 → 压缩,与 main.tex:283 有重叠) +- [x] main.tex:898(初值处交互项非零的性质 → 压成一句脚注) + +### P1-3 公式数量压缩 + +**状态:已达标**(2026-08-24)。正文编号式 53 个(`main.aux` 计数,含 subequations 子项), +远低于 65 的目标;`\label{eq:` 计数 91 → 其中含 14 组 subequations 的父/子标签。 + +- [x] 内联的简单定义:`eq:qp_delta_s`($\ell_i$ 平均段长)、`eq:field_source_sets`(三个势源集合)、 + `eq:field_grid`(栅格点集 $\Xi$)、`eq:corner_transform`(角点刚体变换 2 式) +- [x] 附录 A「曲率二阶差分离散化」整节 6 式迁入 **S-V**,正文只留换算关系 + 误差量级一句 + ($R_\text{min}=12$ m、$\ell=1$ m 时 $0.06\%$,且偏保守)+ 指针 +- [x] `\appendices` 环境连同 `\counterwithin` / `\theHequation` 锚点设置一并删除 + (附录 A 入 S-V、附录 B 已于 P1-1 入 S-IV,正文再无附录) +- [x] 补充材料章节序重排:新增 S-V,原「实现细节与补充结果」顺延为 **S-VI**; + main.tex 中指向消融表的 S-V 指针已同步改为 S-VI +- 保留未内联:`eq:tangent_normal`(被 2 处 `\eqref` 引用)、`eq:reference_offset`(被 3 处引用), + 内联会使这些交叉引用失去锚点,收益不抵可读性损失 + +**遗留(P3 校对时一并处理)**:24 个 `\label{eq:...}` 目前零引用,多为 subequations 内的 +子式标签(`eq:qp_obj1`–`4`、`eq:joint_obj/eq/ineq`、`eq:cons_bc_park/exit` 等)。 +草稿阶段正文为注释,去掉注释后部分会被引用;投稿前清一次真正无用的标签。 + +### P1-4 写作纪律(从现在起) + +- [x] 凡判断为"脚注级但有价值"的段落,**直接写入 supplement.tex**,不进主文 +- [x] 决定放哪里的成本在写的当下最低,不要留到最后挑 + +--- + +## P2 补齐实验(P0 完成后开始,带预算写) + +### P2-1 修掉悬空引用 + +- [x] 已建第 VI 章 Experiments 骨架,8 个小节标签全部定义: + `sec:exp`、`subsec:exp_setup`、`subsec:exp_baselines`、`subsec:exp_throughput`、 + `subsec:exp_geometry`、`subsec:exp_topology`、`subsec:exp_efficiency`、 + `subsec:exp_ablation`、`subsec:exp_realvehicle`。 + 各小节内以注释形式列明待填指标,无未定义引用。 + +### P2-2 基线与指标(最低配置) + +**状态:实验设计已定稿写入正文**(2026-08-24,`subsec:exp_baselines`)。 +五类基线各自"只回答一个问题"的定位、九项指标的分组与判定方式均已落在 main.tex; +下列勾选表示**设计已写定**,实测数据待补。 + +**基线**(每项只剥离一处设计选择): +- [x] ① 双路径独立 Hybrid A* + 优化(无场、无交互项)→ 回答"是否需要双向先验" +- [x] ② 固定渠化规则(预设双向参考路线)→ 回答"自动提取 vs 人工预设" +- [x] ③ 交替优化而非联立 → 为 S-III 的论证提供实证 +- [x] ④ 同索引点距惩罚 → subsec:objective 已论证其不适用,此处给实证 +- [x] ⑤ 时间维协同调度作为性能上界 → **代理关系的唯一直接检验,不可省** + +**指标**(三组): +- [x] 组一(代理目标有效性):`T_wait` 相对基线①的压缩幅度;离散事件仿真吞吐量(趟/小时), + 须与基线⑤的上界对照 +- [x] 组二(几何与拓扑):扫掠域重叠面积、两路径最小间距分布、 + 按 `eq:topology_consistency` 判定的拓扑一致率 +- [x] 组三(计算性质):求解时间与成功率(≥100 组随机装载位)、 + 搜索阶段**墙钟时间与扩展节点数并列**(每次扩展多 6 次基元积分 + 6 次场查询, + 节点数降但单节点变贵,只报节点数会被打回)、走廊半空间数 `m_k` 分布与最大值、 + 信赖域外循环触发率、热启动 vs 冷启动迭代数对照 +- [ ] 全部实测数据(待实验) + +### P2-2c 消融设计(已写入 `subsec:exp_ablation`) + +- [x] 四项逐一剥离:`tau_d ≡ 1`、去 `J_Psi`、去场自适应步长、`w_U` 对称化 +- [x] 正文只报 (1)(2) 主要指标,完整表入 S-VI +- [ ] 实测数据(待实验) + +### P2-2b 实车验证(★ 本文最硬的一块,单独成小节) + +**状态:小节结构与论证分工已写入正文**(2026-08-24,`subsec:exp_realvehicle`)。 +定位已明确写为"不是可行性演示,而是检验前文两处以标称值作出的解析论断"。 + +**必须交代的试验条件**(已在正文列明待填): +- [x] 矿卡型号与关键参数(`L_v`、`B_v`、`L_w`、`R_min`、实测 `ψ̇_max`) +- [x] 场地规模、边界感知方式(激光雷达型号/点云分辨率 → `bar_ell_e` 实际取值) +- [x] 试验规模:装载循环次数、覆盖的装载位数量、总里程/时长 +- [x] 定位方案与精度(须与所报误差量级一并给出,否则误差数据不可信) + +**承担两项独立论证**(分工已写定): +1. **跟踪可行性**(检验 `eq:sigma_time_conversion` 的折算与 `σ_max` 取值) + - [x] 横向误差沿弧长分布,尤其换向段与装载位邻域 + - [x] 实测前轮转角速率是否触顶 —— 正文已如实写明不利可能:低速段大量触顶 + 则说明以 `v_0` 折算偏松而非偏保守,`σ_max` 应改由分段速度剖面给出 + - [x] 实测车体轮廓到边界最小间隙,与 `eq:corner_cut_margin` 的 `Δ_cut` 对照 +2. **吞吐量增益**(与离散事件仿真互为验证) + - [x] 实测 `T_wait`/`T_park`/`T_exit` 与仿真预测对照 + - [x] 与现行作业方式的趟/小时对比 +- [ ] 全部实测数据(待实验) + +**对照组安排**:已写定实车只跑①与本文方法两组。 +- [x] 理由已明确写出:基线②--⑤或需改动既有作业规则、或需放开时间维调度权限, + 生产矿区不具备实施条件。如实说明以免被理解为回避不利对比。 + +### P2-3 T_wait 下界的论证 + +**状态:已完成**(2026-08-24),按推荐方案降级为实测值。 +- [x] main.tex:138 不再断言存在下界,改为:给出会车所需通道净宽的几何条件 + (`W + B_v` 加两侧安全间隔,且 `W` 自身受 `eq:interaction_radius` 约束), + 指出该条件在最窄处不成立时 `T_wait` 必为正; + 并**明确声明不给出闭式下界**——它取决于最窄区段长度与两车速度剖面, + 构造性推导须引入本文有意排除的时间维决策量。改以实测值与压缩幅度报告。 + +### P2-4 实时性与刷新频次 + +**状态:已完成**(2026-08-24),在 `subsec:igf_build` 末尾新增两段。 +- [x] 以**时间尺度分离**回应:IGF 输入只有边界点集 `S_e`,中线不过装载位、 + 故场对装载位变更不敏感;重建只由边界几何实质变化触发,典型为**班次级** + (爆破或一段推进之后),远长于装载循环的分钟级节拍。 + 两次重建之间装载位变更只重解路径、场不变 —— 即镜像构造的工程收益: + 拓扑先验的有效期由边界而非装载位决定。 +- [x] 移动障碍(挖掘机、其他车辆)**不纳入 `S_e`**,理由是重建代价与其运动时间尺度 + 不匹配;由凸走廊在每次重规划时以当次感知快照施加硬约束避让。 + 并据此界定适用边界:IGF 承担随边界缓变的**通行拓扑**,非随车流快变的**瞬时占据**。 +- [ ] 场重建耗时与重规划频次的实测值(待实验,已在 `subsec:exp_setup` 挂钩) + +### P2-5 结论与摘要 + +**状态:已写定,留数字占位**(2026-08-24)。 + +- [x] Abstract(原为 `yes`):按 P3-1 的要求,**第二句即点出三点新颖性** + (离线镜像场固化拓扑 / 时延加权核积分交互代价 / 非对称引导权重), + 随后三句方法、一句验证规模(五基线 + 实车 N 次循环)、一句结果。 + **数字以 `($x$)`、`($y$)`、`($z$)`、`($N$)` 占位**,待实测替换。 +- [x] IEEEkeywords:Autonomous mining vehicles / path planning / open-pit mine / + spatial decoupling / guidance field / joint optimization / convex corridor +- [x] Conclusion:三点结论对应三点新颖性;第二段主动交代适用边界 + (IGF 管缓变拓扑非瞬时占据、优化的是吞吐量必要条件、拓扑一致性为软先验), + 并给出两个后续方向。末尾留 TODO:补量化结论句,与 Abstract 占位数字同步替换。 +- [ ] Conclusion(main.tex:900 空) + +--- + +## P3 包装与收尾 + +### P3-1 新颖性表述重做 ★ + +**风险**:按模块拆解,全部是现成件——EVG-thin 骨架 + Apollo FEM-pos 平滑 + Hybrid A* ++ 椭球凸分解走廊(safe flight corridor 那条线)+ APF 式核场 + Ipopt。 +审稿人给 "engineering integration, insufficient novelty" 的概率高。 + +**真正新的只有三点**,必须顶到 Abstract 第二句和 Contributions 最前: +1. 镜像方向性场把双向拓扑**前置固化到离线**(拓扑要求从在线约束变为离线先验) +2. 核积分式交互代价(不依赖采样点配对,适配两条路径的弧长/分段非对称) +3. 非对称引导权重(满载优先的工程语义) + +- [ ] 重写 Contributions 三段,每段明确"与最接近工作的差别是什么" +- [ ] **主动引单向交通组织文献**:矿区运输道路单向流设计、AGV 单向流网络是成熟做法, + 不引会让"空间解耦"看起来像重新发明单行道。 + 差异点:非结构化、边界随开采变化、含换向段的运动学可行路径、双路径联合优化 + +### P3-2 参考文献 + +当前 29 条,TVT 常规 40–60。质量分布也偏弱:6 条 arXiv 预印本、 +5 条 MDPI 刊(Applied Sciences / Symmetry / Electronics / Machines / Aerospace), +仅 1 条 TVT/T-IV。 + +- [ ] 补到 40+,优先补 TVT / T-ITS / T-ASE / RA-L 正式发表文献 +- [x] arXiv 条目尽量替换为已发表版本 +- [x] **正面讨论已在 bib 但全文未引的三条**(审稿人必问的对照方法): + - `zhang2021obca`(OBCA — 避碰约束的对偶形式,与本文凸走廊直接可比) + - ~~`li2022narrowparking`~~ → 已替换为 `lian2023valetparking` + `li2022parkingcorridor` + - `dolgov2010voronoi`(Voronoi 场 — 与 IGF 最接近的先前工作,**必须明确差异**) + +**2026-08-24 进展**:refs.bib 29 → 33 条,`bibtex` 零警告(此前 15 条 empty-author)。 + +清理内容: +- `li2022narrowparking` 是凭记忆写的占位条目,该标题在 Crossref 查无此文,**实际不存在**。 + 已替换为两篇真实文献:`lian2023valetparking`(T-IV 2023, 8(6):3723–3734)与 + `li2022parkingcorridor`(Bai Li, T-ITS 2022, 23(8):11970–11981)。main.tex:98 + 相应改写为"粗解引导 + 走廊化避碰",该说法已核对两篇摘要确认。 +- 4 条 arXiv 预印本查到正式发表版并替换:`mine2024unstructured`(LNEE 2025 章节, + 作者含 Guizhen Yu)、`ramp2024spatiotemporal`(ICTLE 2024)、 + `apf2024globalrepulsive`(ICARM 2024)、`apf2024wallfollower`(ICRA 2025)、 + `corridor2024convexcover`(RA-L 2025, 10(5):4762–4769)。 +- `apf2024globalrepulsive` 的真实内容是 subharmonic APF,与原占位标题 + "Improved APF Addressing Local Minimum and Goal Unreachability" 不符。 + main.tex:103 与 474 两处原写"目标不可达",已按两篇实际论点改为 + "局部极小致停滞"(wallfollower)+ "贴近障碍处势场导数急剧增大"(globalrepulsive)。 +- `apollo2020qp` 作者列表原先整个写错(Zhou/He/Wang… ),Crossref 实为 + Yajia Zhang, Hongyi Sun, Jinyun Zhou, Jiacheng Pan, Jiangtao Hu, Jinghao Miao。 +- `fan2018apolloem` 确无正式发表版,保留 arXiv 但补 eprint/archivePrefix/primaryClass。 + +仍待办:补到 40+(当前 33)。MDPI 占比偏高的问题未解决,宜在补引时用 +TVT/T-ITS/T-ASE/RA-L 正式文献替换部分 MDPI 条目。 + +方法学教训:文献必须经 Crossref/arXiv 核实,不可凭记忆重建。 +`api.crossref.org` 与 `export.arxiv.org`(须用 https)可 curl; +`link.springer.com`、`pubsonline.informs.org`、`www.mdpi.com` 在本环境被 WebFetch 拦截。 + +### P3-3 图与算法 + +全部图已画好并接入正文(`\graphicspath{{figs/}}`,均按原生尺寸 `\includegraphics` 引入、不缩放): +- [x] `fig_scenario`(装载场景)— TikZ,251.6×121.9 pt +- [x] `fig_conflict`(时空冲突与解耦,(a)-(d) 四联图)— TikZ,251.2×143.7 pt +- [x] `fig_bicycle`(车辆模型与几何参数)— TikZ,251.8×238.5 pt +- [x] `fig_framework`(三阶段框架)— TikZ,198.8×231.1 pt +- [x] IGF 可视化(`make_igf.py`,三联板:势源 / $\hat U_\text{park}$ / $\hat U_\text{exit}$)— 515.5×126.0 pt,`figure*` +- [x] 骨架+搜索、走廊+平滑后对比(`make_center.py`,三联板:距离场+骨架+A\* / 局部走廊+QP / 曲率剖面)— 515.5×140.4 pt,`figure*` +- [x] 6 探测点方位与步长调制示意(`fig_probe.tex`)— 152.4×287.0 pt +- [x] 凸分解几何示意(`fig_convex_decomp.tex`,接入 supplement S-IV)— 250.0×97.2 pt +- [x] 整体流程伪代码(`alg:overall`,algorithm2e,三阶段 17 行) + +#### 2026-08-24 进展(P3-3 完成) + +**图的生成方式分两类**,这一区分必须在投稿时保持: +- 纯示意图(scenario / conflict / bicycle / framework / probe / convex_decomp)用 TikZ 按正文定义直接画,坐标凡涉及运动学或几何的一律先用 Python 算准再写入 `.tex`(`calc_convex.py` 就是为凸分解图算椭球半轴、半空间法向与多面体顶点的)。 +- 算法产物图(`fig_igf` / `fig_center`)由 Python **按正文公式在合成场地上真算**,图注已明确写 "illustrates the construction and is not an experimental result",避免被误读为实验结果。 + +**共享模块**: +- `figs/figstyle.tex` — TikZ 图共用前言,`mathptmx` 对齐 IEEEtran 的 Times;颜色 `parkc/exitc/sitec/fillc/corrc/centc/confc`。 +- `figs/sitegeom.py` — 合成场地几何与 stage-1 全流程(`rasterize` / `clearance` / `skeleton` / `astar` / `qp_smooth` / `build_centerline`),`fig_igf` 与 `fig_center` 共用,保证两图的中线与引导线完全一致。 + +**数值自检(全部通过,改动 sitegeom/make_* 后须重跑确认)**: +- 中线曲率 `|κ|max = 0.0832 → R = 12.01 m ≥ R_min = 12 m`;粗解为 `0.6278 → R = 1.59 m`,即 `fig_center(c)` 的对比是真实的。 +- IGF 镜像恒等式残差 `|(U_park+U_exit) − 2U_e| = 1.8e-15`。 +- 方向性验证:`Û_park` 在 $\Lambda_\text{park}$ 上均值 0.033、在 $\Lambda_\text{exit}$ 上 0.159;`Û_exit` 为 0.155 / 0.037,即两个场确实互为镜像。 +- 凸分解:14 个障碍点剪到 7 个半空间、多面体 7 顶点且封闭;障碍点二次型最小值 = 1.000000(恰好相切),线段二次型最大值 = 1.000000(完整包裹)。 + +**踩过的坑(同类图再画时直接照搬结论)**: +- `qp_smooth` 的曲率投影必须放在走廊投影**之后**,否则被走廊投影撤销;且二阶差分上界 `ell_i²/R_min` 必须在**每轮迭代按当前折线自身间距**重算,用参考折线的间距会导致"约束满足但验证不过"(前后差 1.0 m vs 0.953 m,够把 R 从 12.6 m 拉到 10.9 m)。 +- 归一化场只落在 0–0.34(`U_e^max = 17` 这个解析上界很保守,正文亦承认它只是量级估计),配色范围必须取实际跨度而非 [0,1],否则两个面板几乎全黑;两个面板共用一个色标,镜像关系才看得出来。 +- 凸多面体在轴向两端不会自动封口——线段延长线方向若无障碍点,`|u| > 1` 的点不约束短轴但**决定纵向封口**,必须补端部障碍点。 +- 三张 TikZ 图原本略超 252 pt 单栏宽(bicycle/scenario/conflict),已通过下调 `scale` 原生适配,而不是靠 `\includegraphics[width=...]` 缩放——后者会把 `\tiny`/`\scriptsize` 标注压到不可读。 + +**顺带修掉的两处 overfull**(均为公式超单栏宽,非图的问题): +- `eq:corner_cut_margin` 超 35.9 pt → 改为 `aligned` 两行。 +- `eq:interaction_field` 超 12.6 pt → 改为 `multline`。 +- 余下 5 处 overfull 均 ≤1.5 pt,是图注段落的正常挤压,不处理。 + +**当前编译状态**:main 7 页、supplement 2 页,两者 exit=0,无 error、无未定义引用/引文。7 张图 + 1 个算法环境均已在正文有 `\ref` 提及(IEEE 要求),补充材料的 `fig:sup_convex_decomp` 亦已在 S-IV 开头引用。 + +**注意**:`.gitignore` 含 `*.pdf`,图的 PDF 产物当前不入库。投稿前需决定是 `git add -f figs/*.pdf`,还是在 `.gitignore` 里对 `figs/` 开例外(推荐后者,`!figs/*.pdf`),否则 clone 出来编译不过。 + +### P3-4 投稿前检查 + +- [ ] 删 main.tex:1012 与 supplement.tex 末尾的 `\nocite{*}` +- [ ] 确认无未定义引用(`grep` 检查 label/ref 配对) +- [ ] 更新致谢中的基金号(main.tex:26 标注"需更新") +- [ ] 页数核对,超页则从 supplement 迁移策略再走一轮 + +--- + +## 备注:期刊选择 —— 已定 TVT + +有实车验证,期刊选择不再是取舍项,投 TVT。 + +实车数据是本文相对同类工作最硬的一块,务必用足: +- 在 Abstract 与 Introduction 末尾**明确点出实车验证**(矿卡型号/场地规模/试验规模), + 这是 TVT 审稿人最先找的信息 +- 实车部分不要只作为"可行性演示"附在最后,应作为独立小节承担 + **跟踪可行性**(曲率连续性、`σ_max` 是否真的够用)与**吞吐量增益**两项论证 +- 详见 P2-2 的实车指标清单 diff --git a/explanation_lines_841_843.md b/explanation_lines_841_843.md new file mode 100644 index 0000000..f5bee4c --- /dev/null +++ b/explanation_lines_841_843.md @@ -0,0 +1,559 @@ +# `main.tex` 第 841--843 行详解 + +本文档解释 `eq:joint_psi_discrete` 为什么能同时影响两条路径、有限支撑核为什么会产生稀疏 Hessian,以及第 843 行所谓“块对角结构”到底是什么意思。 + +## 1. 先把决策变量拆开 + +联合优化变量写成 + +$$ +\mathbf z= +\begin{bmatrix} +\mathbf z_{\mathrm{park}}\\ +\mathbf z_{\mathrm{exit}} +\end{bmatrix}. +$$ + +其中,$\mathbf z_{\mathrm{park}}$ 包含泊入路径的全部配置点状态、区间控制量和弧长步长,$\mathbf z_{\mathrm{exit}}$ 同理。每条路径的变量维数为 + +$$ +n_{\mathrm{park}}=5M_{\mathrm{park}}, +\qquad +n_{\mathrm{exit}}=5M_{\mathrm{exit}}, +$$ + +所以 $\mathbf z\in\mathbb R^{n_z}$,其中 + +$$ +n_z=n_{\mathrm{park}}+n_{\mathrm{exit}}. +$$ + +这里的 $5M_\bullet$ 来自 $M_\bullet$ 个四维状态、$M_\bullet-1$ 个控制量以及一个弧长步长。 + +第 $i$ 个泊入路径位置是 + +$$ +\mathbf p_i^{\mathrm{park}} += +\begin{bmatrix}x_i^{\mathrm{park}}\\y_i^{\mathrm{park}}\end{bmatrix}, +$$ + +它只是 $\mathbf z_{\mathrm{park}}$ 中第 $i$ 个状态的位置分量,并不是额外的决策变量。定义状态到位置的选择矩阵 + +$$ +\mathbf S_p= +\begin{bmatrix} +1&0&0&0\\ +0&1&0&0 +\end{bmatrix}. +$$ + +再定义作用于整个联合变量 $\mathbf z$ 的常数选择矩阵 + +$$ +\mathbf E_i^{\mathrm{park}}\in\mathbb R^{2\times n_z}, +\qquad +\mathbf E_j^{\mathrm{exit}}\in\mathbb R^{2\times n_z}. +$$ + +$\mathbf E_i^{\mathrm{park}}$ 在泊入路径第 $i$ 个四维状态对应的列上放置 $\mathbf S_p$,其余元素均为零;$\mathbf E_j^{\mathrm{exit}}$ 在驶离路径第 $j$ 个四维状态对应的列上放置 $\mathbf S_p$,其余元素均为零。因此 + +$$ +\boxed{ +\mathbf p_i^{\mathrm{park}} +=\mathbf E_i^{\mathrm{park}}\mathbf z, +\qquad +\mathbf p_j^{\mathrm{exit}} +=\mathbf E_j^{\mathrm{exit}}\mathbf z.} +$$ + +若用从 1 开始的元素下标表示,则 $\mathbf E_i^{\mathrm{park}}$ 选取 $\mathbf z$ 的第 $4(i-1)+1$、$4(i-1)+2$ 个元素;$\mathbf E_j^{\mathrm{exit}}$ 选取第 + +$$ +n_{\mathrm{park}}+4(j-1)+1, +\qquad +n_{\mathrm{park}}+4(j-1)+2 +$$ + +个元素。 + +因此,只要目标函数同时包含 $\mathbf p_i^{\mathrm{park}}$ 和 $\mathbf p_j^{\mathrm{exit}}$,它就是整个 $\mathbf z$ 的函数。 + +## 2. 将交互项显式写成 $\mathbf z$ 的函数 + +为简化记号,定义点对选择矩阵 + +$$ +\mathbf D_{ij} +=\mathbf E_i^{\mathrm{park}}-\mathbf E_j^{\mathrm{exit}} +\in\mathbb R^{2\times n_z}. +$$ + +于是两个配置点的相对位置和距离分别为 + +$$ +\mathbf r_{ij}(\mathbf z) +=\mathbf p_i^{\mathrm{park}}-\mathbf p_j^{\mathrm{exit}} +=\mathbf D_{ij}\mathbf z, +$$ + +$$ +d_{ij}(\mathbf z) +=\|\mathbf D_{ij}\mathbf z\|. +$$ + +正文实现将两个弧长步长冻结为粗解给出的常数。记 + +$$ +c_0=\frac{w_\varPsi}{v_0} +\Delta s_{\mathrm{park}}^{(0)} +\Delta s_{\mathrm{exit}}^{(0)}, +$$ + +其中上标 $(0)$ 表示粗解值。离散交互项便可以显式写成 + +$$ +\boxed{ +J_\varPsi(\mathbf z) +=c_0\sum_{i=1}^{M_{\mathrm{park}}} +\sum_{j=1}^{M_{\mathrm{exit}}} +K\!\left( +\|\mathbf D_{ij}\mathbf z\|; +\rho_\varPsi,m_\varPsi +\right).} +$$ + +把核函数的分段定义代入后,还可以完全展开为 + +$$ +J_\varPsi(\mathbf z) +=c_0\sum_{i=1}^{M_{\mathrm{park}}} +\sum_{j=1}^{M_{\mathrm{exit}}} +\begin{cases} +\displaystyle +\left( +1-\frac{\|\mathbf D_{ij}\mathbf z\|}{\rho_\varPsi} +\right)^{m_\varPsi}, +& \|\mathbf D_{ij}\mathbf z\|<\rho_\varPsi,\\[8pt] +0, +& \|\mathbf D_{ij}\mathbf z\|\geq\rho_\varPsi. +\end{cases} +$$ + +至此,表达式右侧只剩下决策变量 $\mathbf z$、常数选择矩阵 $\mathbf D_{ij}$ 以及固定参数,不再把 $\mathbf p_i^{\mathrm{park}}$ 和 $\mathbf p_j^{\mathrm{exit}}$ 当成独立符号。这里使用 $\mathbf D_{ij}$ 而不使用 $\mathbf A_{ij}$,是为了避免和正文凸走廊约束中的 $\mathbf A_k$ 混淆。 + +对于每个点对 $(i,j)$,定义 + +$$ +\mathbf r_{ij}(\mathbf z) +=\mathbf D_{ij}\mathbf z, +\qquad +d_{ij}(\mathbf z)=\|\mathbf D_{ij}\mathbf z\|. +$$ + +当 $00$;当两个点精确重合时,$\|\mathbf r_{ij}\|$ 在零点没有唯一梯度,需要使用平滑距离或在实现中单独处理该点对。 + +直接对联合变量 $\mathbf z$ 求导,则一个有效点对的梯度为 + +$$ +\nabla_{\mathbf z} +K\!\left(\|\mathbf D_{ij}\mathbf z\|\right) +=K'(d_{ij}) +\frac{\mathbf D_{ij}^{\mathsf T}\mathbf D_{ij}\mathbf z}{d_{ij}}. +$$ + +定义当前有限支撑域内的有效点对集合 + +$$ +\mathcal I(\mathbf z)= +\left\{(i,j)\ \middle|\ +0<\|\mathbf D_{ij}\mathbf z\|<\rho_\varPsi +\right\}, +$$ + +便得到完整交互项关于联合决策变量的梯度: + +$$ +\boxed{ +\nabla_{\mathbf z}J_\varPsi(\mathbf z) +=c_0\sum_{(i,j)\in\mathcal I(\mathbf z)} +K'\!\left(\|\mathbf D_{ij}\mathbf z\|\right) +\frac{\mathbf D_{ij}^{\mathsf T}\mathbf D_{ij}\mathbf z} +{\|\mathbf D_{ij}\mathbf z\|}.} +$$ + +由于 + +$$ +\mathbf D_{ij} +=\mathbf E_i^{\mathrm{park}}-\mathbf E_j^{\mathrm{exit}}, +$$ + +$\mathbf D_{ij}^{\mathsf T}$ 会把同一个二维点对梯度以相反符号写回 $\mathbf z_{\mathrm{park}}$ 和 $\mathbf z_{\mathrm{exit}}$ 对应的位置分量。这就是 $J_\varPsi(\mathbf z)$ 在一次联合求解中同时更新两条路径的代数原因。 + +两个梯度大小相等、方向相反。因为 $K'(d)<0$,梯度下降时: + +- 泊入点 $\mathbf p_i^{\mathrm{park}}$ 沿远离驶离点的方向移动; +- 驶离点 $\mathbf p_j^{\mathrm{exit}}$ 沿远离泊入点的方向移动。 + +这就是第 841 行所说的“两条路径可在同一次求解中相互推离”。它并不是先固定一条路径再移动另一条,而是同一个目标函数对两组决策变量同时提供梯度。 + +需要注意,梯度形式是对称的,不代表最终位移一定相等。两条路径还分别受到引导场、长度、平滑性和走廊约束的作用;哪条路径更容易移动,取决于这些项共同形成的“刚度”。 + +## 4. Hessian 的“跨路径耦合块”是什么 + +将联合变量按两条路径分块后,目标函数 Hessian 的结构可以概念性地写成 + +$$ +\nabla^2_{\mathbf z\mathbf z}J= +\begin{bmatrix} +H_{\mathrm{pp}} & H_{\mathrm{pe}}\\ +H_{\mathrm{ep}} & H_{\mathrm{ee}} +\end{bmatrix}. +$$ + +这里: + +- $H_{\mathrm{pp}}$ 描述泊入变量之间的二阶关系; +- $H_{\mathrm{ee}}$ 描述驶离变量之间的二阶关系; +- $H_{\mathrm{pe}}$ 和 $H_{\mathrm{ep}}$ 描述泊入变量与驶离变量之间的二阶关系,称为跨路径耦合块。 + +若目标函数可以完全分离为 + +$$ +J(\mathbf z)=J_{\mathrm{park}}(\mathbf z_{\mathrm{park}}) ++J_{\mathrm{exit}}(\mathbf z_{\mathrm{exit}}), +$$ + +那么 + +$$ +H_{\mathrm{pe}}=H_{\mathrm{ep}}=0, +$$ + +整个 Hessian 按两条路径呈块对角结构。加入 $J_\varPsi$ 后,一个核项同时依赖 $\mathbf p_i^{\mathrm{park}}$ 和 $\mathbf p_j^{\mathrm{exit}}$,所以相应的跨路径二阶导数一般不为零。 + +对于单个点对,可以把它的 Hessian 贡献写成 + +$$ +\begin{bmatrix} +G_{ij} & -G_{ij}\\ +-G_{ij} & G_{ij} +\end{bmatrix}, +$$ + +其中 $G_{ij}$ 是关于二维相对位置 $\mathbf r_{ij}$ 的 $2\times2$ 二阶导数矩阵。非对角位置的 $-G_{ij}$ 正是该点对造成的跨路径耦合。 + +## 5. 为什么有限支撑核会让跨路径块稀疏 + +核函数满足 + +$$ +K(d)=0,\qquad d\geq\rho_\varPsi. +$$ + +在严格满足 $d_{ij}>\rho_\varPsi$ 的区域内,$K(d_{ij})$ 是常数零,因此它的梯度和 Hessian 也都是零。于是: + +- 若点对 $(i,j)$ 的距离小于 $\rho_\varPsi$,它在跨路径块中产生非零项; +- 若点对 $(i,j)$ 的距离大于 $\rho_\varPsi$,它不产生任何导数项。 + +例如,两条路径各有 4 个点,理论上共有 $4\times4=16$ 个点对。假设只有 + +$$ +(1,1),\ (2,2),\ (2,3),\ (3,3),\ (4,4) +$$ + +这 5 对点的距离小于作用半径,那么跨路径块中只有与这 5 对点有关的位置非零,其余 11 对均为零。这就是第 841 行所说的“并非稠密的 $M_{\mathrm{park}}\times M_{\mathrm{exit}}$ 块”。 + +这里的 $M_{\mathrm{park}}\times M_{\mathrm{exit}}$ 是按“配置点对”描述的概念尺寸。由于每个位置点有 $x,y$ 两个分量,实际位置 Hessian 的跨路径块尺寸是 + +$$ +2M_{\mathrm{park}}\times2M_{\mathrm{exit}}, +$$ + +每个有效点对通常对应一个 $2\times2$ 小块。 + +## 6. “其余部分均为块对角结构”是什么意思 + +第 843 行的“块对角”是按两条路径分成两个大块而言,并不是说单条路径内部的矩阵是对角矩阵。 + +### 6.1 单条路径内部仍然存在耦合 + +配置约束 + +$$ +\mathbf x_{k+1}=\mathbf x_k+ +\frac{\Delta s}{2} +\left[\mathbf f(\mathbf x_k,\sigma_k) ++\mathbf f(\mathbf x_{k+1},\sigma_k)\right] +$$ + +同时依赖 $\mathbf x_k$、$\mathbf x_{k+1}$ 和 $\sigma_k$。所以,单条路径内部相邻配置点之间存在耦合,其 Jacobian/Hessian 通常是带状矩阵,而不是对角矩阵。 + +### 6.2 但这些约束不连接两条路径 + +泊入路径的配置约束只包含 $\mathbf z_{\mathrm{park}}$,驶离路径的配置约束只包含 $\mathbf z_{\mathrm{exit}}$。因此按两条路径分块后,约束 Jacobian 具有如下形式: + +$$ +J_{\mathrm{independent}}= +\begin{bmatrix} +B_{\mathrm{park}}&0\\ +0&B_{\mathrm{exit}} +\end{bmatrix}. +$$ + +其中 $B_{\mathrm{park}}$、$B_{\mathrm{exit}}$ 内部可以是带状的,并不要求是对角的。 + +同样地: + +- 曲率与曲率变化率上界只约束各自路径; +- 泊入走廊约束只作用于泊入路径; +- 驶离走廊约束只作用于驶离路径; +- $J_\ell$、$J_U$ 和 $J_\kappa$ 都可以分别写成泊入部分与驶离部分之和。 + +所以,在不考虑 $J_\varPsi$ 时,两条路径的数值结构基本可以分开处理。 + +## 7. 关于装载位约束的一处重要问题 + +第 843 行称:“唯一的另一处跨路径耦合来自装载位处共享同一位姿”。结合当前论文第 335--347 行的定义,这句话并不严格准确。 + +当前边界条件写成 + +$$ +\boldsymbol\eta^{\mathrm{park}}(s_{\mathrm{park}}) +=\boldsymbol\eta_{\mathrm{load}}, +$$ + +$$ +\boldsymbol\eta^{\mathrm{exit}}(0) +=\boldsymbol\eta_{\mathrm{load}}, +$$ + +而正文明确说明 $\boldsymbol\eta_{\mathrm{load}}$ 是由上层系统给出的固定值。若它确实是常量,那么这只是两组分别等于同一常量的边界约束: + +$$ +h_{\mathrm{park}}(\mathbf z_{\mathrm{park}})=0, +\qquad +h_{\mathrm{exit}}(\mathbf z_{\mathrm{exit}})=0. +$$ + +第一组不含 $\mathbf z_{\mathrm{exit}}$,第二组不含 $\mathbf z_{\mathrm{park}}$,所以它们不会在 Jacobian 或 Hessian 中产生跨路径非零块。两条路径在几何上共享同一个已知端点,但在导数结构上没有直接耦合。 + +在当前问题定义下,固定的 $\boldsymbol\eta_{\mathrm{load}}$ 不会形成跨路径导数耦合。只有在另外重新定义约束时,才可能形成真正的跨路径约束,例如: + +1. 直接施加 + + $$ + \boldsymbol\eta^{\mathrm{park}}(s_{\mathrm{park}}) + -\boldsymbol\eta^{\mathrm{exit}}(0)=0; + $$ + +2. 由上层模型额外引入一个待优化的共享位姿变量,并让两条路径的边界条件同时依赖该变量。这个做法已经改变了当前论文中“装载位姿由上层系统给定”的问题定义。 + +因此,按照论文当前“装载位姿固定”的问题定义,真正的跨路径导数耦合只来自 $J_\varPsi$。第 843 行建议相应修改。 + +## 8. 可微性表述还需要哪些条件 + +第 841 行称 $J_\varPsi$ 对 $\mathbf z$ 整体可微,这需要附加条件: + +- 当两个路径点完全重合,即 $d_{ij}=0$ 时,欧氏范数 $\|\mathbf r_{ij}\|$ 的梯度没有唯一方向;当前核函数在 $d=0$ 处的径向导数通常又不为零,因此复合函数在重合点处不可微。 +- 在截断点 $d=\rho_\varPsi$ 处,若 $m_\varPsi>1$,一阶导数可连续衔接到零;若还希望二阶导数连续,通常需要 $m_\varPsi>2$。 + +这不一定造成实际求解失败,因为车辆路径点通常不会精确重合,且参数可以选择足够高的 $m_\varPsi$。但论文若要声称“整体可微”,最好明确参数条件,并对 $d=0$ 使用平滑距离,例如 + +$$ +d_\varepsilon=\sqrt{\|\mathbf r\|^2+\varepsilon^2}. +$$ + +## 9. 用一句话重新理解第 841--843 行 + +这几行的核心意思是: + +> 大部分目标项和约束都只在各自路径内部产生带状导数结构;交互项 $J_\varPsi$ 同时依赖两条路径,因此能在一次 NLP 求解中推动双方分离。由于核函数只作用于距离小于 $\rho_\varPsi$ 的点对,交互项产生的跨路径 Hessian 块通常是稀疏的。 + +按照当前“装载位姿为固定常量”的定义,不应再把装载位边界条件称为跨路径导数耦合。 + +## 10. 建议替换原文的表述 + +可以将第 841--843 行改写为: + +> 式 (joint\_psi\_discrete) 同时依赖泊入与驶离路径的位置变量,故其关于两组变量的梯度均非零,两条路径可在同一次求解中相互推离。由有限支撑核的定义,仅当配置点对的距离小于 $\rho_\varPsi$ 时,该点对才对梯度及 Hessian 产生贡献;因此,交互项所形成的跨路径 Hessian 块仅在空间上相近的配置点对处非零。除 $J_\varPsi$ 外,其余目标项与约束均只作用于单条路径内部:配置约束在各自路径内耦合相邻配置点,形成带状结构;物理上界及走廊约束也不连接两条路径。由于 $\boldsymbol\eta_\mathrm{load}$ 是给定常量,两条路径分别等于该位姿的边界条件不产生跨路径导数耦合。因此,联合问题仅通过稀疏的 $J_\varPsi$ 块发生跨路径耦合。 diff --git a/figs/__pycache__/sitegeom.cpython-313.pyc b/figs/__pycache__/sitegeom.cpython-313.pyc new file mode 100644 index 0000000..47c845e Binary files /dev/null and b/figs/__pycache__/sitegeom.cpython-313.pyc differ diff --git a/figs/calc_convex.py b/figs/calc_convex.py new file mode 100644 index 0000000..5023cb7 --- /dev/null +++ b/figs/calc_convex.py @@ -0,0 +1,176 @@ +#!/usr/bin/env python3 +"""Compute exact coordinates for the convex-decomposition schematic. + +Follows supplement.tex S-IV verbatim: + + eq:sup_ellipsoid_quadratic E = { p | (p-d)^T (C C^T)^{-1} (p-d) <= 1 }, + o_i not in int(E) + eq:sup_halfspace_normal atil_i = (C C^T)^{-1} (o_i - d), a_i = atil/|atil|, + b_i = a_i^T o_i + +Construction: d is the segment midpoint, the major axis is the segment +direction with semi-axis equal to the segment half-length, and the minor +semi-axis is shrunk until the boundary first touches an obstacle point. +Redundant obstacles are pruned greedily: after each half-space is emitted, +every obstacle it already excludes is dropped. + +Prints TikZ-ready numbers; nothing is drawn here. +""" +import numpy as np + +# --- segment (figure units = cm in the TikZ picture) ------------------------ +P0 = np.array([0.0, 0.0]) +P1 = np.array([5.2, 0.0]) +D = 0.5 * (P0 + P1) +A_AX = 0.5 * np.linalg.norm(P1 - P0) # semi-major, along the segment + +# --- obstacle points (site-boundary / ore-pile samples) -------------------- +OBST = np.array([ + [0.30, 1.42], [1.35, 1.05], [2.55, 1.28], [3.75, 1.62], [4.85, 1.35], + [0.65, -1.30], [1.90, -1.62], [3.10, -1.12], [4.35, -1.45], [5.35, -1.02], + [-0.55, 0.85], [5.75, 0.62], + # points beyond the segment ends: they do not constrain the minor axis + # (|u| > 1) but they do cap the polytope longitudinally + [-1.05, 0.12], [6.35, -0.18], +]) + + +def main(): + # ---- minor semi-axis: shrink until the boundary touches an obstacle ---- + u = (OBST[:, 0] - D[0]) / A_AX + live = np.abs(u) < 1.0 - 1e-9 + b_req = np.abs(OBST[live, 1]) / np.sqrt(1.0 - u[live] ** 2) + B_AX = float(b_req.min()) + touch = int(np.nonzero(live)[0][int(np.argmin(b_req))]) + print("semi-axes: a = %.4f, b = %.4f center d = (%.3f, %.3f)" + % (A_AX, B_AX, D[0], D[1])) + print("touching obstacle index %d at (%.3f, %.3f)" + % (touch, OBST[touch, 0], OBST[touch, 1])) + + C = np.diag([A_AX, B_AX]) + Minv = np.linalg.inv(C @ C.T) + + def qform(P): + dv = P - D + return np.einsum("ij,jk,ik->i", dv, Minv, dv) + + q = qform(OBST) + print("min obstacle quadratic form = %.6f (must be >= 1)" % q.min()) + assert q.min() >= 1.0 - 1e-9, "eq:sup_ellipsoid_quadratic violated" + # the segment must lie inside the ellipsoid + seg = P0 + np.linspace(0, 1, 201)[:, None] * (P1 - P0) + print("max segment quadratic form = %.6f (must be <= 1)" % qform(seg).max()) + assert qform(seg).max() <= 1.0 + 1e-9 + + # ---- greedy half-space generation with redundancy pruning -------------- + remaining = list(range(len(OBST))) + planes = [] + while remaining: + # process the obstacle closest in the ellipsoid metric first + qi = qform(OBST[remaining]) + k = remaining[int(np.argmin(qi))] + o = OBST[k] + at = Minv @ (o - D) + a = at / np.linalg.norm(at) + b = float(a @ o) + planes.append((k, a, b)) + # the ellipsoid (hence the segment) must be on the safe side + sup = float(a @ D + np.sqrt((a @ (C @ C.T)) @ a)) + assert sup <= b + 1e-9, "ellipsoid crosses the half-space" + remaining = [j for j in remaining if float(a @ OBST[j]) < b - 1e-9] + + print("\n%d half-spaces retained out of %d obstacles" + % (len(planes), len(OBST))) + for k, a, b in planes: + print(" o_%-2d (%6.3f,%6.3f) a = (%7.4f,%7.4f) b = %7.4f" + % (k, OBST[k, 0], OBST[k, 1], a[0], a[1], b)) + + # ---- polytope vertices, for drawing ------------------------------------ + A = np.array([p[1] for p in planes]) + bb = np.array([p[2] for p in planes]) + verts = [] + for i in range(len(planes)): + for j in range(i + 1, len(planes)): + M = np.array([A[i], A[j]]) + if abs(np.linalg.det(M)) < 1e-9: + continue + v = np.linalg.solve(M, [bb[i], bb[j]]) + if np.all(A @ v <= bb + 1e-7): + verts.append(v) + V = np.array(verts) + ctr = V.mean(axis=0) + V = V[np.argsort(np.arctan2(V[:, 1] - ctr[1], V[:, 0] - ctr[0]))] + print("\npolytope P: %d vertices" % len(V)) + print(" tikz path: " + " -- ".join("(%.3f,%.3f)" % (x, y) for x, y in V) + + " -- cycle") + + # ---- ellipse as a TikZ primitive --------------------------------------- + print("\n tikz ellipse: (%.3f,%.3f) ellipse [x radius=%.4f, " + "y radius=%.4f]" % (D[0], D[1], A_AX, B_AX)) + print(" tikz obstacles: " + " ".join("(%.2f,%.2f)" % (x, y) + for x, y in OBST)) + kept = " ".join("o%d" % p[0] for p in planes) + print(" retained: " + kept) + + # ---- support points: where each half-space touches the ellipsoid ------- + # The boundary point whose outward normal is parallel to a_i is + # p = d + (C C^T) a / sqrt(a^T (C C^T) a). + M = C @ C.T + print("\n ellipsoid support points (tangency anchors of a_i):") + for k, a, b in planes: + p = D + (M @ a) / np.sqrt(a @ M @ a) + assert abs(qform(p[None, :])[0] - 1.0) < 1e-9, "anchor off the boundary" + print(" o_%-2d: anchor (%.3f,%.3f) gap to o_i = %.3f" + % (k, p[0], p[1], float(a @ OBST[k]) - float(a @ p))) + + # ---- pruned (redundant) obstacles, drawn hollow in the figure ---------- + kept_idx = {p[0] for p in planes} + pruned = [i for i in range(len(OBST)) if i not in kept_idx] + print("\n pruned as redundant: " + + " ".join("(%.2f,%.2f)" % (OBST[i, 0], OBST[i, 1]) for i in pruned)) + print(" retained points: " + + " ".join("(%.2f,%.2f)" % (OBST[p[0], 0], OBST[p[0], 1]) + for p in planes)) + + # ---- initial sphere before the minor-axis shrink ------------------------ + inside_sphere = [i for i in range(len(OBST)) + if np.linalg.norm(OBST[i] - D) < A_AX] + print("\n initial sphere radius %.3f encloses %d obstacle(s)" + % (A_AX, len(inside_sphere))) + + # ---- ready-to-paste TikZ for the half-space boundaries ----------------- + # Each line a^T p = b is drawn through a*b along t = (-a_y, a_x) and left + # for the picture's own \clip to trim. + print("\n TikZ half-space boundaries (draw long, clip in the picture):") + for k, a, b in planes: + p_on = a * b + t = np.array([-a[1], a[0]]) + q0, q1 = p_on - 9.0 * t, p_on + 9.0 * t + print(" \\draw[hsp] (%.3f,%.3f) -- (%.3f,%.3f); %% o_%d" + % (q0[0], q0[1], q1[0], q1[1], k)) + + # ---- half-space boundary segments clipped to the drawing box ---------- + print("\n half-space boundary lines (clipped to x in [-1.2, 6.4]):") + for k, a, b in planes: + # parameterize the line a^T p = b + t = np.array([-a[1], a[0]]) + p_on = a * b # closest point of the line to the origin + ts = [] + for xlim in (-1.2, 6.4): + if abs(t[0]) > 1e-9: + ts.append((xlim - p_on[0]) / t[0]) + for ylim in (-2.3, 2.3): + if abs(t[1]) > 1e-9: + ts.append((ylim - p_on[1]) / t[1]) + pts = [p_on + tv * t for tv in ts] + pts = [p for p in pts + if -1.2 - 1e-6 <= p[0] <= 6.4 + 1e-6 + and -2.3 - 1e-6 <= p[1] <= 2.3 + 1e-6] + if len(pts) >= 2: + pts = sorted(pts, key=lambda p: (p[0], p[1])) + print(" o_%-2d: (%.3f,%.3f) -- (%.3f,%.3f)" + % (k, pts[0][0], pts[0][1], pts[-1][0], pts[-1][1])) + + +if __name__ == "__main__": + main() diff --git a/figs/fig_bicycle.pdf b/figs/fig_bicycle.pdf new file mode 100644 index 0000000..8f92428 Binary files /dev/null and b/figs/fig_bicycle.pdf differ diff --git a/figs/fig_bicycle.tex b/figs/fig_bicycle.tex new file mode 100644 index 0000000..9cd7797 --- /dev/null +++ b/figs/fig_bicycle.tex @@ -0,0 +1,79 @@ +% Kinematic bicycle model and geometric parameters of the mining truck. +% Drawn to scale in metres with L_v = 12, B_v = 3, L_w = 6.5, rear overhang 1.5, +% steering at psi_max = arctan(L_w / R_min) so that the ICR sits at R_min = 12 m. +\documentclass[border=1pt]{standalone} +\input{figstyle} +\begin{document} +\begin{tikzpicture}[scale=0.53] + + % ---------- global frame ------------------------------------------------ + \draw[->, thin@] (-4.8,-2.8) -- (-2.6,-2.8) node[ann, right] {$x$}; + \draw[->, thin@] (-4.8,-2.8) -- (-4.8,-0.6) node[ann, above] {$y$}; + + % horizontal reference through the rear-axle centre, for the heading angle + \draw[thin@, sitec, dash pattern=on 1.6pt off 1.2pt] (0,0) -- (5.6,0); + \draw[thin@] (4.2,0) arc[start angle=0, end angle=18, radius=4.2]; + \node[ann] at (5.05,0.72) {$\theta$}; + + \begin{scope}[rotate=18] + + % ---------- vehicle body --------------------------------------------- + \draw[veh, sitec, fill=fillc, fill opacity=0.6] + (-1.5,-1.5) rectangle (10.5,1.5); + \draw[thin@, sitec, dash pattern=on 1.4pt off 1pt] (-1.5,0) -- (11.6,0); + + % ---------- wheels ---------------------------------------------------- + % rear wheels, aligned with the body + \foreach \sy in {-1.5,1.5}{ + \draw[veh, fill=sitec] (-0.9,\sy-0.22) rectangle (0.9,\sy+0.22); + } + % front wheels, steered by psi_max = 28 deg + \foreach \sy in {-1.5,1.5}{ + \begin{scope}[shift={(6.5,\sy)}, rotate=28] + \draw[veh, fill=parkc, fill opacity=0.85] + (-0.9,-0.22) rectangle (0.9,0.22); + \end{scope} + } + + % ---------- steering angle ------------------------------------------- + \draw[thin@, parkc] (6.5,0) -- ++(28:3.1); + \draw[thin@] (8.7,0) arc[start angle=0, end angle=28, radius=2.2]; + \node[ann] at (9.35,0.66) {$\psi$}; + \node[annt, parkc] at (9.9,1.95) {$\dot\psi$}; + \draw[->, thin@, parkc] (9.05,1.55) arc[start angle=32, end angle=52, + radius=3.0]; + + % ---------- instantaneous centre of rotation -------------------------- + \draw[thin@, sitec, dash pattern=on 1.6pt off 1.2pt] (0,0) -- (0,12.2); + \draw[thin@, sitec, dash pattern=on 1.6pt off 1.2pt] (6.5,0) -- (0,12.2); + \fill[sitec] (0,12.2) circle (0.22); + \node[ann, above] at (0,12.45) {ICR}; + \node[ann, left] at (-0.25,7.0) {$R_\text{min}=1/\kappa_\text{max}$}; + + % ---------- rear-axle centre = path reference point ------------------- + \fill[parkc] (0,0) circle (0.26); + \node[ann, parkc] at (-2.35,-1.05) + {$\mathbf{p}=[x,y]^\top$}; + + % ---------- dimensions ----------------------------------------------- + % wheelbase + \draw[dimline] (0,-0.75) -- (6.5,-0.75); + \node[annt, fill=fillc, inner sep=0.4pt] at (3.25,-0.75) {$L_\text{w}$}; + % overall length + \draw[dimline] (-1.5,-2.55) -- (10.5,-2.55); + \node[annt, fill=white, inner sep=0.4pt] at (4.5,-2.55) {$L_\text{v}$}; + \draw[thin@] (-1.5,-1.6) -- (-1.5,-2.75); + \draw[thin@] (10.5,-1.6) -- (10.5,-2.75); + % width + \draw[dimline] (-2.9,-1.5) -- (-2.9,1.5); + \node[annt, rotate=90, fill=white, inner sep=0.4pt] + at (-2.9,0) {$B_\text{v}$}; + \draw[thin@] (-1.65,-1.5) -- (-3.1,-1.5); + \draw[thin@] (-1.65,1.5) -- (-3.1,1.5); + + % swept rectangle annotation + \node[annt, sitec] at (7.4,-0.95) {$\mathcal{V}(\boldsymbol{\eta})$}; + + \end{scope} +\end{tikzpicture} +\end{document} diff --git a/figs/fig_center.pdf b/figs/fig_center.pdf new file mode 100644 index 0000000..5761867 Binary files /dev/null and b/figs/fig_center.pdf differ diff --git a/figs/fig_conflict.pdf b/figs/fig_conflict.pdf new file mode 100644 index 0000000..83bf566 Binary files /dev/null and b/figs/fig_conflict.pdf differ diff --git a/figs/fig_conflict.tex b/figs/fig_conflict.tex new file mode 100644 index 0000000..f933b6c --- /dev/null +++ b/figs/fig_conflict.tex @@ -0,0 +1,118 @@ +% Spatiotemporal conflict and its resolution by spatial decoupling. +% (a)(c) coupled single-channel paths -> the empty truck must wait; +% (b)(d) decoupled dual-channel paths -> both maneuvers proceed in parallel. +\documentclass[border=1pt]{standalone} +\input{figstyle} +\begin{document} +\begin{tikzpicture}[scale=0.0872] + + % ====================================================================== + % geometry shared by the two spatial panels + % ====================================================================== + \def\sitebnd{ + (2,6) -- (14,3.5) -- (30,3) -- (40,6) -- (45,13) -- (41,22) + -- (28,25) -- (14,22) -- (2,17) + } + % channel spine from the entrance to the loading bay + \def\spine{(2,11.5) .. controls (14,10.5) and (24,11.5) .. (34,15.5)} + + % ---------------------------------------------------------------- panel a + \begin{scope}[shift={(0,0)}] + \fill[fillc, opacity=0.55] \sitebnd -- cycle; + \fill[white] \sitebnd -- cycle; + \draw[siteline] \sitebnd; + + % conflict zone: both paths occupy the same channel + \fill[confc, opacity=0.16] + (4,8.6) .. controls (14,7.6) and (24,8.6) .. (33,12.6) + -- (35,18.4) .. controls (24,14.4) and (14,13.4) .. (4,14.4) -- cycle; + + % the two paths coincide on the spine + \draw[parkpath] \spine; + \draw[exitpath, dash pattern=on 2.4pt off 1.6pt] + (34,15.5) .. controls (24,11.5) and (14,10.5) .. (2,11.5); + + % loading pose + \fill[sitec] (34,15.5) circle (0.7); + \node[annt, sitec, above right] at (34.2,15.9) {$\boldsymbol{\eta}_\text{load}$}; + + \node[annt, confc] at (18,17.4) {conflict zone}; + \node[panel] at (23.5,-1.8) {(a) coupled}; + \end{scope} + + % ---------------------------------------------------------------- panel b + \begin{scope}[shift={(52,0)}] + \fill[fillc, opacity=0.55] \sitebnd -- cycle; + \fill[white] \sitebnd -- cycle; + \draw[siteline] \sitebnd; + + % virtual centerline and the two offset guidance lines + \draw[ctrline] \spine; + \draw[parkpath] (2,8.6) .. controls (14,7.6) and (24,8.6) .. (33.4,13.0); + \draw[exitpath] (34.6,18.0) .. controls (24,14.4) and (14,13.4) .. (2,14.4); + + % channel width W between the two guidance lines + \draw[dimline] (16,8.0) -- (16,13.8); + \node[annt, fill=white, inner sep=0.3pt] at (16,10.9) {$W$}; + + \fill[sitec] (34,15.5) circle (0.7); + \node[annt, sitec, above right] at (34.2,15.9) {$\boldsymbol{\eta}_\text{load}$}; + \node[annt, centc] at (7.5,19.3) {$\varLambda_\text{center}$}; + \node[panel] at (23.5,-1.8) {(b) decoupled}; + \end{scope} + + % ====================================================================== + % time-line panels + % ====================================================================== + \def\tlen{40} + + % ---------------------------------------------------------------- panel c + \begin{scope}[shift={(0,-24)}] + \draw[->, thin@] (2,0) -- (2+\tlen+3,0) node[annt, right] {$t$}; + \draw[thin@] (2,0) -- (2,10.5); + + % loaded truck leaves + \fill[exitc, opacity=0.75] (4,6.2) rectangle (18,8.6); + \node[annt, white] at (11,7.4) {outbound}; + % empty truck waits, then parks + \fill[sitec, opacity=0.28] (4,2.6) rectangle (18,5.0); + \node[annt, sitec] at (11,3.8) {waiting}; + \fill[parkc, opacity=0.75] (18,2.6) rectangle (32,5.0); + \node[annt, white] at (25,3.8) {inbound}; + + % excavator idle window + \draw[decorate, decoration={brace, amplitude=1.6pt, raise=0.6pt}, + line width=0.4pt, confc] (18,1.9) -- (4,1.9); + \node[annt, confc] at (11,-1.2) {$T_\text{wait}>0$}; + + \node[annt, exitc, left] at (3.6,7.4) {L}; + \node[annt, parkc, left] at (3.6,3.8) {E}; + \node[panel] at (23.5,-5.4) {(c) coupled timing}; + \end{scope} + + % ---------------------------------------------------------------- panel d + \begin{scope}[shift={(52,-24)}] + \draw[->, thin@] (2,0) -- (2+\tlen+3,0) node[annt, right] {$t$}; + \draw[thin@] (2,0) -- (2,10.5); + + \fill[exitc, opacity=0.75] (4,6.2) rectangle (18,8.6); + \node[annt, white] at (11,7.4) {outbound}; + \fill[parkc, opacity=0.75] (4,2.6) rectangle (18,5.0); + \node[annt, white] at (11,3.8) {inbound}; + + \draw[decorate, decoration={brace, amplitude=1.6pt, raise=0.6pt}, + line width=0.4pt, corrc] (18,1.9) -- (4,1.9); + \node[annt, corrc] at (11,-1.2) {in parallel}; + + % the cycle ends earlier by the eliminated waiting time + \draw[thin@, sitec, dash pattern=on 1.4pt off 1.2pt] (32,1.9) -- (32,9.4); + \draw[dimline, confc] (18,9.8) -- (32,9.8); + \node[annt, confc, fill=white, inner sep=0.3pt] at (25,9.8) {saved}; + + \node[annt, exitc, left] at (3.6,7.4) {L}; + \node[annt, parkc, left] at (3.6,3.8) {E}; + \node[panel] at (23.5,-5.4) {(d) decoupled timing}; + \end{scope} + +\end{tikzpicture} +\end{document} diff --git a/figs/fig_convex_decomp.pdf b/figs/fig_convex_decomp.pdf new file mode 100644 index 0000000..314d46e Binary files /dev/null and b/figs/fig_convex_decomp.pdf differ diff --git a/figs/fig_convex_decomp.tex b/figs/fig_convex_decomp.tex new file mode 100644 index 0000000..37cc37a --- /dev/null +++ b/figs/fig_convex_decomp.tex @@ -0,0 +1,100 @@ +% Geometric intuition of the convex decomposition (supplement S-IV). +% All coordinates are computed by calc_convex.py from +% eq:sup_ellipsoid_quadratic and eq:sup_halfspace_normal +% and pasted here verbatim; do not hand-edit the numbers. +\documentclass[tikz,border=1pt]{standalone} +\input{figstyle} + +\tikzset{ + obst/.style={circle, fill=sitec, inner sep=0pt, minimum size=1.7pt}, + obstx/.style={circle, draw=sitec, line width=0.3pt, fill=white, + inner sep=0pt, minimum size=1.7pt}, + hsp/.style={corrc, line width=0.35pt, dash pattern=on 1.4pt off 1.0pt}, + ell/.style={parkc, line width=0.6pt}, + sph/.style={sitec, line width=0.35pt, dash pattern=on 1.0pt off 1.0pt}, + segl/.style={exitc, line width=1.0pt}, +} +\newcommand{\allobst}{% + \foreach \x/\y in {0.30/1.42, 3.75/1.62, 4.85/1.35, 1.90/-1.62, + 4.35/-1.45, 5.35/-1.02, -0.55/0.85} + {\node[obst] at (\x,\y) {};}% + \foreach \x/\y in {3.10/-1.12, 1.35/1.05, 2.55/1.28, 5.75/0.62, + 0.65/-1.30, -1.05/0.12, 6.35/-0.18} + {\node[obst] at (\x,\y) {};}% +} + +\begin{document} +\begin{tikzpicture}[scale=0.50] + +% ============================ panel (a) ================================== +\begin{scope} + \begin{scope} + \clip (-1.45,-2.80) rectangle (6.65,2.80); + % initial sphere: radius = segment half-length, before the minor-axis shrink + \draw[sph] (2.600,0) circle [radius=2.6000]; + % collision-free ellipsoid after shrinking along the minor axis + \draw[ell, fill=parkc, fill opacity=0.10] (2.600,0) + ellipse [x radius=2.6000, y radius=1.1413]; + \end{scope} + % shrink direction along the minor axis + \foreach \s in {1,-1} + {\draw[line width=0.35pt, ->, >={Latex[length=1.0mm,width=0.8mm]}] + (2.600,\s*2.45) -- (2.600,\s*1.30);} + % the path segment, fully enclosed by the ellipsoid + \draw[segl] (0,0) -- (5.200,0); + \node[obst, fill=exitc] at (0,0) {}; + \node[obst, fill=exitc] at (5.200,0) {}; + \node[obst, fill=black] at (2.600,0) {}; + \allobst + % the obstacle that stops the shrink lies exactly on the boundary + \draw[confc, line width=0.45pt] (3.100,-1.120) circle [radius=0.19]; + \node[annt, anchor=north] at (0.00,-0.10) {$\mathbf{p}_0$}; + \node[annt, anchor=north] at (5.20,-0.10) {$\mathbf{p}_1$}; + \node[annt, anchor=south west] at (2.62,0.04) {$\mathbf{d}$}; + \node[annt, parkc, anchor=south] at (2.60,1.20) {$\mathcal{E}$}; + \node[annt, confc, anchor=north west] at (3.28,-1.22) {$\mathbf{o}_i$}; + \node[annt, sitec, anchor=south east] at (4.60,1.95) {initial sphere}; + \node[panel, anchor=north] at (2.60,-2.95) {(a)}; +\end{scope} +% ============================ panel (b) ================================== +\begin{scope}[shift={(9.4,0)}] + % convex polytope P = { p | A p <= b }, 7 retained half-spaces + \fill[corrc, fill opacity=0.13] + (-1.201,-0.765) -- (0.732,-1.324) -- (6.182,-0.855) -- + (6.393,-0.009) -- (5.057,1.299) -- (2.346,1.278) -- + (-0.983,0.515) -- cycle; + \draw[corrc, line width=0.6pt] + (-1.201,-0.765) -- (0.732,-1.324) -- (6.182,-0.855) -- + (6.393,-0.009) -- (5.057,1.299) -- (2.346,1.278) -- + (-0.983,0.515) -- cycle; + \begin{scope} + \clip (-1.45,-2.80) rectangle (6.65,2.80); + % supporting half-space boundaries, tangent to the ellipsoid metric + \draw[hsp] (-8.848,-2.148) -- (9.085,-0.605); % o_7 + \draw[hsp] (8.611,2.716) -- (-8.933,-1.309); % o_1 + \draw[hsp] (8.990,1.328) -- (-9.009,1.193); % o_2 + \draw[hsp] (9.555,-3.105) -- (-3.307,9.487); % o_11 + \draw[hsp] (-8.943,1.473) -- (8.349,-3.525); % o_5 + \draw[hsp] (0.474,9.049) -- (-2.554,-8.694); % o_12 + \draw[hsp] (3.846,-10.233) -- (8.197,7.233); % o_13 + \draw[ell, dash pattern=on 1.2pt off 1.0pt] (2.600,0) + ellipse [x radius=2.6000, y radius=1.1413]; + \end{scope} + \draw[segl] (0,0) -- (5.200,0); + % retained obstacles: solid; pruned as redundant: hollow + \foreach \x/\y in {0.30/1.42, 3.75/1.62, 4.85/1.35, 1.90/-1.62, + 4.35/-1.45, 5.35/-1.02, -0.55/0.85} + {\node[obstx] at (\x,\y) {};} + \foreach \x/\y in {3.10/-1.12, 1.35/1.05, 2.55/1.28, 5.75/0.62, + 0.65/-1.30, -1.05/0.12, 6.35/-0.18} + {\node[obst] at (\x,\y) {};} + % one normal drawn from its tangency anchor to the generating obstacle + \draw[line width=0.35pt, ->, >={Latex[length=1.0mm,width=0.8mm]}] + (2.555,1.141) -- (2.55,1.28); + \node[annt, anchor=west] at (2.70,1.62) + {$\mathbf{a}_i^{\!\top}\mathbf{p}=b_i$}; + \node[annt, corrc, anchor=north east] at (6.30,-0.95) {$\mathcal{P}$}; + \node[panel, anchor=north] at (2.60,-2.95) {(b)}; +\end{scope} +\end{tikzpicture} +\end{document} diff --git a/figs/fig_framework.pdf b/figs/fig_framework.pdf new file mode 100644 index 0000000..edc5eb7 Binary files /dev/null and b/figs/fig_framework.pdf differ diff --git a/figs/fig_framework.tex b/figs/fig_framework.tex new file mode 100644 index 0000000..a99471e --- /dev/null +++ b/figs/fig_framework.tex @@ -0,0 +1,92 @@ +% Overall three-stage framework: offline field prior -> parallel coarse search +% -> joint numerical optimization. Laid out to fit one IEEE column (252 pt) +% at full size, so no scaling is applied when included. Section numbers are +% plain text so the standalone figure compiles independently of main.tex. +\documentclass[border=1pt]{standalone} +\input{figstyle} +\begin{document} +\begin{tikzpicture}[ + blk/.style={draw=sitec, line width=0.5pt, rounded corners=1.2pt, + align=center, inner sep=2.2pt, font=\tiny, + text width=23mm, minimum height=5.4mm}, + io/.style={blk, fill=fillc, text width=20mm}, + offb/.style={blk, fill=centc!10, draw=centc!70}, + parkb/.style={blk, fill=parkc!10, draw=parkc!70, text width=21mm}, + exitb/.style={blk, fill=exitc!10, draw=exitc!70, text width=21mm}, + optb/.style={blk, fill=corrc!10, draw=corrc!70, text width=52mm}, + stage/.style={draw=sitec!45, line width=0.4pt, + dash pattern=on 1.4pt off 1.2pt, rounded corners=2pt}, + lbl/.style={font=\tiny\itshape, sitec}, + ar/.style={->, line width=0.45pt, sitec, + >={Latex[length=1.3mm,width=1.0mm]}}, + note/.style={font=\tiny, sitec, align=left}, + ] + + % ===================================================================== + % Stage 1 -- offline construction of the guidance-field prior + % ===================================================================== + \node[io] (bnd) at (0,0) {site boundary point cloud}; + \node[offb] (skel) at (0,-0.98) {EVG skeleton $+$ QP smoothing + $\rightarrow \varLambda_\text{center}$}; + \node[offb] (guid) at (0,-1.96) {normal offset $\pm W/2$ + $\rightarrow \varLambda_\text{park}, + \varLambda_\text{exit}$}; + \node[offb] (fld) at (0,-3.05) {kernel superposition + $\rightarrow U_\text{park}, U_\text{exit}$ + (mirrored about $\varLambda_\text{center}$)}; + + \foreach \a/\b in {bnd/skel, skel/guid, guid/fld}{ \draw[ar] (\a) -- (\b); } + + \node[stage, fit=(bnd)(fld), inner sep=3pt] (s1) {}; + \node[lbl, above=0.8pt of s1.north] {Stage 1: offline (Sec.~III)}; + + % ===================================================================== + % Stage 2 -- two coarse paths searched independently and in parallel + % ===================================================================== + \node[parkb] (hap) at (3.72,-0.82) {field-adaptive Hybrid A* + on $U_\text{park}$}; + \node[exitb] (hax) at (3.72,-2.24) {field-adaptive Hybrid A* + on $U_\text{exit}$}; + + \node[stage, fit=(hap)(hax), inner sep=3pt] (s2) {}; + \node[lbl, above=0.8pt of s2.north, align=center] + {Stage 2: online, parallel (Sec.~IV)}; + + \draw[ar] (fld.east) -- ++(0.22,0) |- (hap.west); + \draw[ar] (fld.east) -- ++(0.22,0) |- (hax.west); + + % ===================================================================== + % Stage 3 -- joint optimization of the two coarse paths + % ===================================================================== + \node[optb] (corr) at (1.86,-4.35) + {convex corridors $\mathcal{P}_k$ from the perception snapshot + (ellipsoid proxy, inset by $\Delta_\text{cut}$)}; + \node[optb] (nlp) at (1.86,-5.45) + {joint NLP: + $\mathbf{z}=[\mathbf{z}_\text{park};\mathbf{z}_\text{exit}]$, + interaction cost $J_\varPsi$, solved by Ipopt}; + \node[io, text width=28mm] (out) at (1.86,-6.45) + {$\varGamma_\text{park}^\star,\ \varGamma_\text{exit}^\star$}; + + \node[stage, fit=(corr)(out), inner sep=3pt] (s3) {}; + \node[lbl, below=0.8pt of s3.south] + {Stage 3: joint optimization (Sec.~V)}; + + \draw[ar] (hap.east) -- ++(0.20,0) |- ([yshift=1.1mm]corr.east); + \draw[ar] (hax.south) -- ++(0,-0.30) -| ([xshift=8mm]corr.north); + \draw[ar] (corr) -- (nlp); + \draw[ar] (nlp) -- (out); + + % ---------- what each stage fixes ------------------------------------ + \node[note] at (0.30,-3.72) {\textbf{fixes} topology}; + \node[note] at (3.30,-3.00) {\textbf{fixes} $N,\{\delta_j\}$}; + \node[note] at (-0.62,-5.45) {\textbf{fixes}\\shape,\\$\kappa$ cont.}; + + % ---------- rebuild trigger ------------------------------------------- + \draw[ar, densely dotted, centc, >={Latex[length=1.3mm,width=1.0mm]}] + (out.west) -- ++(-0.42,0) |- (skel.west); + \node[font=\tiny, centc, align=center] at (-1.32,-2.55) + {rebuild only\\on boundary\\change}; + +\end{tikzpicture} +\end{document} diff --git a/figs/fig_igf.pdf b/figs/fig_igf.pdf new file mode 100644 index 0000000..a39d0ac Binary files /dev/null and b/figs/fig_igf.pdf differ diff --git a/figs/fig_probe.pdf b/figs/fig_probe.pdf new file mode 100644 index 0000000..4337f4b Binary files /dev/null and b/figs/fig_probe.pdf differ diff --git a/figs/fig_probe.tex b/figs/fig_probe.tex new file mode 100644 index 0000000..a9b7fc5 --- /dev/null +++ b/figs/fig_probe.tex @@ -0,0 +1,118 @@ +% Field-adaptive expansion step. +% (a) the six probe poses D(eta_i) reached with psi in {-psi_max, 0, +psi_max} +% and delta in {+1,-1} at the baseline step mu_0; +% (b) the resulting per-direction steps mu_j^delta after modulation. +% +% All arcs are drawn with the true geometry of the paper's numbers: +% L_w = 6.5 m, R_min = 12 m, psi_max = arctan(L_w/R_min) = 28.44 deg, +% so a constant-psi_max arc of length mu turns mu/R_min rad. +% mu_0 = 4 m -> 19.10 deg; modulated steps use +% mu = mu_0 [w_min + (w_max-w_min)(1-Utilde)], [w_min,w_max] = [0.6,1.4]. +\documentclass[border=1pt]{standalone} +\input{figstyle} +\begin{document} +\begin{tikzpicture}[ + scale=0.30, + probe/.style={line width=0.7pt}, + pnode/.style={circle, draw, line width=0.4pt, inner sep=0pt, + minimum size=1.5mm}, + lo/.style={corrc}, % low potential -> long step + hi/.style={confc}, % high potential -> short step + panel/.style={font=\footnotesize}, + ] + + % ===================================================================== + % (a) six probe poses at the baseline step mu_0 + % ===================================================================== + \begin{scope} + + % boundary that the vehicle is heading towards (source of high U) + \draw[siteline] (-7.4,7.0) -- (9.0,7.0); + \draw[pattern=north east lines, pattern color=sitec!45, draw=none] + (-7.4,7.0) rectangle (9.0,8.6); + \node[annt, sitec] at (6.2,7.9) {$\mathcal{S}_\text{e}$}; + + % current node eta_i + \fill[parkc] (0,0) circle (0.30); + \node[annt, parkc, below left] at (0.15,-0.25) {$\boldsymbol{\eta}_i$}; + \draw[->, thin@, parkc] (0,0) -- (2.1,0); + \node[annt, parkc] at (2.55,-0.55) {$\theta$}; + + % --- forward arcs (delta = +1), sweep 19.0986 deg over mu_0 = 4 m --- + % left: centre at (0, +R), arc from angle -90 to -90+19.0986 + \draw[probe, hi] (0,0) arc[start angle=-90, end angle=-70.9014, radius=12]; + % straight + \draw[probe, sitec] (0,0) -- (4,0); + % right: centre at (0, -R) + \draw[probe, sitec] (0,0) arc[start angle=90, end angle=70.9014, radius=12]; + + % --- reverse arcs (delta = -1) -------------------------------------- + \draw[probe, lo] (0,0) arc[start angle=-90, end angle=-109.0986, radius=12]; + \draw[probe, lo] (0,0) -- (-4,0); + \draw[probe, sitec] (0,0) arc[start angle=90, end angle=109.0986, radius=12]; + + % --- probe nodes (computed endpoints) ------------------------------- + \node[pnode, hi, fill=confc!25] at ( 3.927, 0.659) {}; + \node[pnode, sitec, fill=fillc] at ( 4.000, 0.000) {}; + \node[pnode, sitec, fill=fillc] at ( 3.927,-0.659) {}; + \node[pnode, lo, fill=corrc!25] at (-3.927, 0.659) {}; + \node[pnode, lo, fill=corrc!25] at (-4.000, 0.000) {}; + \node[pnode, sitec, fill=fillc] at (-3.927,-0.659) {}; + + \node[annt, hi] at (6.3,1.9) {high $U$}; + \node[annt, lo] at (-6.4,2.2) {low $U$}; + + % baseline step annotation + \draw[dimline] (0,-2.5) -- (4,-2.5); + \node[annt, fill=white, inner sep=0.3pt] at (2,-2.5) {$\mu_0$}; + + \node[annt, sitec] at (0,-4.6) + {$\psi\in\{-\psi_\text{max},0,\psi_\text{max}\},\ \delta=\pm1$}; + \node[panel] at (0,-6.6) {(a) six probes $\mathcal{D}(\boldsymbol{\eta}_i)$}; + \end{scope} + + % ===================================================================== + % (b) modulated steps -- same six directions, lengths from eq (step) + % ===================================================================== + \begin{scope}[shift={(0,-17.5)}] + + \draw[siteline] (-8.6,7.0) -- (9.0,7.0); + \draw[pattern=north east lines, pattern color=sitec!45, draw=none] + (-8.6,7.0) rectangle (9.0,8.6); + + \fill[parkc] (0,0) circle (0.30); + \node[annt, parkc, below left] at (0.15,-0.25) {$\boldsymbol{\eta}_i$}; + + % fwd-left : Utilde = 1.00 -> w = 0.60, mu = 2.400 m, sweep 11.4592 deg + \draw[probe, hi] (0,0) arc[start angle=-90, end angle=-78.5408, radius=12]; + \node[pnode, hi, fill=confc!25] at (2.383,0.238) {}; + % fwd-straight : Utilde = 0.72 -> w = 0.824, mu = 3.296 m + \draw[probe, sitec] (0,0) -- (3.296,0); + \node[pnode, sitec, fill=fillc] at (3.296,0) {}; + % fwd-right : Utilde = 0.48 -> w = 1.016, mu = 4.064 m, sweep 19.4042 + \draw[probe, sitec] (0,0) arc[start angle=90, end angle=70.5958, radius=12]; + \node[pnode, sitec, fill=fillc] at (3.988,-0.680) {}; + % rev-left : Utilde = 0.30 -> w = 1.160, mu = 4.640 m, sweep 22.1544 + \draw[probe, lo] (0,0) arc[start angle=-90, end angle=-112.1544, radius=12]; + \node[pnode, lo, fill=corrc!25] at (-4.525,0.884) {}; + % rev-straight : Utilde = 0.08 -> w = 1.336, mu = 5.344 m + \draw[probe, lo] (0,0) -- (-5.344,0); + \node[pnode, lo, fill=corrc!25] at (-5.344,0) {}; + % rev-right : Utilde = 0.00 -> w = 1.400, mu = 5.600 m, sweep 26.7380 + \draw[probe, lo] (0,0) arc[start angle=90, end angle=116.7380, radius=12]; + \node[pnode, lo, fill=corrc!25] at (-5.399,-1.283) {}; + + % shortest / longest annotations + \node[annt, hi] at (4.9,1.75) {$w_\text{min}\mu_0$}; + \draw[->, line width=0.4pt, hi] (3.7,1.35) -- (2.6,0.55); + \node[annt, lo] at (-6.9,-2.7) {$w_\text{max}\mu_0$}; + \draw[->, line width=0.4pt, lo] (-6.3,-2.15) -- (-5.4,-1.35); + + \node[annt, sitec, align=center] at (0,-4.6) + {$\mu_j^\delta=\mu_0\bigl[w_\text{min} + +(w_\text{max}-w_\text{min})(1-\tilde U_j^\delta)\bigr]$}; + \node[panel] at (0,-6.6) {(b) modulated steps}; + \end{scope} + +\end{tikzpicture} +\end{document} diff --git a/figs/fig_scenario.pdf b/figs/fig_scenario.pdf new file mode 100644 index 0000000..4cb37b8 Binary files /dev/null and b/figs/fig_scenario.pdf differ diff --git a/figs/fig_scenario.tex b/figs/fig_scenario.tex new file mode 100644 index 0000000..9aba7be --- /dev/null +++ b/figs/fig_scenario.tex @@ -0,0 +1,73 @@ +% Loading operation in an open-pit mine loading area. +% Semi-enclosed drivable region with a single entrance, an excavator working +% against the bench face, and a truck at the designated loading pose. +\documentclass[border=1pt]{standalone} +\input{figstyle} +\begin{document} +\begin{tikzpicture}[scale=0.094] + + % ---------- terrain / non-drivable surroundings ------------------------- + \begin{scope} + \clip (-3,-1) rectangle (79,44); + \fill[fillc] (-3,-1) rectangle (79,44); + \draw[pattern=north east lines, pattern color=sitec!55, draw=none] + (-3,-1) rectangle (79,44); + \end{scope} + + % ---------- drivable loading area (Omega_free) -------------------------- + \def\sitepath{ + (0,10) -- (16,6.5) -- (33,5) -- (50,6.5) -- (63,11) -- (70,19) + -- (66,30) -- (52,36) -- (36,35) -- (21,30) -- (8,24) -- (0,20) + } + \fill[white] \sitepath -- cycle; + \draw[siteline] \sitepath; + + % ---------- entrance ---------------------------------------------------- + \draw[white, line width=1.4pt] (0.2,10.4) -- (0.2,19.6); + \draw[->, line width=0.7pt, sitec] (-9,15) -- (-1.2,15); + \node[ann, sitec, align=center] at (-9,20.5) {single\\entrance}; + + % ---------- bench face / ore pile -------------------------------------- + % jagged toe line along the upper-right boundary + \draw[siteline, sitec] + (70,19) -- (72.5,22) -- (69.5,25) -- (72,28) -- (68,31) + -- (70,34) -- (65,35.5) -- (66,38.5) -- (60,38) -- (55,40); + \node[ann, sitec, align=center] at (60,25.5) {bench face\\/ ore pile}; + \node[ann, sitec] at (12,38) {$\Omega_\text{obs}$}; + \node[ann] at (20,15) {$\Omega_\text{free}$}; + + % ---------- excavator --------------------------------------------------- + \begin{scope}[shift={(57,31)}, rotate=-155] + \draw[veh, fill=sitec!35] (-3.2,-2.0) rectangle (3.2,2.0); % tracks + \draw[veh, fill=sitec!70] (-1.8,-1.5) rectangle (1.4,1.5); % house + \draw[line width=0.9pt, sitec] (1.2,0.6) -- (5.6,2.6); % boom + \draw[line width=0.9pt, sitec] (5.6,2.6) -- (7.4,-0.6); % stick + \draw[veh, fill=sitec!45] (7.4,-0.6) -- (8.9,-1.9) -- (7.4,-2.9) + -- (6.4,-1.5) -- cycle; % bucket + \end{scope} + \node[ann, sitec] at (57,36.5) {excavator}; + + % ---------- truck at the loading pose ---------------------------------- + % rear-axle centre at (44,24), heading 205 deg, L_v = 12 m, B_v = 3 m, + % rear overhang 1.5 m (body spans a in [-1.5, 10.5] in body frame) + \begin{scope}[shift={(44,24)}, rotate=205] + \draw[veh, parkc, fill=parkc!12] (-1.5,-1.5) rectangle (10.5,1.5); + \draw[veh, parkc, fill=parkc!30] (6.6,-1.5) rectangle (10.5,1.5); % cab + \foreach \sx in {0,6.5}{ + \foreach \sy in {-1.5,1.5}{ + \draw[line width=0.4pt, parkc, fill=parkc!60] + (\sx-0.9,\sy-0.28) rectangle (\sx+0.9,\sy+0.28); + } + } + \fill[parkc] (0,0) circle (0.42); + \end{scope} + \node[ann, parkc, align=center] at (34,20) + {loading pose\\$\boldsymbol{\eta}_\text{load}$}; + \draw[->, line width=0.5pt, parkc] (37.5,22.6) -- (42,23.4); + + % ---------- shared channel --------------------------------------------- + \draw[<->, line width=0.5pt, sitec] (6,14.2) -- (16.5,11.3); + \node[annt, sitec, align=center] at (12.5,7.6) {shared\\channel}; + +\end{tikzpicture} +\end{document} diff --git a/figs/figstyle.tex b/figs/figstyle.tex new file mode 100644 index 0000000..29daf41 --- /dev/null +++ b/figs/figstyle.tex @@ -0,0 +1,35 @@ +% Shared style for the standalone figures of the mine-planning paper. +% Each figure compiles on its own: pdflatex -interaction=nonstopmode fig_*.tex +% Fonts follow IEEEtran (Times) so that included figures match the body text. +\usepackage{mathptmx} +\usepackage{amsmath} +\usepackage{tikz} +\usepackage{pgfplots} +\pgfplotsset{compat=1.18} +\usetikzlibrary{arrows.meta,positioning,calc,decorations.pathreplacing, + decorations.markings,patterns,fit,shapes.geometric, + backgrounds,intersections} + +\definecolor{parkc}{RGB}{0,84,159} % inbound / parking-in path +\definecolor{exitc}{RGB}{196,78,10} % outbound / exit path +\definecolor{sitec}{RGB}{88,88,88} % site boundary, neutral linework +\definecolor{fillc}{RGB}{228,228,228} % obstacle / terrain fill +\definecolor{corrc}{RGB}{0,124,76} % convex corridor +\definecolor{centc}{RGB}{112,58,148} % virtual road centerline +\definecolor{confc}{RGB}{198,32,44} % conflict zone + +\tikzset{ + >={Latex[length=1.6mm,width=1.2mm]}, + siteline/.style={sitec, line width=0.7pt}, + parkpath/.style={parkc, line width=1.0pt}, + exitpath/.style={exitc, line width=1.0pt}, + ctrline/.style={centc, line width=0.7pt, dash pattern=on 2pt off 1.2pt}, + guide/.style={line width=0.6pt, dash pattern=on 1.6pt off 1.2pt}, + veh/.style={line width=0.5pt}, + thin@/.style={line width=0.4pt}, + ann/.style={font=\scriptsize}, + annt/.style={font=\tiny}, + dimline/.style={line width=0.4pt, <->, + >={Latex[length=1.2mm,width=0.9mm]}}, + panel/.style={font=\footnotesize}, +} diff --git a/figs/make_center.py b/figs/make_center.py new file mode 100644 index 0000000..305b192 --- /dev/null +++ b/figs/make_center.py @@ -0,0 +1,162 @@ +#!/usr/bin/env python3 +"""Build the virtual-centerline construction figure (fig_center.pdf). + +Three panels, following subsec:centerline of the paper: + + (a) clearance field of the free space (distance transform), the EVG-thin + skeleton ridge extracted from it, and the coarse A* path on the skeleton + graph from the entrance to the loading bay. + (b) the local tangent--normal rectangular corridors of + eq:local_corridor_tangent / eq:local_corridor_normal built around each + resampled reference point, and the centerline returned by the FEM-pos QP + smoother of eq:qp_problem, overlaid on the coarse path. + (c) the discrete curvature profile before and after smoothing, obtained from + the second difference ||d_i|| = ell^2 kappa_i + O(ell^4), against the + bound kappa_max = 1 / R_min imposed by eq:qp_curvature. + +Construction illustration on a synthetic site -- not an experimental result. +""" +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from matplotlib.patches import Polygon as MplPolygon, Rectangle + +import sitegeom as sg + +R_MIN = 12.0 +KAP_MAX = 1.0 / R_MIN +HALF_W = 1.6 # lateral corridor half-width used by qp_smooth +S_HALF = 0.5 # tangential corridor half-length, for illustration + + +def curvature(P): + """Discrete curvature via second differences, on P's own spacing.""" + seg = np.hypot(*np.diff(P, axis=0).T) + ell = 0.5 * (seg[:-1] + seg[1:]) + d2 = P[:-2] - 2.0 * P[1:-1] + P[2:] + kap = np.hypot(d2[:, 0], d2[:, 1]) / ell ** 2 + s = np.concatenate([[0.0], np.cumsum(seg)]) + return s[1:-1], kap + + +def main(): + g = sg.build_centerline() + xs, ys, inside, dist = g["xs"], g["ys"], g["inside"], g["dist"] + skel, raw, center = g["skel"], g["raw"], g["center"] + + coarse = sg.resample(raw, 1.0) + t_c, n_c = sg.tangent_normal(coarse) + + s_raw, k_raw = curvature(coarse) + s_sm, k_sm = curvature(center) + print("coarse |kappa| max %.4f -> R %.2f m" % (k_raw.max(), 1 / k_raw.max())) + print("smooth |kappa| max %.4f -> R %.2f m" % (k_sm.max(), 1 / k_sm.max())) + print("bound kappa_max %.4f -> R %.2f m" % (KAP_MAX, R_MIN)) + print("smoothed violates bound: %s" % bool((k_sm > KAP_MAX + 1e-9).any())) + print("coarse length %.2f m / smoothed length %.2f m" + % (np.hypot(*np.diff(coarse, axis=0).T).sum(), + np.hypot(*np.diff(center, axis=0).T).sum())) + print("max lateral deviation from coarse %.2f m" + % np.abs(((center - coarse) * n_c).sum(axis=1)).max()) + + plt.rcParams.update({ + "font.family": "serif", + "font.serif": ["Nimbus Roman", "Times New Roman", "DejaVu Serif"], + "font.size": 7, + "mathtext.fontset": "stix", + "axes.linewidth": 0.5, + "pdf.fonttype": 42, + }) + fig = plt.figure(figsize=(7.16, 1.95), constrained_layout=True) + gs = fig.add_gridspec(1, 3, width_ratios=[1.0, 1.0, 0.72]) + ax0, ax1, ax2 = (fig.add_subplot(gs[0]), fig.add_subplot(gs[1]), + fig.add_subplot(gs[2])) + + # ---- (a) clearance field, skeleton, coarse A* -------------------------- + dm = np.ma.array(dist, mask=~inside) + im = ax0.pcolormesh(xs, ys, dm, cmap="Blues", shading="auto", + rasterized=True, vmin=0.0, vmax=dist.max()) + rr, cc = np.nonzero(skel) + ax0.plot(xs[cc], ys[rr], ls="none", marker="s", ms=0.55, + color="#4A4A4A", label="EVG skeleton", zorder=3) + ax0.plot(raw[:, 0], raw[:, 1], color="#C44E0A", lw=0.9, + label=r"coarse A$^\ast$", zorder=4) + ax0.plot(*sg.ENTRANCE, marker=">", ms=3.2, color="#111111", zorder=5) + ax0.plot(*sg.LOAD_POSE, marker="o", ms=3.0, color="#111111", zorder=5) + ax0.annotate("entrance", sg.ENTRANCE, textcoords="offset points", + xytext=(3, -6), fontsize=5.6) + ax0.annotate("loading bay", sg.LOAD_POSE, textcoords="offset points", + xytext=(-13, 4), fontsize=5.6) + ax0.legend(loc="lower right", fontsize=5.2, frameon=False, + handlelength=1.4, borderaxespad=0.1, labelspacing=0.25, + markerscale=3.0) + ax0.set_title("(a) clearance field and skeleton", fontsize=6.6, pad=2) + cb = fig.colorbar(im, ax=ax0, fraction=0.040, pad=0.015) + cb.set_ticks([0.0, dist.max()]) + cb.set_ticklabels(["0", "%.0f m" % dist.max()]) + cb.ax.tick_params(labelsize=5.2, width=0.4, length=1.8) + cb.outline.set_linewidth(0.4) + + # ---- (b) local corridors and the smoothed centerline ------------------- + ax1.add_patch(MplPolygon(sg.SITE, closed=True, facecolor="#F4F4F4", + edgecolor="#585858", lw=0.7, zorder=1)) + for i in range(0, len(coarse), 3): + ang = np.degrees(np.arctan2(t_c[i, 1], t_c[i, 0])) + r = Rectangle((-S_HALF, -HALF_W), 2 * S_HALF, 2 * HALF_W, + facecolor="#BBD7EE", edgecolor="#4A87BE", + lw=0.25, alpha=0.75, zorder=2) + tr = (matplotlib.transforms.Affine2D() + .rotate_deg(ang).translate(*coarse[i]) + ax1.transData) + r.set_transform(tr) + ax1.add_patch(r) + ax1.plot(coarse[:, 0], coarse[:, 1], color="#C44E0A", lw=0.7, + ls=(0, (2.0, 1.3)), label=r"coarse A$^\ast$", zorder=4) + ax1.plot(center[:, 0], center[:, 1], color="#703A94", lw=1.2, + label=r"$\Lambda_{\mathrm{center}}$ (QP)", zorder=5) + # annotate one corridor with its four bounds + i0 = len(coarse) // 2 + p0 = coarse[i0] + ax1.annotate(r"$s_i^\pm,\ l_i^\pm$", p0, textcoords="offset points", + xytext=(6, 7), fontsize=5.8, + arrowprops=dict(arrowstyle="-", lw=0.4, color="#333333", + shrinkA=0, shrinkB=1)) + ax1.legend(loc="lower right", fontsize=5.2, frameon=False, + handlelength=1.5, borderaxespad=0.1, labelspacing=0.25) + ax1.set_title("(b) local corridors and QP smoothing", fontsize=6.6, pad=2) + + for ax in (ax0, ax1): + ax.set_aspect("equal") + ax.set_xlim(sg.SITE[:, 0].min() - 1, sg.SITE[:, 0].max() + 1) + ax.set_ylim(sg.SITE[:, 1].min() - 1, sg.SITE[:, 1].max() + 1) + ax.set_xticks([]) + ax.set_yticks([]) + for sp in ax.spines.values(): + sp.set_visible(False) + + # ---- (c) curvature profile -------------------------------------------- + ax2.plot(s_raw, k_raw, color="#C44E0A", lw=0.7, ls=(0, (2.0, 1.3)), + label=r"coarse A$^\ast$") + ax2.plot(s_sm, k_sm, color="#703A94", lw=1.0, + label=r"$\Lambda_{\mathrm{center}}$") + ax2.axhline(KAP_MAX, color="#111111", lw=0.6, ls=(0, (4.0, 1.6))) + ax2.annotate(r"$\kappa_{\max}=1/R_{\min}$", (s_sm[-1], KAP_MAX), + textcoords="offset points", xytext=(-2, 3), fontsize=5.6, + ha="right") + ax2.set_xlabel("arc length $s$ (m)", fontsize=6.2, labelpad=1.5) + ax2.set_ylabel(r"$\kappa$ (m$^{-1}$)", fontsize=6.2, labelpad=1.5) + ax2.set_title("(c) curvature profile", fontsize=6.6, pad=2) + ax2.tick_params(labelsize=5.6, width=0.4, length=2.0, pad=1.5) + ax2.set_xlim(0, max(s_raw[-1], s_sm[-1])) + ax2.set_ylim(0, max(k_raw.max(), KAP_MAX) * 1.18) + ax2.legend(loc="upper left", fontsize=5.2, frameon=False, + handlelength=1.5, borderaxespad=0.2, labelspacing=0.25) + for sp in ("top", "right"): + ax2.spines[sp].set_visible(False) + + fig.savefig("fig_center.pdf", dpi=600) + print("wrote fig_center.pdf") + + +if __name__ == "__main__": + main() diff --git a/figs/make_igf.py b/figs/make_igf.py new file mode 100644 index 0000000..cb780b5 --- /dev/null +++ b/figs/make_igf.py @@ -0,0 +1,183 @@ +#!/usr/bin/env python3 +"""Build the IGF illustration figure (fig_igf.pdf). + +Implements the paper's equations verbatim on the synthetic site of sitegeom.py: + + eq:compact_kernel K(d; rho, m) = (1 - d/rho)^m for d < rho, else 0 + eq:source_field U_S(z) = alpha_S * sum_{xi in S} K(|z-xi|; rho_S, m_S) ds_xi + eq:field_park U_park = U_e - U_p + U_x + eq:field_exit U_exit = U_e + U_p - U_x + eq:field_bounds U_g^max = 2 alpha_g rho_g / (m_g + 1) + U_e^max = alpha_e (2 rho_e / lbar_e + 1) + eq:field_normalize Uhat = (U + U_g^max) / (U_e^max + 2 U_g^max), clipped [0,1] + +For S_e the paper takes ds_xi == 1 (vertex counting); S_p and S_x are +equal-arc-length samples carrying their true line element. Both are reproduced. + +Construction illustration on a synthetic site -- not an experimental result. +""" +import numpy as np +import matplotlib +matplotlib.use("Agg") +import matplotlib.pyplot as plt +from matplotlib.patches import Polygon as MplPolygon +from matplotlib.path import Path + +import sitegeom as sg + +# Field parameters; alpha_e is set so that eq:alpha_dominance holds. +RHO_E, M_E, ALPHA_E = 8.0, 3.0, 1.00 +RHO_G, M_G, ALPHA_G = 9.0, 3.0, 0.28 +LBAR_E = 1.0 # mean boundary-vertex spacing, enters U_e^max +DS_G = 0.5 # arc-length element of the guidance-line samples +DELTA = 0.25 # field grid resolution + + +def kernel(d, rho, m): + out = np.zeros_like(d) + ins = d < rho + out[ins] = (1.0 - d[ins] / rho) ** m + return out + + +def source_field(Z, S, alpha, rho, m, ds): + U = np.zeros(Z.shape[0]) + for i in range(0, S.shape[0], 256): + blk = S[i:i + 256] + d = np.linalg.norm(Z[:, None, :] - blk[None, :, :], axis=2) + U += (kernel(d, rho, m) * ds).sum(axis=1) + return alpha * U + + +def resample_closed(poly, step): + pts = np.vstack([poly, poly[:1]]) + seg = np.diff(pts, axis=0) + L = np.hypot(seg[:, 0], seg[:, 1]) + cum = np.concatenate([[0.0], np.cumsum(L)]) + s = np.arange(0.0, cum[-1], step) + out = np.empty((s.size, 2)) + for i, si in enumerate(s): + k = min(np.searchsorted(cum, si, side="right") - 1, len(seg) - 1) + t = (si - cum[k]) / L[k] + out[i] = pts[k] + t * seg[k] + return out + + +def main(): + g = sg.build_centerline() + center, park_line, exit_line = g["center"], g["park_line"], g["exit_line"] + + # ---- source sets ------------------------------------------------------- + S_e = resample_closed(sg.SITE, LBAR_E) + S_p = sg.resample(park_line, DS_G) + S_x = sg.resample(exit_line, DS_G) + + # ---- grid -------------------------------------------------------------- + x0, x1 = sg.SITE[:, 0].min() - 1.0, sg.SITE[:, 0].max() + 1.0 + y0, y1 = sg.SITE[:, 1].min() - 1.0, sg.SITE[:, 1].max() + 1.0 + xs = np.arange(x0, x1, DELTA) + ys = np.arange(y0, y1, DELTA) + XX, YY = np.meshgrid(xs, ys) + Z = np.column_stack([XX.ravel(), YY.ravel()]) + + U_e = source_field(Z, S_e, ALPHA_E, RHO_E, M_E, 1.0) + U_p = source_field(Z, S_p, ALPHA_G, RHO_G, M_G, DS_G) + U_x = source_field(Z, S_x, ALPHA_G, RHO_G, M_G, DS_G) + + Ug_max = 2.0 * ALPHA_G * RHO_G / (M_G + 1.0) + Ue_max = ALPHA_E * (2.0 * RHO_E / LBAR_E + 1.0) + assert Ue_max > Ug_max, "eq:alpha_dominance violated" + + def norm(U): + return np.clip((U + Ug_max) / (Ue_max + 2.0 * Ug_max), 0.0, 1.0) + + Up_raw, Ux_raw = U_e - U_p + U_x, U_e + U_p - U_x + U_park = norm(Up_raw).reshape(XX.shape) + U_exit = norm(Ux_raw).reshape(XX.shape) + + inside = Path(sg.SITE).contains_points(Z).reshape(XX.shape) + U_parkm = np.ma.array(U_park, mask=~inside) + U_exitm = np.ma.array(U_exit, mask=~inside) + + # ---- numeric checks reported to stdout --------------------------------- + print("U_g^max = %.4f U_e^max = %.4f" % (Ug_max, Ue_max)) + print("Uhat_park in [%.4f, %.4f]" % (U_parkm.min(), U_parkm.max())) + print("Uhat_exit in [%.4f, %.4f]" % (U_exitm.min(), U_exitm.max())) + print("mirror residual |(U_park+U_exit) - 2 U_e| = %.2e" + % np.abs(Up_raw + Ux_raw - 2 * U_e).max()) + # the park field must be lower on the park line than on the exit line + def sample(F, P): + ii = np.clip(((P[:, 0] - x0) / DELTA).astype(int), 0, len(xs) - 1) + jj = np.clip(((P[:, 1] - y0) / DELTA).astype(int), 0, len(ys) - 1) + return F[jj, ii] + print("mean Uhat_park on Lambda_park = %.4f, on Lambda_exit = %.4f" + % (sample(U_park, park_line).mean(), sample(U_park, exit_line).mean())) + print("mean Uhat_exit on Lambda_park = %.4f, on Lambda_exit = %.4f" + % (sample(U_exit, park_line).mean(), sample(U_exit, exit_line).mean())) + + # A common display ceiling for both panels: the analytic bound U_e^max is a + # worst-case estimate, so the realized field only reaches ~0.34. Both + # panels share one scale, which is what makes the mirror relation visible; + # the colorbar is annotated with the true values, not rescaled to [0,1]. + vmax = float(max(U_parkm.max(), U_exitm.max())) + + # ---- plot -------------------------------------------------------------- + plt.rcParams.update({ + "font.family": "serif", + "font.serif": ["Nimbus Roman", "Times New Roman", "DejaVu Serif"], + "font.size": 7, + "mathtext.fontset": "stix", + "axes.linewidth": 0.5, + "pdf.fonttype": 42, + }) + fig, axes = plt.subplots(1, 3, figsize=(7.16, 1.75), + constrained_layout=True) + + ax = axes[0] + ax.add_patch(MplPolygon(sg.SITE, closed=True, facecolor="white", + edgecolor="#585858", lw=0.7, zorder=1)) + ax.plot(center[:, 0], center[:, 1], color="#703A94", lw=0.9, + ls=(0, (2.2, 1.2)), label=r"$\Lambda_{\mathrm{center}}$", zorder=3) + ax.plot(park_line[:, 0], park_line[:, 1], color="#00549F", lw=1.0, + label=r"$\Lambda_{\mathrm{park}}$", zorder=3) + ax.plot(exit_line[:, 0], exit_line[:, 1], color="#C44E0A", lw=1.0, + label=r"$\Lambda_{\mathrm{exit}}$", zorder=3) + ax.plot(*sg.LOAD_POSE, marker="o", ms=2.8, color="#222222", zorder=4) + ax.annotate(r"$\boldsymbol{\eta}_{\mathrm{load}}$", sg.LOAD_POSE, + textcoords="offset points", xytext=(2.5, 2.5), fontsize=6) + ax.legend(loc="lower right", fontsize=5.2, frameon=False, + handlelength=1.4, borderaxespad=0.1, labelspacing=0.2) + ax.set_title(r"(a) boundary and guidance sources", fontsize=6.6, pad=2) + + for ax, U, name in ((axes[1], U_parkm, r"(b) $\hat U_{\mathrm{park}}$"), + (axes[2], U_exitm, r"(c) $\hat U_{\mathrm{exit}}$")): + im = ax.pcolormesh(XX, YY, U, cmap="viridis", vmin=0.0, vmax=vmax, + shading="auto", rasterized=True) + ax.contour(XX, YY, U.filled(np.nan), + levels=np.linspace(0.06, vmax * 0.92, 5), + colors="white", linewidths=0.25, alpha=0.7) + ax.add_patch(MplPolygon(sg.SITE, closed=True, facecolor="none", + edgecolor="#585858", lw=0.7)) + ax.set_title(name, fontsize=6.6, pad=2) + + cb = fig.colorbar(im, ax=axes[2], fraction=0.046, pad=0.02) + cb.set_ticks([0.0, vmax / 2.0, vmax]) + cb.set_ticklabels(["0", "%.2f" % (vmax / 2.0), "%.2f" % vmax]) + cb.ax.tick_params(labelsize=5.4, width=0.4, length=1.8) + cb.outline.set_linewidth(0.4) + + for ax in axes: + ax.set_aspect("equal") + ax.set_xlim(x0, x1) + ax.set_ylim(y0, y1) + ax.set_xticks([]) + ax.set_yticks([]) + for sp in ax.spines.values(): + sp.set_visible(False) + + fig.savefig("fig_igf.pdf", dpi=600) + print("wrote fig_igf.pdf") + + +if __name__ == "__main__": + main() diff --git a/figs/sitegeom.py b/figs/sitegeom.py new file mode 100644 index 0000000..07e12ea --- /dev/null +++ b/figs/sitegeom.py @@ -0,0 +1,252 @@ +#!/usr/bin/env python3 +"""Shared synthetic loading-area geometry for the paper's illustration figures. + +Reproduces the pipeline of subsec:centerline / subsec:guide_route as faithfully +as the available toolchain allows: + + 1. rasterize the site polygon, compute the Euclidean distance transform + (clearance field) -- this is the quantity the extended Voronoi graph + partitions space by; + 2. extract the clearance ridge (EVG skeleton approximation) by non-maximum + suppression of the distance transform; + 3. connect entrance to loading bay by A* over the skeleton cells, with the + edge cost penalizing low clearance; + 4. smooth the resulting polyline with the paper's QP model -- minimize the + second-difference (smoothness) plus reference-deviation cost subject to a + tangential/normal box corridor, solved as a projected linear system + (the paper uses OSQP; here the same objective is solved by direct + factorization with projection onto the corridor box, which is adequate + for an illustration); + 5. offset by +-W/2 along the local normal to obtain the two guidance lines. + +Everything here is a *construction illustration* on a synthetic site, not an +experimental result. +""" +import numpy as np +from scipy import ndimage +from matplotlib.path import Path + +# ------------------------------------------------------------------ site plan +SITE = np.array([ + [0.0, 10.0], [16.0, 6.5], [33.0, 5.0], [50.0, 6.5], [63.0, 11.0], + [70.0, 19.0], [66.0, 30.0], [52.0, 36.0], [36.0, 35.0], [21.0, 30.0], + [8.0, 24.0], [0.0, 20.0], +]) +ENTRANCE = np.array([0.6, 15.0]) # on the open left edge +LOAD_POSE = np.array([44.0, 24.0]) # loading position inside the bay +W = 9.0 # channel width +RES = 0.25 # raster resolution for the DT/skeleton + + +def rasterize(res=RES, pad=1.0): + x0, x1 = SITE[:, 0].min() - pad, SITE[:, 0].max() + pad + y0, y1 = SITE[:, 1].min() - pad, SITE[:, 1].max() + pad + xs = np.arange(x0, x1, res) + ys = np.arange(y0, y1, res) + XX, YY = np.meshgrid(xs, ys) + pts = np.column_stack([XX.ravel(), YY.ravel()]) + inside = Path(SITE).contains_points(pts).reshape(XX.shape) + return xs, ys, XX, YY, inside + + +def clearance(inside, res=RES): + """Euclidean distance to the nearest boundary/obstacle cell, in metres.""" + return ndimage.distance_transform_edt(inside) * res + + +def skeleton(dist, inside): + """Clearance ridge: cells whose distance value is a local maximum along at + least one of the four axes. A cheap stand-in for EVG-thin thinning that + needs no extra dependency.""" + d = dist + ridge = np.zeros_like(inside, dtype=bool) + for ax, sh in ((0, 1), (1, 1)): + a = np.roll(d, sh, axis=ax) + b = np.roll(d, -sh, axis=ax) + ridge |= (d >= a) & (d >= b) + # a genuine ridge needs some clearance; drop the noisy skin near the wall + return ridge & inside & (d > 1.5 * RES) + + +def astar(dist, inside, start_rc, goal_rc, clear_w=6.0): + """8-connected A* over cells. Step cost = geometric length times a factor + that grows as clearance drops, so the path hugs the clearance ridge.""" + import heapq + nr, nc = dist.shape + dmax = dist.max() + inf = float("inf") + g = np.full(dist.shape, inf) + came = {} + sr, sc = start_rc + gr, gc = goal_rc + g[sr, sc] = 0.0 + + def h(r, c): + return np.hypot(r - gr, c - gc) * RES + + openq = [(h(sr, sc), sr, sc)] + nbrs = [(-1, 0, 1.0), (1, 0, 1.0), (0, -1, 1.0), (0, 1, 1.0), + (-1, -1, 1.4142), (-1, 1, 1.4142), (1, -1, 1.4142), (1, 1, 1.4142)] + seen = np.zeros(dist.shape, dtype=bool) + while openq: + _, r, c = heapq.heappop(openq) + if seen[r, c]: + continue + seen[r, c] = True + if (r, c) == (gr, gc): + break + for dr, dc, w in nbrs: + rr, cc = r + dr, c + dc + if not (0 <= rr < nr and 0 <= cc < nc) or not inside[rr, cc]: + continue + # penalty in [1, 1+clear_w]; lowest where clearance is largest + pen = 1.0 + clear_w * (1.0 - dist[rr, cc] / dmax) + ng = g[r, c] + w * RES * pen + if ng < g[rr, cc]: + g[rr, cc] = ng + came[(rr, cc)] = (r, c) + heapq.heappush(openq, (ng + h(rr, cc), rr, cc)) + if (gr, gc) not in came and (gr, gc) != (sr, sc): + raise RuntimeError("A* failed to reach the goal") + path = [(gr, gc)] + while path[-1] != (sr, sc): + path.append(came[path[-1]]) + return np.array(path[::-1]) + + +def to_xy(rc, xs, ys): + return np.column_stack([xs[rc[:, 1]], ys[rc[:, 0]]]) + + +def resample(poly, step): + seg = np.diff(poly, axis=0) + L = np.hypot(seg[:, 0], seg[:, 1]) + cum = np.concatenate([[0.0], np.cumsum(L)]) + s = np.arange(0.0, cum[-1] + 1e-9, step) + out = np.empty((s.size, 2)) + for i, si in enumerate(s): + k = min(np.searchsorted(cum, si, side="right") - 1, len(seg) - 1) + k = max(k, 0) + t = (si - cum[k]) / L[k] + out[i] = poly[k] + t * seg[k] + return out + + +def qp_smooth(ref, half_width, w_smooth=12.0, w_ref=1.0, iters=400, + r_min=12.0): + """Minimize w_smooth * sum |p_{i-1} - 2 p_i + p_{i+1}|^2 + + w_ref * sum |p_i - p_i^ref|^2 + s.t. |p_i - p_i^ref| <= half_width (isotropic proxy for the + tangential/normal box corridor) + |p_{i-1} - 2 p_i + p_{i+1}| <= ell^2 / r_min + (curvature bound, subsec:centerline: + ||d_i|| = ell^2 kappa_i + O(ell^4)) + with the endpoints fixed. + + Solved by projected gradient iterations; the paper solves the same objective + with OSQP under linear constraints. The curvature projection is applied as + a Gauss-Seidel sweep: where the second difference exceeds its bound, the + point is pulled toward the midpoint of its neighbours, which reduces |d_i| + monotonically. + """ + P = ref.copy() + # Per-point step length: the second-difference bound ||d_i|| <= ell_i^2/r_min + # is local, so use the local spacing rather than the mean (the mean would + # under-constrain the segments that are longer than average). + + def cap_of(Q): + """Local second-difference cap ell_i^2 / r_min, evaluated on Q's own + spacing so that the enforced bound matches the curvature actually + measured on the returned polyline.""" + seg = np.hypot(*np.diff(Q, axis=0).T) + ell_i = np.minimum(seg[:-1], seg[1:]) + return ell_i ** 2 / r_min + for _ in range(iters): + lap = np.zeros_like(P) + lap[1:-1] = P[:-2] - 2.0 * P[1:-1] + P[2:] + grad = np.zeros_like(P) + grad[1:-1] += 2.0 * w_smooth * (-2.0) * lap[1:-1] + grad[2:-1] += 2.0 * w_smooth * lap[1:-2] + grad[1:-2] += 2.0 * w_smooth * lap[2:-1] + grad += 2.0 * w_ref * (P - ref) + step = 0.02 / (w_smooth + w_ref) + P[1:-1] = P[1:-1] - step * grad[1:-1] + + # --- corridor projection ------------------------------------------- + off = P - ref + r = np.hypot(off[:, 0], off[:, 1]) + bad = r > half_width + if bad.any(): + P[bad] = ref[bad] + off[bad] * (half_width / r[bad])[:, None] + P[0], P[-1] = ref[0], ref[-1] + + # --- curvature projection, applied last so that it is the binding + # constraint on the returned polyline --------------------------- + for _ in range(60): + d_cap = cap_of(P) + d = P[:-2] - 2.0 * P[1:-1] + P[2:] + mag = np.hypot(d[:, 0], d[:, 1]) + over = mag > d_cap + if not over.any(): + break + # shift p_i along +d to shrink |d_i| toward the cap + shrink = np.zeros_like(mag) + shrink[over] = 0.5 * (mag[over] - d_cap[over]) / mag[over] + P[1:-1] += d * shrink[:, None] + P[0], P[-1] = ref[0], ref[-1] + return P + + +def tangent_normal(P): + t = np.gradient(P, axis=0) + t /= np.linalg.norm(t, axis=1)[:, None] + n = np.stack([-t[:, 1], t[:, 0]], axis=1) + return t, n + + +def build_centerline(verbose=False): + """Full stage-1 geometry. Returns a dict of everything the figures need.""" + xs, ys, XX, YY, inside = rasterize() + dist = clearance(inside) + skel = skeleton(dist, inside) + + def nearest_cell(pt, mask): + rr, cc = np.nonzero(mask) + d = np.hypot(xs[cc] - pt[0], ys[rr] - pt[1]) + i = int(np.argmin(d)) + return (rr[i], cc[i]) + + start = nearest_cell(ENTRANCE, inside) + goal = nearest_cell(LOAD_POSE, inside) + raw_rc = astar(dist, inside, start, goal) + raw = to_xy(raw_rc, xs, ys) + + # the centerline covers the entrance->bay main channel; resample then smooth + coarse = resample(raw, 1.0) + center = qp_smooth(coarse, half_width=1.6) + + t, n = tangent_normal(center) + park_line = center + (W / 2.0) * n + exit_line = center - (W / 2.0) * n + + if verbose: + print("grid %d x %d, res %.2f m" % (XX.shape[1], XX.shape[0], RES)) + print("max clearance %.2f m" % dist.max()) + print("A* raw length %.2f m, %d cells" % + (np.hypot(*np.diff(raw, axis=0).T).sum(), len(raw))) + print("centerline length %.2f m, %d points" % + (np.hypot(*np.diff(center, axis=0).T).sum(), len(center))) + # curvature of the smoothed centerline via second differences + d2 = center[:-2] - 2 * center[1:-1] + center[2:] + ell = np.hypot(*np.diff(center, axis=0).T).mean() + kap = np.hypot(d2[:, 0], d2[:, 1]) / ell ** 2 + print("centerline |kappa| max %.4f (1/m) -> R_min %.2f m" + % (kap.max(), 1.0 / max(kap.max(), 1e-9))) + + return dict(xs=xs, ys=ys, XX=XX, YY=YY, inside=inside, dist=dist, + skel=skel, raw=raw, center=center, + park_line=park_line, exit_line=exit_line, tang=t, nrm=n) + + +if __name__ == "__main__": + build_centerline(verbose=True) diff --git a/main.tex b/main.tex new file mode 100644 index 0000000..ce9bca4 --- /dev/null +++ b/main.tex @@ -0,0 +1,1219 @@ +\documentclass[journal]{IEEEtran} +\usepackage{etoolbox} +\usepackage{orcidlink} +\usepackage{bookmark} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{booktabs} +\usepackage{multirow} +\usepackage{graphicx} +\graphicspath{{figs/}} +\usepackage[ruled,vlined,linesnumbered]{algorithm2e} +\hypersetup{hidelinks} + +\begin{document} + +% 基于集成引导场与联合优化的露天矿装载场地进出路径空间解耦规划 +\title{Spatially Decoupled Inbound and Outbound Path Planning for Open-Pit Mine Loading Areas via Integrated Guidance Fields and Joint Optimization} + +\author{ + Chuang Wang\orcidlink{0009-0003-5795-2504}, + Peng Chen\orcidlink{0000-0002-8076-8989},~\IEEEmembership{Member,~IEEE,} + Yiming Li\orcidlink{0009-0007-7859-4987}, + Han Li\orcidlink{0000-0001-5136-7396}, + Guizhen Yu\orcidlink{0000-0001-8374-7422} + + % 需更新 + \thanks{This work is partially supported by the National Key Technologies R\&D Program of China 2022YFB4703700, China National Postdoctoral Program for Innovative Talents BX20250498 and National Natural Science Foundation of China 52272327.} + \thanks{C. Wang, P. Chen, Y. Li, H. Li (Corresponding author), G. Yu, are affiliated with the Key Laboratory of Autonomous Transportation Technology for Special Vehicles, Ministry of Industry and Information Technology, School of Transportation Science and Engineering, Beihang University, Beijing 100191, China. (e-mail: chuang2025@buaa.edu.cn, cpeng@buaa.edu.cn, lym2000@buaa.edu.cn, leehan@buaa.edu.cn, yugz@buaa.edu.cn)} +} + +\maketitle + +\begin{abstract} + % TODO(P2-5):待实验数据到位后,将下文括号内的占位数字替换为实测值。 + % 结构:1 句问题 → 1 句三点新颖性(P3-1)→ 3 句方法 → 1 句验证规模 → 1 句结果。 + In open-pit mines, the loading area is a semi-enclosed, single-entrance space without lane markings, where inbound and outbound haul trucks share the same narrow channel; the resulting spatio-temporal conflicts idle the excavator and cap the productivity of the entire haulage chain. + This paper makes three contributions: the bidirectional traffic topology is \emph{precomputed offline} into a pair of mirrored directional fields rather than imposed as an online constraint; the inter-path conflict cost is defined as a \emph{delay-weighted double arc-length integral} of a compactly supported kernel, which depends only on the overall geometry of the two paths and therefore requires no pairing of samples between them; and the guidance weights are made \emph{asymmetric} so that a loaded truck is given priority over an empty one, matching mine operating practice. + Concretely, throughput is replaced by a purely geometric surrogate---the delay-weighted spatial separation of the two paths---and the planner is organized in three stages. An integrated guidance field (IGF) is built offline by discretizing the site boundary and two directional guidance lines into potential sources; because the field is constructed from boundary geometry alone, a change of loading pose requires no rebuild. A field-adaptive Hybrid A* then produces two coarse paths independently and in parallel on the two mirrored fields, fixing the discrete gear sequence. Finally the two paths are stacked into a single decision vector and solved jointly as a nonlinear program, with the non-convex collision condition replaced by convex corridors obtained from ellipsoid-based convex decomposition. + The method is evaluated against five baselines---including a time-domain cooperative scheduler as a performance upper bound---and validated on a real mine haul truck over ($N$) loading cycles. + Results show ($x$)\% shorter waiting time and ($y$)\% higher throughput than independent planning, with per-cycle solution times of ($z$)~ms. +\end{abstract} +\begin{IEEEkeywords} + Autonomous mining vehicles, path planning, open-pit mine, spatial decoupling, guidance field, joint optimization, convex corridor. +\end{IEEEkeywords} + +\section{Introduction} + \label{sec:intro} + + \IEEEPARstart{T}{he} + % 在露天矿山部署自动驾驶技术具有显著潜力,合理的规划路径是自动驾驶车辆高效执行运输作业的重要前提\cite{mine2020lastsection,mine2023secure}。现有的研究大多都是针对城市场景,遵循结构化道路或停车场场景的通行规则。然而,露天矿区装载运输作业有其特殊的场景特点和效率要求,需要针对性的适配和设计。 + + % 露天矿区的运输作业由装载、运输、卸载三个环节循环构成,其中装载环节的作业效率直接决定整条运输链的产能:挖掘机是矿区昂贵且数量固定的生产设备,其空闲即意味着产能损失。执行装载作业的区域(以下简称装载场地)是一个半封闭、单出入口的不规则空间,运输车辆需在其中泊入指定的装载位、完成装载后再驶离,如图 \ref{fig:scenario} 所示。与城市结构化道路或规则停车场不同,装载场地内没有车道线等显式的通行规则,其边界由矿料堆和作业面构成、形状不规则且随开采进度变化,可通行空间狭窄。 + + % 在这一场景下,车队的连续作业带来了一个城市场景中并不突出的效率瓶颈。由于装载位附近空间有限,满载车的驶离路径与空载车的泊入路径往往共用同一通道,二者在时间上有先后、在空间上有重叠,形成时空冲突:空载车必须等待满载车完全驶出冲突区后才能开始泊入,这段等待直接转化为挖掘机的空闲,如图 \ref{fig:conflict}(a)(c) 所示。若将两条路径的空间拓扑加以调整、使其相互解耦,两车的动作即可并行展开,等待随之消除,如图 \ref{fig:conflict}(b)(d) 所示。 + + % 本文因此研究装载场地内泊入路径与驶离路径的协同规划问题:以两条路径的空间解耦为手段,压缩车辆切换过程中的等待时间,从而提升装载场地的运输吞吐量。与以往面向单车点对点行驶的路径规划不同,本文所求解的是一对具有特定空间关系的路径,二者需在满足矿用车辆运动学与狭窄空间避碰约束的前提下相互推离。 + + \begin{figure}[htbp] + \centering + \includegraphics{fig_scenario} + \caption{Loading operation in an open-pit mine. The excavator works against the ore pile and + a truck must park at a designated loading position before loading can start.} + \label{fig:scenario} + \end{figure} + + \begin{figure}[htbp] + \centering + \includegraphics{fig_conflict} + \caption{Spatiotemporal conflict and its resolution by spatial decoupling. + (a)(c) Coupled single-channel paths: the empty truck must wait until the loaded + truck has fully cleared the conflict zone. + (b)(d) Decoupled dual-channel paths: both maneuvers proceed in parallel.} + \label{fig:conflict} + \end{figure} + + \subsection{Planning Challenges} + % 将上述设想落实为可求解的规划问题,面临以下三方面挑战。 + + \subsubsection{Coupling and Asymmetry of Inbound and Outbound Paths} + % 双向路径的耦合与非对称性: + % 消解时空冲突要求两条路径协同规划,其困难有三层。其一,优化目标无法直接表达:吞吐量取决于车队到达时刻与排队节拍,二者由上层派车系统与挖掘机作业决定,并不属于场地内路径规划的决策空间,因此需要一个仅由路径几何构成的代理目标。其二,两条路径通过空间接近程度相互耦合,且该耦合关于路径形状非凸,独立求解再叠加无法保证解耦效果。其三,两条路径地位并不对等:泊入需经换向动作贴合装载位、弧长通常显著大于驶离路径,二者的分段结构与采样点之间不存在几何上有意义的配对关系,使得多车规划中常用的同索引点间距惩罚在此不再适用。 + + \subsubsection{Topological Consistency Under Loading-Pose Updates} + % 装载位动态变更下的拓扑稳定: + % 装载位的位置与朝向随挖掘进度持续变更,路径须随之重新生成;但每次重规划都必须保持双向路径的空间拓扑不变——即泊入与驶离在共用通道内始终分居两侧、不发生换边,其形式化定义见 \eqref{eq:topology_consistency}——否则车队的排列关系被打乱,流水线作业的节拍反而恶化。这一要求造成两难:若将拓扑作为优化问题的约束,则每次重规划都需求解一个附加拓扑约束的非凸问题,计算代价高且可能不可行;若不加约束,所得解的拓扑将随装载位与初值而摆动。因此需要一种将拓扑先验与在线求解相分离的机制。 + + \subsubsection{Kinematic Feasibility in Confined Loading Areas} + % 矿用车辆运动学与狭窄空间的双重限制: + % 矿区运输车辆转弯半径大、液压转向响应迟滞、运动构件机械损耗高\cite{mine2024truckreversing},要求路径沿弧长曲率连续、曲率变化率有界,并尽量减少换挡等冗余执行动作。而装载场地边界不规则、可行空间狭窄,泊入过程往往必须包含“前进—停顿—后退”的换向段。二者叠加使问题进一步复杂:大转弯半径与狭窄空间本身相互矛盾,可行域窄;避碰约束建立在不规则边界点云之上、形式非凸;换向段的存在又引入了档位序列这一离散决策,使问题整体上成为混合整数非凸规划。 + + \subsection{Related Work} + \label{sec:related_work} + % 本文的问题涉及三条相关研究脉络:多车时空冲突的消解、非结构化场景中的单车路径生成、以及以场或规则表达通行先验的方法。以下分别评述,并指出其与装载场地双向路径规划之间的差距。 + + \subsubsection{Spatiotemporal Conflict Resolution for Multiple Vehicles} + % 多车之间的时空冲突消解通常被建模为协同轨迹规划或通行权分配问题。一类方法在时空维度上联合规划,为每辆车预先分配无冲突的轨迹或通行时隙,从而"提前消除"时空冲突,典型应用于高速匝道合流\cite{ramp2024spatiotemporal,ramp2026distributed};在矿区场景中,相应工作多集中于交叉口的通行权与通行顺序决策\cite{mine2025rightofway},或车队层面的任务调度\cite{mine2023scheduling}。这些方法的共同前提是各车严格执行既定的时空动作序列,其效率增益来自对到达时刻与速度剖面的精确调度。然而在装载场地,车辆到达时刻由上层派车系统决定、装载时长由挖掘机作业节拍决定,二者均不在场地内路径规划模块的可控范围;且实际生产中车辆常因人工接管、设备待料等原因偏离既定时序。因此依赖时间维精确调度的方法在此难以落地,本文转而在\emph{空间}维度消解冲突:一旦两条路径的空间拓扑充分解耦,冲突的消除便不再依赖时序的准确执行。 + + \subsubsection{Path Planning in Unstructured Mining Environments} + % 面向非结构化场景的单车路径生成已有大量成熟工作。基于运动基元的图搜索方法以 Hybrid A*\cite{dolgov2008practical} 为代表,能够在车辆状态格上直接处理非完整约束与前进/后退混合的换向动作,后续研究进一步改进了其扩展效率与路径质量\cite{sedighi2023hybridastar};在矿区场景中,已有工作研究了装载位变更下的最后一段路径规划\cite{mine2020lastsection}、前后端解耦的安全轨迹规划\cite{mine2023secure},以及大型矿卡的倒车与泊车规划\cite{mine2024truckreversing};亦有工作从人工驾驶数据出发生成类人的装载泊车轨迹\cite{mine2025humanlikeparking}。与本文在几何条件上最接近的是狭窄空间泊车规划\cite{lian2023valetparking,li2022parkingcorridor}:其同样须在逼仄可行域内处理含换向段的非完整路径,且同样先由图搜索给出粗解、再沿粗解构造行驶走廊将逐障碍避碰约束替换为走廊内的盒式约束,这一"粗解引导 + 走廊化避碰"的建模思路与本文相通;差别在于该问题只有一条路径、其目标函数中不存在另一条路径,故不涉及本文所关注的双路径相对关系。这些方法针对的是\emph{单条}路径的点对点生成:其目标函数仅由该路径自身的长度、耗时或平滑性构成,不包含与另一条路径的相对关系。将其独立地应用于泊入与驶离两条路径,各自都会收敛到几何上最优但空间上相互重合的解,反而加剧本文所关注的时空冲突。一种自然的简化是以两条路径同索引采样点之间的距离作为分离度量,但该做法要求两条路径长度相近、采样一一对应;而泊入路径含换向段、其弧长通常显著大于驶离路径,二者采样点之间不存在几何意义上的配对关系,故并不适用。 + + \subsubsection{Field- and Rule-Based Traffic Guidance} + % 为在无车道线的场景中引入通行先验,一类工作显式制定行驶规则,如依据地形与作业特点划分渠化车道或生成固定的双向参考路线。矿区道路缺乏明确的车道标线与边界约束信息,这一点已被广泛观察到\cite{mine2024unstructured}。 + % 须指出,以单向流组织车流本身是成熟做法,本文并不声称这一想法的新颖性。矿区运输道路设计中,行车方向与所需路面宽度依车型与会车需求确定\cite{baek2017haulroad};在自动化制造与物流领域,单向流路网的设计更已形成完整的问题体系,如单向环路的布局优化\cite{kouvelis1992unidirectional}与 AGV 单向流路径网络的柔性设计\cite{seo2006flowpath}。这些工作与本文的差别在于问题层次:其对象是\emph{路网拓扑}的离线设计——在给定站点与流量矩阵下决定各段的行车方向,路网一经确定即长期沿用,车辆沿既定路段行驶而不再涉及自身的运动学可行性。本文所面对的则是非结构化的作业面:边界随开采推进而变、无既定路段可循,且所规划的是含换向段的运动学可行路径、两条路径还须联合优化。因此单向流的\emph{思想}可以借用,其\emph{方法}不可直接套用。 + % 此类显式规则方法能够有效实现车流的空间解耦,但规则一经设定即难以随作业面推进而调整。另一类工作以人工势场(APF)将障碍与目标表达为连续场并沿其梯度生成路径,其泛化性强、且天然适合表达"倾向"而非"硬约束",但以梯度驱动路径生成时存在局部极小问题——机器人可能停滞于非目标点而无法到达终点\cite{apf2024wallfollower},且势场导数在贴近障碍处急剧增大、损害路径质量\cite{apf2024globalrepulsive},在装载场地这类狭窄通道中尤为突出。本文借用势场的表达能力而回避其求解方式:所构建的引导场仅作为标量代价注入图搜索的评价函数,路径由离散状态空间的系统性扩展产生,因而不受局部极小影响;同时,将双向拓扑固化在离线构建的场中,使装载位变更时无需重新制定规则、亦无需附加拓扑约束。 + + % 综上,现有工作或依赖矿区不具备的时间维调度能力,或聚焦于单条路径的点对点生成而不涉及路径之间的空间关系,或虽能表达通行先验但受限于规则的静态性与势场求解的局部极小。本文针对装载场地的双向路径规划问题,同时处理代理目标的构造、两条非对称路径的耦合优化、以及狭窄空间下的混合整数非凸约束。 + + \subsection{Contributions} + % 三点贡献分别回应上述三个挑战。为便于与已有工作对照,每点均先指出其新颖之处,再说明与最接近工作的具体差别。 + % 需要预先说明本文的定位:三阶段框架中的若干环节沿用了成熟部件(维诺骨架提取、参考线二次规划平滑、Hybrid A*、椭球凸分解走廊、内点法求解 NLP),本文并不声称这些部件本身的新颖性。真正新的是双向路径之间\emph{关系}的建模方式——如何表达冲突、如何固化拓扑、如何引入非对称——这三点构成下述贡献。 + + \subsubsection{Delay-Weighted Kernel-Integral Conflict Cost} + % 针对 Challenge 1,本文以两条路径的空间解耦程度作为吞吐量的代理目标,将不可直接优化的排队指标转化为纯几何量;其核心是把两条路径之间的冲突代价定义为有限支撑核的\emph{时延加权二重弧长积分}。 + % 与最接近的做法——以两条路径同索引采样点之间的距离作为分离度量——相比,差别有两处,且均为本文问题所必需。其一,该形式只取决于两条路径的整体几何关系、不依赖采样点之间的配对,因而适应泊入路径含换向段、其弧长显著大于驶离路径这一非对称性;同索引点距在此没有几何意义。其二,被积函数带一个由两点弧长之差给出的时延权重,使代价集中在两车\emph{确有}时序冲突之处,而非笼统惩罚空间接近——装载位邻域的重叠因两车不同时经过而不受惩罚,故该处结构性的、无法由任何路径形状消除的重叠不会污染目标函数。该权重仅依赖配置点序号与冻结步长,故在优化中为常系数,不改变问题的稀疏结构。 + % 在此基础上建立"离线场先验—在线粗解搜索—联合数值优化"的三阶段框架,将耦合的混合整数非凸问题分解为三个各自可高效求解的子问题。 + + \subsubsection{Bidirectional Topology Precomputed as an Offline Field Prior} + % 针对 Challenge 2,本文提出集成引导场(IGF):将场地边界与两条方向性引导线离散为势源、经有限支撑核叠加为一对关于虚拟道路中线\emph{互为镜像}的方向性势场——泊入路径所感知的势谷恰为驶离路径所感知的脊线。其新颖之处不在于用场表达通行先验,而在于双向通行的拓扑要求由此从一项\emph{在线约束}转变为一项\emph{离线先验}。 + % 与两条最接近的工作线相比:显式渠化规则一类方法同样实现空间解耦,但规则一经人工设定即难以随作业面推进而调整,本文的中线与引导线则由场地边界几何自动提取;Voronoi 场一类方法\cite{dolgov2010voronoi}构造的是各向同性的排斥场、只表达"离障碍物远些",不含方向信息,无法区分两个行驶方向。 + % 该构造带来一处可直接检验的性质:场只用到边界几何、不含装载位信息,故装载位变更时无需重建场、亦无需附加拓扑约束,仅以新的边界条件重新求解路径即可;且两条路径可在各自的场上\emph{独立并行}搜索,避免了耦合搜索的状态空间膨胀。相应地,本文改进 Hybrid A* 的扩展步长、代价函数与启发函数,使其在该场引导下生成两条已初步解耦的粗解。 + + \subsubsection{Asymmetric Joint Optimization of the Two Paths} + % 针对 Challenge 3,本文以粗解固定档位序列,将混合整数非凸问题化归为连续非线性规划;避碰约束经凸分解转化为线性不等式组——围绕粗解各段开辟不含边界点的凸多面体,在狭窄场地内尽可能保留可行域。与以对偶形式处理避碰的做法\cite{zhang2021obca}相比,凸走廊的半空间数由局部边界点分布自适应确定,代价是须以一次性内缩覆盖配置点之间的车体切角,本文给出该内缩量的解析上界。 + % 此处真正新的一点是\emph{非对称}引导权重:两条路径在目标函数中取不同的场引导权重,使"满载车绕行代价高、应主要由空载车让开"这一矿区作业语义直接进入优化。该非对称性无法仅由权重比例引入——若交互项不含时延加权,则其关于两条路径完全对称,分别加权之和恒等于二者之\emph{和}乘以同一个积分,比例对极小点毫无影响;本文的时延权重恰好打破这一退化。 + % 最终两条路径被堆叠为单一决策向量联立求解,而非交替迭代:共享装载位姿的等式约束因而被一次性精确满足,且问题的稀疏结构使联立求解的规模随配置点数线性增长。 + + % 本文余下部分组织如下。 + % 第 \ref{sec:problem} 章建立问题模型:由吞吐量目标导出空间解耦这一代理目标,给出目标函数与约束的完整形式,并概述三阶段求解框架。 + % 第 \ref{sec:igf} 章构建集成引导场,将双向通行的空间拓扑固化为离线的场先验。 + % 第 \ref{sec:search} 章在该场上以改进的 Hybrid A* 生成两条路径的初值粗解。 + % 第 \ref{sec:opt} 章以粗解为初值,经凸分解处理避碰约束、并引入交互场将两条路径联立优化。 + % 第 \ref{sec:exp} 章给出实验与分析,第 \ref{sec:conclusion} 章总结全文。 + +\section{Problem Formulation and Planning Framework} + \label{sec:problem} + + \subsection{Spatial Decoupling as a Throughput Surrogate} + \label{subsec:proxy} + % 如 \ref{sec:intro} 节所述,装载场地的生产目标是最大化单位时间内的装载趟数,即吞吐量。严格地表述该目标需要引入车队排队模型与时间维决策变量,其决策空间同时包含每辆车的到达时刻、等待时长与行驶轨迹,是一个耦合的多车时空调度问题。然而在实际矿区生产中,车队调度由上层派车系统负责、且装载位处的采装节拍由挖掘机作业决定,二者均不属于本文所讨论的场地内路径规划模块的可控范围。因此本文不直接优化吞吐量,而是采用\emph{空间解耦程度}作为其代理目标(surrogate objective),其合理性可作如下说明。记装载场地在一个采装循环内的时间开销为 + \begin{equation} + T_\text{cycle} = T_\text{exit} + T_\text{wait} + T_\text{park} + T_\text{load}, + \label{eq:cycle_time} + \end{equation} + % 其中 $T_\text{load}$ 由挖掘机作业能力决定,$T_\text{exit}$ 与 $T_\text{park}$ 分别为满载车驶离与空载车泊入的行驶耗时,而 $T_\text{wait}$ 为空载车因等待满载车让出冲突区而产生的附加等待时间。 + + % 在挖掘机数量固定的前提下,$T_\text{load}$ 不可压缩,故提升吞吐量等价于压缩 $T_\text{exit} + T_\text{wait} + T_\text{park}$。其中 $T_\text{wait}$ 由两条路径在\emph{时空}上的冲突程度决定:二者共用同一通道时,$T_\text{wait}$ 退化为满载车通过冲突区的完整耗时;而随着两条路径在空间上相互分离,可同时通行的区段增多,$T_\text{wait}$ 随之下降。 + % 需要强调的是,决定 $T_\text{wait}$ 的并非扫掠域重叠的总面积,而是重叠\emph{发生在何处}:由 \eqref{eq:wait_as_sup} 可见,$T_\text{wait}$ 取决于两车通过同一冲突点的时刻之差,故同样面积的重叠若发生在两车先后次序悬殊之处则代价高昂、若发生在两车本就不同时经过之处则不产生等待。这一区分是本文构造 \eqref{eq:cost_interaction} 中时延权重 $\tau_\text{d}$ 的依据,其详细说明见 \ref{subsec:objective} 节。 + % 一个直接的推论是:$T_\text{wait}$ 原则上可被压至零。\eqref{eq:cons_boundary} 要求两条路径在装载位处共享位姿,故装载位邻域内的扫掠域重叠是结构性的、无法由任何路径形状消除;但由 \eqref{eq:cost_delay_weight},该邻域恰是 $\tau_\text{d} = 0$ 之处——泊入路径行至末端时驶离路径刚刚起步,两车虽在空间上重叠却不在时间上相遇。因此这一不可消除的几何重叠并不构成 $T_\text{wait}$ 的下界,真正的约束来自主通道能否容纳双向并行通行:由 \eqref{eq:reference_offset},两条引导线相距 $W$,两车车体各沿其路径向外展开 $B_\text{v}/2$,故会车所需的通道净宽至少为 $W + B_\text{v}$ 再加上两侧车体到场地边界的安全间隔,而 $W$ 自身又须不小于两车贴合时的 $B_\text{v}$ 与横向净空之和(见 \eqref{eq:interaction_radius})。该条件在主通道最窄处不成立时,双向并行在几何上即不可能,$T_\text{wait}$ 必然为正;本文不给出该正下界的闭式表达——它取决于场地最窄区段的长度与两车的速度剖面,构造性推导须引入本文有意排除的时间维决策量。相应地,下文不再将“$T_\text{wait}$ 的下界”作为理论断言,而以实测值报告本文方法所达到的 $T_\text{wait}$ 及其相对基线的压缩幅度,见 \ref{subsec:exp_throughput} 节。 + % 由此,本文将吞吐量目标分解为两个几何上可直接优化的指标:其一为两条路径的通行耗时(对应 \eqref{eq:cost_time}、\eqref{eq:cost_gear}),其二为两条路径之间\emph{按时延加权}的空间分离程度(对应 \eqref{eq:cost_field}、\eqref{eq:cost_interaction})。下文不再直接处理 \eqref{eq:cycle_time} 中的各项 $T$,而以 \eqref{eq:cost} 所定义的等效耗时分项替代之。这一代理关系是本文全部建模的出发点,也意味着本文所优化的是吞吐量的必要条件而非其本身:空间解耦消除了冲突导致的等待,但并不保证上层派车节拍与之匹配。 + + % 此外,Challenge 2 所述的拓扑稳定性要求需先予以形式化,否则“拓扑不变”一语无从检验。本文在虚拟道路中线 $\varLambda_\text{center}$ 的基础上定义路径点的\emph{带符号横向偏移}:对工作空间中任一点 $\mathbf{p}$,取其在中线上的最近点投影及相应的法向投影量 + \begin{equation} + i^*(\mathbf{p}) = \arg\min_{1 \le i \le N_\text{c}} + \left\lVert \mathbf{p} - \mathbf{q}_i \right\rVert , + \quad + \lambda(\mathbf{p}) = \mathbf{n}_{i^*(\mathbf{p})}^\top + \left( \mathbf{p} - \mathbf{q}_{i^*(\mathbf{p})} \right) , + \label{eq:signed_offset} + \end{equation} + % 其中 $\mathbf{q}_i$ 与 $\mathbf{n}_i$ 分别为中线采样点及其单位法向量,由 \eqref{eq:tangent_normal} 给出。由于中线只沿入口—出口主通道提取、不经过装载位(\ref{subsec:centerline} 节),装载位所在的支路区段自然地由其到中线的距离区分出来。据此记两条路径落在主通道内的部分为\emph{共享通道段} + \begin{equation} + \varGamma_\bullet^\text{sh} = \left\{ + \mathbf{p} \in \varGamma_\bullet + \;\middle|\; + \left\lVert \mathbf{p} - \mathbf{q}_{i^*(\mathbf{p})} \right\rVert \le W + \right\} , + \quad \bullet \in \{\,\text{park},\ \text{exit}\,\} , + \label{eq:shared_channel} + \end{equation} + % 并称一组解满足\emph{拓扑一致},若两条路径的带符号横向偏移在各自的共享通道段内不变号、且二者符号相反: + \begin{equation} + \lambda(\mathbf{p}) \ge 0 \quad \forall\, \mathbf{p} \in \varGamma_\text{park}^\text{sh} , + \qquad + \lambda(\mathbf{p}) \le 0 \quad \forall\, \mathbf{p} \in \varGamma_\text{exit}^\text{sh} , + \label{eq:topology_consistency} + \end{equation} + % 其符号约定与 \eqref{eq:reference_offset} 中两条引导线的偏移方向一致;取非严格不等号是因为等号可在通道端点处成立,该处两条路径分别与进入、离开位姿相接、横向偏移可为零。\eqref{eq:topology_consistency} 把“拓扑”落实为一个可判定的谓词:泊入与驶离在共享通道内始终分居中线两侧,不发生穿越或换边。 + + % 该要求在本文框架中不作为优化问题的约束项、而是通过求解结构本身予以保证:双向路径的空间拓扑被前置固化在第 \ref{sec:igf} 章离线构建的引导场之中,装载位变更时仅需重新求解路径、而拓扑先验保持不变(详见 \ref{subsec:framework} 节)。此处需如实指出该保证的强度:\eqref{eq:topology_consistency} 是由 \eqref{eq:cost_field} 的软代价倾向性地促成的,而非由硬约束强制的。$U_\text{park}$ 以 $\varLambda_\text{park}$ 为势谷、以 $\varLambda_\text{exit}$ 为脊线,使搜索与优化在能量上偏好正确的一侧;但当装载位移至中线另一侧、致使沿正确一侧行驶的绕行代价显著超过穿越脊线的代价时,所得解仍可能换边。本文因此不声称拓扑一致性的硬保证,而将其作为软先验下的经验性质,以跨装载位序列的\emph{拓扑一致率}——即满足 \eqref{eq:topology_consistency} 的重规划次数占比——加以量化,见 \ref{subsec:exp_topology} 节。将 \eqref{eq:topology_consistency} 升级为硬约束在本文框架下是可行的(对 \eqref{eq:joint_nlp} 而言它是一族线性不等式),但会使装载位位于中线另一侧时的问题不可行,与重规划必须始终返回可行解的工程要求相悖,故本文不予采用。 + + \subsection{Coordinated Path Planning Formulation} + % 露天矿区自动驾驶装载场地内的路径规划任务,涉及到泊入、驶离两条路径,可以被描述为一个优化问题: + \begin{subequations} \label{eq:overall_problem} + \begin{align} + \min \quad + & J(\varGamma_\text{park}, \varGamma_\text{exit}) + \label{eq:overall_object} \\ + \text{s.t.} \quad + & \mathbf{h}(\varGamma_\text{park}, \varGamma_\text{exit}) = \mathbf{0} + \label{eq:overall_eq} \\ + & \mathbf{g}(\varGamma_\text{park}, \varGamma_\text{exit}) \leq \mathbf{0} + \label{eq:overall_ineq} \\ + & D(\varGamma_\text{park}) \cup D(\varGamma_\text{exit}) \subseteq \Omega_\text{free} + \label{eq:overall_set} + \end{align} + \end{subequations} + % 其中,$\varGamma_\text{park}$ 表示车辆进入场地并泊车到装载位的路径(泊入路径,parking-in),$\varGamma_\text{exit}$ 表示车辆装载完成后从装载位离开的路径(驶离路径,exit),二者即本问题的决策变量;$J(\cdot)$ 是目标函数(\ref{subsec:objective} 节); + % $\mathbf{h}(\cdot) = \mathbf{0}$ 汇总等式约束,即运动学 \eqref{eq:cons_kinodynamic}、换挡衔接 \eqref{eq:cons_junction} 与边界条件 \eqref{eq:cons_boundary}; + % $\mathbf{g}(\cdot) \leq \mathbf{0}$ 汇总不等式约束,即物理能力 \eqref{eq:cons_physics}与凸走廊 \eqref{eq:cons_corridor}; + % 而 \eqref{eq:overall_set} 为避碰要求所对应的集合包含条件(\eqref{eq:cons_collision})。 + % 三类约束的具体形式详见 \ref{subsec:constraints} 节。 + + % 需要说明的是,两条路径的总弧长 $s_\text{park}$、$s_\text{exit}$ 及其分段数并非预先给定,而是与路径形状一同确定的自由量,故 \eqref{eq:overall_problem} 是一个终端时刻(此处为终端弧长)自由的最优控制问题。这一自由度在数值求解阶段被有限度地保留:\ref{subsec:joint_nlp} 节以粗解固定配置点数与分段结构,仅将配置步长 $\Delta s_\bullet$ 留作长度自由度,并以 \eqref{eq:cons_step_trust} 限制其相对粗解的变动范围。 + + % 本文只进行路径规划,生成路径的过程不随时间 $t$ 演化,而是随路程 $s$ 演化,车辆物理模型如图 \ref{fig:bicycle} 所示。全文按三个层次记路径与几何量:完整路径状态 $\mathbf{x}(s)=[x,y,\theta,\kappa]^\top$($(x,y)$ 为后轴中心)、不含曲率的车辆位姿 $\boldsymbol{\eta}=[x,y,\theta]^\top$、以及工作空间中的几何点 $\mathbf{p}=[x,y]^\top$,其余符号见 Nomenclature 表。 + + % 车辆几何以车长 $L_\text{v}$、车宽 $B_\text{v}$(breadth)与轴距 $L_\text{w}$ 描述;记 $\mathcal{V}(\boldsymbol{\eta}) \subset \mathbb{R}^2$ 为车辆在位姿 $\boldsymbol{\eta}$ 处所占据的闭区域,即以 $\boldsymbol{\eta}$ 的位置分量为后轴中心、沿航向 $\theta$ 摆放的 $L_\text{v} \times B_\text{v}$ 实心矩形,则任一路径 $\varGamma$ 的扫掠域(swept set)定义为该轮廓沿路径的并集: + \begin{equation} + D(\varGamma) = \bigcup_{s \in [0,\, s_\varGamma]} + \mathcal{V}\!\left( \boldsymbol{\eta}(s) \right) + \label{eq:swept_set} + \end{equation} + % 其中 $\boldsymbol{\eta}(s)$ 为路径状态 $\mathbf{x}(s)$ 的位姿分量、$s_\varGamma$ 为该路径的总弧长;因此,两条路径的扫掠域分别写为 $D(\varGamma_\text{park})$ 与 $D(\varGamma_\text{exit})$。 + % 全文主要符号汇总于 Table \ref{tab:nomenclature}。 + + \begin{figure}[htbp] + \centering + \includegraphics{fig_bicycle} + \caption{Kinematic bicycle model and geometric parameters of the mining truck. + The path state is $\mathbf{x}=[x,y,\theta,\kappa]^\top$ defined at the rear-axle center, + with vehicle length $L_\text{v}$, width $B_\text{v}$, wheelbase $L_\text{w}$ + and front-wheel steering angle $\psi$ with its rate $\dot\psi$.} + \label{fig:bicycle} + \end{figure} + + \begin{table}[htbp] + \centering + \caption{Nomenclature of Principal Symbols} + \label{tab:nomenclature} + \footnotesize + \begin{tabular}{@{}llc@{}} + \toprule + Symbol & Description & Unit \\ + \midrule + \multicolumn{3}{@{}l}{\textit{States, paths and geometry}} \\ + $s$ & Arc length (path parameter) & m \\ + $\mathbf{x}=[x,y,\theta,\kappa]^\top$ & Full path state & --- \\ + $\boldsymbol{\eta}=[x,y,\theta]^\top$ & Vehicle pose (search node) & --- \\ + $\mathbf{p}=[x,y]^\top$ & Geometric point in workspace & m \\ + $\kappa,\ \sigma$ & Curvature and its rate & m$^{-1}$, m$^{-2}$ \\ + $\varGamma_\text{park},\varGamma_\text{exit}$ & Parking-in / exit path & --- \\ + $\Omega_\text{free},\Omega_\text{obs}$ & Drivable / obstacle region & --- \\ + $L_\text{v},B_\text{v},L_\text{w}$ & Vehicle length / breadth / wheelbase & m \\ + $R_\text{min}$ & Minimum turning radius & m \\ + $v_0,\ t_0$ & Nominal speed / gear-shift time & m\,s$^{-1}$, s \\ + \midrule + \multicolumn{3}{@{}l}{\textit{Guidance lines and centerline optimization}} \\ + $\varLambda_\text{center}$ & Virtual road centerline & --- \\ + $\varLambda_\text{park},\varLambda_\text{exit}$ & Parking-in / exit guidance line & --- \\ + $\mathbf{A}_i^\text{c},\mathbf{b}_i^\text{c}$ & Tangential--normal corridor at $\mathbf{q}_i$ & --- \\ + $W$ & Channel width & m \\ + $\lambda(\mathbf{p})$ & Signed lateral offset w.r.t. $\varLambda_\text{center}$ & m \\ + $\varGamma_\bullet^\text{sh}$ & Shared-channel portion of a path & --- \\ + \midrule + \multicolumn{3}{@{}l}{\textit{Integrated guidance field (IGF)}} \\ + $K(d;\rho,m)$ & Compactly supported kernel & --- \\ + $U_\text{park},U_\text{exit}$ & Directional IGF, $\in[0,1]$ & --- \\ + $\varPsi_\text{exit}(\mathbf{p};s_\text{park})$ & Interaction field from $\varGamma_\text{exit}$ & s\,m \\ + $\tau_\text{d},\ \tau_{ij}$ & Delay weight of a conflicting pair & s \\ + \midrule + \multicolumn{3}{@{}l}{\textit{Search and optimization}} \\ + $g,\ h$ & Search cost / heuristic & s \\ + $J_\ell,J_\text{gear},J_U,J_\varPsi,J_\kappa$ & Objective terms & s \\ + $w_U^{\bullet},\ w_\varPsi,\ w_\kappa$ & Equivalent-time multipliers & --- \\ + $N_\bullet,\ M_\bullet$ & Gear-shift / collocation-point count & --- \\ + $\Delta s_\bullet$ & Collocation step & m \\ + $\Delta_\text{slide}$ & Longitudinal slide margin & m \\ + $\Delta_\text{cut}$ & Lateral corner-cutting inset & m \\ + % $\rho_\varPsi,\ m_\varPsi,\ d_\varPsi,\ \varepsilon_\varPsi$ & Interaction radius / decay / clearance / distance regularizer & m, ---, m, m \\ + $\mathbf{z}$ & Stacked decision vector & --- \\ + \bottomrule + \end{tabular} + \end{table} + + \subsubsection{Objective Function} + \label{subsec:objective} + % \eqref{eq:overall_object} 所表示的目标函数定义为 + \begin{equation} + J = J_\ell + J_\text{gear} + J_U + J_\varPsi + J_\kappa + \label{eq:cost} + \end{equation} + % 本文将全部分项统一折算为\emph{等效通行耗时}(单位:秒),从而避免各权重携带互不相同的隐含量纲、也便于跨分项比较其相对重要性。为书写简洁,对两条路径权重相同的分项记 $\varGamma = \varGamma_\text{park} \cup \varGamma_\text{exit}$;而对两条路径取值不同的分项(\eqref{eq:cost_field}、\eqref{eq:cost_interaction})则显式列出两项。五个分项定义为 + \begin{subequations} \label{eq:cost_all} + \begin{align} + J_\ell & = \frac{1}{v_0} \int_{\varGamma} \mathrm{d}{s} + \label{eq:cost_time} \\ + J_\text{gear} & = t_0 \left( N_\text{park} + N_\text{exit} \right) + \label{eq:cost_gear} \\ + J_U & = \frac{1}{v_0} \left[ + w_U^\text{park} \int_{\varGamma_\text{park}} U_\text{park}(\mathbf{p}) \,\mathrm{d}{s} + + w_U^\text{exit} \int_{\varGamma_\text{exit}} U_\text{exit}(\mathbf{p}) \,\mathrm{d}{s} + \right] + \label{eq:cost_field} \\ + \begin{split} + J_\varPsi & = \frac{w_\varPsi}{\rho_\varPsi^2} + \int_{\varGamma_\text{park}} \int_{\varGamma_\text{exit}} + \tau_\text{d}\!\left( s_\text{park}, s_\text{exit} \right) \\ + & \quad \cdot K\!\left( d_{\varepsilon}(\mathbf{p}^\text{park},\mathbf{p}^\text{exit}); \rho_\varPsi, m_\varPsi \right) + \,\mathrm{d}s_\text{exit} \,\mathrm{d}s_\text{park} + \end{split} + \label{eq:cost_interaction} \\ + J_\kappa & = \frac{w_\kappa L_\text{v}^2}{v_0} \int_{\varGamma} \kappa^2(s) \,\mathrm{d}{s} + \label{eq:cost_smoothness} + \end{align} + \end{subequations} + % 其中 $N_\text{park}$ 与 $N_\text{exit}$ 分别为两条路径的换挡次数(与 \eqref{eq:ha_g_gear} 中的 $N$ 同义)。\eqref{eq:cost_time} 为车辆以场地内平均速度 $v_0$ 跟踪路径所需的行驶耗时,对应 \eqref{eq:cycle_time} 中的 $T_\text{park}$ 与 $T_\text{exit}$。该项的被积量为弧长微元、即本质上是路径长度代价(注:全文以 $\ell$ 表示由几何决定的长度量(路径剩余长度 $\ell_\text{rem}$、采样间距 $\ell_i$、边界顶点平均间距 $\bar\ell_\text{e}$),以 $L$ 表示车辆固定几何尺寸,以 $\Delta s$ 表示各类弧长离散步长);除以 $v_0$ 仅是为了与 \eqref{eq:cost} 中其余各项统一折算到秒,并不改变其“惩罚路径变长”的作用。 + + % \eqref{eq:cost_gear} 为换挡引入的真实时间损失:每次换挡期间车辆处于停止状态、耗时 $t_0$,故该项与换挡次数 $N$ 成正比、用于惩罚冗余的前进/后退切换。该项直接回应 Challenge 3 所述的减少冗余执行动作与机械损耗的要求。 + + % \eqref{eq:cost_field} 为路径在融合引导场(Integrated Guidance Field, IGF)中的势能积分(IGF 的定义详见第 \ref{sec:igf} 章)。注意,两条路径查询的是\emph{各自方向对应}的 IGF:$U_\text{park}$ 与 $U_\text{exit}$ 由 \eqref{eq:field_park}、\eqref{eq:field_exit} 分别定义,二者关于虚拟道路中线互为镜像。此处及全文的 $U$ 均指经 \eqref{eq:field_normalize} 平移归一化后的场值,故 $U \in [0,1]$,其在此被解释为等效减速因子,无量纲权重 $w_U^\bullet$ 的物理含义为路径完全偏离势谷($U \equiv 1$)时所额外付出的耗时倍数。 + + % \eqref{eq:cost_smoothness} 为路径平滑性代价,以车长 $L_\text{v}$ 为特征尺度使 $\kappa^2 L_\text{v}^2$ 无量纲化,其含义为路径弯曲导致的等效额外耗时;该项与 \eqref{eq:cons_kappa} 的曲率硬约束互补——后者保证可行性,前者在可行域内部进一步抑制曲率波动,以适配 Challenge 3 所述的液压转向迟滞特性。 + + % \eqref{eq:cost_interaction} 为双路径之间的交互惩罚,是本文实现双向空间解耦、进而压缩 \eqref{eq:cycle_time} 中 $T_\text{wait}$ 的核心项。它是一个沿两条路径的\emph{二重}弧长积分:$s_\text{park}$、$s_\text{exit}$ 分别为两条路径各自的弧长参数,$\mathbf{p}^\text{park} = \mathbf{p}^\text{park}(s_\text{park})$、$\mathbf{p}^\text{exit} = \mathbf{p}^\text{exit}(s_\text{exit})$ 为相应的路径点;核函数 $K$ 由 \eqref{eq:compact_kernel} 定义,其自变量为分属两条路径的点对间距,故两条路径上任意一对相互靠近的点都会贡献一份代价,且该贡献随间距增大而衰减、超出影响半径 $\rho_\varPsi$ 后为零。$\rho_\varPsi$、$m_\varPsi$ 分别为核的影响半径与衰减阶数,其取值依据详见 \ref{subsec:psi_build} 节。 + + % 与单纯的几何接近度惩罚不同,\eqref{eq:cost_interaction} 中每一对点的接近程度还额外乘以一个时延权重 $\tau_\text{d}$,其定义为 + \begin{equation} + \tau_\text{d}\!\left( s_\text{park}, s_\text{exit} \right) + = \frac{1}{v_0} + \left[ s_\text{exit} - s_\text{park} \right]_+ , + \qquad [\,\cdot\,]_+ \triangleq \max\{\cdot,\,0\} + \label{eq:cost_delay_weight} + \end{equation} + % 该权重的来由如下。设两车以相同的平均速度 $v_0$ 行驶、满载车在空载车开始泊入的同时启动驶离,则满载车通过其弧长 $s_\text{exit}$ 处的时刻为 $s_\text{exit}/v_0$,而空载车若不等待、将于 $s_\text{park}/v_0$ 时刻抵达其弧长 $s_\text{park}$ 处。若这两处恰为同一冲突点,则空载车必须推迟 $\left( s_\text{exit} - s_\text{park} \right)/v_0$ 才能避免与满载车相遇;该差为负时说明空载车本就晚于满载车通过该点、无需等待,故取正部。于是 $T_\text{wait}$ 即为全部冲突点对所要求的推迟量之上确界 + \begin{equation} + T_\text{wait} = \sup \left\{ + \tau_\text{d}\!\left( s_\text{park}, s_\text{exit} \right) + \;\middle|\; + \left\lVert \mathbf{p}^\text{park} - \mathbf{p}^\text{exit} \right\rVert \le B_\text{v} + \right\} + \label{eq:wait_as_sup} + \end{equation} + % 即 $T_\text{wait}$ 由\emph{最不利}的那一对冲突点决定。\eqref{eq:cost_interaction} 是 \eqref{eq:wait_as_sup} 的一个可微松弛:以核函数 $K$ 替代硬性的冲突判定 $\lVert \cdot \rVert \le B_\text{v}$,以加权积分替代上确界,从而使该指标可参与连续优化。除以 $\rho_\varPsi^2$ 是为抵消二重弧长积分所引入的面积量纲,使 $J_\varPsi$ 的量纲为秒、$w_\varPsi$ 与 \eqref{eq:cost_field} 中的 $w_U^\bullet$ 同为无量纲权重。 + + % 引入 $\tau_\text{d}$ 的必要性在于,路径重叠对 $T_\text{wait}$ 的贡献强烈依赖于\emph{重叠发生在何处},而不仅取决于重叠的几何程度。考察两个端点即可看出这一点:在装载位邻域,泊入路径已行至末端($s_\text{park}$ 接近其总长)而驶离路径刚刚起步($s_\text{exit} \approx 0$),故 $\tau_\text{d} = 0$——两车虽在\emph{空间}上必然重叠(\eqref{eq:cons_boundary} 要求其共享位姿),但在\emph{时间}上并不在此相遇,该处的重叠不产生任何等待;而在场地入口邻域情形恰好相反,$s_\text{park} \approx 0$ 而 $s_\text{exit}$ 接近驶离路径全长,空载车几乎须等待满载车驶完整条路径,$\tau_\text{d}$ 在此取到最大值。若如通常做法那样对全弧长的重叠等权计费,则装载位邻域这一\emph{不可消除且不产生等待}的结构性重叠会贡献大量代价,优化器将把改进余量耗费在无法改变、也无需改变的区域;加权之后,代价被自动集中到入口侧的通道,即真正决定 $T_\text{wait}$ 的位置。 + + % 需要说明 $\tau_\text{d}$ 对该项对称性的影响。$\tau_\text{d}$ 关于两条路径并不对称,故 \eqref{eq:cost_interaction} 不再像无权重的二重积分那样对两条路径完全等价——交换两条路径的角色会得到不同的数值。这一非对称性正是本文所需要的:它使排斥作用的强度本身就带有“满载车优先”的时序含义(详见 \ref{subsec:asymmetry} 节)。但该项对两条路径\emph{同时}可微这一性质不受影响:$\mathbf{p}^\text{park}$ 与 $\mathbf{p}^\text{exit}$ 在被积函数中仍处于对等地位,$\tau_\text{d}$ 亦仅依赖弧长参数而不依赖路径形状,因此该项的变分对两条路径的形状同时非零,这是第 \ref{sec:opt} 章将两条路径联立求解的依据(详见 \ref{subsec:joint_nlp} 节)。 + + \paragraph{Stagewise Objective Reduction} + % \eqref{eq:cost} 中的 $J_\text{gear}$ 依赖换挡次数 $N_\text{park}$、$N_\text{exit}$,而后者与 \eqref{eq:cons_kinodynamic} 中的档位序列 $\{\delta_j\}$ 同为离散决策量,因此 \eqref{eq:overall_problem} 整体上是一个混合整数非线性规划(MINLP)问题。本文并不直接求解该 MINLP,而是按 \ref{subsec:framework} 节所述的分阶段策略处理:离散量 $(N_\text{park}, N_\text{exit}, \{\delta_j\})$ 由第 \ref{sec:search} 章的启发式搜索确定,第 \ref{sec:opt} 章的优化阶段沿用之、仅对连续的路径形状求解。在这些离散量固定的前提下,优化阶段的目标函数为 + \begin{equation} + J_\text{opt} = J_\ell + J_U + J_\varPsi + J_\kappa + \label{eq:cost_opt} + \end{equation} + % 即 $J_\text{gear}$ 因 $N_\text{park}$、$N_\text{exit}$ 已固定而退化为常数、不影响极小点,故可从优化阶段的目标中略去。经此简化,第 \ref{sec:opt} 章所求解的是一个纯粹的非线性规划(NLP)问题,而 $J_\text{gear}$ 的作用完整地体现在搜索阶段对折点数量的抑制上(对应 \eqref{eq:ha_g_gear})。 + + % 需要强调的是,$J_\ell$ 不可从 \eqref{eq:cost_opt} 中一并略去,尽管它在形式上同样是“路程”而非“形状”的量。该项在本文的参数化下具有明确而有限的作用,须与其在自由长度参数化中的常见含义相区别。如 \ref{subsec:joint_nlp} 节所述,本文以粗解固定配置点数 $M_\bullet$,路径长度的唯一自由度是配置步长 $\Delta s_\bullet$,故由 \eqref{eq:cost_time} 离散得到的 $J_\ell$ 是 $\Delta s_\text{park}$、$\Delta s_\text{exit}$ 两个标量的线性函数。此时 $J_\ell$ 所抑制的是\emph{步长膨胀}:$J_U$、$J_\varPsi$ 与 $J_\kappa$ 均可通过放大 $\Delta s_\bullet$ 而在几何上“摊薄”——同样的形状以更大的步长走完,弯道被展开、势能与曲率的逐点取值下降,而 $J_\ell$ 是目标中唯一随 $\Delta s_\bullet$ 单调增长的项,因而确定了弯道展开程度的平衡点。类似的长度—平滑配重在弹性带类路径优化中亦是通行做法\cite{quinlan1991elastic,quinlan1994thesis},但需指出本文并不依赖该类方法中“无长度项则弯道无限外扩”的论证:在 $M_\bullet$ 固定且 $\Delta s_\bullet$ 受 \eqref{eq:cons_step_trust} 信赖域约束的参数化下,路径总长的可变范围本就是有界的。 + + \paragraph{Path Interaction Cost} + % \eqref{eq:cost_interaction} 的内层积分可单独解释为驶离路径所诱导的\emph{交互场} $\varPsi_\text{exit}$:其数值在靠近 $\varGamma_\text{exit}$ 时增大、在远离时衰减,于是 $J_\varPsi$ 即为一条路径在另一条路径所诱导的场中的势能积分。与由场地边界和引导规则离线构造的\emph{静态} IGF 不同,该场随对向路径的形状在求解过程中变化,其核参数取值依据与该记号的确切含义详见 \ref{subsec:psi_build} 节。 + + % 这里需要说明 \eqref{eq:cost_field} 与 \eqref{eq:cost_interaction} 之间的关系,二者并非重复计费,而是分别作用于\emph{标称先验}与\emph{实际实现}两个层面:$U_\text{park}$ 中的 $+U_\text{x}$ 项惩罚的是泊入路径偏离\emph{标称}驶离引导线 $\varLambda_\text{exit}$ 的程度,该引导线由场地几何离线确定、与本次求解的实际路径无关;而 $\varPsi_\text{exit}$ 惩罚的是泊入路径与\emph{本次实际求解出}的驶离路径之间的接近程度。由于装载位位置、车辆入场位姿的差异,实际路径可能显著偏离引导线(尤其在装载位附近的“分叉”段),此时仅靠静态 IGF 无法保证两条实际路径的分离,交互项因此是必要的。换言之,IGF 提供的是与求解无关的方向先验,交互项提供的是求解过程内部的耦合反馈。 + + \paragraph{Asymmetric Weighting of the Two Paths} + \label{subsec:asymmetry} + % 最后说明本文“非对称双通道”这一设计取向在目标函数中的实现方式。该取向源自矿区实际生产逻辑:满载车辆载重大、制动距离长,且其驶离路径的绕行会直接增加运输里程与油耗,而空载车辆机动性好、绕行代价低;因此在两条路径必须相互让开时,应主要由空载的泊入路径承担绕行。 + % 本文以两处机制共同实现这一取向,二者作用于不同层面。 + + % 其一是交互项自身所含的时序非对称。如 \eqref{eq:cost_delay_weight} 所述,$\tau_\text{d}$ 关于两条路径并不对称,故 \eqref{eq:cost_interaction} 对两条路径的作用强度天然不等。这一点值得强调,因为它区别于不加权的二重积分:若 $\tau_\text{d} \equiv 1$,则该项关于两条路径完全对称,此时\emph{无法}通过给两条路径分别加权来引入非对称——仿 \eqref{eq:cost_field} 的形式以 $w_\varPsi^\text{park}$、$w_\varPsi^\text{exit}$ 分别加权之和恒等于 $(w_\varPsi^\text{park} + w_\varPsi^\text{exit})$ 乘以同一个二重积分,两个权重只以其\emph{和}的形式进入目标,其比例对极小点毫无影响。引入 $\tau_\text{d}$ 后这一退化不再发生:代价被集中到 $s_\text{exit} > s_\text{park}$ 的点对上,即满载车尚未通过而空载车已抵达之处,排斥作用因而主要作用于泊入路径的前段。\eqref{eq:cost_interaction} 仍只保留单一权重 $w_\varPsi$,但其非对称性已由 $\tau_\text{d}$ 承载,无需依赖权重比例。 + + % 其二是两条路径各自\emph{抵抗偏离自身引导线}的代价。本文在 \eqref{eq:cost_field} 中取 + \begin{equation} + w_U^\text{exit} > w_U^\text{park} + \label{eq:asymmetric_weights} + \end{equation} + % 即以更大的权重将满载驶离路径约束在其引导线附近。其作用机理可作如下定性理解:在极小点处,交互项施于两条路径的排斥作用相互平衡,而各自 $J_U$ 项的增量必须与之相抵;$w_U$ 较大的一方为产生同等的 $J_U$ 增量只需较小的偏离,故位移较小。需要说明这仅是一种设计取向而非可严格量化的力学关系:$J_U$ 是场值沿弧长的积分、并非以引导线为平衡位置的二次恢复势,$U$ 在引导线邻域的形状由 \eqref{eq:compact_kernel} 的核决定,两条路径所感知的场也不严格相同,因此 $w_U^\text{exit}/w_U^\text{park}$ 与位移分配之比并无解析对应关系。该比值因而按 \ref{subsec:exp_setup} 节的方式经实验标定,其对位移分配的实际影响由 \ref{subsec:exp_ablation} 节的对照实验给出。 + + % 两处机制的分工可概括为:$\tau_\text{d}$ 决定排斥作用\emph{施加在何处}(沿弧长的分布),\eqref{eq:asymmetric_weights} 决定两条路径\emph{各自让开多少}(横向位移的分配)。若取 $w_U^\text{park} = w_U^\text{exit}$,则在 $\tau_\text{d}$ 较大的区段两条路径将对称地各自外扩,使满载路径同样被拉长;反之若仅靠 $w_U$ 的差异而不加 $\tau_\text{d}$,则排斥作用会均匀分布于全弧长,包括装载位邻域那些并不产生等待的重叠。二者因此不可相互替代。此外,\eqref{eq:asymmetric_weights} 的效果不依赖于求解方式:无论两条路径联立求解还是交替求解,$w_U$ 的差异都会如实反映在最终的位移分配上。 + + \subsubsection{Constraints} + \label{subsec:constraints} + % \eqref{eq:overall_eq}--\eqref{eq:overall_set} 所表示的约束项主要包含以下内容。 + + \paragraph{Piecewise Nonholonomic Kinematics} + % 装载场地内的泊入动作通常无法一次前进完成,而需要经由“前进—停顿—后退”的换向动作贴合装载位;因此本文不将路径视为单一的连续曲线,而是视为由若干\emph{同向段}首尾相接构成的分段曲线。记路径 $\varGamma$(可为 $\varGamma_\text{park}$ 或 $\varGamma_\text{exit}$)被划分为 $N+1$ 个同向段,第 $j$ 段的弧长区间为 $s \in [s_{j-1}, s_j]$、其行驶方向由档位指示 $\delta_j \in \{+1, -1\}$ 给出。由 \eqref{eq:cons_junction_gear},相邻段档位必反号,故 $N+1$ 个同向段之间恰含 $N$ 个换向折点。计入起步挂挡这一次,换挡总次数即为 $N+1$;为记法简洁,全文以 $N$ 表示换向折点数,并在 \eqref{eq:cost_gear}、\eqref{eq:ha_g_gear} 中以其惩罚换挡动作,省略与决策无关的起步常数项。则第 $j$ 个档位段内路径状态 $\mathbf{x}(s)$ 沿弧长的演化须满足 + \begin{equation} + \frac{\mathrm{d}\mathbf{x}}{\mathrm{d}s} + = \left[ \delta_j \cos{\theta(s)}, \; \delta_j \sin{\theta(s)}, \; \delta_j \kappa(s), \; \sigma(s) \right]^\top + \label{eq:cons_kinodynamic} + \end{equation} + % 其中 $\delta_j = +1$ 表示前进、$\delta_j = -1$ 表示后退,$s$ 始终为非负的已行驶路程。\eqref{eq:cons_kinodynamic} 的四个分量自下而上构成一条级联积分关系:曲率变化率 $\sigma$ 沿弧长积分得到曲率 $\kappa$,$\kappa$ 积分得到航向角 $\theta$,$\theta$ 再经 $[\cos\theta, \sin\theta]^\top$ 积分得到位置 $(x, y)$。该式同时从形式上体现了车辆运行的非完整性:车辆无法沿车身侧向运动,其可行路径的切向必须始终与航向共线(前进时同向、后退时反向)。 + + % 在相邻两段的衔接处 $s = s_j$,车辆处于静止状态并完成一次换挡,故其衔接条件为 + \begin{subequations} \label{eq:cons_junction} + \begin{align} + \boldsymbol{\eta}(s_j^-) & = \boldsymbol{\eta}(s_j^+) + \label{eq:cons_junction_pose} \\ + \delta_{j+1} & = -\delta_j + \label{eq:cons_junction_gear} + \end{align} + \end{subequations} + % 即位置与航向连续、行驶方向反号。 + + % \eqref{eq:cons_junction} \emph{不}要求 $\kappa$ 在衔接处连续:车辆在此已完全停止、前轮可原地转向,故 $\kappa$ 允许在换挡点跳变(即路径几何上的折点,cusp),相应地 \eqref{eq:cons_sigma} 的曲率变化率约束仅在\emph{段内}成立。 + + \paragraph{Curvature and Steering-Rate Limits} + % 车辆的物理约束如 \eqref{eq:cons_physics} 所示,其中 $R_\text{min}$ 是车辆的最小转弯半径,$\sigma_\text{max}$ 是车辆允许的最大曲率变化率: + \begin{subequations} \label{eq:cons_physics} + \begin{align} + & \left\lvert \kappa(s) \right\rvert \leq \kappa_\text{max} = \frac{1}{R_\text{min}}, + && s \in [0, s_\varGamma] + \label{eq:cons_kappa} \\ + & \left\lvert \sigma(s) \right\rvert \leq \sigma_\text{max}, + && s \in (s_{j-1}, s_j) + \label{eq:cons_sigma} + \end{align} + \end{subequations} + % $\sigma_\text{max}$ 反映了液压转向系统的响应能力:转向机构在单位行驶距离内能够改变的前轮转角有限,该约束因此保证了路径曲率的连续性与可跟踪性,对应 Challenge 3 所述的曲率变化率连续要求。 + + % 此处需说明 $\sigma_\text{max}$ 的量纲折算及其保守性,因为它关系到 \eqref{eq:cons_sigma} 在装载位邻域的松紧程度。转向系统的物理限制是前轮转角的\emph{时间}导数上界 $\dot\psi_\text{max}$,而本文的路径规划以弧长 $s$ 为自变量、不含时间,二者相差一个速度因子。由自行车模型 $\kappa = \tan\psi / L_\text{w}$ 与链式法则, + \begin{equation} + \sigma = \frac{\mathrm{d}\kappa}{\mathrm{d}s} + = \frac{1}{L_\text{w}\cos^{2}\psi} \cdot \frac{\mathrm{d}\psi}{\mathrm{d}s} + = \frac{\dot\psi}{L_\text{w} v \cos^{2}\psi} , + \label{eq:sigma_time_conversion} + \end{equation} + % 可见同一个 $\dot\psi_\text{max}$ 在低速时对应更宽松的弧长导数上界。本文按标称速度 $v_0$ 折算,并在 $\psi$ 的允许范围内取使 \eqref{eq:sigma_time_conversion} 右端最小的一档(即 $\psi = 0$、$\cos^2\psi = 1$),得保守常值 $\sigma_\text{max} = \dot\psi_\text{max} / (L_\text{w} v_0)$。该折算在车辆实际速度低于 $v_0$ 的区段是\emph{偏保守}的:车辆开得越慢,单位弧长内可用的转角变化越多,而 \eqref{eq:cons_sigma} 并未据此放宽。这一保守性恰好落在装载位邻域——该处车辆减速、换向,同时也是可行空间最紧、最需要急转的地方。采用常值 $\sigma_\text{max}$ 的理由是本文不规划速度剖面(速度由下游的跟踪控制器决定),故无从在规划阶段得知各段的实际速度;代价是可能拒绝一部分实际可跟踪的路径,即该约束是可行性的充分而非必要条件。若后续引入分段速度剖面,可按段替换为 $\sigma_\text{max}^{(j)} \propto 1/v_j$ 以回收这部分余量。本文实车试验中实测的前轮转角速率是否触及 $\dot\psi_\text{max}$,见 \ref{subsec:exp_realvehicle} 节。 + + \paragraph{Boundary Conditions} + % 本研究中共有三个固定位姿需要处理。进入位姿 $\boldsymbol{\eta}_\text{enter}$ 表示车辆进入装载场地的入口位姿,即泊入路径的起点;装载位姿 $\boldsymbol{\eta}_\text{load}$ 表示车辆进行采装作业的位姿,它既是泊入路径的终点、又是驶离路径的起点;离开位姿 $\boldsymbol{\eta}_\text{leave}$ 表示车辆最终离开采装场地的位姿,即驶离路径的终点。三者均由上层派车系统给出,是本问题框架下的固定值、即优化问题的硬约束: + \begin{subequations} \label{eq:cons_boundary} + \begin{align} + \boldsymbol{\eta}^\text{park}(0) & = \boldsymbol{\eta}_\text{enter}, + & \boldsymbol{\eta}^\text{park}(s_\text{park}) & = \boldsymbol{\eta}_\text{load} + \label{eq:cons_bc_park} \\ + \boldsymbol{\eta}^\text{exit}(0) & = \boldsymbol{\eta}_\text{load}, + & \boldsymbol{\eta}^\text{exit}(s_\text{exit}) & = \boldsymbol{\eta}_\text{leave} + \label{eq:cons_bc_exit} + \end{align} + \end{subequations} + % 其中,$\boldsymbol{\eta}^\text{park}(\cdot)$ 与 $\boldsymbol{\eta}^\text{exit}(\cdot)$ 分别为泊入、驶离路径上的位姿,$s_\text{park}$ 与 $s_\text{exit}$ 为两条路径各自的总弧长。需要注意的是,\eqref{eq:cons_boundary} 仅约束位姿 $\boldsymbol{\eta} = [x, y, \theta]^\top$ 而\emph{不}约束曲率 $\kappa$:车辆在这三处均处于静止或准静止状态,其前轮转角可自由调整,两条路径各自端点处的曲率作为自由变量交由优化过程确定。\eqref{eq:cons_boundary} 中 $\boldsymbol{\eta}_\text{load}$ 在两式中同时出现,表明两条路径在装载位处共享同一\emph{位姿},这也是双路径问题在几何上的衔接条件。但二者在该点处并不共享曲率与档位:车辆在装载位需完全停止以完成采装作业,其停留时间远大于一次换挡耗时,故装载位本身即一个天然的换向点——若车辆倒车泊入($\delta = -1$),则其驶离动作通常以前进($\delta = +1$)开始,\eqref{eq:cons_junction} 所述的衔接条件在该点同样成立。 + + \paragraph{Collision-Avoidance Constraints} + % 为了保证路径在装载场地空间内安全行驶,本研究要求两条路径的扫掠域完全落在可行驶区域之内: + \begin{equation} + D(\varGamma_\text{park}) \cup D(\varGamma_\text{exit}) \subseteq \Omega_\text{free} + \label{eq:cons_collision} + \end{equation} + % 其中,$\Omega_\text{free} = \Omega_\text{site} \setminus \Omega_\text{obs}$ 表示装载场地内的可行驶区域,$\Omega_\text{site}$ 为场地边界所围成的区域、$\Omega_\text{obs}$ 为障碍物(含挖掘机、矿料堆及其他静态障碍)所占据的空间,$\partial\Omega_\text{free}$ 为可行驶区域的边界。 + + % \eqref{eq:cons_collision} 在数值优化中难以直接处理:$\Omega_\text{free}$ 由不规则的场地边界点云描述、其形状非凸,而扫掠域 $D(\varGamma)$ 又是决策变量的泛函。尤其在矿区装载场地这类狭窄空间中,可行域本身十分逼仄,直接以障碍点距离形式施加约束会产生大量非凸约束、严重损害求解效率与收敛性。为此,第 \ref{sec:opt} 章提出一种开辟最大凸空间的处理方法:沿粗解将 $\Omega_\text{free}$ 分解为一列相互重叠的凸多面体 $\{\mathcal{P}_k\}$,并将 \eqref{eq:cons_collision} 松弛为“各路径段的车辆凸四边形轮廓顶点落在对应凸多面体内”的线性不等式约束,从而在保持安全性的同时获得可由数值方法高效求解的凸可行域。 + + \subsection{Three-Stage Planning Framework} + \label{subsec:framework} + % \eqref{eq:overall_problem} 所定义的问题难以直接求解,其困难来自三个方面:其一,\eqref{eq:cost_interaction} 使两条路径相互耦合,任一路径的代价依赖于另一条路径的求解结果;其二,\eqref{eq:cons_kinodynamic} 的换挡次数 $N$ 与各段档位 $\delta_j$ 是离散决策量,与连续的路径形状一同构成混合整数问题;其三,\eqref{eq:cons_collision} 的可行域非凸且在狭窄场地内十分逼仄。因此本文不采用单一求解器直接处理该问题,而是将其分解为“离线先验构建—在线粗解搜索—联合数值优化”三个阶段依次求解,整体框架如图 \ref{fig:framework} 所示。 + + % 第一阶段(第 \ref{sec:igf} 章 \ref{subsec:igf_build} 节)在离线阶段完成双向通行先验的构建。该阶段自场地边界点云出发,先经扩展维诺骨架提取与二次规划平滑得到虚拟道路中线 $\varLambda_\text{center}$,再沿其法向偏移生成进出双向引导线 $\varLambda_\text{park}$、$\varLambda_\text{exit}$,最终将场地边界与两条引导线离散为势源、叠加为两个方向性引导场 $U_\text{park}$、$U_\text{exit}$。该阶段的意义在于,双向空间解耦这一拓扑要求被\emph{前置固化}在场的构造之中:两个场关于中线互为镜像,泊入路径所感知的势谷恰为驶离路径所感知的脊线。由此,Challenge 2 所述的拓扑稳定性得以保证——中线只沿进出场地的主通道提取、不经过装载位(详见 \ref{subsec:centerline} 节),故装载位变更时引导场无需重建(场地边界未变),仅需以新的边界条件重新求解路径,而路径的空间拓扑由不变的引导场先验决定。 + + % 第二阶段(第 \ref{sec:search} 章)在两个方向性场上分别进行启发式搜索,生成两条路径的初值粗解。由于空间解耦要求已由第一阶段的场先验承担,该阶段的 $\varGamma_\text{park}$ 与 $\varGamma_\text{exit}$ 可在各自的场上\emph{独立且并行}地求解,无需按特定顺序串行迭代,从而避免了耦合搜索所面临的状态空间维度膨胀。相应地,该阶段求解的是 \eqref{eq:cost} 的一个简化代理——以 \eqref{eq:ha_g} 定义的广义通行耗时替代完整目标函数,其中交互项 $J_\varPsi$ 被暂时略去、而由 $U_\text{park}$、$U_\text{exit}$ 中的静态排斥项近似承担解耦作用。该阶段的输出确定了 \eqref{eq:cons_kinodynamic} 中的离散量:换挡次数 $N$ 与各段档位 $\delta_j$,即混合整数问题中的整数部分在此被固定。 + + % 第三阶段(第 \ref{sec:opt} 章)以粗解为初值,对两条路径进行联合数值优化。该阶段沿用第二阶段确定的分段结构,因此 \eqref{eq:cost} 退化为 \eqref{eq:cost_opt} 所示的关于连续路径形状的 NLP 问题、\eqref{eq:cost_gear} 退化为常数;同时 \eqref{eq:cons_collision} 经凸分解转化为线性不等式约束,\eqref{eq:cons_sigma} 所要求的曲率连续性亦在此阶段首次被完整施加——粗解仅满足曲率上界,其曲率剖面在基元拼接点处的跳变由本阶段消除。两条路径之间的真正协同发生在本阶段:两条路径被堆叠为单一决策变量、经 \eqref{eq:cost_interaction} 所定义的交互项联立求解,使其在满足各自运动学与避碰约束的前提下进一步相互推离,压缩其时空冲突区域。 + + % 综上,该框架的设计逻辑可概括为:将难以在线处理的拓扑要求转化为离线场先验,将混合整数问题中的离散决策交由图搜索确定,将非凸避碰约束经凸分解交由数值优化处理,从而以三个各自可高效求解的子问题逼近 \eqref{eq:overall_problem} 的解。这一分解的代价是不再保证全局最优性,其来源有二——状态格判重与启发函数的不可采纳性,相应的讨论分别见 \ref{subsec:primitive} 节与 \ref{subsec:heuristic} 节。 + + \begin{figure}[htbp] + \centering + \includegraphics{fig_framework} + \caption{Overall framework of the proposed method. The offline stage builds the directional + guidance fields $U_\text{park}$ and $U_\text{exit}$ from the site boundary; the online stage + searches two coarse paths in parallel on the corresponding fields and then jointly + refines them within convex corridors.} + \label{fig:framework} + \end{figure} + +\section{Construction of Integrated Guidance Fields} + \label{sec:igf} + % 集成引导场的构建 + % 如 \ref{subsec:proxy} 节所述,进出路径的空间分离能够减少车辆因共享通道而产生的交会冲突与等待。本章据此将进出双路径的空间关系转化为集成引导场(IGF),为第 \ref{sec:search} 章的粗解搜索提供拓扑引导。 + + % IGF 的构建分三步:先提取虚拟道路中线,再沿其法向偏移生成进出双向引导线,最后将场地边界与两条引导线离散为势源、叠加并归一化为方向性引导场。矿山装载场地内没有城市道路那样显式的车道限制\cite{mine2024unstructured},已有工作依据地形与作业特点制定显式行驶规则(渠化车道或固定参考路线),实现双向车流在空间层面的解耦。本文沿用"先建立双向参考基准、再据此约束路径"这一思路,首先生成装载场地内的进出双向引导路线(\ref{subsec:centerline}、\ref{subsec:guide_route} 节),再据此构建引导场(\ref{subsec:igf_build} 节)。 + + \subsection{Virtual Road Centerline Extraction} + \label{subsec:centerline} + % 构建虚拟道路中线 + % 对于需要组织双向通行的场地,可先提取自由空间的中轴线,再以其为几何基准构造两个方向的参考路线。对于矿区装载场地,其边界形状不规则、不连续,无法从数学上描述边界走势,边界噪声不可微,导致“道路中线”无法被解析推导。基于搜索的方法获取“道路中线”时,又受制于代价函数的复杂设计和对场景的严苛假设,致使相关方法难以适配矿区装载场地。基于人工势场的方法虽然泛化性强,但其陷入局部极小无法跳出\cite{apf2024wallfollower}、且在贴近障碍处势场导数急剧增大而致路径质量下降\cite{apf2024globalrepulsive},限制了其在真实生产中的应用。 + % 扩展维诺图(Extended Voronoi Graph, EVG)\cite{beeson2005evg}是一种按与障碍物最近距离划分空间的空间表示,其克服了传统维诺图方法对场景中噪声敏感的问题,能够获取高质量的行驶走廊中轴骨架。在实现上,本文采用 EVG-thin 细化算法\cite{evgthin}从栅格占据图中逼近提取该扩展维诺骨架,相比解析构造维诺边的方式更为高效、且对边界噪声更鲁棒。 + + % 首先对栅格化后的装载场地边界,采用 EVG-thin 细化算法提取扩展维诺意义下的自由空间中轴骨架。随后在该骨架图上使用 A* 连接进入位姿 $\boldsymbol{\eta}_\text{enter}$ 与离开位姿 $\boldsymbol{\eta}_\text{leave}$ 的位置分量,得到原始虚拟道路中线$\varLambda_\text{center}^{\text{ref}}=\{\mathbf{q}_{i}^{\text{ref}}\}_{i=1}^{N_\text{c}}$,其中 $\mathbf{q}_{i}^{\text{ref}}=[x_{i}^{\text{ref}},y_{i}^{\text{ref}}]^\top$。对该原始中线进一步进行等弧长重采样,并结合一维插值与梯度平滑做轻量正则化。 + + % 需要强调中线的端点取法:$\varLambda_\text{center}$ 只连接进出场地的两个\emph{通道}端点,而\emph{不}经过装载位 $\boldsymbol{\eta}_\text{load}$。这一取法是 Challenge 2 所述拓扑稳定性得以成立的前提。若如通常做法那样将装载位一并作为中线的途经点,则装载位每次变更都会改变 $\varLambda_\text{center}$ 的走势,两条引导线与由其诱导的引导场随之改变,\ref{subsec:framework} 节所称“装载位变更时引导场无需重建”便不再成立;而将装载位排除在中线之外后,中线仅由场地边界几何决定,其对装载位的变更完全不敏感。相应地,装载位不再由场先验表达,而是作为 \eqref{eq:cons_boundary} 的边界条件在搜索阶段施加:路径沿引导场的势谷行至装载位附近后,经 \ref{subsec:primitive} 节的解析扩展从主通道“分叉”至指定的装载位姿。换言之,引导场承担的是\emph{主通道内双向通行的拓扑},装载位的对齐由边界条件与解析扩展承担,二者的分工也正是 \ref{subsec:heuristic} 节中启发函数只取当前节点场值、不取累计值的原因。 + % 由于骨架离散误差和图搜索分支的影响,路径中仍可能保留局部离群点和锯齿段。为在保持全局拓扑结构不变的前提下抑制这些局部伪影,本文复用 Apollo 提出的 FEM-pos 参考线平滑方法\cite{zhou2020apolloqp,fan2018apolloem}对中线做进一步正则化优化。 + + % 对原始中线上的每个采样点,根据参考航向分别计算其局部单位切向量和单位法向量: + \begin{equation} + \mathbf{t}_i = + \begin{bmatrix} + \cos\theta_i^\text{ref} \\ + \sin\theta_i^\text{ref} + \end{bmatrix}, \qquad + \mathbf{n}_i = \begin{bmatrix} -t_{i,y} \\ t_{i,x} \end{bmatrix}, + \label{eq:tangent_normal} + \end{equation} + % 其中 $\mathbf{t}_i=[t_{i,x},t_{i,y}]^\top$,$\theta_i^\text{ref}$ 由插值及梯度平滑后的参考中线计算得到,首尾若干点采用入口与离开方向先验。记$\bar{\mathbf{q}}=[\mathbf{q}_{1}^\top,\mathbf{q}_{2}^\top,\dots,\mathbf{q}_{N_\text{c}}^\top]^\top$为优化后中线 $\varLambda_\text{center}=\{\mathbf{q}_{i}\}_{i=1}^{N_\text{c}}$ 的堆叠优化变量。该平滑优化沿用 FEM-pos 参考线平滑器\cite{zhou2020apolloqp}的建模思路,其目标由 FEM-pos 平滑项、路径长度项与参考偏移项构成;区别在于,本文在 \eqref{eq:local_corridor_tangent}--\eqref{eq:local_corridor_normal} 中引入由场地边界点云自动生成的切向-法向走廊,并施加曲率上界约束以适配矿区大转弯半径车辆。 + % 加入曲率约束后的平滑问题可写为 + \begin{subequations} \label{eq:qp_problem} + \begin{align} + \min_{\bar{\mathbf{q}},\,\boldsymbol{\varepsilon}} \quad + & J_\text{center} = J_\text{fem} + J_\text{len} + J_\text{ref} + J_\text{slack} + \label{eq:qp_obj_mixed} \\ + \text{s.t.} \quad + & \mathbf{A}_i^\text{c} \mathbf{q}_i \le \mathbf{b}_i^\text{c},\quad i=1,\dots,N_\text{c} + \label{eq:qp_constraints} \\ + & \|\mathbf{d}_i\|^2 + \le (\ell_i^2\kappa_\text{max})^2+\varepsilon_i,\quad i=2,\dots,N_\text{c}-1 + \label{eq:qp_curvature} \\ + & \varepsilon_i \ge 0,\quad i=2,\dots,N_\text{c}-1 + \label{eq:qp_slack} \\ + \text{where}\quad + & \mathbf{d}_i = \mathbf{q}_{i-1}-2\mathbf{q}_i+\mathbf{q}_{i+1}. + \notag + \end{align} + \end{subequations} + % 其中,各目标项定义为 + \begin{subequations} \label{eq:qp_obj_all} + \begin{align} + J_\text{fem} & = w_\text{fem} \cdot \sum_{i=2}^{N_\text{c}-1} \left\lVert \mathbf{q}_{i-1} - 2\mathbf{q}_i + \mathbf{q}_{i+1} \right\rVert^2 \label{eq:qp_obj1} \\ + J_\text{len} & = w_\text{len} \cdot \sum_{i=1}^{N_\text{c}-1} \left\lVert \mathbf{q}_{i+1} - \mathbf{q}_i \right\rVert^2 \label{eq:qp_obj2} \\ + J_\text{ref} & = w_\text{ref} \cdot \sum_{i=1}^{N_\text{c}} \left\lVert \mathbf{q}_i - \mathbf{q}_i^\text{ref} \right\rVert^2 \label{eq:qp_obj3} \\ + J_\text{slack} & = w_{\varepsilon} \cdot \sum_{i=2}^{N_\text{c}-1} \varepsilon_i \label{eq:qp_obj4} + \end{align} + \end{subequations} + % 在 \eqref{eq:qp_obj_all} 中,前三项沿用 FEM-pos 平滑器\cite{zhou2020apolloqp}的标准定义:$J_\text{fem}$ 为有限元位置偏差平滑项,通过二阶差分抑制高频几何振荡、提升中线平滑性;$J_\text{len}$ 通过一阶差分惩罚相邻采样点间距,等价约束路径总长;$J_\text{ref}$ 惩罚优化中线相对原始 EVG-A* 中线的偏移。$J_\text{slack}$ 则为本文为引入曲率约束而增设的松弛惩罚项,$\boldsymbol{\varepsilon}=[\varepsilon_2,\dots,\varepsilon_{N_\text{c}-1}]^\top$ 为非负松弛变量。式 \eqref{eq:qp_curvature} 是对曲率上界的离散化表达。对间距为 $\ell$ 的等弧长折线,其二阶差分 $\mathbf{d}_i=\mathbf{q}_{i-1}-2\mathbf{q}_i+\mathbf{q}_{i+1}$为离散的二阶导数,与该点曲率满足$\left\lVert \mathbf{d}_i \right\rVert = \ell^2 \kappa_i + O(\ell^4)$,因此曲率约束 $\kappa_i \le \kappa_\text{max}$ 可改写为 \eqref{eq:qp_curvature} 中对$\left\lVert \mathbf{d}_i \right\rVert^2$ 的上界约束,其中 $\kappa_\text{max}=1/R_\text{min}$ 为车辆最小转弯半径对应的曲率上界。该换算关系的推导、误差量级以及采用平方形式的原因见补充材料 S-V;以 $R_\text{min} = 12$~m、$\ell = 1$~m 计,其相对误差约 $0.06\%$,且该近似在安全性上偏保守。由于重采样后各段长度并非严格相等,此处的换算尺度取第 $i$ 个点左右两段的平均长度 $\ell_i = \tfrac{1}{2} ( \lVert \mathbf{q}_i^\text{ref} - \mathbf{q}_{i-1}^\text{ref} \rVert + \lVert \mathbf{q}_{i+1}^\text{ref} - \mathbf{q}_i^\text{ref} \rVert )$。 + + % \eqref{eq:qp_problem} 是一个\emph{凸} QCQP:$\mathbf{d}_i$ 关于 $\mathbf{q}$ 线性,故 $\lVert \mathbf{d}_i \rVert^2$ 与 \eqref{eq:qp_obj_all} 各项同为凸二次、\eqref{eq:qp_constraints} 为线性,其局部最优即全局最优。序列化求解并非因非凸性,而是出于求解器接口:OSQP 仅接受线性约束,故将 \eqref{eq:qp_curvature} 在当前迭代点线性化后转为一列 QP 依次求解,并逐步增大松弛权重 $w_{\varepsilon}$ 以渐次收紧曲率约束。等弧长重采样则是上述二阶差分换算成立的前提。 + + % 为限制平滑后的中线偏离自由空间骨架,本文在每个参考点附近建立局部切向--法向矩形走廊。走廊边界由车载激光雷达获取并按左右两侧划分的场地边界点云自动确定,并施加安全收缩。记 $s_i^-$、$s_i^+$ 为切向后向与前向边界,$l_i^-$、$l_i^+$ 为法向右向与左向边界,则优化点 $\mathbf{q}_i$ 满足 + \begin{subequations} + \begin{align} + -s_i^- &\le \mathbf{t}_i^\top(\mathbf{q}_i-\mathbf{q}_i^\text{ref}) \le s_i^+ \label{eq:local_corridor_tangent} \\ + -l_i^- &\le \mathbf{n}_i^\top(\mathbf{q}_i-\mathbf{q}_i^\text{ref}) \le l_i^+ . \label{eq:local_corridor_normal} + \end{align} + \end{subequations} + % 该局部约束等价于紧凑的全局半空间形式 $\mathbf{A}_i^\text{c}\mathbf{q}_i\le\mathbf{b}_i^\text{c}$,并代入 \eqref{eq:qp_constraints}。其中 $\mathbf{A}_i^\text{c}$、$\mathbf{b}_i^\text{c}$ 由上述四个边界和参考点坐标直接确定。该走廊仅用于中线及引导线的几何平滑,不保证最终车辆扫掠域无碰;后者由第 \ref{sec:opt} 章的凸分解走廊和车辆角点约束保证。本小节的完整构造过程如图 \ref{fig:center} 所示:图 \ref{fig:center}(a) 给出自由空间的距离场、由其脊线提取的 EVG 骨架以及骨架图上的 A* 粗解,图 \ref{fig:center}(b) 给出局部切向--法向走廊与 QP 平滑所得的 $\varLambda_\text{center}$,图 \ref{fig:center}(c) 则对比平滑前后的离散曲率剖面,可见粗解的折角处曲率远超 $\kappa_\text{max}$,而平滑后全程满足 \eqref{eq:qp_curvature} 的上界。 + \begin{figure*}[htbp] + \centering + \includegraphics{fig_center} + \caption{Construction of the virtual road centerline on a synthetic loading site. + (a) Clearance field of the free space, the EVG-thin skeleton extracted from its + ridge, and the coarse A$^\ast$ path from the entrance to the loading bay. + (b) Local tangent--normal corridors of \eqref{eq:local_corridor_tangent} and + \eqref{eq:local_corridor_normal} around each reference point, and the centerline + $\varLambda_\text{center}$ returned by the FEM-pos QP smoother \eqref{eq:qp_problem}. + (c) Discrete curvature profiles before and after smoothing, obtained from the + second difference of \eqref{eq:qp_curvature}, against the bound + $\kappa_\text{max}=1/R_\text{min}$. This figure illustrates the geometric + construction and is not an experimental result.} + \label{fig:center} + \end{figure*} + + \subsection{Inbound and Outbound Guidance-Line Generation} + \label{subsec:guide_route} + % 生成双向引导路线 + % 基于优化后的虚拟道路中线 $\varLambda_{\text{center}}$,沿中线上各点的局部法向正、负方向分别偏移 $\frac{W}{2}$,生成进场参考路线 $\varLambda_{\text{park}}$ 与离场参考路线 $\varLambda_{\text{exit}}$。其中,$W$ 表示虚拟道路宽度,局部法向量由式 \eqref{eq:tangent_normal} 确定。然而,在曲率较大的区域,直接采用等距法向偏移所生成的参考路线容易出现局部卷曲与折角现象,如图~a 所示。为提高参考路线的几何连续性与平滑性,本文依次采用路径采样、插值重构和平滑优化方法对原始偏移曲线进行处理,平滑优化所采用的二次规划模型与前文保持一致。这两条引导线并不是车辆最终可执行路径,而是作为后续代价场构建和初始路径搜索的方向先验。由 \eqref{eq:reference_offset} 可见,两条引导线的弧长范围完全由 $\varLambda_\text{center}$ 继承,因此与中线一样只覆盖入口—出口主通道;在装载位所在的支路区域,方向性势源 $\mathcal{S}_\text{p}$、$\mathcal{S}_\text{x}$ 的支撑集之外,引导场退化为仅由场地边界 $\mathcal{S}_\text{e}$ 诱导的排斥场。这一退化是有意为之:该区域两条路径按 \eqref{eq:cons_boundary} 必须收敛到同一装载位姿,本不存在需要由场先验表达的双向拓扑,此处只需保证避障即可。因此影响半径 $\rho_\text{p}$、$\rho_\text{x}$ 的取值只需覆盖主通道宽度,无需延伸至支路。 + \begin{equation} + \tilde{\mathbf{q}}_i^{\text{park}} = \mathbf{q}_i + \frac{W}{2} \mathbf{n}_i,\qquad + \tilde{\mathbf{q}}_i^{\text{exit}} = \mathbf{q}_i - \frac{W}{2} \mathbf{n}_i. + \label{eq:reference_offset} + \end{equation} + + \subsection{Guidance Field Construction and Normalization} + \label{subsec:igf_build} + % 基于有限支撑核函数和离散势源集合的离线势场构建 + % 将装载场地边界以及两条方向性引导线离散化,得到三个势源点集合 $\mathcal{S}_\text{e}$、$\mathcal{S}_\text{p}$、$\mathcal{S}_\text{x}$,下标分别对应场地边界、泊入引导线和驶离引导线。为避免在线规划阶段逐点累积全部势源的影响,本文在离线阶段预先在均匀栅格上构建融合引导场:取覆盖装载场地的轴对齐包围盒,以分辨率 $\delta$ 在其上铺设均匀栅格,记全部栅格中心构成的有限点集为 $\Xi = \{\, \mathbf{p}_0 + \delta [\,j,\ k\,]^\top \mid 0 \le j < N_x,\ 0 \le k < N_y \,\}$,其中 $\mathbf{p}_0$ 为包围盒左下角的栅格中心,$N_x$、$N_y$ 为两个方向的栅格数。沿用第 \ref{sec:problem} 章的约定,栅格中心作为势场查询点是工作空间中的几何点,为区别于势源点、在下文中专记为 $\boldsymbol{\zeta}$。对于任一栅格中心 $\boldsymbol{\zeta}\in\Xi$,势源集合 $\mathcal{S}$ 对该点的影响通过一个有限支撑核函数计算: + \begin{equation} + K(d;\rho,m)= + \begin{cases} + \left(1-\dfrac{d}{\rho}\right)^m, & 0\le d<\rho \\ + 0, & d\ge \rho + \end{cases} + \label{eq:compact_kernel} + \end{equation} + % 其中,$\rho$ 表示影响半径,$m$ 用于控制核函数的衰减速率。由势源集合 $\mathcal{S}$ 诱导得到的标量场可进一步定义为 + \begin{equation} + U_{\mathcal{S}}(\boldsymbol{\zeta}) + = + \alpha_{\mathcal{S}} + \sum_{\boldsymbol{\xi}\in\mathcal{S}} + K\!\left( + \left\lVert \boldsymbol{\zeta}-\boldsymbol{\xi} \right\rVert; + \rho_{\mathcal{S}},m_{\mathcal{S}} + \right)\Delta s_{\boldsymbol{\xi}}, + \label{eq:source_field} + \end{equation} + % 其中,$\alpha_{\mathcal{S}}$ 为场强系数,$\Delta s_{\boldsymbol{\xi}}$ 为势源点 $\boldsymbol{\xi}$ 所代表的线元长度。三个势源集合均沿折线分布:$\mathcal{S}_\text{p}$ 与 $\mathcal{S}_\text{x}$ 为两条方向性引导线的等弧长采样点,$\mathcal{S}_\text{e}$ 为描述装载场地边界的不规则闭合多边形的顶点序列。 + % 对场地边界,由于其顶点由感知模块直接给出、相邻顶点间距不均匀且不具备明确的弧长语义,本文取 $\Delta s_{\boldsymbol{\xi}} \equiv 1$,即以顶点计数的形式累积边界排斥作用。该处理使 $U_\text{e}$ 与 $U_\text{p}$、$U_\text{x}$ 之间相差一个采样密度量纲,该差异可由场强系数 $\alpha_{\mathcal{S}}$ 进行调节,其标定条件满足 \eqref{eq:alpha_dominance}。 + + % 由 \eqref{eq:compact_kernel} 的有限支撑性质可给出各分场的取值范围:下界平凡地为 $0$,上界则由势源在支撑域内的最大累积量确定,其推导见补充材料 S-I。其中下标 $\text g \in \{\text p, \text x\}$ 表示两条方向性引导线中的任一条,二者因关于中线几何对称而取相同的 $\alpha$、$\rho$ 与 $m$,故共享同一上界。 + \begin{subequations} \label{eq:field_bounds} + \begin{align} + 0 \le U_\text{g} & \le + \alpha_\text{g} \int_{-\rho_\text{g}}^{\rho_\text{g}} + \left( 1 - \frac{|t|}{\rho_\text{g}} \right)^{m_\text{g}} \mathrm{d}t + = \frac{2\alpha_\text{g} \rho_\text{g}}{m_\text{g} + 1} + \triangleq U_\text{g}^\text{max} + \label{eq:bound_guide} \\ + 0 \le U_\text{e} & \le + \alpha_\text{e} \left( \frac{2\rho_\text{e}}{\bar\ell_\text{e}} + 1 \right) + \triangleq U_\text{e}^\text{max} + \label{eq:bound_edge} + \end{align} + \end{subequations} + % 其中 $\bar\ell_\text{e}$ 表示边界多边形相邻顶点的平均间距。两个上界的一处结构性差异需在此指出:$U_\text{g}^\text{max}$ 与采样密度无关,而 $U_\text{e}^\text{max}$ 反比地依赖于 $\bar\ell_\text{e}$,故更换感知配置或边界提取分辨率时须对 $\alpha_\text{e}$ 重新标定。此外,\eqref{eq:bound_edge} 在凹形拐角处是典型量级的估计而非全局上界,其代价与所采取的截断处理见下文 \eqref{eq:field_normalize} 处的说明,严格上界的构造见补充材料 S-I。综合 \eqref{eq:field_bounds} 与 \eqref{eq:field_park}、\eqref{eq:field_exit} 中各项的符号,可得组合场的先验取值区间 + \begin{equation} + U_\text{park},\, U_\text{exit} \in + \left[ -U_\text{g}^\text{max},\; U_\text{e}^\text{max} + U_\text{g}^\text{max} \right] + \label{eq:field_range} + \end{equation} + % 其中 $U_\text{e}^\text{max}$ 与 $U_\text{g}^\text{max}$ 为 \eqref{eq:field_bounds} 所定义的两个上界。该区间为后文 \eqref{eq:field_normalize} 的归一化提供了与具体场地无关的先验范围。 + + % 将 \eqref{eq:source_field} 分别作用于上述三个势源集合后,可得到边界场 $U_\text{e}$、泊入通道场 $U_\text{p}$ 和驶离通道场 $U_\text{x}$。其中,$U_\text{e}$ 在靠近装载区边界时形成排斥脊线,而 $U_\text{p}$ 与 $U_\text{x}$ 则分别编码双向通道的空间先验。 + + % 对于泊入动作,本文将 $U_\text{p}$ 视为吸引势谷、将 $U_\text{x}$ 视为排斥脊线;对于驶离动作,则相反地将 $U_\text{x}$ 视为吸引势谷、将 $U_\text{p}$ 视为排斥脊线。由此可分别定义面向两种行驶方向的 IGF: + \begin{subequations} + \begin{equation} + U_\text{park}(\boldsymbol{\zeta}) + = + U_\text{e}(\boldsymbol{\zeta}) + - + U_\text{p}(\boldsymbol{\zeta}) + + + U_\text{x}(\boldsymbol{\zeta}), + \label{eq:field_park} + \end{equation} + \begin{equation} + U_\text{exit}(\boldsymbol{\zeta}) + = + U_\text{e}(\boldsymbol{\zeta}) + + + U_\text{p}(\boldsymbol{\zeta}) + - + U_\text{x}(\boldsymbol{\zeta}). + \label{eq:field_exit} + \end{equation} + \end{subequations} + % 由于 IGF 在离线阶段完成构建,其计算开销不影响在线搜索过程;在线阶段只需对预计算的栅格场作连续空间查询。本文以张量积三次 B 样条作为场的连续化表示,其系数由栅格场值经预滤波(prefiltering)在离线阶段一并解出,在线查询时场值及其一阶、二阶导数均由基函数解析给出,为常数时间。相应地,\eqref{eq:compact_kernel} 中各核函数的衰减阶数须取 $m_\text{e}, m_\text{g} \ge 3$,使连续意义下的场本身即为 $C^2$,以满足 \ref{subsec:joint_nlp} 节对 \eqref{eq:cost_field} 的二阶连续可微性要求;该取值与交互核所需的 $m_\varPsi \ge 3$ 同源。选取样条而非双线性插值的理由、以及搜索与优化两阶段统一采用同一表示的理由,见补充材料 S-II。 + % 需要强调的是,本文对势场的使用方式与传统人工势场法(Artificial Potential Field, APF)存在本质区别。如 \ref{sec:related_work} 节所述,APF 类方法在狭窄通道处易陷入局部极小值、且存在目标不可达问题,其根源在于这类方法将势场梯度 $-\nabla U$ 直接用作驱动力以迭代推进路径点:一旦合力为零而该点并非目标点,迭代即停滞且无法自行跳出。与之不同,本文并不对 IGF 求梯度、也不以梯度驱动路径生成,而是仅将 $U(\mathbf{p})$ 作为标量代价注入下文 \eqref{eq:ha_g}--\eqref{eq:ha_h_all} 的图搜索评价函数中。路径的生成机制仍然是对离散状态空间的系统性扩展:势谷区域仅表现为更低的节点代价、从而被优先扩展,而势能较高的区域并不会被排除在搜索之外。因此,当势谷方向受阻时,搜索会自然回退并扩展代价次优的节点,算法的可达性与分辨率完备性由图搜索本身保证,而不依赖于 $U$ 的形状。换言之,IGF 在本文中承担的是“方向先验”而非“驱动力”的角色,这使得矿区双向通行规则能够以连续、可微的形式嵌入规划器,同时规避了 APF 固有的局部极小值缺陷。 + + % 本文取 $\alpha_\text{p} = \alpha_\text{x}$、$\rho_\text{p} = \rho_\text{x}$、$m_\text{p} = m_\text{x}$,即 \eqref{eq:bound_guide} 中统一记为 $\alpha_\text{g}$、$\rho_\text{g}$、$m_\text{g}$ 的三个参数;该组等式源于泊入与驶离两条引导线在几何上关于中线对称,令其取相同参数可使两个方向性场互为镜像,从而避免在双向路径之间引入人为的偏置。对于边界项,则要求其在最坏情况下仍能支配双向引导项,使车辆在任何情况下都不会为贴合引导线而逼近场地边界。需要注意的是,如前所述 $\alpha_\text{e}$ 与 $\alpha_\text{g}$ 因 $\Delta s_{\boldsymbol{\xi}}$ 取法不同而相差一个长度量纲,二者不可直接比较;该支配关系应通过 \eqref{eq:field_bounds} 给出的实际场值上界来锚定,即 + \begin{equation} + U_\text{e}^\text{max} > U_\text{g}^\text{max}, + \quad\text{i.e.}\quad + \alpha_\text{e}\left( \frac{2\rho_\text{e}}{\bar\ell_\text{e}} + 1 \right) + > + \frac{2\alpha_\text{g} \rho_\text{g}}{m_\text{g} + 1} + \label{eq:alpha_dominance} + \end{equation} + % \eqref{eq:alpha_dominance} 为场强系数的标定提供了明确依据。需要强调的是,该式比较的是两个分场各自的上界,而非逐点的大小关系:在远离边界的引导线附近有 $U_\text{e} = 0$,此时引导项占优,这正是方向先验得以发挥作用之处。该式所保证的是最坏情形下的余量——在边界项取到其上界 $U_\text{e}^\text{max}$ 的构型下,即使引导项同时取到 $U_\text{g}^\text{max}$,由 \eqref{eq:field_park}、\eqref{eq:field_exit} 及 $U_\text{p}, U_\text{x} \ge 0$ 仍有 $U \ge U_\text{e}^\text{max} - U_\text{g}^\text{max} > 0$,即边界排斥脊线处的代价始终高于远离全部势源的中性自由空间($U = 0$),引导吸引作用不会将该排斥脊压平为势谷。 + + % 至于叠加方式本身,本文采用线性组合而非取极值或乘性组合,理由是线性组合保持 \eqref{eq:compact_kernel} 在支撑域内的 $C^{m-1}$ 光滑性,而该光滑性是 \eqref{eq:cost_field} 参与连续优化的前提;两种替代方式各自破坏光滑性的方式见补充材料 S-I。 + + % 由于 \eqref{eq:field_park} 与 \eqref{eq:field_exit} 含负号项,$U$ 的取值可能为负;为使其可直接作为非负代价参与 A* 搜索(详见第 \ref{sec:search} 章),在栅格场构建完成后统一做一次平移与归一化,将场值映射到 $[0,1]$ 区间: + \begin{equation} + \hat U(\boldsymbol{\zeta}) + = \frac{U(\boldsymbol{\zeta}) + U_\text{g}^\text{max}} + {U_\text{e}^\text{max} + 2 U_\text{g}^\text{max}} + \label{eq:field_normalize} + \end{equation} + % 其中平移量与区间长度均由 \eqref{eq:field_bounds} 的两个上界解析给出,而非取自栅格实测极值 $\min_\Xi U$、$\max_\Xi U$:实测极值随场地形状与势源密度而变,且 $U_\text{park}$ 与 $U_\text{exit}$ 的实测极值一般不等(两条引导线相对场地边界的位置并不对称),以其归一化将使 \eqref{eq:field_park}、\eqref{eq:field_exit} 的镜像关系在数值上被破坏。共同的先验端点则使两个场共享同一与场地无关的标度,\eqref{eq:ha_g_field} 中的权重 $w_U^{\bullet}$ 因而无需随场地更换而重新标定。该变换不改变场的空间形态与相对高低关系;为表述简洁,下文中的 $U$ 均指经 \eqref{eq:field_normalize} 归一化后的场值。 + + % 这里须补充说明 \eqref{eq:field_normalize} 的值域。下界是严格的:由 \eqref{eq:bound_guide},$U_\text{g}^\text{max}$ 是引导线分场的严格上界,故 $U \ge -U_\text{g}^\text{max}$ 处处成立、$\hat U \ge 0$ 无条件满足,A* 搜索所要求的代价非负性因而得到保证。上界则不然:如 \eqref{eq:bound_edge} 处所述,$U_\text{e}^\text{max}$ 在凹形拐角处只是典型量级的估计而非全局上界,故 $\hat U$ 在少数凹角栅格上可能略微超过 $1$。本文在离线构建栅格场时统一施加截断 $\hat U \leftarrow \min\{\hat U,\, 1\}$,使 $\hat U \in [0,1]$ 成为严格值域,从而 \eqref{eq:ha_g_field} 中把 $\hat U$ 解释为等效减速因子、以及 \ref{subsec:primitive} 节据 $\hat U$ 调制扩展步长时所依赖的标度均严格成立。该截断只作用于紧贴边界的凹角处——那里 $\hat U$ 已接近 $1$、代价已足够高以排斥路径,故截断不改变搜索与优化的行为;但需注意截断使场在该处的梯度为零,因此 \eqref{eq:cost_field} 在被截断的栅格上不再提供推离边界的梯度,路径与边界的安全间隔在优化阶段完全由 \ref{subsec:convex} 节的凸走廊硬约束保证,不依赖 $J_U$。 + + % 最后需要指出 \eqref{eq:field_park} 与 \eqref{eq:field_exit} 这一构造方式在方法框架层面的意义。双向路径的空间解耦要求,已经通过两个方向性场中 $U_\text{p}$ 与 $U_\text{x}$ 的符号互换被前置固化在场的构造之中:泊入路径所感知的势场以泊入引导线为势谷、以驶离引导线为脊线,驶离路径则恰好相反,如图 \ref{fig:igf} 所示。因此在后续的初始搜索阶段,$\varGamma_\text{park}$ 与 $\varGamma_\text{exit}$ 各自在对应的$U_\text{park}$、$U_\text{exit}$ 上独立完成搜索,二者之间不存在任何信息交互,也不需要按特定顺序串行求解——两条路径的搜索过程是相互独立且可并行的。这一设计的意义在于,它将“双向解耦”这一空间拓扑约束从在线求解过程中剥离出来,转化为离线场构造阶段的先验知识,从而避免了耦合搜索所面临的状态空间维度膨胀问题。双路径之间真正的协同发生在第 \ref{sec:opt} 章的数值优化阶段:该阶段以本章生成的两条粗解为初值,通过 \eqref{eq:cost_interaction} 所定义的交互项对两条路径进行联合优化,以进一步压缩其时空冲突区域。 + + % 最后须明确本文所称“离线”的实际含义,因为装载场地的边界并非静止:随开采推进,台阶坡面持续后退,而挖掘机本身在作业间隙亦会整机移位。本文以\emph{时间尺度分离}处理这一矛盾。IGF 的输入只有场地边界点集 $\mathcal{S}_\text{e}$;由 \ref{subsec:centerline} 节,中线与两条引导线均不经过装载位,故场对装载位变更完全不敏感。于是场的重建仅由边界几何的实质变化触发,其典型时间尺度为班次级(一次爆破或一段推进之后),远长于装载循环的分钟级节拍;在两次重建之间,装载位每次变更只需以新的边界条件重新求解两条路径,引导场保持不变。这正是 \eqref{eq:field_park}、\eqref{eq:field_exit} 的镜像构造所带来的工程收益:拓扑先验的有效期由边界而非装载位决定。 + % 至于挖掘机与其他车辆这类移动障碍,本文不将其纳入 $\mathcal{S}_\text{e}$,理由是场的重建代价与其运动时间尺度不匹配;它们由 \ref{subsec:convex} 节的凸走廊在每次重规划时以当次感知快照施加硬约束避让。这一分工也界定了本文方法的适用边界:IGF 承担的是随边界缓变的\emph{通行拓扑},而非随车流快变的\emph{瞬时占据}。场的重建耗时与重规划频次的实测值见 \ref{subsec:exp_setup} 节。 + + \begin{figure*}[htbp] + \centering + \includegraphics{fig_igf} + \caption{Integrated guidance fields on a synthetic loading site. + (a) Site boundary, the virtual road centerline $\varLambda_\text{center}$, and the + two directional guidance lines $\varLambda_\text{park}$, $\varLambda_\text{exit}$ + offset from it by $W/2$, which together supply the source sets + $\mathcal{S}_\text{e}$, $\mathcal{S}_\text{p}$, $\mathcal{S}_\text{x}$. + (b) Normalized inbound field $\hat U_\text{park}$ of \eqref{eq:field_park}. + (c) Normalized outbound field $\hat U_\text{exit}$ of \eqref{eq:field_exit}. + Both panels share one color scale; each field forms a valley along its own + guidance line and a ridge along the mirrored one, so that the two searches are + pushed apart while both remain repelled by the boundary. This figure illustrates + the field construction and is not an experimental result.} + \label{fig:igf} + \end{figure*} + +\section{Integrated-Field-Guided Inbound and Outbound Path Search} + \label{sec:search} + % 进出双路径的启发搜索 + % 本章在第 \ref{sec:igf} 章构建的 IGF 基础上,以改进的 Hybrid A* 生成进出双路径粗解。泊入路径 $\varGamma_\text{park}$ 与驶离路径 $\varGamma_\text{exit}$ 分别在 $U_\text{park}$ 与 $U_\text{exit}$ 上独立搜索,两次搜索所用的算法完全相同、仅所查询的场不同。因此本章以泛指的 $U$ 表述搜索过程,其在两条路径的求解中分别取对应的方向性场。本文选择 Hybrid A* 作为粗解生成的骨架,而非另寻搜索框架,是因其与本文需求的结构性契合。装载场地的粗解需同时满足三件事:非完整的车辆运动学(路径切向与航向共线)、前进与后退混合的多段拓扑(泊入必经换向)、以及在无显式车道的自由空间内连续可行。Hybrid A* 以运动基元在$(x, y, \theta)$ 状态格上扩展\cite{dolgov2008practical},天然满足前两者,且其格点离散对自由空间不作任何结构化假设,正好适配第三点。 + + % 本文对经典 Hybrid A* 的改进有三处:运动基元的扩展步长随局部势能自适应调制(\ref{subsec:primitive} 节),代价函数中引入场势能项以偏向 IGF 势谷(\ref{subsec:cost} 节),以及启发函数以固定特征长度折算势能、避免过度贪心(\ref{subsec:heuristic} 节)。三者分别对应粗解"贴合引导、代价可解释、搜索高效"三项要求,下文依次说明。除此之外,运动基元的形式、以终点位姿为目标的解析扩展、以及状态格上的重复节点剪枝均沿用经典算法\cite{dolgov2008practical},不作改动。 + + \subsection{Field-Adaptive Motion-Primitive Expansion} + \label{subsec:primitive} + % 运动基元的设计取决于粗解在三阶段框架中所承担的职责。由 \ref{subsec:framework} 节,粗解的作用是确定两条路径的拓扑走向、换挡分段结构以及各段所处的自由空间通道,即固定 \eqref{eq:cons_kinodynamic} 中的离散量并为第 \ref{sec:opt} 章的联合优化提供位于可行域附近的初值;曲率剖面的连续性与变化率有界性 \eqref{eq:cons_sigma} 属于对最终路径的要求,由第 \ref{sec:opt} 章的连续优化实现。本章所介绍的运动基元沿用经典 Hybrid A* 的形式,同时提出一种扩展步长随局部势能自适应调制方法。 + + % 基元以恒定前轮转角 $\psi$ 的圆弧给出,节点状态取位姿 $\boldsymbol{\eta}=[x,y,\theta]^\top$,段内状态沿弧长的演化满足 + \begin{equation} + \frac{\mathrm{d}}{\mathrm{d}s} + \begin{bmatrix} x\\ y\\ \theta \end{bmatrix} + = \delta + \begin{bmatrix} + \cos\theta\\ + \sin\theta\\ + \tan\psi / L_\text{w} + \end{bmatrix} + \label{eq:search_sample} + \end{equation} + % 其中 $\delta\in\{+1,-1\}$ 为档位、$L_\text{w}$ 为轴距。该式即 \eqref{eq:cons_kinodynamic} 在 $\psi$ 取常值时的特例,故基元本身满足非完整约束;其段内曲率为常值 $\kappa=\tan\psi/L_\text{w}$,在相邻基元的拼接点处允许跳变。前轮转角在车辆的机械上界内均匀离散为 + \begin{equation} + \psi_j = \frac{j}{N_\psi}\, \psi_\text{max}, + \qquad j \in \{-N_\psi, \ldots, N_\psi\}, + \label{eq:search_steer_set} + \end{equation} + % 其中 $\psi_\text{max} = \arctan(L_\text{w}/R_\text{min})$ 由最小转弯半径反推,从而使基元的曲率自动满足 \eqref{eq:cons_kappa} 的上界,无需逐段额外校验。每次扩展在 $2N_\psi+1$ 档转角与两个档位上展开,共 $2(2N_\psi+1)$ 个候选。由节点 $\boldsymbol{\eta}_i$ 出发、以转角 $\psi_j$ 与档位 $\delta$ 行进弧长 $\mu_j^\delta$ 后到达的子节点记为 $\boldsymbol{\eta}_{i+1} = \varPhi(\boldsymbol{\eta}_i, \psi_j, \delta\mu_j^\delta)$,其中 $\mu_j^\delta$ 为该方向上的扩展步长,由下文 \eqref{eq:search_step} 给出。$\varPhi$ 对 \eqref{eq:search_sample} 作数值积分求得,基元内部的中间位姿一并用于碰撞检测。 + + \paragraph{State Lattice and Duplicate-State Pruning} + % 基元扩展所得的位姿是连续量,为控制搜索规模须对其判重。本文沿用经典 Hybrid A* 的做法\cite{dolgov2008practical}:以空间分辨率 $\Delta_{xy}$ 与角度分辨率 $\Delta_\theta$ 在 $(x,y,\theta)$ 上铺设状态格,将位姿 $\boldsymbol{\eta}$ 映射为整数索引 + \begin{equation} + \mathcal{I}(\boldsymbol{\eta}) = \left( \left\lfloor x / \Delta_{xy} \right\rfloor,\; + \left\lfloor y / \Delta_{xy} \right\rfloor,\; + \left\lfloor \theta / \Delta_\theta \right\rfloor \right), + \label{eq:search_lattice} + \end{equation} + % 索引相同的节点视为同一状态,其中仅保留 $g$ 值最小者、其余在扩展时即被剪除。 + % 状态格在此仅充当判重的键,而\emph{不}参与位姿的表示:被保留的节点存储 \eqref{eq:search_sample} 积分所得的连续位姿,路径点不吸附至格心,故非完整可行性由基元逐点保证、不因判重而受损。其代价是最优性——同格内两个位姿的航向最多可相差近 $\Delta_\theta$,保留 $g$ 值较小者未必保留通向全局最优的那一支,故仅具备分辨率意义下的完备性;这与 \ref{subsec:heuristic} 节所述启发函数的不可采纳性一同构成 \ref{subsec:framework} 节“不再保证全局最优”的两个来源。 + + % 判重机制同时对基元的弧长提出了下界要求:若扩展步长小于状态格的对角尺寸,子节点将落回父节点所在的格而被判为重复,扩展即无法推进。故须使各方向上的实际步长满足 + \begin{equation} + \min_{j,\delta} \mu_j^\delta \; > \; \sqrt{2\,\Delta_{xy}^2 + \left( R_\text{min} \Delta_\theta \right)^2}, + \label{eq:search_step_bound} + \end{equation} + % 其中右端为状态格对角线在弧长意义下的等效尺度,第三项以 $R_\text{min}\Delta_\theta$ 将角度分辨率折算为弧长。由 \eqref{eq:search_step} 的调制下界,该条件即 $w_\text{min}\mu_0$ 须超出该值,这构成基准步长 $\mu_0$ 的取值依据。 + + \paragraph{Boundary and Gear-Shift Handling} + % 边界条件 \eqref{eq:cons_boundary} 仅约束位姿,与基元的状态量一致,故 $\boldsymbol{\eta}_\text{enter}$ 直接作为搜索的起点施加,$\boldsymbol{\eta}_\text{load}$ 则经下文的解析扩展精确到达。换挡折点处依 \eqref{eq:cons_junction} 位姿连续、档位反号;由于车辆在该处完全停止、前轮可原地转向,折点两侧的曲率无需衔接。粗解因此在分段结构上与优化阶段的设定一致:段界由换挡折点划定,而段内仍可存在非换挡的曲率断点(相邻基元的拼接点、以及解析段内部圆弧与直线的衔接处),这些断点连同段内曲率剖面一并留待优化阶段精化。 + + \paragraph{Field-Adaptive Expansion Step} + % 本节的改动落在扩展步长上:\eqref{eq:search_sample} 中的弧长 $\mu_j^\delta$ 不取固定值,而随该方向上的局部势能自适应调制。为此在每次扩展前先以基准步长 $\mu_0$ 作一次短程探测,探测集合取转角与档位的极值组合 + \begin{equation} + \begin{aligned} + \mathcal{D}\left( {{\boldsymbol{\eta} _i}} \right) = \bigl\{ \, & \boldsymbol{\eta} _j^\delta = \varPhi \left( {{\boldsymbol{\eta} _i},\psi _j,\delta {\mu _0}} \right) \; \big| \\ + & j \in \left\{ { - {N_\psi },0,{N_\psi }} \right\},\;\delta \in \left\{ { + 1, - 1} \right\} \bigr\} + \end{aligned} + \label{eq:search_probe} + \end{equation} + % \eqref{eq:search_probe} 对应车辆以直行及左、右满转角行进 $\mu_0$ 所到达的极端位姿,共 $3 \times 2 = 6$ 个探测点;这些探测点只用于评估各方向的势能高低以调制步长,并不直接进入粗解。探测点的势能值刻画了各方向上的通行倾向:势能越高,表明该方向偏离势谷或趋近场地边界,应以更小的步长进行精细扩展;反之则可用更大的步长快速推进。 + + % 由于 IGF 的绝对幅值随场地尺寸与势源密度而变化,若直接以 $U$ 的绝对值设定步长,需针对每个场地重新标定阈值。为此,本文在探测点集合内部对势能进行归一化。记 $\mathbf{p}_j^\delta$ 为探测位姿 $\boldsymbol{\eta}_j^\delta$ 的位置分量,则 + \begin{equation} + {\tilde U_j^\delta} = \frac{{U\left( {\mathbf{p}_j^\delta} \right) - \mathop {\min }\limits_{\mathcal{D}} U}}{{\mathop {\max }\limits_{\mathcal{D}} U - \mathop {\min }\limits_{\mathcal{D}} U + {\epsilon _0} }} \in \left[ {0,1} \right] + \label{eq:search_normU} + \end{equation} + % 并将步长写为关于 $\tilde U$ 的有界单调递减映射。 + % 注意每个探测方向 $(j, \delta)$ 各自得到一个步长,即该方向上运动基元的实际扩展弧长: + \begin{equation} + \mu_j^\delta = \mu_0 \left[ w_\text{min} + \left( w_\text{max} - w_\text{min} \right) \left( 1 - \tilde U_j^\delta \right) \right] + \label{eq:search_step} + \end{equation} + % 其中,$\epsilon_0$ 为防止零除的小量(区别于 \eqref{eq:qp_slack} 中的松弛变量 $\varepsilon_i$),$[w_\text{min}, w_\text{max}] = [0.6, 1.4]$ 为调制系数的取值区间。归一化使该策略仅依赖于探测点之间势能的相对高低,因而对 IGF 的绝对标度不敏感,无需随场地更换而重新调参。该调制的几何效果如图 \ref{fig:probe} 所示:落在低势能区的探测方向其步长被拉长至 $w_\text{max}\mu_0$,落在高势能区者被压缩至 $w_\text{min}\mu_0$,于是节点扩展沿引导势谷伸展、在贴近边界处自动细化。 + % 由 \eqref{eq:search_step} 步长有界,$\mu_j^\delta \in [w_\text{min}\mu_0,\, w_\text{max}\mu_0]$,其下界已由 \eqref{eq:search_step_bound} 约束在状态格对角尺度之上,故调制不改变搜索的分辨率完备性。碰撞检测亦不以节点为单位,而是在每个运动基元内部按固定弧长增量 $\Delta s_\text{cc} \le B_\text{v}/2$(即车宽的一半,为 $\mathcal{V}$ 的最小外廓尺寸)细分后逐位姿进行,因此不会因步长增大而产生漏检。 + + \begin{figure}[htbp] + \centering + \includegraphics{fig_probe} + \caption{Field-adaptive expansion of a single node. + (a) The six probe poses reached by combining + $\psi\in\{-\psi_\text{max},0,\psi_\text{max}\}$ with + $\delta\in\{+1,-1\}$ at the baseline step $\mu_0$. + (b) Steps modulated by \eqref{eq:search_step}: a probe landing in a + low-potential region is extended toward $w_\text{max}\mu_0$, whereas one landing + in a high-potential region is shortened toward $w_\text{min}\mu_0$, so that the + expansion stretches along the guidance valley and refines near the boundary.} + \label{fig:probe} + \end{figure} + + \paragraph{Analytic Expansion to the Terminal Pose} + % 仅以 \eqref{eq:search_sample} 的离散基元扩展,节点难以精确落在 $\boldsymbol{\eta}_\text{load}$ 上:状态格的分辨率决定了终点判定只能在一个容差邻域内进行,而装载位的朝向恰是需要精确对齐的量。为此本文沿用经典 Hybrid A* 的解析扩展(analytic expansion)机制\cite{dolgov2008practical}:每扩展固定数目的节点后,尝试以一条 Reeds--Shepp 曲线\cite{reedsshepp1990}将当前节点与 $\boldsymbol{\eta}_\text{load}$ 直接相连,该曲线由最小转弯半径 $R_\text{min}$ 的圆弧与直线段拼接而成、可含前进与后退的换向,其长度亦即 \eqref{eq:ha_h_time} 中的 $\ell_\text{RS}$。若该曲线通过碰撞检测,则搜索提前终止,粗解由已扩展的基元序列与该解析段拼接而成;否则继续扩展。这一机制使终点位姿被精确满足,同时显著减少了在装载位附近为对齐朝向所需的节点扩展量。 + + % 解析段与前文两点设定相容。其曲率剖面同样分段常值、在拼接点跳变,与 \eqref{eq:search_sample} 的基元一致,故粗解处处满足 \eqref{eq:cons_kappa}(解析段取 $R_\text{min}$),曲率剖面的连续化仍由第 \ref{sec:opt} 章承担。解析段自身的换向折点与基元扩展所产生的换向一并计入 $\{\delta_j\}$ 与 $N$;相应地,\eqref{eq:ha_g_gear} 的换挡代价在解析段被接受时须计入该段引入的折点,以免搜索因末段换向不计代价而偏好过早直连。 + + \subsection{Search Cost Function} + \label{subsec:cost} + % 代价: g = 耗时 + 场 + 换挡次数 + % 本方法中,路径搜索过程中的代价由三部分组成:路径的假想耗时、换挡耗时、以及通行条件劣化带来的等效耗时: + \begin{equation} + g = g_\text{time} + g_\text{gear} + g_\text{field} + \label{eq:ha_g} + \end{equation} + % 其中各分项定义为 + \begin{subequations} \label{eq:ha_g_all} + \begin{align} + g_\text{time} & = \frac{1}{v_0} \sum_i \mu_i + \label{eq:ha_g_time} \\ + g_\text{gear} & = N \, t_0 + \label{eq:ha_g_gear} \\ + g_\text{field} & = \frac{w_U^{\bullet}}{v_0} \sum_i U_\bullet(\mathbf{p}_i) \, \mu_i + \label{eq:ha_g_field} + \end{align} + \end{subequations} + % 三个分项均以秒为量纲,因此 $g$ 可统一解释为一条路径的\emph{广义通行耗时}。该式与第 \ref{sec:opt} 章优化阶段所用的完整目标函数 \eqref{eq:cost} 采用同一量纲口径,二者的对应关系为:\eqref{eq:ha_g_time} 对应 \eqref{eq:cost_time}、\eqref{eq:ha_g_gear} 对应 \eqref{eq:cost_gear}、\eqref{eq:ha_g_field} 对应 \eqref{eq:cost_field}。差异在于本阶段略去了 \eqref{eq:cost} 中的交互项 $J_\varPsi$ 与平滑项 $J_\kappa$:前者因两条路径在本阶段独立并行求解、其耦合作用由 $U_\text{park}$、$U_\text{exit}$ 中的静态排斥项近似承担(详见 \ref{subsec:framework} 节),后者因运动基元的曲率分段常值、$\kappa^2$ 在本阶段不具备区分不同候选路径平滑性的能力,二者均在第 \ref{sec:opt} 章的连续优化阶段被完整引入。 + + % \eqref{eq:ha_g_time} 体现了单条路径的最高效原则,$\mu_i$ 表示路径上第 $i$ 步扩展所实际采用的运动基元弧长,即该步所选方向对应的 \eqref{eq:search_step} 之值;该项为车辆以恒定速度 $v_0$(本文取矿区车辆装载区内平均速度)跟踪该路径所需的时间。\eqref{eq:ha_g_gear} 保证了路径尽可能减少换挡次数、减少车辆机械损耗,其中 $N$ 为路径的换挡次数,$t_0$ 表示单次换挡动作的实测耗时;由于换挡期间车辆处于停止状态,该项即为换挡引入的真实时间损失。 + + % \eqref{eq:ha_g_field} 引入了露天矿区所要求的双路径空间分布与行驶倾向。该项将归一化势能 $U \in [0,1]$ 解释为\emph{等效减速因子}:势能越高表明该处越偏离引导通道、通行条件越差,车辆在此处的有效通行速度相应下降,因而付出额外的等效时间。无量纲权重 $w_U^{\bullet}$ 的物理含义即为:路径完全偏离势谷($U \equiv 1$)时,相对自由通行状态所额外付出的耗时倍数;其上标 $\bullet \in \{\text{park}, \text{exit}\}$ 表示两条路径各自取值,与 \eqref{eq:cost_field} 中的优化阶段权重同值,故 \eqref{eq:asymmetric_weights} 的非对称取向在搜索阶段即已生效。 + + % 此处以弧长 $\mu_i$ 加权而非按节点计数累加,是因 \eqref{eq:search_step} 的步长自适应变化,按计数累加会使同一条几何路径在不同步长下得到不同代价;加权后该项即为 $\int_{\varGamma_\bullet} U_\bullet(\mathbf{p})\,\mathrm{d}s$ 的离散近似,与采样密度无关。 + + \subsection{Field-Augmented Heuristic Function} + \label{subsec:heuristic} + % 启发: h = 场 + max(A*, RS) + % 本方法中,路径搜索的启发式函数由两部分组成:剩余路程的预估耗时、以及当前节点通行条件对应的等效耗时: + \begin{equation} + h = h_\text{time} + h_\text{field} + \label{eq:ha_h} + \end{equation} + % 其中各分项定义为 + \begin{subequations} \label{eq:ha_h_all} + \begin{align} + h_\text{time} & = \frac{\ell_\text{rem}}{v_0}, + \quad \ell_\text{rem} = \max \left\{ \ell_{\text{A*}}, \, \ell_\text{RS} \right\} + \label{eq:ha_h_time} \\ + h_\text{field} & = \frac{w_U^{\bullet}}{v_0} \, U_\bullet(\mathbf{p}) \, L_\text{v} + \label{eq:ha_h_field} + \end{align} + \end{subequations} + % 与 \eqref{eq:ha_g_all} 一致,两个分项的量纲同为秒。\eqref{eq:ha_h_time} 是 Hybrid A* 算法中的经典启发函数,$\ell_{\text{A*}}$ 表示考虑碰撞的 A* 路径剩余预估长度,$\ell_\text{RS}$ 表示不考虑碰撞的 Reeds-Shepp 曲线剩余预估长度,二者取较大值作为剩余路程估计 $\ell_\text{rem}$。 + + % 另外,由于中线不经过装载位(\ref{subsec:centerline} 节),路径越靠近装载位就越需要从主通道“分叉”,其走势必然与 IGF 的势谷产生偏离;此时若把沿途势能累加进启发函数,分叉段的必要偏离会被当作代价持续累积、进而压制正确的分叉行为。因此 \eqref{eq:ha_h_field} 仅取待探索节点位置 $\mathbf{p}$ 处的势能强度,不再取累计值。为与 \eqref{eq:ha_g_field} 保持量纲一致,该项以车长 $L_\text{v}$ 作为特征尺度,即将节点处的势能折算为车辆通过自身长度这段距离所付出的等效额外耗时。此处采用固定特征长度而非剩余路程 $\ell_\text{rem}$ 作为尺度,是为了避免势能项随剩余距离线性放大、使搜索过度贪心。 + + % 关于启发函数的可采纳性,此处作一点说明。经典 Hybrid A* 中的 \eqref{eq:ha_h_time} 取无碰撞 Reeds-Shepp 长度与考虑碰撞的 A* 长度的较大值,二者均为剩余真实耗时的下界,因此该项是可采纳(admissible)的。但叠加 \eqref{eq:ha_h_field} 后,$h$ 中包含了并非源于剩余路程的等效耗时项,其数值可能超出节点到目标的真实剩余代价,故本文的 $h$ 整体上不再保证可采纳性,相应地也就不保证所得路径在 \eqref{eq:ha_g} 定义的广义通行耗时意义下全局最优。这是本文有意作出的设计取舍:本阶段搜索的目标并非求解最优路径,而是快速生成拓扑结构正确、且满足双向解耦要求的初值粗解,其几何品质由第 \ref{sec:opt} 章的数值优化阶段进一步保证。引入势能项后,节点扩展会明显偏向 IGF 势谷方向,从而在保证搜索成功率的同时显著减少扩展节点数(详见 \ref{sec:exp} 章的对比实验)。事实上,由于 \eqref{eq:ha_h_field} 以固定特征长度 $L_\text{v}$ 为尺度,该项的数值上界为 $w_U^{\bullet} L_\text{v} / v_0$,即其对可采纳性的破坏程度是有界的;且当 $w_U^{\bullet} \to 0$ 时,$h$ 退化为经典可采纳启发函数。该参数因此提供了在搜索效率与解的最优性之间进行权衡的显式接口。 + + % 整体流程与伪代码 + % 至此三个阶段的构成要素均已给出,算法 \ref{alg:overall} 汇总其整体流程。第 1--4 行为离线阶段,仅在场地边界更新时重建;第 5--12 行为在线阶段,两条粗解在各自的引导场上并行搜索;第 13--17 行为联合优化阶段,两条粗解合并为单一决策向量后一次求解。 + \begin{algorithm}[htbp] + \caption{Spatially Decoupled Inbound/Outbound Planning} + \label{alg:overall} + \DontPrintSemicolon + \SetKwInOut{Input}{Input} + \SetKwInOut{Output}{Output} + \SetKwFunction{Skel}{SkeletonAStar} + \SetKwFunction{Smooth}{SmoothQP} + \SetKwFunction{Offset}{OffsetLines} + \SetKwFunction{Field}{BuildField} + \SetKwFunction{Search}{FieldAdaptiveHybridAStar} + \SetKwFunction{Corr}{ConvexCorridors} + \SetKwFunction{Nlp}{SolveNLP} + \Input{site boundary $\partial\Omega$; loading pose + $\boldsymbol{\eta}_\text{load}$; entry/exit poses + $\boldsymbol{\eta}_\text{in}$, $\boldsymbol{\eta}_\text{out}$; + channel width $W$} + \Output{jointly optimized path pair + $\varGamma^\ast=(\varGamma_\text{park}^\ast, + \varGamma_\text{exit}^\ast)$} + \BlankLine + \tcp{Stage 1: offline field prior, rebuilt only on boundary change} + $\varLambda_\text{raw} \leftarrow$ \Skel{$\partial\Omega$}\; + $\varLambda_\text{center} \leftarrow$ + \Smooth{$\varLambda_\text{raw}$} \tcp*{\eqref{eq:qp_problem}} + $\varLambda_\text{park}, \varLambda_\text{exit} \leftarrow$ + \Offset{$\varLambda_\text{center}, W/2$} + \tcp*{\eqref{eq:reference_offset}} + $\hat U_\text{park}, \hat U_\text{exit} \leftarrow$ + \Field{$\mathcal{S}_\text{e}, \mathcal{S}_\text{p}, + \mathcal{S}_\text{x}$} + \tcp*{\eqref{eq:field_park}--\eqref{eq:field_normalize}} + \BlankLine + \tcp{Stage 2: two coarse searches, run in parallel} + \ForPar{$\bullet \in \{\text{park}, \text{exit}\}$}{ + $(\boldsymbol{\eta}_\text{s}, \boldsymbol{\eta}_\text{g}) + \leftarrow + \begin{cases} + (\boldsymbol{\eta}_\text{in}, + \boldsymbol{\eta}_\text{load}), & \bullet=\text{park} \\ + (\boldsymbol{\eta}_\text{load}, + \boldsymbol{\eta}_\text{out}), & \bullet=\text{exit} + \end{cases}$\; + $\varGamma_\bullet^{(0)} \leftarrow$ + \Search{$\boldsymbol{\eta}_\text{s}, + \boldsymbol{\eta}_\text{g}, \hat U_\bullet$}\; + } + fix the gear sequence $\{\delta_j\}$ and the number of + collocation points $N$ from + $\varGamma_\text{park}^{(0)}, \varGamma_\text{exit}^{(0)}$\; + \BlankLine + \tcp{Stage 3: joint refinement of both paths at once} + $\{\mathcal{P}_k\} \leftarrow$ + \Corr{$\varGamma_\text{park}^{(0)}, + \varGamma_\text{exit}^{(0)}, \mathcal{O}$} + \tcp*{shrunk by $\Delta_\text{cut}$} + \Repeat{all collocation points stay in their corridors}{ + $\mathbf{z}^\ast \leftarrow$ + \Nlp{$\mathbf{z}^{(0)}, \{\mathcal{P}_k\}$} + \tcp*{\eqref{eq:joint_nlp}} + rebuild the violated corridors around $\mathbf{z}^\ast$\; + } + \Return $\varGamma^\ast$ decoded from $\mathbf{z}^\ast$\; + \end{algorithm} + + +\section{Joint Optimization of Inbound and Outbound Paths} + \label{sec:opt} + % 狭窄空间安全约束与数值优化 + % 本章以第 \ref{sec:search} 章生成的两条粗解为初值,求解 \eqref{eq:overall_problem} 的连续优化部分。沿用粗解确定的分段结构后,\eqref{eq:cost} 中的换挡项 \eqref{eq:cost_gear} 退化为常数、目标函数简化为 \eqref{eq:cost_opt},本章因此聚焦于两件事:将 \eqref{eq:cons_collision} 的非凸避碰约束转化为可高效处理的线性形式(\ref{subsec:convex} 节),以及引入 \eqref{eq:cost_interaction} 的交互项完成两条路径的联合优化(\ref{subsec:joint_nlp} 节)。 + + \subsection{Convex-Corridor Construction in Confined Free Space} + \label{subsec:convex} + % 本小节将 \eqref{eq:cons_collision} 的非凸避碰约束转化为线性不等式形式。该约束难以直接处理的原因在于 $\Omega_\text{free}$ 由不规则的场地边界点云描述、其形状非凸。以障碍点距离形式直接施加约束,则约束数量随点云规模线性增长、且每一条均为非凸约束;沿参考线逐点开辟\emph{形状预设}的邻域(如前文的局部切向--法向矩形走廊用于中线平滑),虽可得到线性约束,但在边界走向不规则处难以充分利用自由空间。 + % 本文因此采用凸分解(convex decomposition)方法\cite{corridor2022voxelgrid,corridor2024convexcover,corridor2023rover}:以粗解的每一段线段为种子,围绕该线段生成一个包裹它、且不含任何边界点的凸多面体,从而将 $\Omega_\text{free}$ 沿路径切分为一列相互重叠的无障碍凸区域(convex corridors)。与上述两类做法相比,凸分解的多面体面数与朝向均由局部边界点分布自适应确定,而非预先设定,故能在狭窄且不规则的装载场地内开辟尽可能大的凸可行空间。 + + % 矿区场地边界由车载激光雷达采集,以二维点集 $\mathcal{O}=\{\mathbf{o}_i\}$ 的形式给出。记粗解经等弧长重采样后的第 $k$ 段为端点 $\mathbf{p}_k^\text{ref}$、$\mathbf{p}_{k+1}^\text{ref}$ 所连线段。该段的多面体经"椭球代理—半空间裁剪"两步构造得到:先以线段为长轴生成一个不含任何边界点的避障椭球,再以该椭球的度量为每个边界点生成分离超平面,其交集即为所求。完整推导见补充材料 S-IV,结果为 + \begin{equation} + \mathcal{P}_k = \left\{ \mathbf{p} \in \mathbb{R}^2 \;\middle|\; + \mathbf{A}_k \mathbf{p} \le \mathbf{b}_k \right\}, + \label{eq:corridor_polytope} + \end{equation} + % 其中 $\mathbf{A}_k \in \mathbb{R}^{m_k \times 2}$ 的各行为分离超平面的单位外法向、$\mathbf{b}_k \in \mathbb{R}^{m_k}$ 为对应偏置。半空间个数 $m_k$ 由该段附近参与分解的边界点分布决定,而非预设常数;算法本身不对 $m_k$ 施加统一的常数上界,其实际分布与最大值将在第 \ref{sec:exp} 章中统计,以评估走廊约束的规模。相邻线段共享端点,故 $\mathcal{P}_k \cap \mathcal{P}_{k+1} \neq \varnothing$。 + + % 但共享端点处的相交尚不足以保证走廊分配的相容性。走廊按粗解的弧长位置编号,第 $k$ 个配置点的标称弧长为 $(k-1)\Delta s_\bullet^{(0)}$;由 \eqref{eq:joint_variable_one},步长 $\Delta s_\bullet$ 本身是决策变量而 $M_\bullet$ 固定,故路径总长偏离粗解时第 $k$ 个配置点将沿路径纵向滑移 $(k-1)\lvert\Delta s_\bullet - \Delta s_\bullet^{(0)}\rvert$,该滑移随 $k$ 递增、在末端累积至最大。若走廊仅由标称线段生成,滑移后的配置点可能落到其被分配的走廊之外,导致虚假不可行。 + % 本文以两项措施消除该风险。其一,生成第 $k$ 个走廊时不以单条标称线段为种子,而是将种子沿粗解折线向两端各延伸弧长 $\Delta_\text{slide}$ 后再作凸分解,使 $\mathcal{P}_k$ 在设计上即包含标称位置前后 $\Delta_\text{slide}$ 弧长带内的全部粗解点,相邻走廊由此在一段有限弧长上重叠、而非仅交于一点。其二,对步长的偏移施加信赖域上界 + \begin{equation} + \left\lvert \Delta s_\bullet - \Delta s_\bullet^{(0)} \right\rvert + \le \frac{\Delta_\text{slide}}{M_\bullet - 1}, + \label{eq:cons_step_trust} + \end{equation} + % 使任意 $k$ 处的滑移量均不超过延伸余量 $\Delta_\text{slide}$。两者结合,走廊编号与配置点编号之间的固定分配在整个可行域内保持有效。$\Delta_\text{slide}$ 的取值是余量与保守性之间的折中:过小则 \eqref{eq:cons_step_trust} 过紧、限制路径长度的调整幅度,过大则走廊因种子过长而收缩、约束趋于保守。本文取 $\Delta_\text{slide}$ 为粗解总长的一个小比例,其具体取值与走廊规模的统计一并列于第 \ref{sec:exp} 章。 + % 若求解结束时 \eqref{eq:cons_step_trust} 取等(即路径长度的调整被信赖域截断),则以当前解重新采样、重建走廊后再解一次,构成一层外循环。该外循环是否构成实质开销取决于粗解所给长度与优化后最优长度的偏差是否落在 $\Delta_\text{slide}$ 之内,无法由本节的建模先行断定;其实测触发频次与 $\Delta_\text{slide}$ 的取值一并在 \ref{subsec:exp_efficiency} 节报告。下文的复杂度分析以单次求解计,若外循环触发则应按其平均次数线性折算。 + + % 需要强调的是,\eqref{eq:cons_collision} 约束的是扫掠域 $D(\varGamma)$ 而非路径中心点的轨迹,因此仅将路径点约束进 $\mathcal{P}_k$ 并不足以保证整车无碰。为此,本文对第 $k$ 个路径点处车辆所占据的矩形 $\mathcal{V}(\boldsymbol{\eta}_k)$ 取其四个顶点$\{\mathbf{c}_k^{(r)}\}_{r=1}^{4}$,并要求它们同时落在该段走廊之内: + \begin{equation} + \mathbf{A}_k \mathbf{c}_k^{(r)} \le \mathbf{b}_k, + \qquad r = 1,\dots,4, + \label{eq:cons_corridor} + \end{equation} + % 其中顶点坐标由位姿经刚体变换给出,即 $\mathbf{c}_k^{(r)} = \mathbf{p}_k + \mathbf{R}(\theta_k) [a_r,\, b_r]^\top$,$\mathbf{R}(\theta_k)$ 为 $\theta_k$ 对应的二维旋转矩阵,$[a_r, b_r]^\top$ 为四个顶点在车体坐标系下的固定坐标,由 $L_\text{v}$、$B_\text{v}$ 及后轴中心位置确定。 由于 $\mathcal{V}(\boldsymbol{\eta}_k)$ 与 $\mathcal{P}_k$ 均为凸集,顶点落入即蕴含整个矩形落入,故 \eqref{eq:cons_corridor} 是 \eqref{eq:cons_collision} 在\emph{离散配置点上}的充分条件,其中 $\mathbf{A}_k$、$\mathbf{b}_k$ 在优化过程中为常量,而 $\mathbf{c}_k^{(r)}$ 关于 $\mathbf{p}_k$ 为线性、关于 $\theta_k$ 为三角函数形式。 + + % 上述充分性仅在配置点上成立,相邻配置点之间车体仍可切出走廊之外,这一点对矿卡尺度不可忽略:车长十余米,转向时远离瞬心的顶点其转弯半径显著大于后轴中心的转弯半径。本文以走廊内缩覆盖该间隙,而不额外施加中点约束。设相邻配置点间车辆绕瞬心转过 $\Delta\theta = \Delta s_\bullet \kappa$,第 $r$ 个顶点到瞬心的距离为 $\rho_\text{c}^{(r)}$,则该顶点在两点之间偏离其弦的最大量为该圆弧的矢高,取四个顶点中最远者并代入曲率上界,得 + \begin{equation} + \begin{aligned} + \Delta_\text{cut} + &= \max_{r}\ \rho_\text{c}^{(r)} + \left[ 1 - \cos\!\left( + \frac{\Delta s_\bullet \kappa_\text{max}}{2} \right) \right] , \\ + \rho_\text{c}^{(r)} + &= \left\lVert + \begin{bmatrix} a_r \\ b_r \end{bmatrix} + - \begin{bmatrix} 0 \\ R_\text{min} \end{bmatrix} + \right\rVert , + \end{aligned} + \label{eq:corner_cut_margin} + \end{equation} + % 于是只需在生成 $\mathcal{P}_k$ 时将其各半空间沿内法向统一内缩 $\Delta_\text{cut}$,\eqref{eq:cons_corridor} 即成为整段弧上无碰的充分条件。该内缩量与 \eqref{eq:cons_step_trust} 中的 $\Delta_\text{slide}$ 是两个相互独立的余量,不可混为一谈:$\Delta_\text{slide}$ 沿路径\emph{纵向}、用于吸收配置点的弧长滑移,$\Delta_\text{cut}$ 沿走廊\emph{横向}、用于吸收点间切角。就矿卡尺度而言 $\Delta_\text{cut}$ 的数值相当小——最远顶点 $\rho_\text{c} = 17.1$\,m 时,$\Delta s_\bullet = 1$\,m 对应 $1.5$\,cm,$\Delta s_\bullet = 1.5$\,m 对应 $3.3$\,cm——故一次性内缩不会实质压缩可行域;但该量随 $\Delta s_\bullet$ 近似二次增长,$\Delta s_\bullet = 3$\,m 时已达 $13$\,cm 量级、接近矿区常用安全余量,因而 \eqref{eq:corner_cut_margin} 同时给出了配置步长的上界依据。\eqref{eq:corner_cut_margin} 的推导与完整数值表见补充材料 S-IV-E,本文所采用的 $\Delta s_\bullet$ 及对应 $\Delta_\text{cut}$ 实际值见 \ref{subsec:exp_setup} 节。 + + + \subsection{Smooth Path-Interaction Cost} + \label{subsec:psi_build} + % 本小节说明 \eqref{eq:cost_interaction} 中交互项的物理含义、并给出其核参数的取值依据。上一小节的凸分解走廊已经保证了两条路径各自的“硬安全”,因此交互项的作用不再是避免碰撞,而是在各自走廊内部尽量拉开两条路径的距离、以获得最大的操作余量。换言之,交互项只影响余量、不影响安全:两条路径之间不设硬隔离约束,与场地边界之间的安全间隔完全由凸分解走廊独立保证。这里不设硬隔离约束并不意味着把双向冲突留给时间维调度——如 \ref{sec:related_work} 节所述,装载场地内的到达时刻与装载时长均不受路径规划模块支配,本文正是为此才转以空间解耦消解冲突。真正的原因在于两条路径按 \eqref{eq:cons_boundary} 必须在装载位处共享位姿,任何处处成立的硬隔离约束都会与该边界条件直接冲突、使问题不可行;故解耦只能以软惩罚的形式追求“尽可能大的空间间隔”,其效果由 \ref{subsec:exp_geometry} 节的重叠面积指标量化。该项需要同时兼顾数学上的可微性与物理上的空间排斥性。 + + % 两个阶段采用不同解耦机制的原因是可用信息不同:搜索阶段两条路径独立并行生成,求解其一时另一条尚未确定、不存在可供积分的实际路径,故只能以名义引导线的静态排斥项近似承担解耦;进入联合优化后两条路径同时成为决策变量,交互项遂改以实际路径诱导的 $\varPsi_\text{exit}$ 直接度量接近程度。即静态排斥是解耦的\emph{先验},交互场是其\emph{校正}。 + + % 为避免两条路径在装载位处共享端点时 $\lVert\mathbf{p}^\text{park}-\mathbf{p}^\text{exit}\rVert=0$ 导致欧氏范数不可微,本文在交互项中采用平滑距离 + \begin{equation} + d_{\varepsilon}(\mathbf{p},\mathbf{q}) + = \sqrt{\lVert\mathbf{p}-\mathbf{q}\rVert^2+\varepsilon_\varPsi^2}, + \qquad 0<\varepsilon_\varPsi\ll\rho_\varPsi, + \label{eq:interaction_distance_smooth} + \end{equation} + % 其中 $\varepsilon_\varPsi$ 仅作为数值正则化尺度,不改变交互核的主要作用范围。\eqref{eq:cost_interaction} 的二重积分可以从“场”的角度获得直观解释。将其内层积分单独记为驶离路径在查询点 $\mathbf{p}$ 处诱导的\emph{交互场} + \begin{multline} + \varPsi_\text{exit}\!\left( \mathbf{p}; s_\text{park} \right) + = \int_{\varGamma_\text{exit}} + \tau_\text{d}\!\left( s_\text{park}, s_\text{exit} \right) \\ + \times K\!\left( d_{\varepsilon}(\mathbf{p},\mathbf{p}^\text{exit}); + \rho_\varPsi, m_\varPsi \right) + \mathrm{d}s_\text{exit} + \label{eq:interaction_field} + \end{multline} + % 则 \eqref{eq:cost_interaction} 可等价紧凑地写为 $J_\varPsi = \frac{w_\varPsi}{\rho_\varPsi^2} \int_{\varGamma_\text{park}} \varPsi_\text{exit}(\mathbf{p}^\text{park}; s_\text{park}) \,\mathrm{d}s_\text{park}$,即泊入路径在驶离路径所诱导的交互场中的势能积分。 + % 需要注意两点。其一,因 \eqref{eq:cost_delay_weight} 的时延权重依赖于查询点在泊入路径上的弧长位置 $s_\text{park}$,$\varPsi_\text{exit}$ 除位置 $\mathbf{p}$ 外还以 $s_\text{park}$ 为参数,即它不是工作空间上的一个纯几何场,而是"在泊入路径的第 $s_\text{park}$ 处所感受到的排斥"。这与不加权时的情形不同:彼时 $\varPsi_\text{exit}$ 仅依赖 $\mathbf{p}$,可视为对向路径在空间中诱导的静态场。 + % 其二,交换两条路径的角色所定义的 $\varPsi_\text{park}$ 与此处的 $\varPsi_\text{exit}$ 给出的\emph{数值不同},因为 $\tau_\text{d}$ 关于两条路径不对称;但由 Fubini 定理,二重积分的值与积分次序无关,故 $J_\varPsi$ 本身是唯一确定的。这一"谁在谁的场中"的写法因此仅是同一代价的两种分解方式,选取哪一种取决于叙述方便,其中以 $\varPsi_\text{exit}$ 的形式更贴合物理图景——受排斥而绕行的主要是泊入路径。 + % 其三,$\varPsi_\text{exit}$ 是以整条 $\varGamma_\text{exit}$ 为自变量的\emph{泛函},而非以之为参数的静态场:它随驶离路径的形状在每次迭代中变化,故不可像 \eqref{eq:cost_field} 的 IGF 那样预先离散为栅格查表。 + + % 核参数中,影响半径按两车会车时所需的横向净空取值,即 + \begin{equation} + \rho_\varPsi \ge B_\text{v} + d_\varPsi, + \label{eq:interaction_radius} + \end{equation} + % 其中 $d_\varPsi$ 为期望的双路径横向净空:两条路径的中心线相距 $B_\text{v}$ 时两车轮廓恰好贴合,故在此基础上再留出 $d_\varPsi$ 的余量。该取值使交互项在两条路径的扫掠域 $D(\varGamma_\text{park})$、$D(\varGamma_\text{exit})$ 发生接触之前即开始上升,从而以连续、可微的方式近似约束二者不要过度接近。 + + % 此处需要交代 \eqref{eq:cost_interaction} 的量纲折算,因为它与 \eqref{eq:cost_field} 的形式并不相同。$J_U$ 是无量纲场值沿路径的\emph{单重}弧长积分,除以 $v_0$ 即得秒;而 $J_\varPsi$ 是\emph{二重}弧长积分,其被积函数中 $\tau_\text{d}$ 已带秒的量纲、$K$ 无量纲,故二重积分的结果为“秒 $\cdot$ 米$^2$”。\eqref{eq:cost_interaction} 因此除以 $\rho_\varPsi^2$ 而非 $v_0$:核的支撑半径是该二重积分唯一的内蕴长度尺度,以其平方折算后 $J_\varPsi$ 的量纲为秒,且该折算不随路径加密或场地尺寸而变。经此处理,$w_\varPsi$ 与 $w_U^\bullet$ 同为无量纲权重、其数值可直接比较,二者共同构成 \eqref{eq:cost} 中各分项的等效耗时口径。需要说明的是,$\rho_\varPsi^2$ 的选取只影响 $w_\varPsi$ 的标定基准而不影响解的性质:任何固定的长度平方尺度都只是给 $w_\varPsi$ 乘一个常数。 + + % 这里说明为何采用 \eqref{eq:cost_interaction} 的核积分形式,而非直接惩罚两条路径同索引采样点之间的距离。后者(如以 $\sum_j f(\lVert \mathbf{p}_j^\text{exit} - \mathbf{p}_j^\text{park} \rVert)$ 形式配以逻辑斯谛惩罚函数)在两条路径长度相近、采样一一对应时是可行的简化,但在本文的问题设定下并不适用:泊入路径含换向段、其弧长通常显著大于驶离路径,两者的采样点之间不存在有几何意义的配对关系,同索引点距离因此无法反映真实的空间接近程度。 \eqref{eq:cost_interaction} 以弧长积分定义,其数值仅取决于两条路径的整体几何关系、与各自的采样数与参数化方式无关,因而不存在上述配对问题。相应地,其离散形式须以弧长而非节点计数加权(见 \eqref{eq:joint_psi_discrete}),其原因与 \eqref{eq:source_field} 相同。 + + \subsection{Joint Nonlinear Programming Formulation} + \label{subsec:joint_nlp} + % 本小节给出优化阶段所求解的问题。 + % 由于 \eqref{eq:cost_interaction} 使两条路径相互耦合,一种自然的处理是交替优化:固定一条、优化另一条,逐次迭代至收敛。本文不采用该方案,而是将两条路径联立为单一非线性规划问题求解,其理由在本小节末尾说明。 + + \paragraph{Discretization and Decision Variables} + % 沿用第 \ref{sec:search} 章粗解确定的分段结构,将两条路径分别按等弧长离散为$M_\text{park}$ 与 $M_\text{exit}$ 个配置点。记单条路径的离散状态序列为 $\{\mathbf{x}_k\}$、控制序列为 $\{\sigma_k\}$,并将两条路径的全部变量堆叠为单一决策向量 + \begin{subequations} \label{eq:joint_variable} + \begin{align} + \mathbf{z} & = \left[ + \mathbf{z}_\text{park}^\top,\; + \mathbf{z}_\text{exit}^\top + \right]^\top + \label{eq:joint_variable_all} \\ + \mathbf{z}_\bullet & = \left[ + \mathbf{x}_1^\top, \ldots, \mathbf{x}_{M_\bullet}^\top,\; + \sigma_1, \ldots, \sigma_{M_\bullet-1},\; + \Delta s_\bullet + \right]^\top + \label{eq:joint_variable_one} + \end{align} + \end{subequations} + % 其中 $\bullet \in \{\text{park}, \text{exit}\}$ 表示两条路径中的任一条(沿用 \eqref{eq:ha_g_field} 的记法),$\mathbf{x}_k = [x_k, y_k, \theta_k, \kappa_k]^\top$ 为 \eqref{eq:cons_kinodynamic} 所定义的路径状态,$\Delta s_\bullet$ 为该条路径的离散弧长步长。将 $\Delta s_\bullet$ 而非各段弧长逐一作为变量,是因为 \eqref{eq:cons_kinodynamic} 中路径总长 $s_\bullet = (M_\bullet - 1)\Delta s_\bullet$ 本身是待优化量(\eqref{eq:overall_problem} 为自由终端问题),而配置点数 $M_\bullet$ 一旦由粗解确定即保持固定。$\Delta s_\bullet$ 可变意味着配置点会沿路径相对粗解纵向滑移,其与固定走廊分配的相容性已由 \eqref{eq:cons_step_trust} 处理。 \eqref{eq:cons_kinodynamic} 的连续微分方程以梯形法离散为等式约束 + \begin{equation} + \mathbf{x}_{k+1} = \mathbf{x}_k + \frac{\Delta s_\bullet}{2} + \left[ \mathbf{f}(\mathbf{x}_k, \sigma_k) + \mathbf{f}(\mathbf{x}_{k+1}, \sigma_k) \right], + \label{eq:joint_collocation} + \end{equation} + % 其中 $\mathbf{f}$ 为 \eqref{eq:cons_kinodynamic} 的右端项。第 $k$ 个配置区间使用其所属第 $j(k)$ 个档位段的固定值 $\delta_{j(k)}$;这里的 $k$ 表示配置区间,而 $j$ 表示档位段。 + + \paragraph{Sparse Cross-Path Coupling} + % 两条路径之间的耦合全部来自交互项。\eqref{eq:cost_interaction} 的两重弧长积分按上述离散化以矩形法求积,即得两条路径采样点之间的双重和 + \begin{equation} + \begin{aligned} + J_\varPsi = & \frac{w_\varPsi}{\rho_\varPsi^2} + \sum_{i=1}^{M_\text{park}} \sum_{j=1}^{M_\text{exit}} + \tau_{ij} + K\!\left( d_{\varepsilon}(\mathbf{p}_i^\text{park},\mathbf{p}_j^\text{exit}); + \rho_\varPsi, m_\varPsi \right) \\ + & \cdot \Delta s_\text{park}^{(0)} \; \Delta s_\text{exit}^{(0)} + \end{aligned} + \label{eq:joint_psi_discrete} + \end{equation} + % 其中 $\mathbf{p}_i^\text{park}$、$\mathbf{p}_j^\text{exit}$ 分别为两条路径第 $i$、$j$ 个配置点状态的位置分量,而 + \begin{equation} + \tau_{ij} = \frac{1}{v_0} + \left[ (j-1)\Delta s_\text{exit}^{(0)} - (i-1)\Delta s_\text{park}^{(0)} \right]_+ + \label{eq:joint_tau_discrete} + \end{equation} + % 为 \eqref{eq:cost_delay_weight} 在配置点对上的取值。与 \eqref{eq:interaction_field} 的对应关系是:对 $j$ 的内层求和即为 $\varPsi_\text{exit}(\mathbf{p}_i^\text{park}; s_\text{park})$ 的求积近似。 + + % $\tau_{ij}$ 仅依赖配置点\emph{序号}与冻结的标称步长 $\Delta s_\bullet^{(0)}$,不依赖任何路径点坐标,故为可离线预计算的常系数:引入时延权重不改变交互项的稀疏结构,$\tau_{ij} = 0$ 的点对(驶离车早已通过之处)更可在装配阶段直接跳过。此处若改用决策变量 $\Delta s_\bullet$ 表达,两个步长变量将与全部点对耦合;由 \eqref{eq:cons_step_trust},冻结所引入的时延偏差不超过 $\Delta_\text{slide} / v_0$,在本文取值下为亚秒量级,相对 \eqref{eq:cycle_time} 的作业周期可忽略。 + + % 与 $\tau_{ij}$ 同理,式中的求积权重 $\Delta s_\text{park} \Delta s_\text{exit}$ 亦冻结为粗解给定的常值、不参与求导,尽管两个步长本身是 \eqref{eq:joint_variable_one} 中的决策变量。这一处理的理由是实现的简洁与偏差的可忽略:冻结之后该权重成为可并入 $w_\varPsi$ 的常数,交互项遂化为纯粹的核函数加权和,无需在每次迭代中重算求积权重及其导数。其代价是当优化后的路径长度偏离粗解时,冻结的权重与真实弧长步长之间出现比例偏差;该偏差有界且可以接受:由 \eqref{eq:cons_step_trust},真实步长与冻结权重之比满足 $\lvert \Delta s_\bullet / \Delta s_\bullet^{(0)} - 1 \rvert \le \Delta_\text{slide} / \left[ (M_\bullet-1)\Delta s_\bullet^{(0)} \right]$,即不超过 $\Delta_\text{slide}$ 与粗解总长之比,故该比值被约束在 $1$ 的一个小邻域内。更重要的是,交互项是软惩罚而非安全约束(硬安全由 \ref{subsec:convex} 节的走廊承担),其权重的常数尺度偏差被 $w_\varPsi$ 的标定所吸收,不影响解的可行性。 + + % 对单个配置点对记 $\mathbf{r}_{ij}=\mathbf{p}_i^\text{park}-\mathbf{p}_j^\text{exit}$、$d_{ij}^{\varepsilon}=\sqrt{\lVert\mathbf{r}_{ij}\rVert^2+\varepsilon_\varPsi^2}$。由 $\nabla_{\mathbf{p}_i^\text{park}}d_{ij}^{\varepsilon}=\mathbf{r}_{ij}/d_{ij}^{\varepsilon}$ 及链式法则, + % $\nabla_{\mathbf{p}_i^\text{park}}K(d_{ij}^{\varepsilon})=K'(d_{ij}^{\varepsilon})\mathbf{r}_{ij}/d_{ij}^{\varepsilon}$,而对驶离点的梯度带相反符号;$\tau_{ij}$ 作为常系数不参与该求导、仅按 \eqref{eq:joint_tau_discrete} 缩放各点对的贡献。故 \eqref{eq:joint_psi_discrete} 同时对两条路径产生梯度,两条路径可在同一次求解中相互推离。需要注意的是,两条路径所受的梯度\emph{大小相等、方向相反}——这一点并未因 $\tau_{ij}$ 的引入而改变,因为每个点对的时延权重对该对中的两个点是同一个数;时延权重所改变的是各点对之间的相对强度,即排斥作用沿弧长的分布,而非单个点对内部的力学平衡。由 \eqref{eq:compact_kernel} 的有限支撑性质,仅当平滑距离 $d_{ij}^{\varepsilon}<\rho_\varPsi$ 时,该点对才对梯度及 Hessian 产生贡献;叠加 $\tau_{ij} = 0$ 的点对亦无贡献,交互项所形成的跨路径 Hessian 块因此仅在\emph{空间上相近且时序上确有冲突}的配置点对处非零,而非稠密的 $M_\text{park} \times M_\text{exit}$ 块。 + + % 除 $J_\varPsi$ 外,其余目标项与约束均只作用于单条路径内部:\eqref{eq:joint_collocation} 的配置约束在各自路径内耦合相邻配置点,形成带状结构;\eqref{eq:cons_physics} 的物理上界与 \eqref{eq:cons_corridor} 的走廊约束也不连接两条路径。由于 $\boldsymbol{\eta}_\text{load}$ 是由上层系统给定的常量,两条路径分别等于该位姿的边界条件 \eqref{eq:cons_boundary} 不产生跨路径导数耦合。因此,联合问题仅通过稀疏的 $J_\varPsi$ 块发生跨路径耦合。综上,优化阶段所求解的问题为 + \begin{subequations} \label{eq:joint_nlp} + \begin{align} + \min_{\mathbf{z}} \quad + & J_\text{opt}(\mathbf{z}) = J_\ell + J_U + J_\varPsi + J_\kappa + \label{eq:joint_obj} \\ + \text{s.t.} \quad + & \text{\eqref{eq:joint_collocation}},\; + \text{\eqref{eq:cons_junction}},\; + \text{\eqref{eq:cons_boundary}} + \label{eq:joint_eq} \\ + & \text{\eqref{eq:cons_kappa}},\; + \text{\eqref{eq:cons_sigma}},\; + \text{\eqref{eq:cons_step_trust}},\; + \Delta s_\bullet > 0 + \label{eq:joint_ineq} \\ + & \mathbf{A}_k \mathbf{c}_k^{(r)} \le \mathbf{b}_k, + \quad r = 1,\dots,4,\; \forall k + \label{eq:joint_corridor} + \end{align} + \end{subequations} + % 该问题为一个稀疏非线性规划问题。运动学右端 \eqref{eq:cons_kinodynamic} 为光滑的三角函数,平滑距离 \eqref{eq:interaction_distance_smooth} 消除了欧氏范数在零点的不可微性,走廊约束 \eqref{eq:joint_corridor} 为线性;核函数 \eqref{eq:compact_kernel} 在截断点处为 $C^{m-1}$ 连续,故取 $m_\varPsi \ge 3$ 时可提供连续二阶导数。在这些条件下,目标函数与约束关于 $\mathbf{z}$ 二阶连续可微,且其一阶导数(Jacobian)与二阶导数(Hessian)具有前述稀疏结构,满足内点法(interior-point method)的标准适用前提\cite{nocedal2006numerical}。 + + % 本文以 Ipopt\cite{wachter2006ipopt} 求解该问题。Ipopt 采用基于滤子的原始-对偶内点算法,在每一步迭代中需求解一个以 Hessian 与约束 Jacobian组装的大型稀疏线性系统(KKT 系统);由于本问题的 Hessian 与 Jacobian 均为前述窄带加稀疏耦合块的结构,该线性系统可经稀疏 LU 或稀疏 Cholesky 分解高效求解,其阶数远低于稠密存储所暗示的规模。求解以第 \ref{sec:search} 章的粗解作为初值:粗解已满足正确的路径拓扑、分段结构与走廊约束,且其运动基元的转角离散由 $R_\text{min}$ 反推,故已满足 \eqref{eq:cons_kappa} 的曲率上界(见 \ref{subsec:primitive} 节),尚待本阶段处理的主要是 \eqref{eq:cons_sigma} 所要求的曲率变化率有界——粗解的 $\kappa(s)$ 在基元拼接点处跳变,该形态由本阶段的连续优化抹平。内点法对初值的可行性并无强制要求,但一个接近可行的初值能显著减少收敛所需迭代数,这也是本文将粗解搜索与数值优化串联、而非直接以随机或直线初值启动优化的原因之一;该收益的具体幅度由 \ref{subsec:exp_efficiency} 节的热启动对照实验量化。 + + \paragraph{Problem Scale and Rationale for Joint Optimization} + % 联立求解相对交替优化的三点实质优势——共享位姿等式约束被一次性精确满足、标准 NLP 的收敛性结论可直接沿用、以及非对称性不依赖求解方式——详见补充材料 S-III。此处只指出使联立成为可能的结构性前提:问题的标度。决策变量数为 $5M_\text{park} + 5M_\text{exit}$(每条路径 $M_\bullet$ 个四元状态、$M_\bullet - 1$ 个控制量与一个步长),而约束总数与 Jacobian、Hessian 的非零元个数均随配置点数线性增长,即 $O(M_\text{park} + M_\text{exit})$:运动学配置、物理上界与走廊约束逐点施加、各自只牵连相邻配置点,其导数的非零元集中在主对角线附近的窄带内;唯一的跨路径耦合来自 $J_\varPsi$,但由前述有限支撑性与 $\tau_{ij}$ 的零值区,该块的非零元仅出现在空间相近且时序确有冲突的点对上,规模为 $O(\rho_\varPsi / \Delta s_\bullet)$ 量级而非稠密的 $O(M_\text{park} \cdot M_\text{exit})$。因此联立所付出的变量翻倍并不带来线性代数开销的相应膨胀,稀疏内点法可充分利用这一结构。 + + % 交互项在初值处的有效性需要一个条件:仅当\emph{既}空间相近($d_{ij}^\varepsilon < \rho_\varPsi$)\emph{又}时序冲突($\tau_{ij} > 0$)的点对存在时,$J_\varPsi$ 才具备非零梯度,否则由有限支撑性 $J_\varPsi \equiv 0$、交互项完全失效。该条件在本文中自然成立,但其成立之处值得指出:装载位邻域虽是两条路径几何上最贴近处,却因 $\tau_\text{d} = 0$ 而\emph{不}提供梯度;真正提供梯度的是入口侧共享通道段,那里 $\tau_{ij}$ 最高、而两条粗解的间距恰为 $W$ 并按 \eqref{eq:interaction_radius} 落在核的支撑域内。这与 \ref{subsec:proxy} 节“$T_\text{wait}$ 的实际约束来自入口侧通道”是同一件事的两个侧面。 + +\section{Experiments} + \label{sec:exp} + % 【P2】本章骨架先行建立,用以消除正文中的悬空引用;各小节内容待数据到位后填写。 + % 全章预算 3.0 页(见 REVISION_PLAN.md 的页数预算表)。 + + \subsection{Experimental Setup} + \label{subsec:exp_setup} + % TODO(P2-2):场地与车辆参数、算法参数、实现与硬件平台。须交代的量: + % - 车辆:L_v、B_v、L_w、R_min、实测 dot_psi_max(对应 P0-7 的 sigma_max 折算) + % - 场地:规模、边界感知方式与 bar_ell_e 的实际取值(对应 alpha_e 的标定) + % - 场:栅格分辨率 delta、各 (alpha, rho, m)、以及 alpha 是否满足 eq:alpha_dominance + % - 搜索:mu_0、[w_min, w_max]、状态格分辨率 + % - 优化:配置步长 Delta_s 及由 eq:corner_cut_margin 得到的 Delta_cut 实际值(对应 P0-6)、 + % Delta_slide 取值(对应 P0-5)、rho_Psi 与 W 的关系、各权重 w + % - IGF 的刷新频次与触发条件,明确"离线"的实际含义(对应 P2-4) + + \subsection{Baselines and Metrics} + \label{subsec:exp_baselines} + % 五类基线按"逐项剥离本文的设计选择"的原则设置,使每一项对比只回答一个问题。 + % ① 独立规划:两条路径各自以经典 Hybrid A* 加同一套数值优化求解,不含引导场、 + % 不含交互项。该组回答"是否需要双向先验",是与现行做法最接近的对照。 + % ② 固定渠化规则:以预设的双向参考路线替代 \ref{sec:igf} 节由场地几何自动提取的 + % 中线与引导线,其余环节相同。该组回答"自动提取相对人工预设的价值", + % 对应 \ref{sec:related_work} 节所述显式行驶规则一类工作。 + % ③ 交替优化:以 \eqref{eq:joint_nlp} 的两条路径交替固定、轮流求解替代联立求解, + % 其余相同。该组为补充材料 S-III 的论证提供实证。 + % ④ 同索引点距惩罚:以两条路径同序号配置点之间的距离惩罚替代 \eqref{eq:cost_interaction} + % 的核积分交互项。\ref{subsec:objective} 节已论证该形式在两条路径弧长悬殊时 + % 不成立,此处须给出实证而非仅停留在论证。 + % ⑤ 时间维协同调度:放开本文有意排除的时间维决策量,以集中式时空调度求解同一算例, + % 作为吞吐量的性能上界参照。该组回答"空间解耦作为代理目标的损失有多大", + % 是 \ref{subsec:proxy} 节代理关系的唯一直接检验,故不可省略。 + + % 九项指标分三组。第一组直接检验代理目标的有效性:$T_\text{wait}$ 及其相对基线①的 + % 压缩幅度、以及离散事件仿真下的实际吞吐量(趟/小时)——后者是代理目标有效性的 + % 唯一直接证据,须与基线⑤的上界对照报告。第二组检验几何与拓扑性质:两条路径 + % 扫掠域的重叠面积、二者的最小间距分布、以及按 \eqref{eq:topology_consistency} + % 判定的拓扑一致率。第三组检验计算性质:求解时间与成功率(不少于 100 组随机装载位)、 + % 搜索阶段的墙钟时间(须与扩展节点数并列报告:\ref{subsec:primitive} 节的场自适应 + % 步长使每次扩展多出 6 次基元积分与 6 次场查询,节点数下降但单节点变贵, + % 只报节点数不足以说明加速)、走廊半空间数 $m_k$ 的分布与最大值、 + % \eqref{eq:cons_step_trust} 信赖域外循环的触发率、以及热启动相对冷启动的迭代数对照。 + + \subsection{Throughput and Waiting Time} + \label{subsec:exp_throughput} + % TODO(P2-2):T_wait、T_park、T_exit 实测;代理目标有效性的验证。 + % 另需给出入口侧通道宽度 W 的可行性判据(对应 subsec:proxy 中 T_wait 下界的论述), + % 并按 P2-3 将"下界"降级为实测参考值。 + + \subsection{Geometric Decoupling} + \label{subsec:exp_geometry} + % TODO(P2-2):扫掠域重叠面积、两条路径的最小间距分布。 + + \subsection{Topological Consistency Across Loading Poses} + \label{subsec:exp_topology} + % TODO(P0-3/P2-2):跨装载位序列的拓扑一致率(>=100 组随机装载位), + % 含装载位位于中线另一侧的情形——按 subsec:proxy 的说明,该处允许换边,须如实报告。 + + \subsection{Computational Efficiency} + \label{subsec:exp_efficiency} + % TODO(P2-2):求解时间与成功率;搜索阶段墙钟时间(不只报扩展节点数); + % 走廊半空间数 m_k 的分布与最大值;信赖域外循环触发率(对应 P0-5); + % 热启动 vs 冷启动的迭代数对照。 + + \subsection{Ablation Study} + \label{subsec:exp_ablation} + % 逐项去除四处设计选择,每项只改动一个环节、其余保持不变: + % (1) 令 $\tau_\text{d} \equiv 1$,即去除 \eqref{eq:cost_delay_weight} 的时延加权。 + % 按 \ref{subsec:asymmetry} 节的论证,此时交互项关于两条路径完全对称、 + % 非对称性无法再由权重比例引入,故该组直接检验时延权重这一核心构造。 + % (2) 去除 \eqref{eq:cost_interaction} 的交互项 $J_\varPsi$,只保留场引导项 $J_U$, + % 用以分离"离线场先验"与"在线联合推离"两种解耦机制各自的贡献。 + % (3) 去除 \eqref{eq:search_step} 的场自适应步长调制,改用固定步长 $\mu_0$。 + % (4) 令 $w_U^\text{park} = w_U^\text{exit}$,去除 \eqref{eq:asymmetric_weights} 的非对称引导权重, + % 检验满载优先这一工程语义是否确实转化为可测的差异。 + % 正文只报关键两项((1) 与 (2))的主要指标,完整消融表迁入补充材料 S-VI。 + + \subsection{Real-Vehicle Validation} + \label{subsec:exp_realvehicle} + % 本小节的作用不是可行性演示,而是检验前文两处以标称值作出的解析论断在实车上是否成立。 + % 须先交代试验条件:矿卡型号与关键参数($L_\text{v}$、$B_\text{v}$、$L_\text{w}$、 + % $R_\text{min}$ 及实测前轮转角速率上界)、场地规模与边界感知方式(激光雷达型号与 + % 点云分辨率,即 \eqref{eq:bound_edge} 中 $\bar\ell_\text{e}$ 的实际取值)、 + % 试验规模(装载循环次数、覆盖的装载位数量、总里程与时长)、定位方案与精度 + % ——后者决定跟踪误差数据本身的可信度,须与所报误差量级一并给出。 + + % 论证一:跟踪可行性,检验 \eqref{eq:sigma_time_conversion} 的量纲折算与由此得到的 + % $\sigma_\text{max}$ 取值是否够用。须报告横向跟踪误差沿弧长的分布,尤其换向段与 + % 装载位邻域这两处曲率变化最剧烈的区段;同时报告实测前轮转角速率是否触及机械上界。 + % 此处须如实说明一种不利可能:\eqref{eq:sigma_time_conversion} 以标称速度 $v_0$ 折算 + % $\sigma_\text{max}$,若低速段出现大量触顶,则说明该折算偏松而非偏保守, + % $\sigma_\text{max}$ 应改由分段速度剖面给出。此外须报告实测车体轮廓到场地边界的 + % 最小间隙,与 \eqref{eq:corner_cut_margin} 所给的 $\Delta_\text{cut}$ 对照, + % 检验一次性内缩是否确实覆盖了配置点之间的切角。 + + % 论证二:吞吐量增益,与离散事件仿真互为验证。须报告实测 $T_\text{wait}$、 + % $T_\text{park}$、$T_\text{exit}$ 与仿真预测值的对照,以及相对现行作业方式的 + % 趟/小时对比。两项论证相互独立:前者说明所规划的路径可被执行, + % 后者说明执行之后确实产生了 \ref{subsec:proxy} 节所预期的吞吐量收益。 + + % 对照组安排:实车上仅跑基线①(独立规划)与本文方法两组,其余基线留在仿真。 + % 理由须明确写出——基线②--⑤或需改动场地既有作业规则、或需放开时间维调度权限, + % 在生产矿区不具备实施条件;此处如实说明,避免被理解为回避不利对比。 + +\section{Conclusion} + \label{sec:conclusion} + % 本文针对露天矿装载场地内进出双向路径的时空冲突问题,提出了以空间解耦程度为吞吐量代理目标的规划方法。 + % 三点结论。其一,双向通行的拓扑要求不必作为在线约束施加:将场地边界与两条方向性引导线离散为势源、 + % 叠加为一对关于虚拟道路中线互为镜像的方向性场,该拓扑即被前置固化于离线阶段;由于场的构造只用到 + % 边界几何、不含装载位信息,装载位变更时无需重建场,两条路径亦可在各自的场上独立并行搜索。 + % 其二,两条路径之间的冲突代价宜以有限支撑核的时延加权二重弧长积分表达:该形式只取决于两条路径的 + % 整体几何关系,因而不受泊入路径含换向段、其弧长显著大于驶离路径这一非对称性的影响;时延权重仅依赖 + % 配置点序号与冻结步长,故为常系数,不改变联合优化问题的稀疏结构。其三,非对称引导权重使满载车优先 + % 这一工程语义直接进入目标函数,而无须依赖权重比例——后者在无时延加权时对极小点并无影响。 + % 实验部分以五类基线(含时间维协同调度作为性能上界)与实车试验对上述结论予以验证。 + + % 本文方法的适用边界亦须明确。IGF 承担的是随场地边界缓变的通行拓扑,而非随车流快变的瞬时占据, + % 故挖掘机与其他车辆等移动障碍由在线凸走廊避让、不进入场的构造。所优化的是吞吐量的必要条件而非 + % 吞吐量本身:空间解耦消除了冲突导致的等待,但并不保证上层派车节拍与之匹配。此外,拓扑一致性由 + % 软代价倾向性地促成而非硬约束强制,装载位移至中线另一侧时仍可能换边。 + % 后续工作将沿两个方向展开:一是将上层派车节拍纳入代理目标的标定,使空间解耦的收益能够传导至 + % 实际吞吐量;二是将场的重建从班次级触发推进到随边界感知增量更新,以适应开采面推进更快的作业面。 + + % TODO(P2-5):实测数据到位后,在第一段末尾补一句量化结论(等待时间压缩幅度、吞吐量增益、求解耗时), + % 与 Abstract 末句的占位数字同步替换。 + +% 【P1-3】原附录 A「Second-Difference Discretization of Curvature Constraints」整节 +% (6 个公式)已迁入补充材料 S-V,正文 subsec:centerline 只保留换算关系本身、误差量级 +% 的一句结论与指针。原附录 B 已于 P1-1 迁入 S-IV,故 \appendices 环境及其计数器/ +% hyperref 锚点设置一并删除;若后续需要恢复附录,需同时恢复 \counterwithin 与 +% \theHequation 等定义,否则附录与正文的图/式编号会产生同名 hyperref destination。 + +% TODO(投稿前): 正文取消注释后删除下面这行 \nocite{*},否则参考文献表会打印 refs.bib 的全部条目。 +% 当前草稿阶段正文均为注释、无任何生效的 \cite,故必须保留此行,否则 thebibliography 为空而编译报错。 +\nocite{*} +\bibliographystyle{IEEEtran} +\bibliography{refs} + +\end{document} diff --git a/orcidlink.sty b/orcidlink.sty new file mode 100644 index 0000000..cf8ba2a --- /dev/null +++ b/orcidlink.sty @@ -0,0 +1,78 @@ +%% +%% This is file `orcidlink.sty', +%% generated with the docstrip utility. +%% +%% The original source files were: +%% +%% orcidlink.dtx (with options: `package') +%% +%% This is a generated file. +%% +%% Copyright (C) 2019-2024 by Leo C. Stein +%% -------------------------------------------------------------------------- +%% This work may be distributed and/or modified under the +%% conditions of the LaTeX Project Public License, either version 1.3 +%% of this license or (at your option) any later version. +%% The latest version of this license is in +%% http://www.latex-project.org/lppl.txt +%% and version 1.3 or later is part of all distributions of LaTeX +%% version 2005/12/01 or later. +%% +\NeedsTeXFormat{LaTeX2e}[1994/06/01] +\ProvidesPackage{orcidlink} + [2024/06/26 v1.1.0 Support ORCID's three different ID formats.] + +%% This started out as Milo's code on TeX.SE, +%% see https://tex.stackexchange.com/a/445583/34063. +%% It has since been expanded with more commands. +\RequirePackage{hyperref} +\RequirePackage{tikz} + +\ProcessOptions\relax + +\usetikzlibrary{svg.path} + +\definecolor{orcidlogocol}{HTML}{A6CE39} +\tikzset{ + orcidlogo/.pic={ + \fill[orcidlogocol] svg{M256,128c0,70.7-57.3,128-128,128C57.3,256,0,198.7,0,128C0,57.3,57.3,0,128,0C198.7,0,256,57.3,256,128z}; + \fill[white] svg{M86.3,186.2H70.9V79.1h15.4v48.4V186.2z} + svg{M108.9,79.1h41.6c39.6,0,57,28.3,57,53.6c0,27.5-21.5,53.6-56.8,53.6h-41.8V79.1z M124.3,172.4h24.5c34.9,0,42.9-26.5,42.9-39.7c0-21.5-13.7-39.7-43.7-39.7h-23.7V172.4z} + svg{M88.7,56.8c0,5.5-4.5,10.1-10.1,10.1c-5.6,0-10.1-4.6-10.1-10.1c0-5.6,4.5-10.1,10.1-10.1C84.2,46.7,88.7,51.3,88.7,56.8z}; + } +} + +%% Reciprocal of the height of the svg whose source is above. The +%% original generates a 256pt high graphic; this macro holds 1/256. +\newcommand{\@OrigHeightRecip}{0.00390625} + +%% We will compute the current X height to make the logo the right height +\newlength{\@curXheight} + +%% Prevent externalization of the ORCiD logo. +\newcommand{\@preventExternalization}{% +\ifcsname tikz@library@external@loaded\endcsname% +\tikzset{external/export next=false}\else\fi% +} + +\newcommand{\orcidlogo}{% +\texorpdfstring{% +\setlength{\@curXheight}{\fontcharht\font`X}% +\XeTeXLinkBox{% +\@preventExternalization% +\begin{tikzpicture}[yscale=-\@OrigHeightRecip*\@curXheight, +xscale=\@OrigHeightRecip*\@curXheight,transform shape] +\pic{orcidlogo}; +\end{tikzpicture}% +}}{}} + +\DeclareRobustCommand\orcidlinkX[3]{\href{https://orcid.org/#2}{% +\ifstrempty{#1}{}{#1\,}\orcidlogo\ifstrempty{#3}{}{\,#3}}} +\newcommand{\orcidlinkf}[1]{\orcidlinkX{}{#1}{https://orcid.org/#1}} +\newcommand{\orcidlinkc}[1]{\orcidlinkX{}{#1}{#1}} +\newcommand{\orcidlinki}[2]{\orcidlinkX{#1}{#2}{}} +\newcommand{\orcidlink}[1]{\orcidlinkX{}{#1}{}} + +\endinput +%% +%% End of file `orcidlink.sty'. diff --git a/refs.bib b/refs.bib new file mode 100644 index 0000000..e086b67 --- /dev/null +++ b/refs.bib @@ -0,0 +1,382 @@ +% --------------------------------------------------------------- +% Bibliography +% All entries below correspond to real, locatable publications. +% All entries verified against Crossref / arXiv metadata (last checked 2026-08-24). +% --------------------------------------------------------------- + +% ===== Hybrid A* and unstructured-environment search ===== +@inproceedings{dolgov2008practical, + author = {Dolgov, Dmitri and Thrun, Sebastian and Montemerlo, Michael and Diebel, James}, + title = {Practical Search Techniques in Path Planning for Autonomous Driving}, + booktitle = {Proc. 1st Int. Symp. Search Techniques in Artificial Intelligence + and Robotics (STAIR), AAAI Workshop}, + year = {2008}, + address = {Chicago, IL, USA} +} + +@article{reedsshepp1990, + author = {Reeds, J. A. and Shepp, L. A.}, + title = {Optimal Paths for a Car That Goes Both Forwards and Backwards}, + journal = {Pacific Journal of Mathematics}, + volume = {145}, + number = {2}, + pages = {367--393}, + year = {1990}, + doi = {10.2140/pjm.1990.145.367} +} + +% NOTE: 以下三条为 Section V 新增基线 B4/B5 所需,投稿前须补全作者与卷期页信息。 +@article{dolgov2010voronoi, + author = {Dolgov, Dmitri and Thrun, Sebastian and Montemerlo, Michael and Diebel, James}, + title = {Path Planning for Autonomous Vehicles in Unknown Semi-structured Environments}, + journal = {International Journal of Robotics Research}, + volume = {29}, + number = {5}, + pages = {485--501}, + year = {2010}, + doi = {10.1177/0278364909359210} +} + +@article{zhang2021obca, + author = {Zhang, Xiaojing and Liniger, Alexander and Borrelli, Francesco}, + title = {Optimization-Based Collision Avoidance}, + journal = {IEEE Transactions on Control Systems Technology}, + volume = {29}, + number = {3}, + pages = {972--983}, + year = {2021}, + doi = {10.1109/TCST.2019.2949540} +} + +@article{lian2023valetparking, + author = {Lian, Jing and Ren, Weiwei and Yang, Dongfang and Li, Linhui and Yu, Fengning}, + title = {Trajectory Planning for Autonomous Valet Parking in Narrow + Environments with Enhanced Hybrid {A*} Search and Nonlinear + Optimization}, + journal = {IEEE Transactions on Intelligent Vehicles}, + volume = {8}, + number = {6}, + pages = {3723--3734}, + year = {2023}, + doi = {10.1109/TIV.2023.3268088} +} + +@article{li2022parkingcorridor, + author = {Li, Bai and Acarman, Tankut and Zhang, Youmin and Ouyang, Yakun and Yaman, Cagdas and Kong, Qi and Zhong, Xiang and Peng, Xiaoyan}, + title = {Optimization-Based Trajectory Planning for Autonomous Parking + with Irregularly Placed Obstacles: A Lightweight Iterative + Framework}, + journal = {IEEE Transactions on Intelligent Transportation Systems}, + volume = {23}, + number = {8}, + pages = {11970--11981}, + year = {2022}, + doi = {10.1109/TITS.2021.3109011} +} + +@article{sedighi2023hybridastar, + author = {Wang, Qi and Li, Guang and Ding, Shuai}, + title = {High-Efficiency Navigation of Nonholonomic Mobile Robots + Based on Improved Hybrid {A*} Algorithm}, + journal = {Applied Sciences}, + volume = {13}, + number = {10}, + pages = {6141}, + year = {2023}, + doi = {10.3390/app13106141} +} + +% ===== Open-pit mine path/trajectory planning ===== +@article{mine2020lastsection, + author = {Zhao, Ziyu and Bi, Lin}, + title = {Path Planning for Autonomous Truck of Open-Pit Mines + in The Last Transport Section}, + journal = {Applied Sciences}, + volume = {10}, + number = {18}, + pages = {6622}, + year = {2020}, + doi = {10.3390/app10186622} +} + +@article{mine2025humanlikeparking, + author = {Li, Han and Yu, Guizhen and Chen, Peng and Li, Yiming and Xia, Qi}, + title = {A Human-Like Parking Trajectory Planning Approach for + Autonomous Vehicle Load Tasks in Mining Site}, + journal = {Automotive Innovation}, + year = {2025}, + doi = {10.1007/s42154-025-00358-8}, + volume = {8}, + number = {4}, + pages = {913--934} +} + +@article{mine2023secure, + author = {Li, Han and Li, Yiming and Chen, Peng and Yu, Guizhen and Liao, Yaping}, + title = {A Secure Trajectory Planning Method for Connected + Autonomous Vehicles at Mining Site}, + journal = {Symmetry}, + volume = {15}, + number = {11}, + pages = {1973}, + year = {2023}, + doi = {10.3390/sym15111973} +} + +@inproceedings{mine2024unstructured, + author = {Li, Lei and Chen, Zhifa and Wang, Jian and Zhou, Bin and Yu, Guizhen and Chen, Xiaoxuan}, + title = {Multimodal Trajectory Prediction for Autonomous Driving on + Unstructured Roads Using Deep Convolutional Network}, + booktitle = {Proceedings of the 2024 International Conference on Artificial + Intelligence and Autonomous Transportation}, + series = {Lecture Notes in Electrical Engineering}, + pages = {32--42}, + publisher = {Springer Nature Singapore}, + year = {2025}, + doi = {10.1007/978-981-96-3957-1{\_}3} +} + +@article{mine2024truckreversing, + author = {Aydemir, Eren and Unel, Mustafa}, + title = {Motion Planning and Path Following for Autonomous Navigation + and Reversing of a Full-Scale Mining Truck and Trailer System}, + journal = {International Journal of Automotive Technology}, + year = {2024}, + doi = {10.1007/s12239-024-00174-9}, + volume = {26}, + number = {3}, + pages = {595--606} +} + +% ===== Multi-vehicle coordination and conflict resolution ===== +@inproceedings{ramp2024spatiotemporal, + author = {Xu, Xiaoxue and Lai, Maokai and Zhang, Haitao and Dong, Xiang and Li, Tao and Wu, Jie and Li, Yuan and Peng, Ting}, + title = {Spatio-Temporal Cooperative Control Method of Highway Ramp + Merge Based on Vehicle-Road Coordination}, + booktitle = {2024 12th International Conference on Traffic and Logistic + Engineering (ICTLE)}, + pages = {93--98}, + year = {2024}, + doi = {10.1109/ICTLE62418.2024.10703891} +} + +@article{ramp2026distributed, + author = {Nie, Linhua and Zhang, Tingyang and Zhao, Yunqing and Li, Yaqiu and Li, Haoran and Yang, Junru}, + title = {Distributed Multi-Vehicle Cooperative Trajectory Planning and + Control for Ramp Merging and Diverging Based on Deep Neural + Networks and {MPC}}, + journal = {Machines}, + volume = {14}, + number = {3}, + pages = {262}, + year = {2026}, + doi = {10.3390/machines14030262} +} + +@article{mine2025rightofway, + author = {Sun, Rentao and Yu, Guizhen and Chen, Peng and Ni, Haoyuan and Zhou, Bin}, + title = {Cooperative Right-of-Way Assignment for Autonomous Mining + Trucks at Multiple Open-Pit Mine Intersections}, + journal = {Automotive Innovation}, + year = {2026}, + doi = {10.1007/s42154-025-00368-6}, + volume = {9}, + number = {1}, + pages = {16--30} +} + +@article{mine2023scheduling, + author = {Fang, Yong and Peng, Xiaoyan}, + title = {Micro-Factors-Aware Scheduling of Multiple Autonomous Trucks + in Open-Pit Mining via Enhanced Metaheuristics}, + journal = {Electronics}, + volume = {12}, + number = {18}, + pages = {3793}, + year = {2023}, + doi = {10.3390/electronics12183793} +} + +% ===== Artificial potential field and its limitations ===== +@inproceedings{apf2024globalrepulsive, + author = {Peng, Bo and Zhang, Lingke and Xiong, Rong}, + title = {Smooth Path Planning with Subharmonic Artificial Potential + Field}, + booktitle = {2024 International Conference on Advanced Robotics and + Mechatronics (ICARM)}, + pages = {1027--1031}, + year = {2024}, + doi = {10.1109/ICARM62033.2024.10715803} +} + +@inproceedings{apf2024wallfollower, + author = {Kim, Joonkyung and Park, Sangjin and Lee, Wonjong and Kim, Woojun and Choi, Hyunga and Doh, Nakju and Nam, Changjoo}, + title = {Escaping Local Minima: Hybrid Artificial Potential Field with + Wall-Follower for Decentralized Multi-Robot Navigation}, + booktitle = {2025 IEEE International Conference on Robotics and Automation + (ICRA)}, + pages = {6616--6622}, + year = {2025}, + doi = {10.1109/ICRA55743.2025.11128765} +} + +% ===== Convex-decomposition safe corridors ===== +@article{corridor2022voxelgrid, + author = {Toumieh, Charbel and Lambert, Alain}, + title = {Voxel-Grid Based Convex Decomposition of 3D Space for + Safe Corridor Generation}, + journal = {Journal of Intelligent \& Robotic Systems}, + year = {2022}, + doi = {10.1007/s10846-022-01708-y}, + volume = {105}, + number = {4} +} + +@article{corridor2024convexcover, + author = {Wu, Yuwei and Spasojevic, Igor and Chaudhari, Pratik and Kumar, Vijay}, + title = {Towards Optimizing a Convex Cover of Collision-Free Space + for Trajectory Generation}, + journal = {IEEE Robotics and Automation Letters}, + volume = {10}, + number = {5}, + pages = {4762--4769}, + year = {2025}, + doi = {10.1109/LRA.2025.3553416} +} + +@article{corridor2023rover, + author = {Li, Yiqun and Liang, Shaoqiang and Gao, Jiahui and Chen, Zong and Qiao, Siyuan and Yin, Zhouping}, + title = {Trajectory Optimization for the Nonholonomic Space Rover in + Cluttered Environments Using Safe Convex Corridors}, + journal = {Aerospace}, + volume = {10}, + number = {8}, + pages = {705}, + year = {2023}, + doi = {10.3390/aerospace10080705} +} + +% ===== Skeleton / centerline extraction ===== +@inproceedings{beeson2005evg, + author = {Beeson, Patrick and Jong, Nicholas K. and Kuipers, Benjamin}, + title = {Towards Autonomous Topological Place Detection Using the + Extended {Voronoi} Graph}, + booktitle = {Proc. IEEE Int. Conf. Robotics and Automation (ICRA)}, + pages = {4373--4379}, + year = {2005}, + address = {Barcelona, Spain} +} + +@misc{evgthin, + title = {{EVG-Thin}: A Thinning-Based Approximation of the + Extended {Voronoi} Graph}, + howpublished = {Software, The University of Texas at Austin}, + year = {2005}, + url = {http://www.cs.utexas.edu/users/qr/software/evg-thin.html} +} + +% ===== Reference-line smoothing (Apollo) ===== +@inproceedings{zhou2020apolloqp, + author = {Zhang, Yajia and Sun, Hongyi and Zhou, Jinyun and Pan, Jiacheng + and Hu, Jiangtao and Miao, Jinghao}, + title = {Optimal Vehicle Path Planning Using Quadratic Optimization for + {Baidu} {Apollo} Open Platform}, + booktitle = {Proc. IEEE Intelligent Vehicles Symposium (IV)}, + pages = {978--984}, + year = {2020}, + doi = {10.1109/IV47402.2020.9304787} +} + +@article{fan2018apolloem, + author = {Fan, Haoyang and Zhu, Fan and Liu, Changchun and Zhang, Liangliang + and Zhuang, Li and Li, Dong and Zhu, Weicheng and Hu, Jiangtao + and Li, Hongye and Kong, Qi}, + title = {Baidu {Apollo} {EM} Motion Planner}, + journal = {arXiv preprint arXiv:1807.08048}, + year = {2018}, + eprint = {1807.08048}, + archivePrefix = {arXiv}, + primaryClass = {cs.RO} +} + +% ===== Elastic band path deformation ===== +@inproceedings{quinlan1991elastic, + author = {Quinlan, Sean and Khatib, Oussama}, + title = {Towards Real-Time Execution of Motion Tasks}, + booktitle = {Proc. 2nd Int. Symp. Experimental Robotics (ISER)}, + year = {1991} +} + +@phdthesis{quinlan1994thesis, + author = {Quinlan, Sean}, + title = {Real-Time Modification of Collision-Free Paths}, + school = {Stanford University}, + year = {1994}, + note = {Technical Report STAN-CS-TR-95-1537} +} + +% ===== Numerical optimization solvers ===== +@article{wachter2006ipopt, + author = {W{\"a}chter, Andreas and Biegler, Lorenz T.}, + title = {On the Implementation of an Interior-Point Filter Line-Search + Algorithm for Large-Scale Nonlinear Programming}, + journal = {Mathematical Programming}, + volume = {106}, + number = {1}, + pages = {25--57}, + year = {2006}, + doi = {10.1007/s10107-004-0559-y} +} + +@book{nocedal2006numerical, + author = {Nocedal, Jorge and Wright, Stephen J.}, + title = {Numerical Optimization}, + edition = {2nd}, + publisher = {Springer}, + year = {2006} +} + +@book{docarmo2016curves, + author = {do Carmo, Manfredo P.}, + title = {Differential Geometry of Curves and Surfaces}, + edition = {2nd}, + publisher = {Dover Publications}, + address = {Mineola, NY, USA}, + year = {2016} +} + +@article{kouvelis1992unidirectional, + author = {Kouvelis, Panagiotis and Kim, Michael W.}, + title = {Unidirectional Loop Network Layout Problem in Automated + Manufacturing Systems}, + journal = {Operations Research}, + volume = {40}, + number = {3}, + pages = {533--550}, + year = {1992}, + doi = {10.1287/opre.40.3.533} +} + +@article{seo2006flowpath, + author = {Seo, Yoonho and Lee, Chulung and Moon, Chiung}, + title = {Tabu Search Algorithm for Flexible Flow Path Design of + Unidirectional Automated-Guided Vehicle Systems}, + journal = {OR Spectrum}, + volume = {29}, + number = {3}, + pages = {471--487}, + year = {2006}, + doi = {10.1007/s00291-006-0047-2} +} + +@article{baek2017haulroad, + author = {Baek, Jieun and Choi, Yosoon}, + title = {A New Method for Haul Road Design in Open-Pit Mines to Support + Efficient Truck Haulage Operations}, + journal = {Applied Sciences}, + volume = {7}, + number = {7}, + pages = {747}, + year = {2017}, + doi = {10.3390/app7070747} +} diff --git a/supplement.tex b/supplement.tex new file mode 100644 index 0000000..f0a5442 --- /dev/null +++ b/supplement.tex @@ -0,0 +1,398 @@ +\documentclass[journal]{IEEEtran} +\usepackage{etoolbox} +\usepackage{orcidlink} +\usepackage{bookmark} +\usepackage{amsmath} +\usepackage{amsfonts} +\usepackage{amssymb} +\usepackage{booktabs} +\usepackage{multirow} +\usepackage{graphicx} +\graphicspath{{figs/}} +\hypersetup{hidelinks} + +% 补充材料内的公式、图、表统一加 S 前缀独立编号,避免与正文编号混淆。 +% 正文引用本材料时写作 "see Section S-I of the supplementary material"。 +\renewcommand{\theequation}{S\arabic{equation}} +\renewcommand{\thefigure}{S\arabic{figure}} +\renewcommand{\thetable}{S\arabic{table}} +\renewcommand{\thesection}{S-\Roman{section}} + +\begin{document} + +\title{Supplementary Material for ``Spatially Decoupled Inbound and Outbound +Path Planning for Open-Pit Mine Loading Areas via Integrated Guidance Fields +and Joint Optimization''} + +\author{ + Chuang Wang\orcidlink{0009-0003-5795-2504}, + Peng Chen\orcidlink{0000-0002-8076-8989},~\IEEEmembership{Member,~IEEE,} + Yiming Li\orcidlink{0009-0007-7859-4987}, + Han Li\orcidlink{0000-0001-5136-7396}, + Guizhen Yu\orcidlink{0000-0001-8374-7422} +} + +\maketitle + +% 本补充材料收录正文因篇幅所限而未展开的推导过程、参数标定依据与实现细节。 +% 正文中仅保留结论性结果(各上界的表达式、标定条件、最终约束形式),其来由见本材料对应各节。 +% 组织如下:S-I 给出引导场取值上界的推导与场强系数标定依据;S-II 说明栅格场的连续化表示; +% S-III 论证联立求解相对交替优化的取舍;S-IV 给出凸走廊构造的完整推导; +% S-V 给出曲率约束二阶差分离散化的推导与误差量级;S-VI 汇总实现参数与补充实验结果。 + +\section{Bounds of the Guidance Field and Gain Calibration} + \label{sup:field_bounds} + + % 【来源:正文 III-C,原 main.tex 510--533、566--577】 + % 正文保留 U_g^max、U_e^max 的表达式与 (eq:alpha_dominance) 的标定条件,此处给出其推导。 + + \subsection{Upper Bound of the Guidance-Line Field} + % 由有限支撑核的非负性,各分场下界平凡地为 0,即势源影响半径之外场值恒为零。 + % 对于上界,考察一条折线穿过查询点的 rho 邻域的情形。假定 rho_S 不超过引导线的最小曲率半径 + % (该曲率上界已由正文中线平滑的曲率约束保证),从而折线至多穿越该邻域一次、不会在邻域内盘绕 + % 而使支撑域内弧长超出弦长;此时落在支撑域内的折线段总长不超过其穿越邻域的路径长度, + % 当折线沿直径方向直线穿过时取到最大值。对采用弧长权重的引导线场,其上界即为核函数沿该直径的积分: + % 以查询点在折线上的投影点为弧长原点,此时 d = |t|、t 属于 [-rho_g, rho_g], + % 代入核函数积分即得引导线场的上界: + \begin{equation} + 0 \le U_\text{g} \le + \alpha_\text{g} \int_{-\rho_\text{g}}^{\rho_\text{g}} + \left( 1 - \frac{|t|}{\rho_\text{g}} \right)^{m_\text{g}} \mathrm{d}t + = \frac{2\alpha_\text{g} \rho_\text{g}}{m_\text{g} + 1} + \triangleq U_\text{g}^\text{max} . + \label{eq:sup_bound_guide} + \end{equation} + % 该式即正文 \eqref{eq:bound_guide}。需注意其成立依赖前述"至多穿越一次"的前提: + % 若 rho_g 超过引导线的最小曲率半径,折线可在支撑域内盘绕,支撑域内弧长将超出弦长, + % 此时 \eqref{eq:sup_bound_guide} 不再是上界。本文对 rho_g 的取值即按此约束选定。 + + \subsection{Counting Bound of the Boundary Field} + % 场地边界顶点由感知模块直接给出、相邻间距不均匀且不具备明确弧长语义,故取线元权重恒为 1, + % 即以顶点计数的形式累积边界排斥作用。核的支撑域为直径 2 rho_e 的圆,故边界局部近似为直线时, + % 落入其中的顶点数约为 2 rho_e / bar_ell_e,计入端点得 + \begin{equation} + 0 \le U_\text{e} \le + \alpha_\text{e} \left( \frac{2\rho_\text{e}}{\bar\ell_\text{e}} + 1 \right) + \triangleq U_\text{e}^\text{max} , + \label{eq:sup_bound_edge} + \end{equation} + % 即正文 \eqref{eq:bound_edge}。该式取核函数在支撑域内的最大值 1 作为每个顶点的贡献, + % 因而在计数正确的前提下是上界。 + + % 但计数本身只是估计。在凹形拐角处,两侧边界同时进入支撑域, + % 落入的顶点数可高于 2 rho_e / bar_ell_e,故 \eqref{eq:sup_bound_edge} 严格意义上并非全局上界。 + % 若需严格上界,可按场地边界的最小内角 theta_e^min 将顶点计数放大 ceil(2 pi / theta_e^min) 倍 + % 得到最坏情形;代价是该上界在绝大多数栅格上过分保守,用于归一化会压缩场值的有效动态范围。 + % 正文因此取 \eqref{eq:sup_bound_edge} 的估计形式用于归一化标定,因该处所需的是场值的典型量级, + % 并在栅格场构建后对归一化结果施加截断 min{hat_U, 1} 使值域严格化(见正文归一化处的说明)。 + % 这一取舍不影响支配条件所要保证的性质:该条件本身留有裕度, + % 且凹角处边界场的局部增大只会强化边界排斥作用,与该条件的意图同向。 + + \subsection{Dimensional Mismatch and Recalibration} + % 引导线场的上界仅由 alpha_g、rho_g 与 m_g 决定,与采样密度无关; + % 而边界场的上界与顶点密度成反比地依赖于平均顶点间距。这一差异要求在更换感知配置 + % 或边界提取分辨率时对 alpha_e 作相应标定;若将边界顶点同样赋以等效弧长权重, + % 边界场的上界即可化为与引导线场一致的形式。 + + \subsection{Choice of Linear Superposition} + % 叠加方式采用线性组合而非取极值或乘性组合,主要出于场的光滑性考虑: + % 核函数在支撑域内为 C^{m-1} 连续,线性组合保持该光滑性。两种替代方式各自破坏光滑性: + % 取极值 max{U_e, U_p, U_x} 会在各分场取值相等的等值面上引入梯度不连续的折痕, + % 该折痕位置随场地几何而变、无法预先规避,且恰可能落在通道中部即路径的必经之处; + % 乘性组合则会在任一分场取零时抹去其余分场的信息——由有限支撑性, + % 支撑域之外分场恒为零,故乘性组合在大部分工作空间中恒为零、方向先验完全失效。 + % 光滑性对本文是必要的:引导场不仅用于搜索代价,还参与联合优化阶段的连续优化, + % 后者要求代价项具备良好的数值可微性。 + % 此外,连续意义下的这一光滑性还须由场的离散化表示予以保持, + % 这正是采用三次 B 样条而非双线性插值查询栅格场的原因,见 Section \ref{sup:spline}。 + +\section{Continuous Representation of the Discretized Field} + \label{sup:spline} + + % 【来源:正文 III-C,原 main.tex 560--563】 + % 正文只保留结论:"以张量积三次 B 样条查询预计算栅格场,核函数衰减阶数取 m >= 3。" + + % 最直接的双线性插值虽已避免最近邻查询的阶跃不连续,但其仅为 C^0 连续: + % 一阶导数在栅格单元的公共边上跳变,而单元内部虽有非零的混合二阶导数、 + % 二阶纯偏导却恒为零。以其表达的场代价项因此不满足联合优化所要求的二阶连续可微性。 + + % 本文因此以张量积三次 B 样条作为场的连续化表示:由栅格场值经预滤波(prefiltering)解出样条系数, + % 该步骤与场的构建一并在离线阶段完成;在线查询时场值及其一阶、二阶导数均由样条基函数解析给出, + % 单次查询在二维情形下涉及 4x4 个系数,仍为常数时间。 + + % 相应地,核函数的衰减阶数须取 m_e、m_g >= 3,使连续意义下的场本身即为 C^2; + % 否则样条虽在形式上给出连续二阶导数,其所逼近的对象在截断半径处并不具备该光滑性。 + % 该取值与交互核所要求的 m_Psi >= 3 同源。 + + % 还需说明两阶段为何统一采用同一表示。搜索阶段仅以场的函数值参与评价、并不求导, + % 故该阶段本可采用更廉价的双线性查询。两阶段统一采用样条表示,是为避免搜索与优化 + % 所依据的代价在数值上不一致——若两阶段查询同一栅格场却得到不同的插值值, + % 粗解相对优化阶段目标函数的"良好初值"性质便失去严格依据。 + + % TODO: 若篇幅允许,补一张双线性与三次 B 样条在同一栅格上的一阶导数对比图, + % 直观展示前者在单元边界处的跳变。 + +\section{Rationale for Joint Rather Than Alternating Optimization} + \label{sup:joint_vs_alternating} + + % 【来源:正文 V-C,原 main.tex 888--896】 + % 正文只保留一句结论 + 指向本节。 + + % 相比交替优化(固定一条、优化另一条,逐次迭代至收敛),联立求解有三点实质优势。 + + % 其一,装载位共享位姿是一条真正的等式约束;交替方案中它在每个子问题内被固定为 + % 对向路径的当前值,等于将一条约束降格为轮流赋值,而联立形式下它被一次性精确满足。 + + % 其二,交替优化的收敛性在本问题上难以给出有意义的保证:交互项与各子问题均非凸, + % 块坐标下降的标准收敛结论所要求的块凸性或子问题唯一解在此都不成立, + % 可断言的仅有目标单调不增且有下界这一较弱性质;而联立问题是一个标准 NLP, + % 可直接沿用求解器的局部收敛性结论。 + + % 其三,本文的非对称性由两处机制共同承担:交互项自带的时延权重 tau_d(决定排斥作用 + % 沿弧长施加在何处)与两条路径引导权重 w_U 的差异(决定各自让开多少)。 + % 二者均不依赖求解方式,在联立求解下同样成立,因此放弃交替更新并不损失 + % "非对称双通道"的设计取向。 + + % 联立的代价是决策变量规模翻倍。但跨路径耦合仅存在于稀疏的交互项块 + % (正文已给出该块的规模量级),稀疏内点法求解器可充分利用这一结构; + % 且双路径生成在车辆抵达装载场地前离线完成,其耗时相对采装作业周期可忽略。 + + % 【待补】交替优化 vs 联立求解的实测对照(迭代数、墙钟时间、最终目标值、共享位姿的约束违反量), + % 与正文实验章的基线 3 共用同一组数据。 + +\section{Ellipsoid-Based Convex Corridor Construction} + \label{sup:convex_decomp} + + % 【来源:正文原附录 B,main.tex 970--1008,整节迁入】 + % 正文只保留凸多面体的最终形式与"由局部边界点分布自适应确定半空间"这一性质。 + + % 本节给出凸分解方法的详细数学推导。其目标是在离散障碍点集合约束下, + % 围绕初始路径的每一段线段,求解一个包裹该线段的无碰撞凸多面体。 + % 将初始路径逐段处理并令相邻走廊保持重叠,即可得到覆盖整条路径的凸走廊序列。 + % 整个构造的几何直观见图 \ref{fig:sup_convex_decomp}。 + + \subsection{Problem Setup and Notation} + % 沿用正文约定,记 p = [x, y]^T 为工作空间中的几何点。设当前路径段的两个端点为 p_0、p_1, + % 障碍点集合为 O = {o_i},则目标是围绕线段 + % L = {(1-t) p_0 + t p_1 | t 属于 [0,1]} + % 求一个无碰撞凸多面体 P = {p | A p <= b}。 + % 方法引入一个包裹线段 L 的辅助椭球 E 作为几何代理,其定义为 + \begin{equation} + \mathcal{E} = \left\{ \mathbf{C}\mathbf{u} + \mathbf{d} + \;\middle|\; \left\lVert \mathbf{u} \right\rVert \le 1 \right\} , + \label{eq:sup_ellipsoid_param} + \end{equation} + % 其中 C 属于 R^{2x2} 为形状矩阵,d 属于 R^2 为椭球中心,u 表示单位球中的点。 + % 椭球 E 的面积与 det(C) 成正比。 + + \subsection{Collision-Free Ellipsoid Construction} + % 以线段中点为椭球中心,取线段方向为椭球长轴,初始将椭球设为半径等于线段半长的球, + % 再沿垂直于线段的短轴方向收缩,直到椭球边界恰好触及最近的障碍点, + % 从而得到一个不含任何障碍点、且完整包裹线段的椭球,其二次型表达为 + \begin{equation} + \mathcal{E} = \left\{ \mathbf{p} \;\middle|\; + (\mathbf{p} - \mathbf{d})^\top + \left( \mathbf{C}\mathbf{C}^\top \right)^{-1} + (\mathbf{p} - \mathbf{d}) \le 1 \right\} , + \quad + \mathbf{o}_i \notin \mathrm{int}(\mathcal{E}) \ \ \forall i . + \label{eq:sup_ellipsoid_quadratic} + \end{equation} + % 以线段中点 d = (p_0 + p_1)/2 为椭球中心。 + + \subsection{Supporting Half-Space Generation} + % 给定避障椭球,逐个为障碍点生成一个将其与线段分离的超平面。 + % 法向量取椭球边界上距该障碍点最近点处的外法线方向,即由椭球度量确定; + % 偏置项使障碍点位于对应半空间边界上,而椭球(及其内部的线段)位于安全一侧。 + % 为避免冗余约束,每生成一个半空间即剔除被其排除的障碍点, + % 仅对剩余障碍点继续生成超平面,直到所有障碍点均被分离。 + % 具体地,为障碍点 o_i 生成分离超平面 a_i^T p = b_i,其法向量由椭球度量确定: + \begin{equation} + \tilde{\mathbf{a}}_i + = \left( \mathbf{C}\mathbf{C}^\top \right)^{-1} + \left( \mathbf{o}_i - \mathbf{d} \right) , + \qquad + \mathbf{a}_i = \frac{\tilde{\mathbf{a}}_i} + {\left\lVert \tilde{\mathbf{a}}_i \right\rVert} , + \label{eq:sup_halfspace_normal} + \end{equation} + % 即取椭球边界上距 o_i 最近点处的外法线方向;偏置项由 b_i = a_i^T o_i 给出, + % 从而保证障碍点位于对应半空间边界上,而椭球(及其内部的线段)位于安全一侧。 + % 将保留的约束堆叠得 A = [a_1, ..., a_m]^T、b = [b_1, ..., b_m]^T, + % 即得包裹线段的凸多面体 P。半空间的数量 m 与方向均由局部障碍点分布自适应确定, + % 不需预设走廊形状。 + + \subsection{Seed Extension and Corridor Overlap} + % 【新增】生成走廊时将种子沿粗解折线向两端各延伸弧长 Delta_slide 后再作凸分解, + % 使相邻走廊在一段有限弧长上重叠、而非仅交于一点,从而容纳配置点的纵向滑移。 + % TODO: 补 Delta_slide 取值、走廊半空间数 m_k 的实测分布、以及外循环触发率。 + + \begin{figure}[htbp] + \centering + \includegraphics{fig_convex_decomp} + \caption{Geometric intuition of the convex decomposition. + (a) The initial sphere centered at the segment midpoint + $\mathbf{d}$ is shrunk along the minor axis until the boundary + of $\mathcal{E}$ first touches an obstacle point + $\mathbf{o}_i$, giving a collision-free ellipsoid that fully + encloses the segment $\mathbf{p}_0\mathbf{p}_1$. + (b) Each retained obstacle (solid) generates one supporting + half-space $\mathbf{a}_i^{\!\top}\mathbf{p}=b_i$ whose normal + is set by the ellipsoid metric of + \eqref{eq:sup_halfspace_normal}; obstacles already excluded by + an emitted half-space are pruned as redundant (hollow), and the + retained half-spaces clip the free space into the convex + polytope $\mathcal{P}$.} + \label{fig:sup_convex_decomp} + \end{figure} + + \subsection{Sufficiency and Safety Margin of the Discretized Constraint} + \label{sup:corner_cut} + % 本节给出正文 \eqref{eq:corner_cut_margin} 所用走廊内缩余量的推导,并量化矿卡尺度下的实际切入量。 + % 正文的顶点约束仅在配置点上成立:顶点落入凸多面体 P_k 是该配置点处整车无碰的充分条件, + % 但相邻两个配置点之间车体仍可切出走廊之外。以下证明该切入量存在一个仅依赖 Delta_s 与 + % kappa_max 的解析上界,故可由走廊的一次性内缩完全覆盖。 + + % 考察相邻配置点 k 与 k+1 之间的一段路径。由正文的曲率约束,该段的曲率满足 + % |kappa| <= kappa_max = 1/R_min。在最坏情形下该段为定曲率圆弧、且取到曲率上界: + % 此时车辆绕瞬时转向中心(ICR)作纯滚动,车体为刚体,故其上任一点亦作圆周运动。 + % 设车体坐标系下顶点 r 的坐标为 [a_r, b_r]^T,ICR 位于后轴延长线上距后轴中心 R_min 处, + % 即车体坐标 [0, R_min]^T,则该顶点到 ICR 的距离为 + \begin{equation} + \rho_\text{c}^{(r)} = \left\lVert + \begin{bmatrix} a_r \\ b_r \end{bmatrix} + - \begin{bmatrix} 0 \\ R_\text{min} \end{bmatrix} + \right\rVert . + \label{eq:sup_rho_c} + \end{equation} + % 该段上后轴中心转过的航向增量为 Delta_theta = Delta_s * kappa_max,而刚体上所有点转过 + % 相同的角度 Delta_theta(绕同一 ICR),故顶点 r 走过一段半径 rho_c^(r)、圆心角 Delta_theta 的圆弧。 + % 该圆弧偏离其弦的最大距离即弓形的矢高(sagitta),在弧中点处取到: + \begin{equation} + \Delta_\text{cut}^{(r)} + = \rho_\text{c}^{(r)} \left[ 1 - \cos\!\left( \frac{\Delta\theta}{2} \right) \right] + = \rho_\text{c}^{(r)} \left[ 1 - \cos\!\left( \frac{\Delta s\, \kappa_\text{max}}{2} \right) \right] . + \label{eq:sup_sagitta} + \end{equation} + % 取四个顶点中最大者,即得正文 \eqref{eq:corner_cut_margin} 的 Delta_cut。 + % 该值是上界而非估计:它同时取到了曲率上界与弧中点位置,且顶点集合已取遍。 + % 因此,若在生成 P_k 时将其每个半空间沿内法向平移 Delta_cut(即 b_k <- b_k - Delta_cut * 1), + % 则配置点处满足内缩后走廊的约束蕴含整段弧上车体不越出原走廊。 + + % 需要指出 \eqref{eq:sup_sagitta} 中的两处保守性,二者方向相反但量级都很小。 + % 其一,Delta_theta 按 kappa_max 计,而实际路径在大部分弧长上曲率远小于上界, + % 故实际切入量通常显著小于 Delta_cut。其二,rho_c^(r) 按 R_min 处的 ICR 计, + % 而曲率较小时 ICR 更远、顶点圆弧半径更大;但矢高中的余弦项随曲率下降得更快 + % (Delta_theta 正比于 kappa),二者相乘后仍随曲率单调下降,故以 kappa_max 取上界是正确的。 + + % 表 \ref{tab:sup_corner_cut} 给出矿卡尺度下的实算结果。取 R_min = 12 m、L_v = 12 m、B_v = 3 m, + % 并设后轴中心距车体后端 1.5 m(即后悬 1.5 m,故前端在车体坐标 a = 10.5 m 处)。 + % 车辆左转时 ICR 位于车体坐标 [0, R_min]^T,四个顶点到 ICR 的距离分别为 + % 17.10 m(右前)、14.85 m(左前)、13.58 m(右后)、10.61 m(左后), + % 故最远顶点为转弯外侧的前保险杠角点,rho_c = 17.10 m。 + \begin{table}[htbp] + \centering + \caption{Maximum corner-cutting deviation between adjacent collocation + points, evaluated at $R_\text{min}=12$\,m, $L_\text{v}=12$\,m, + $B_\text{v}=3$\,m and a rear overhang of $1.5$\,m + (farthest corner at $\rho_\text{c}=17.10$\,m).} + \label{tab:sup_corner_cut} + \begin{tabular}{@{}cc@{}} + \toprule + Collocation step $\Delta s$ (m) & $\Delta_\text{cut}$ (cm) \\ + \midrule + 0.5 & 0.37 \\ + 1.0 & 1.48 \\ + 1.5 & 3.34 \\ + 2.0 & 5.93 \\ + 3.0 & 13.34 \\ + \bottomrule + \end{tabular} + \end{table} + + % 两点结论。其一,在 Delta_s <= 1.5 m 时切入量不超过 3.4 cm,远小于矿区常用的车体安全间隔, + % 故一次性内缩不会实质压缩可行域,也无须在配置点之间追加中点约束——后者会使约束数近似加倍, + % 而所换取的余量收益不足 4 cm。其二,Delta_cut 随 Delta_s 近似二次增长 + % (小角度下 1 - cos(x/2) ≈ x^2/8),Delta_s = 3 m 时已达 13 cm 量级、接近安全余量本身, + % 因此 \eqref{eq:sup_sagitta} 亦为配置步长提供了上界依据:本文取 Delta_s 不超过 1.5 m。 + % TODO: 待实车数据到位后,在此补一行实测车体轮廓到边界的最小间隙,与 Delta_cut 对照。 + +\section{Second-Difference Discretization of Curvature Constraints} + \label{sup:curvature} + + % 本节给出正文虚拟中线平滑问题中二阶差分与曲率之间换算关系的推导,即 + % \lVert d_i \rVert ≈ ell^2 kappa_i,并给出该近似的误差量级。 + + \subsection{Taylor-Series Derivation} + % 设中线经等弧长重采样后,相邻点的弧长间距为 $\ell$,并将其视为对某条以弧长为参数的光滑曲线 $\mathbf{r}(s)$ 的采样,即 $\mathbf{q}_{i} = \mathbf{r}(s_i)$、$\mathbf{q}_{i \pm 1} = \mathbf{r}(s_i \pm \ell)$。在 $s_i$ 处对前后两个采样点作泰勒展开: + \begin{subequations} \label{eq:sup_taylor} + \begin{align} + \mathbf{q}_{i+1} & = \mathbf{r} + \ell\, \mathbf{r}' + + \frac{\ell^2}{2} \mathbf{r}'' + + \frac{\ell^3}{6} \mathbf{r}''' + O(\ell^4) \\ + \mathbf{q}_{i-1} & = \mathbf{r} - \ell\, \mathbf{r}' + + \frac{\ell^2}{2} \mathbf{r}'' + - \frac{\ell^3}{6} \mathbf{r}''' + O(\ell^4) + \end{align} + \end{subequations} + % 其中 $\mathbf{r}$ 及其各阶导数均在 $s_i$ 处取值。两式相加时,奇数阶项因中心对称而相互抵消,故 $\mathbf{d}_i = \mathbf{q}_{i-1} - 2\mathbf{q}_i + \mathbf{q}_{i+1} = \ell^2\, \mathbf{r}''(s_i) + O(\ell^4)$。由于曲线以弧长为参数,其一阶导数即为单位切向量 $\mathbf{r}' = \mathbf{T}$,由 Frenet 公式\cite{docarmo2016curves}有 $\mathbf{r}'' = \mathrm{d}\mathbf{T}/\mathrm{d}s = \kappa\, \mathbf{N}$,其中 $\mathbf{N}$ 为单位法向量。由 $\lVert \mathbf{N} \rVert = 1$ 知 $\lVert \mathbf{r}'' \rVert = \kappa$,代入即得 + \begin{equation} + \left\lVert \mathbf{d}_i \right\rVert = \ell^2 \kappa_i + O(\ell^4) + \label{eq:sup_curvature_relation} + \end{equation} + + \subsection{Approximation Error and Discretization Choice} + % 为定量评估 \eqref{eq:sup_curvature_relation} 的近似精度,考察三个采样点恰好落在半径 $R = 1/\kappa$ 圆周上的情形,此时可得到闭式结果。设相邻点对应的圆心角间隔为 $\theta$,将圆心置于原点,则三点可表示为 $\mathbf{q}_{i} = R[1, 0]^\top$、$\mathbf{q}_{i \pm 1} = R[\cos\theta, \pm\sin\theta]^\top$,代入二阶差分得精确表达式 $\lVert \mathbf{d}_i \rVert = 2R(1 - \cos\theta) = 4R \sin^2(\theta/2)$。将弧长关系 $\theta = \ell / R = \ell\, \kappa$ 代入并对 $\sin(\cdot)$ 作级数展开,可得 + \begin{equation} + \left\lVert \mathbf{d}_i \right\rVert + = \ell^2 \kappa \left( 1 - \frac{\ell^2 \kappa^2}{12} + + O\!\left( \ell^4 \kappa^4 \right) \right) + \label{eq:sup_curvature_error} + \end{equation} + % 即 \eqref{eq:sup_curvature_relation} 的相对误差约为 $\frac{1}{12}( \ell / R )^2$,随采样间距与曲率半径之比的平方衰减。以本文所针对的矿用运输车辆为例,其最小转弯半径 $R_\text{min}$ 约为 12 m,而中线重采样间距取 $\ell = 1$~m,此时相对误差约为 $0.06\%$;即使取 $\ell = 3$~m,误差亦不超过 $0.5\%$,对约束的实际影响可以忽略。此外,由 \eqref{eq:sup_curvature_error} 可见近似值 $\ell^2 \kappa$ 略大于真实的 $\lVert \mathbf{d}_i \rVert$,因此以 $\lVert \mathbf{d}_i \rVert \le \ell_i^2 \kappa_\text{max}$ 作为约束时实际允许的曲率略小于 $\kappa_\text{max}$,即该离散化在安全性上偏保守。 + + % 离散曲率还可由三点外接圆法或航向角差分法估计。前者含有路径点范数的乘积作为分母,后者含有反三角函数;将它们直接写成曲率上界约束会引入非二次的非线性结构。相比之下,本文采用的二阶差分 $\mathbf{d}_i=\mathbf{q}_{i-1}-2\mathbf{q}_i+\mathbf{q}_{i+1}$ 是路径点的线性函数,因而 $\|\mathbf{d}_i\|^2$ 给出凸二次约束,并保持与目标函数相同的稀疏结构。平方形式还避免了 $\|\mathbf{d}_i\|$ 在零点的不可微性。故本文接受 \eqref{eq:sup_curvature_error} 所示的离散误差,以换取更简单、稳定的优化结构。 + +\section{Implementation Details and Additional Results} + \label{sup:implementation} + + \subsection{Full Parameter Settings} + % TODO: 汇总全部参数取值(核参数 alpha/rho/m、场分辨率 delta、状态格分辨率、 + % 基准步长 mu_0、调制区间、权重 w_U/w_Psi/w_kappa、Delta_slide、Ipopt 收敛容差等), + % 并注明各参数的标定方式(解析条件 / 实验标定 / 沿用文献)。 + + \begin{table}[htbp] + \centering + \caption{Complete Parameter Settings} + \label{tab:sup_params} + \footnotesize + \begin{tabular}{@{}llcl@{}} + \toprule + Symbol & Description & Value & Source \\ + \midrule + % TODO: 填表 + \bottomrule + \end{tabular} + \end{table} + + \subsection{Nearest-Neighbor Query for the Interaction Term} + % 【新增,对应审阅意见】交互项的非零元数为 O(rho_Psi / Delta_s),但朴素实现仍需 + % M_park x M_exit 次距离计算才能找出近邻点对。 + % TODO: 说明所采用的空间索引结构(KD 树 / 均匀网格哈希)、其重建频次, + % 以及每次迭代中该步骤的实测耗时占比。 + + \subsection{Additional Ablation Results} + % TODO: 正文因篇幅只保留主要消融项,此处收录完整消融表 + % (逐项去除 J_U / J_Psi / 时序权重 / 自适应步长 / 场增强启发的对照)。 + + \subsection{Failure Cases} + % TODO: 收录求解失败或退化的算例(极端装载位、通道宽度不足以容纳双通道时的行为), + % 并说明方法的适用边界。审稿人通常会追问这一点,主动给出比被问到更好。 + +% TODO(投稿前): 正文取消注释、产生有效 \cite 后删除下面这行 \nocite{*}。 +% 当前草稿阶段本材料正文均为注释、无任何生效的 \cite,故必须保留此行,否则 thebibliography 为空而编译报错。 +\nocite{*} +\bibliographystyle{IEEEtran} +\bibliography{refs} + +\end{document}