summaryrefslogtreecommitdiff
path: root/macros/latex
diff options
context:
space:
mode:
Diffstat (limited to 'macros/latex')
-rw-r--r--macros/latex/contrib/easybook/easybook.dtx96
-rw-r--r--macros/latex/contrib/easybook/easybook.pdfbin586978 -> 586959 bytes
-rw-r--r--macros/latex/contrib/easybook/easybook.tex6
-rw-r--r--macros/latex/contrib/footmisc/changes.txt5
-rw-r--r--macros/latex/contrib/footmisc/footmisc-code.pdfbin363832 -> 363788 bytes
-rw-r--r--macros/latex/contrib/footmisc/footmisc-doc.pdfbin249093 -> 249001 bytes
-rw-r--r--macros/latex/contrib/footmisc/footmisc.dtx29
-rw-r--r--macros/latex/contrib/robotarm/README.md3
-rw-r--r--macros/latex/contrib/robotarm/robotarm.dtx940
-rw-r--r--macros/latex/contrib/robotarm/robotarm.pdfbin0 -> 185467 bytes
-rw-r--r--macros/latex/contrib/robotarm/robotarm.sty375
11 files changed, 1397 insertions, 57 deletions
diff --git a/macros/latex/contrib/easybook/easybook.dtx b/macros/latex/contrib/easybook/easybook.dtx
index c7a2ae3560..54cc922175 100644
--- a/macros/latex/contrib/easybook/easybook.dtx
+++ b/macros/latex/contrib/easybook/easybook.dtx
@@ -15,7 +15,7 @@
%<*class>
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{l3keys2e}
-\ProvidesExplClass{easybook}{2022/03/06}{1.641}
+\ProvidesExplClass{easybook}{2022/03/08}{1.642}
{Easily typesetting Chinese theses or books}
\bool_set_false:N \l__eb_compile_draft_bool
@@ -76,22 +76,22 @@
\cs_new_eq:NN \eb_switch_family:n \ctex_ltj_switch_family:n
}
\cs_new_protected:Npn \eb_setmainfont:nn #1#2
- { \__fontspec_main_setmainfont:nn {#1} {#2} }
+ { \__fontspec_main_setmainfont:nn {#2} {#1} }
\cs_new_protected:Npn \eb_setsansfont:nn #1#2
- { \__fontspec_main_setsansfont:nn {#1} {#2} }
+ { \__fontspec_main_setsansfont:nn {#2} {#1} }
\cs_new_protected:Npn \eb_setmonofont:nn #1#2
- { \__fontspec_main_setmonofont:nn {#1} {#2} }
+ { \__fontspec_main_setmonofont:nn {#2} {#1} }
\cs_new_protected:Npn \eb_setCJKmainfont:nn #1#2
- { \eb_set_family:nnn { \CJKrmdefault } {#1} {#2} }
+ { \eb_set_family:nnn { \CJKrmdefault } {#2} {#1} }
\cs_new_protected:Npn \eb_setCJKsansfont:nn #1#2
- { \eb_set_family:nnn { \CJKsfdefault } {#1} {#2} }
+ { \eb_set_family:nnn { \CJKsfdefault } {#2} {#1} }
\cs_new_protected:Npn \eb_setCJKmonofont:nn #1#2
- { \eb_set_family:nnn { \CJKttdefault } {#1} {#2} }
+ { \eb_set_family:nnn { \CJKttdefault } {#2} {#1} }
\eb_seq_map_inline:nn
{ main,sans,mono,CJKmain,CJKsans,CJKmono }
{
\exp_args:Nc \RenewDocumentCommand { set#1font }{O{}mO{}}
- {\use:c { eb_set#1font:nn } {##1,##3} {##2}}
+ {\use:c { eb_set#1font:nn } {##2} {##1,##3}}
}
\RenewDocumentCommand{\newCJKfontfamily}{omO{}mO{}}
{
@@ -303,7 +303,7 @@
%<*package>
\NeedsTeXFormat{LaTeX2e}[2020/10/01]
\RequirePackage{l3keys2e,etoolbox}
-\ProvidesExplPackage{easybase}{2022/03/06}{1.641}
+\ProvidesExplPackage{easybase}{2022/03/08}{1.642}
{Easily typesetting Chinese theses or books}
\cs_generate_variant:Nn \dim_set:Nn { NV }
@@ -451,7 +451,7 @@
{
style,subfont,spread,
refset,bibset,thmset,
- geoset,hdrset,tocset
+ geoset,hdrset,tocset,list
}
{
\ctex_define:n { #1 .meta:nn = { ctex/#1 } {##1} }
@@ -873,11 +873,10 @@
fnindent .dim_set:N = \footindent,
fnindent .initial:n = 0.8em,
fnparskip .skip_set:N = \footparskip,
- fnparskip .initial:n = 0ex,
+ fnparskip .initial:n = 0ex plus .1ex,
fnparindent .tl_set:N = \footparindent,
fnparindent .initial:n = 2em,
fnpara-form .tl_set:N = \l__eb_fnpara_format_tl,
-
fntext-pos .tl_set:N = \l__eb_fntext_position_tl,
fntext-pos .initial:n = super,
fntext-code .code:n = \eb_assign_fntext_code:n {#1},
@@ -885,20 +884,17 @@
fnmate-form .code:n = \eb_fnboth_format_set:nn {#1} { mate },
fncust-form .code:n = \eb_fnboth_format_set:nn {#1} { cust },
fnboth-form .meta:n = { fnmate-form = #1,fncust-form = #1 },
-
footnotetype .multichoices:nn =
{ default,hang,bottom,para,flush }
{ \eb_footnote_value_handle:n {#1} },
footnotetype .value_required:n = true,
footnotetype .initial:n = hang,
-
fnmark-vmove .code:n = \eb_fnmate_move_set:nnn {#1} { mark } { v },
fnmark-hmove .code:n = \eb_fnmate_move_set:nnn {#1} { mark } { h },
fntext-vmove .code:n = \eb_fnmate_move_set:nnn {#1} { text } { v },
fnmark-vmove .initial:n = 0pt,
fnmark-hmove .initial:n = 0pt,
fntext-vmove .initial:n = 0pt,
-
fnmark-num .choices:nn =
{ plain,pifont,pifont*,pifont-sans,pifont-sans* }
{ \eb_fnmate_normal_label_set:Nn \theupfootnote {#1} },
@@ -1261,7 +1257,7 @@
{
\ctex_define:n
{
- list/#1 .meta:n =
+ list/#1 .meta:n =
{
figure/#1 = ##1,table/#1 = ##1,
lstlisting/#1 = ##1
@@ -1273,7 +1269,7 @@
{
\ctex_define:nn { tocset }
{
- #1-every .code:n =
+ #1-every .code:n =
{
\ctex_set:n
{
@@ -1325,32 +1321,47 @@
{ \p@numberline{\use:c { #1name }~\use:c { the#1 }} }
\ctex_set:n
{
- part/tocformat = \addvspace{1pc}\sffamily\large,
- part/tocindent = 0em,
- part/tocrule = \tocrule{}[\bfseries],
- part/tocline = \CTEXnumberline{#1}#2,
- chapter/tocformat = \addvspace{1pc}\sffamily,
- chapter/tocindent = 0em,
- chapter/tocrule = \tocrule{$\cdot$}[\bfseries],
- chapter/tocline = \CTEXnumberline{#1}#2,
- section/tocformat = \bool_if:NF \l__eb_class_mode_book_bool { \sffamily },
- section/tocindent = \bool_if:NTF \l__eb_class_mode_book_bool { 1.5em } { 0em },
- section/tocrule =
+ part =
{
- \bool_if:NTF \l__eb_class_mode_book_bool
- { \tocrule{$\cdot$} }
- { \tocrule{$\cdot$}[\bfseries] }
+ tocformat = \addvspace{1pc}\sffamily\large,
+ tocindent = 0em,
+ tocrule = \tocrule{}[\bfseries],
+ tocline = \CTEXnumberline{#1}#2
+ },
+ chapter =
+ {
+ tocformat = \addvspace{1pc}\sffamily,
+ tocindent = 0em,
+ tocrule = \tocrule{$\cdot$}[\bfseries],
+ tocline = \CTEXnumberline{#1}#2
+ },
+ section =
+ {
+ tocformat = \bool_if:NF \l__eb_class_mode_book_bool { \sffamily },
+ tocindent = \bool_if:NTF \l__eb_class_mode_book_bool { 1.5em } { 0em },
+ tocrule =
+ {
+ \bool_if:NTF \l__eb_class_mode_book_bool
+ { \tocrule{$\cdot$} }
+ { \tocrule{$\cdot$}[\bfseries] }
+ }
+ },
+ subsection =
+ {
+ tocindent = \bool_if:NTF \l__eb_class_mode_book_bool { 3.8em } { 1.4em },
+ tocrule = \tocrule{$\cdot$}
+ },
+ list =
+ {
+ tocindent = 0em,
+ tocrule = \tocrule{$\cdot$},
+ between = \bool_if:NT \l__eb_class_mode_book_bool { \vspace*{-10pt} }
},
- subsection/tocindent = \bool_if:NTF \l__eb_class_mode_book_bool { 3.8em } { 1.4em },
- subsection/tocrule = \tocrule{$\cdot$},
- list/tocindent = 0em,
- list/tocrule = \tocrule{$\cdot$},
- list/between = \bool_if:NT \l__eb_class_mode_book_bool { \vspace*{-10pt} },
table/tocline = \listnumberline{table}#2,
figure/tocline = \listnumberline{figure}#2,
- lstlisting/tocline = \listnumberline{lstlisting}#2
+ lstlisting/tocline = \listnumberline{lstlisting}#2,
+ tocset/tocafter-every = \hspace{1em}
}
-\ctex_set:nn { tocset } { tocafter-every = \hspace{1em} }
\prop_new:N \l__eb_list_label_entry_prop
\prop_set_from_keyval:Nn \l__eb_list_label_entry_prop
{
@@ -1784,9 +1795,8 @@
\tl_gset:Nn \dblfloatpagefraction { 0.9 }
}
\dim_zero_new:N \mathindent
-\skip_set:Nn \parskip { 0pt plus 2pt minus 1pt }
-\skip_set:Nn \textfloatsep { 12pt plus 2pt minus 4pt }
-\skip_set:Nn \dbltextfloatsep { 12pt plus 2pt minus 4pt }
+\skip_set:Nn \textfloatsep { 12pt plus 4pt minus 3pt }
+\skip_set:Nn \dbltextfloatsep { 12pt plus 4pt minus 3pt }
\skip_set:Nn \multicolsep { 12pt plus 4pt minus 3pt }
%% \int_gset:Nn \vbadness { 10000 }
%% \int_gset:Nn \hbadness { 10000 }
@@ -2217,7 +2227,6 @@
linktype/colors .code:n = \eb_link_colors_set:,
linktype/various .meta:n = linktype/colors,
linktype .initial:n = edge,
-
linktoc .choice:,
linktoc/unknown .code:n = \eb_link_toc_put:n {#1},
linktoc .default:n = all,
@@ -2257,6 +2266,7 @@
urlcolor = ctex@url,urlbordercolor = ctex@url,
citecolor = ctex@cite,citebordercolor = ctex@cite
}
+ \hypersetup{bookmarksnumbered = true}
\exp_args:NV \hypersetup \l__eb_hyperref_clist
}
@@ -2307,7 +2317,7 @@
}
%</package>
%<*tcolorbox>
-\ProvidesExplFile{eb-tcolorbox.cfg}{2022/03/06}{1.641}
+\ProvidesExplFile{eb-tcolorbox.cfg}{2022/03/08}{1.642}
{Customization of tcolorbox for easybook}
\cs_set_protected:Npn \addtotcbstyle #1#2
diff --git a/macros/latex/contrib/easybook/easybook.pdf b/macros/latex/contrib/easybook/easybook.pdf
index db967b2641..e17b80e4c5 100644
--- a/macros/latex/contrib/easybook/easybook.pdf
+++ b/macros/latex/contrib/easybook/easybook.pdf
Binary files differ
diff --git a/macros/latex/contrib/easybook/easybook.tex b/macros/latex/contrib/easybook/easybook.tex
index 26b7f8986a..20fd6cbb52 100644
--- a/macros/latex/contrib/easybook/easybook.tex
+++ b/macros/latex/contrib/easybook/easybook.tex
@@ -21,8 +21,8 @@
name = easybook,
color-scheme = blue,
title = EASYBOOK使用手册,
- version = v1.641,
- date = 2022/03/06,
+ version = v1.642,
+ date = 2022/03/08,
authors = 瞿毅,
info = 简便地排版中文学位论文或书籍,
email = q1jx@foxmail.com,
@@ -531,7 +531,7 @@
\subsection{超链接}
\label{subsec:hyperlinks}
-模块 \module*{refset} 将超链接选项交给 \pkg*{hyperref} 宏包处理,除了一些关于 \code{pdf} 书签或已预设的选项可能失效,其它由接口命令 \cs*{hypersetup} 支持的多数选项可用。
+模块 \module*{refset} 将超链接选项交给 \pkg*{hyperref} 宏包处理。除了一些超链接颜色的选项失效,其它由宏包全局和接口命令 \cs*{hypersetup} 支持的多数选项可用。
\begin{options}
\keychoice{linktype}{edge,colors,none}\Module{refset}\Default{edge}
超链接类型。\code{edge} 使超链接形式为边框,\code{colors} 使超链接字体为彩色,\code{none} 关闭超链接边框与颜色,此时 \option{linkcolor} 选项无效。
diff --git a/macros/latex/contrib/footmisc/changes.txt b/macros/latex/contrib/footmisc/changes.txt
index 8471cde6e0..dc51273e12 100644
--- a/macros/latex/contrib/footmisc/changes.txt
+++ b/macros/latex/contrib/footmisc/changes.txt
@@ -1,3 +1,8 @@
+2022-03-08 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
+
+ * footmisc.dtx (subsection{The other footnote commands}):
+ Also support optional arg of \cs{MakePerPage} (gh/03)
+
2022-03-07 Frank Mittelbach <Frank.Mittelbach@latex-project.org>
* footmisc.dtx (subsection{The other footnote commands}):
diff --git a/macros/latex/contrib/footmisc/footmisc-code.pdf b/macros/latex/contrib/footmisc/footmisc-code.pdf
index d1428e73fd..affa9e8a4d 100644
--- a/macros/latex/contrib/footmisc/footmisc-code.pdf
+++ b/macros/latex/contrib/footmisc/footmisc-code.pdf
Binary files differ
diff --git a/macros/latex/contrib/footmisc/footmisc-doc.pdf b/macros/latex/contrib/footmisc/footmisc-doc.pdf
index 71f7811af1..d738cb5e0d 100644
--- a/macros/latex/contrib/footmisc/footmisc-doc.pdf
+++ b/macros/latex/contrib/footmisc/footmisc-doc.pdf
Binary files differ
diff --git a/macros/latex/contrib/footmisc/footmisc.dtx b/macros/latex/contrib/footmisc/footmisc.dtx
index c3a31d2e6a..bafdb76df3 100644
--- a/macros/latex/contrib/footmisc/footmisc.dtx
+++ b/macros/latex/contrib/footmisc/footmisc.dtx
@@ -38,7 +38,7 @@
%<+package>\DeclareCurrentRelease{}{2022-02-14}
%<package>\ProvidesPackage{footmisc}%
%<*!debugins>
- [2022/03/07 v6.0c
+ [2022/03/08 v6.0d
%</!debugins>
%<package> a miscellany of footnote facilities%
%<*dtx>
@@ -1865,24 +1865,31 @@
% resets footnotes at each chapter start. As a result the first
% footnote on the first page of a chapter starts with 2. We
% therefore alter one \LaTeX{} internal if \pkg{perpage} is in use:
-% \changes{v6.0c}{2022/03/07}{Fix an issue in perpage packag (gh/03)}
+% \changes{v6.0c}{2022/03/07}{Fix an issue in perpage package (gh/03)}
+% \changes{v6.0d}{2022/03/07}{Also support optional arg of \cs{MakePerPage} (gh/03)}
% \begin{macrocode}
\def\@stpelt#1{\global\csname c@#1\endcsname \m@ne
\stepcounter{#1}%
- \setcounter{#1}{0}%
+ \pp@fix@MakePerPage{#1}%
+ }
+ \def\pp@fix@MakePerPage#1{%
+ \ifnum \value{#1}>\z@
+ \addtocounter{#1}\m@ne\fi
}
% \end{macrocode}
-% The above code may look a bit odd: the \cs{stepcounter} sets
-% the counter to zero and then the \cs{setcounter} does the
-% same. The reason is that \cs{stepcounter} resets other counters
-% and when perpage is loaded this results in updating counters on
-% the reset list to 1, which is precisely the problem here. So
-% the second \cs{setcounter} undoes this if it happens.
+% The above code may look a bit odd: the \cs{stepcounter} sets the
+% counter to zero and then we alter it if it is not zero. The
+% reason is that \cs{stepcounter} resets other counters and when
+% perpage is loaded this results in updating counters on the reset
+% list to 1 (or to a higher starting value if \cs{MakePerPage} is
+% used with an optional argument, which is precisely the problem
+% here. By subtracting 1 in that case we set it back to 1 lower
+% than the starting value.
%
-% But to make this fully work we also need to update a suport
+% But to make this fully work we also need to update a support
% command in \pkg{perpage}:
% \begin{macrocode}
- \def\pp@cl@end@iii\stepcounter#1\setcounter#2#3{}
+ \def\pp@cl@end@iii\stepcounter#1\pp@fix@MakePerPage#2{}
% \end{macrocode}
%
% \begin{macrocode}
diff --git a/macros/latex/contrib/robotarm/README.md b/macros/latex/contrib/robotarm/README.md
new file mode 100644
index 0000000000..f95f712205
--- /dev/null
+++ b/macros/latex/contrib/robotarm/README.md
@@ -0,0 +1,3 @@
+# `robotarm` LaTeX package
+
+This LaTeX package uses Tikz to draw parameterized 2D robot arms, for example to be used in educational material. \ No newline at end of file
diff --git a/macros/latex/contrib/robotarm/robotarm.dtx b/macros/latex/contrib/robotarm/robotarm.dtx
new file mode 100644
index 0000000000..79986b388f
--- /dev/null
+++ b/macros/latex/contrib/robotarm/robotarm.dtx
@@ -0,0 +1,940 @@
+% \iffalse meta-comment
+%
+% Copyright (C) 2021 by M.J.W. Snippe
+% -----------------------------------
+%
+% 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.
+%
+% This work has the LPPL maintenance status `author-maintained'.
+%
+% This work consists of the files found at github.com/max-sn/robotarm.
+%
+% \fi
+%
+% \iffalse
+%<*driver>
+\documentclass{ltxdoc}
+\input{robotarm.doc.settings.sty}
+\EnableCrossrefs
+\RecordChanges
+\begin{document}
+ \DocInput{robotarm.dtx}
+\end{document}
+%</driver>
+%
+% \fi
+%
+% \iffalse
+%
+%<*robotarm-doc-settings>
+
+\usepackage[utf8]{inputenc}
+\usepackage{xspace}
+\usepackage{multicol}
+\usepackage{geometry}
+\usepackage{mathpazo}
+\usepackage{robotarm}
+\usepackage{biblatex}
+\usepackage{hypdoc}
+\usepackage{tcolorbox}
+
+\addbibresource{robotarm.doc.bib.bib}
+\defbibheading{robotarmbibheading}[\bibname]{%
+ \clearpage\section*{#1}\addcontentsline{toc}{section}{#1}}
+
+\geometry{pass}
+
+\tcbuselibrary{documentation,breakable,minted}
+\tcbset{
+ index german settings,
+ index colorize,
+ docexample/.append style={
+ before lower={\begin{center}\begin{tikzpicture}},
+ after lower={\end{tikzpicture}\end{center}},
+ documentation minted options={autogobble},
+ breakable,
+ }
+}
+
+\makeindex
+
+\renewcommand{\MacroFont}{\color{black!70!blue}\small\ttfamily}
+
+\def\robotarmpackage{\textsl{robotarm}\xspace}
+\def\Tikz{{\normalfont Ti\textit{k}Z}\xspace}
+
+%</robotarm-doc-settings>
+%
+%<*robotarm-doc-main>
+
+\title{The \robotarmpackage package}
+\author{Marcus J.W. Snippe \\
+ \normalsize\href{mailto:maxsnippe@gmail.nl}
+ {\texttt{maxsnippe[at]gmail.nl}}}
+\date{\filedate\\[0.4em]\normalsize\fileversion}
+
+\maketitle
+
+\begin{abstract}
+ With the \robotarmpackage package, you can draw configurable planar robot arms with ease, using \Tikz. It defines the macro (\refCom{robotArm}) and a lot of ways to configure it. Additionally, you can use or redefine the macros used to draw the base link (\refCom{robotArmBaseLink}), a single link (\refCom{robotArmLink}), or the end effector (\refCom{robotArmEndEffector}).
+\end{abstract}
+
+\begin{multicols}{2}
+ \tableofcontents
+\end{multicols}
+
+\section{Macros}
+
+ \subsection{\texttt{robotArm}}
+
+ \begin{docCommand}{robotArm}{\oarg{key-value list}\marg{num}}
+ This is the main macro of the \robotarmpackage package. It is meant to be used in the \texttt{tikzpicture} environment\footnote{The first example still includes the \texttt{tikzpicture} environment, but for following examples,it will be omitted in the example code.}, from the \Tikz\cite{tantau:tikz_and_pgf} package,
+ and installs some styles for additional drawing, e.g. \refKey{/tikz/in link}.
+
+ \begin{dispExample*}{before lower={}, after lower={}}
+ \begin{tikzpicture}
+ \robotArm[config={q1=60,q2=-40,q3=-50}]{3}
+ \end{tikzpicture}
+ \end{dispExample*}
+
+ \meta{num} defines the number of links that will be drawn. For an $N$ link robot arm, the $N$\textsuperscript{th} link will be the end effector link.
+
+ The \meta{key-value list} values can consist of the keys listed below.
+
+
+
+ \begin{docKey}{geometry}{=\meta{key-value list}}{}
+
+ The \refKey{geometry} key can be used to set geometrical configuration options of the robot arm, e.g. link length and link width. The keys in \meta{key-value list} can be one or more of the following.
+
+ ^^A \begin{docKey}[][doc label=/geometry/a0]{a0}{=\meta{value}}{initially \texttt{0.0}}
+ ^^A Sets the height of the base link.
+
+ ^^A \begin{dispExample}
+ ^^A \robotArm[config={q1=60},geometry={a0=2}]{2}
+ ^^A \end{dispExample}
+ ^^A \end{docKey}
+
+ \begin{docKeys}
+ [
+ doc parameter={=\meta{value}},
+ ]
+ {
+ {
+ doc name=a,
+ doc label=/geometry/a,
+ doc description={initially \texttt{2}}
+ },
+ {
+ doc name=a\meta{num},
+ doc label=/geometry/anum,
+ doc description={initially the value of \refKey{/geometry/a}}
+ },
+ }
+
+ The \refKey{/geometry/a} key sets the default length for all links that are drawn in the \refCom{robotArm} command. For every link, this can be overruled by the dynamically created keys \refKey{/geometry/anum}, e.g. to set only the length of link 3 to 3, use \texttt{a3=3}.
+
+ \begin{dispExample}
+ \robotArm[config={q1=20,q2=-20,q3=-20},
+ geometry={a=3,a3=1}]{3}
+ \end{dispExample}
+ \end{docKeys}
+
+ \begin{docKeys}
+ [
+ doc parameter={=\meta{value}}
+ ]
+ {
+ {
+ doc name=r,
+ doc label=/geometry/r,
+ doc description={initially \texttt{0.25}}
+ },
+ {
+ doc name=r\meta{num},
+ doc label=/geometry/rnum,
+ doc description={initially the value of \refKey{/geometry/r}}
+ },
+ }
+ The \refKey{/geometry/r} key sets the default joint radius for all links drawn in the \refCom{robotArm} command. For every link this can be overruled by the dynamically created keys \refKey{/geometry/rnum}.
+
+ \begin{dispExample}
+ \robotArm[config={q1=20,q2=-20},
+ geometry={r=0.5,r1=0.3}]{2}
+ \end{dispExample}
+ \end{docKeys}
+
+ \begin{docKeys}
+ [
+ doc parameter={=\meta{value}}
+ ]
+ {
+ {
+ doc name=w,
+ doc label=/geometry/w,
+ doc description={initially \texttt{0.4}}
+ },
+ {
+ doc name=w\meta{num},
+ doc label=/geometry/wnum,
+ doc description={initially the value of \refKey{/geometry/w}}
+ },
+ }
+ The \refKey{/geometry/w} key sets the default link width for all links drawn in the \refCom{robotArm} command. For every link this can be overruled by the dynamically created keys \refKey{/geometry/wnum}.
+ \end{docKeys}
+
+ \end{docKey}
+
+ \begin{dispExample}
+ \tikzset{/robotarm/geometry={a=1}}
+ \robotArm{1}
+ \begin{scope}[xshift=3cm]
+ \robotArm{6}
+ \end{scope}
+ \end{dispExample}
+
+ \begin{docKey}[robotarm/styles]{link}{}{default \texttt{draw,fill=lightgray}}
+ \end{docKey}
+
+ \end{docCommand}
+
+ \subsection{\texttt{robotArmBaseLink}}
+
+ \begin{docCommand}{robotArmBaseLink}{\oarg{key-value list}}
+ This command is used in \refCom{robotArm} to draw the base link. It can also be used to draw your own base link. The default base link looks as follows:
+ \begin{dispExample}
+ \robotArmBaseLink
+ \end{dispExample}
+ The \meta{key-value list} can consist of the keys listed below.
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/base link},
+ doc parameter={=\meta{value}},
+ ]
+ {
+ {
+ doc name=height,
+ doc description={initially \texttt{0.6}}
+ },
+ {
+ doc name=width,
+ doc description={initially \texttt{0.3}}
+ },
+ }
+ The width and height of the base link can be specified with these keys. The height is measured from the center of the half-circle at the top, to the base.
+ \begin{dispExample}
+ \robotArmBaseLink[width=1, height=0.6]
+ \end{dispExample}
+ \end{docKeys}
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/base link},
+ doc parameter={=\meta{value}},
+ ]
+ {
+ {
+ doc name=world width,
+ doc description={initially \texttt{1.0}},
+ },
+ {
+ doc name=world height,
+ doc description={initially \texttt{0.3}},
+ }
+ }
+ The width and height of the `world' drawn below the base link can be specified with these keys.
+ \begin{dispExample}
+ \robotArmBaseLink[world width=5, world height=1]
+ \end{dispExample}
+ \end{docKeys}
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/base link},
+ doc description={code executing key},
+ ]
+ {
+ {doc name=draw base link},
+ {doc name=draw world},
+ }
+ These keys are used to draw the `world' and the base link. If the configuration options above are insufficient, you can redefine these keys, as shown in the not-so-creative example below.
+ \begin{dispExample}
+ \robotArmBaseLink[
+ draw world/.code={
+ \filldraw[fill=brown] (-2,-1) rectangle (2, -0.3);
+ },
+ draw base link/.code={
+ \filldraw[fill=black!60] (-0.5, -0.3) rectangle
+ (0.5, 0.3);
+ }]
+ \end{dispExample}
+ To access the values of the keys listed above you can use the following macros in your redefinition:
+ \begin{itemize}
+ \item \docAuxCommand{RA@baselink@width},
+ \item \docAuxCommand{RA@baselink@height},
+ \item \docAuxCommand{RA@baselink@worldwidth}, and
+ \item \docAuxCommand{RA@baselink@worldheight}.
+ \end{itemize}
+ \end{docKeys}
+
+ \end{docCommand}
+
+
+ \subsection{\texttt{robotArmLink}}
+
+ \begin{docCommand}{robotArmLink}{\oarg{key-value list}}
+ This command is used in \refCom{robotArm} to draw the links in a \texttt{foreach} loop. It can also be used to draw your own link(s). The default link looks as follows:
+ \begin{dispExample}
+ \robotArmLink
+ \end{dispExample}
+ The \meta{key-value list} can consist of the keys listed below.
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/link},
+ doc parameter={=\meta{value}},
+ ]{
+ {
+ doc name=width,
+ doc description={initially \texttt{0.4}},
+ },
+ {
+ doc name=length,
+ doc description={initially \texttt{2.0}},
+ },
+ {
+ doc name=joint radius,
+ doc description={initially \texttt{0.25}},
+ },
+ }
+ The geometrical properties of the links can be configured with these keys.
+ \begin{dispExample}
+ \robotArmLink[width=0.75,joint radius=0.4,length=5]
+ \end{dispExample}
+ \end{docKeys}
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/link},
+ doc description={code executing key},
+ ]
+ {
+ {doc name=draw link},
+ {doc name=draw joint},
+ }
+ Same as for the base link, the actual drawing is done by calling these keys. These can also be redefined to change the drawing.
+ \begin{dispExample}
+ \robotArmLink[draw link/.code={
+ \draw[line cap=round, double=lightgray,
+ double distance=4mm]
+ (0,0) to[bend left] (2,0);}]
+ \end{dispExample}
+ Of course you can also do this globally so it applies to all links\footnote{For the end effector to change too, you have to redefine \refKey{/robotarm/end effector/draw joint} too.}.
+ \begin{dispExample}
+ \pgfkeys{/robotarm/link/draw joint/.code={
+ \path[link style] (-0.3,-0.3) rectangle ++(0.6,0.6);
+ \path[link style] (0,0) circle (0.2);}}
+ \robotArm[geometry={a=1.5},
+ config={q1=60,q2=-30,q3=-30}]{3}
+ \end{dispExample}
+ To access the values of the keys listed above you can use the following macros in your redefinition:
+ \begin{itemize}
+ \item \docAuxCommand{RA@link@width},
+ \item \docAuxCommand{RA@link@length}, and
+ \item \docAuxCommand{RA@link@jointradius}.
+ \end{itemize}
+ \end{docKeys}
+
+ \end{docCommand}
+
+ \subsection{\texttt{robotArmEndEffector}}
+
+ \begin{docCommand}{robotArmEndEffector}{\oarg{key-value list}}
+ This command is used in \refCom{robotArm} to draw the final link with the end effector attached. You can also use it outside that command to draw your own end effector.
+ \begin{dispExample}
+ \robotArmEndEffector
+ \end{dispExample}
+ The \meta{key-value list} can consist of the keys listed below.
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/end effector},
+ doc parameter={=\meta{value}},
+ ]
+ {
+ {
+ doc name=width,
+ doc description={initially \texttt{0.4}},
+ },
+ {
+ doc name=length,
+ doc description={initially \texttt{2.0}},
+ },
+ {
+ doc name=joint radius,
+ doc description={initially \texttt{0.25}},
+ },
+ {
+ doc name=gripper radius,
+ doc description={initially \texttt{0.3}},
+ },
+ {
+ doc name=gripper opening angle,
+ doc description={initially \texttt{60}},
+ doc parameter={=\meta{angle}},
+ },
+ }
+ The geometrical properties of the final link and the end effector, which defaults to a gripper, can be tuned with these keys. Due to some trigonometric functions in the drawing code of \refKey{/robotarm/end effector/draw end effector}, \refKey{/robotarm/end effector/gripper radius} should not be smaller than half of \refKey{/robotarm/end effector/width}.
+
+ \end{docKeys}
+
+ \begin{docKeys}
+ [
+ doc keypath={robotarm/end effector},
+ doc description={code executing key},
+ ]
+ {
+ {doc name=draw link},
+ {doc name=draw joint},
+ {doc name=draw end effector},
+ }
+ Again the actual drawing is done by calling these keys. And these can also be redefined to change how the end effector will look, as shown in the example below.
+ \begin{dispExample}
+ \robotArm[
+ config={q1=100,q2=-100},
+ end effector/.cd,
+ draw link/.code={
+ \draw[line cap=round, double=lightgray,
+ double distance=4mm]
+ (0,0) to[bend left] (2, 0.8);},
+ draw end effector/.code={
+ \path[link style]
+ (1.8, 0.8) arc (180:0:0.2) -- (2.1, 0.4)
+ -- (1.9, 0.4) -- cycle;
+ \path[link style]
+ (2.05,0.4) rectangle (1.95,0.0);
+ \fill (2,0) circle (0.05);}]{2}
+ \end{dispExample}
+ To access the values of the keys listed above you can use the following macros in your redefinition:
+ \begin{itemize}
+ \item \docAuxCommand{RA@endeff@width},
+ \item \docAuxCommand{RA@endeff@length},
+ \item \docAuxCommand{RA@endeff@jointradius},
+ \item \docAuxCommand{RA@endeff@gripperradius}, and
+ \item \docAuxCommand{RA@endeff@gripperopeningangle}.
+ \end{itemize}
+ \end{docKeys}
+
+ \end{docCommand}
+
+\section{\Tikz styles}
+
+ \begin{docKeys}
+ [
+ doc keypath=tikz,
+ doc description=style,
+ ]
+ {
+ {
+ doc name=in link,
+ doc parameter={=\meta{number}},
+ },
+ {
+ doc name=in base link,
+ },
+ {
+ doc name=in world,
+ },
+ {
+ doc name=in end effector,
+ }
+ }
+ Only installed after calling \refCom{robotArm} at least once (last called macro defines these styles, but within scope can be made unique).
+ \end{docKeys}
+
+ \begin{docKey}[tikz]{link style}{}{default \texttt{/robotarm/styles/link}}
+ Always installed, forwards to \refKey{/robotarm/styles/link}. Only works one way. To change link styles used in \refCom{robotArm}, change the appropriate \refKey{/robotarm/styles/link}.
+ \begin{dispExample}
+ \tikzset{link style/.style={draw=none, fill=red!50}}
+ \robotArm[config={q1=40},styles={
+ link 1/.style={fill=blue!50}}]{3}
+ \end{dispExample}
+ \end{docKey}
+
+
+ %^^A \section{\robotarmpackage keys}
+ %^^A \begin{docKeys}
+ %^^A [
+ %^^A doc keypath=robotarm/annotations/labels,
+ %^^A ]{
+ %^^A {
+ %^^A doc name=a,
+ %^^A doc description={no default, initially \texttt{a}},
+ %^^A },
+ %^^A {
+ %^^A doc name=q,
+ %^^A doc description={no default, initially \texttt{q}},
+ %^^A }
+ %^^A }
+ %^^A \begin{dispExample}
+ %^^A \robotArm[
+ %^^A config={q1=60,q2=-40,q3=40},
+ %^^A annotations/labels/a=l,
+ %^^A annotations/labels/q=\theta,
+ %^^A annotations/labels/q3=?]{3}
+ %^^A \end{dispExample}
+ %^^A \end{docKeys}
+
+ %^^A \section{\Tikz keys}
+
+
+ %^^A \begin{docKeys}
+ %^^A [
+ %^^A doc keypath=robotarm/frames,
+ %^^A doc description={style},
+ %^^A ]{
+ %^^A {doc name=in link 0},
+ %^^A {doc name=in link 1},
+ %^^A {doc name=in link 2},
+ %^^A {doc name=in link 3},
+ %^^A {doc name=in link 4},
+ %^^A {doc name=in link 5},
+ %^^A {doc name=in link 6}
+ %^^A }
+ %^^A \end{docKeys}
+
+
+%</robotarm-doc-main>
+%
+%<*robotarm-doc-bib>
+@manual{tantau:tikz_and_pgf,
+ author = {Till Tantau},
+ title = {The TikZ and PGF Packages},
+ subtitle = {Manual for version 3.1.8b},
+ url = {https://mirrors.ctan.org/graphics/pgf/base/doc/pgfmanual.pdf},
+ date = {2021-03-19},
+}
+%</robotarm-doc-bib>
+%
+% \fi
+%
+% \CheckSum{286}
+%
+% \CharacterTable
+% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
+% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
+% Digits \0\1\2\3\4\5\6\7\8\9
+% Exclamation \! Double quote \" Hash (number) \#
+% Dollar \$ Percent \% Ampersand \&
+% Acute accent \' Left paren \( Right paren \)
+% Asterisk \* Plus \+ Comma \,
+% Minus \- Point \. Solidus \/
+% Colon \: Semicolon \; Less than \<
+% Equals \= Greater than \> Question mark \?
+% Commercial at \@ Left bracket \[ Backslash \\
+% Right bracket \] Circumflex \^ Underscore \_
+% Grave accent \` Left brace \{ Vertical bar \|
+% Right brace \} Tilde \~}
+%
+%
+% \DoNotIndex{\angleannotationcase,\link@angleannotspacing,\begin,\begingroup,\DeclareDocumentCommand,\draw,\end,\endgroup,\fi,\foreach,\ifcase,\ifnum,\ifRA@robotarm@drawannotations,\lenghtannotationspacing,\link@lenght,\link@radius,\link@startangle,\link@width,\lengthannotationspacing,\link@length,\link@case}
+%
+% \changes{v0.1}{2022/03/08}{Initial version for publishing}
+%
+% \GetFileInfo{robotarm.sty}
+%
+% \input{robotarm.doc.main.tex}
+%
+% \StopEventually{\printbibliography[heading=robotarmbibheading]\printindex\PrintChanges}
+%
+% \section{Implementation}
+% \begin{macrocode}
+%<*robotarm-package>
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{robotarm}
+ [2022/03/08 v0.1 Tikz commands to draw planar robot arms]
+
+\RequirePackage{tikz}
+
+\usetikzlibrary{patterns}
+
+\makeatletter
+
+\newif\ifRA@robotarm@drawannotations
+
+\pgfkeys{
+ /robotarm/base link/.cd,
+ width/.code={\pgfmathsetmacro\RA@baselink@width{#1}},
+ width=0.6,
+ height/.code={\pgfmathsetmacro\RA@baselink@height{#1}},
+ height=0.3,
+ world width/.code={\pgfmathsetmacro\RA@baselink@worldwidth{#1}},
+ world width=1.0,
+ world height/.code={\pgfmathsetmacro\RA@baselink@worldheight{#1}},
+ world height=0.3,
+ draw base link/.code={%
+ \path[link style]
+ (-1/2*\RA@baselink@width,0)
+ arc (180:0:1/2*\RA@baselink@width)
+ -- ++ (0, -\RA@baselink@height)
+ -- ++ (-\RA@baselink@width, 0)
+ -- cycle;
+ },
+ draw world/.code={%
+ \path[world style]
+ (-1/2*\RA@baselink@worldwidth,-\RA@baselink@height)
+ arc (180:360:{1/2*\RA@baselink@worldwidth}
+ and {\RA@baselink@worldheight}) -- cycle;
+ \path[draw, world style]
+ (-1/2*\RA@baselink@worldwidth,-\RA@baselink@height)
+ -- ++(\RA@baselink@worldwidth,0);
+ },
+ /robotarm/link/.cd,
+ width/.code={\pgfmathsetmacro\RA@link@width{#1}},
+ width=0.4,
+ length/.code={\pgfmathsetmacro\RA@link@length{#1}},
+ length=2.0,
+ joint radius/.code={\pgfmathsetmacro\RA@link@jointradius{#1}},
+ joint radius=0.25,
+ draw link/.code={%
+ \path[link style]
+ (0,1/2*\RA@link@width)
+ -- ++ ( \RA@link@length, 0)
+ arc (90:-90:1/2*\RA@link@width)
+ -- ++ (-\RA@link@length, 0)
+ arc (270:90:1/2*\RA@link@width)
+ -- cycle;
+ },
+ draw joint/.code={%
+ \path[link style]
+ (0,0) circle (\RA@link@jointradius);
+ \path[link style]
+ (0,0) circle (1/3*\RA@link@jointradius);
+ },
+ /robotarm/end effector/.cd,
+ width/.code={\pgfmathsetmacro\RA@endeff@width{#1}},
+ width=0.4,
+ length/.code={\pgfmathsetmacro\RA@endeff@length{#1}},
+ length=2,
+ joint radius/.code={\pgfmathsetmacro\RA@endeff@jointradius{#1}},
+ joint radius=0.25,
+ gripper radius/.code={\pgfmathsetmacro\RA@endeff@gripperradius{#1}},
+ gripper radius=0.3,
+ gripper opening angle/.code={%
+ \pgfmathsetmacro\RA@endeff@gripperopeningangle{#1}},
+ gripper opening angle=60,
+ draw joint/.code={%
+ \path[link style]
+ (0,0) circle (\RA@endeff@jointradius);
+ \path[link style]
+ (0,0) circle (1/3*\RA@endeff@jointradius);
+ },
+ draw link/.code={%
+ \pgfmathsetmacro{\link@startangle}{%
+ 180-asin(1/2*\RA@endeff@width/\RA@endeff@gripperradius)}
+ \pgfmathsetmacro{\link@endangle}{%
+ 180+asin(1/2*\RA@endeff@width/\RA@endeff@gripperradius)}
+
+ \path[link style]
+ (\RA@endeff@length, 0)
+ ++ (\link@startangle:\RA@endeff@gripperradius)
+ arc (\link@startangle:\link@endangle:\RA@endeff@gripperradius)
+ -- (0,0|-0,-1/2*\RA@endeff@width)
+ arc (-90:90:1/2*\RA@endeff@width)
+ -- cycle;
+ },
+ draw end effector/.code={
+ \draw[link style]
+ (\RA@endeff@length, 0)
+ ++ (-1/2*\RA@endeff@gripperopeningangle:%
+ \RA@endeff@gripperradius)
+ arc [start angle=-1/2*\RA@endeff@gripperopeningangle,
+ delta angle=-360+\RA@endeff@gripperopeningangle,
+ radius=\RA@endeff@gripperradius]
+ -- ++(180+1/2*\RA@endeff@gripperopeningangle:%
+ 0.4*\RA@endeff@gripperradius)
+ arc [start angle=1/2*\RA@endeff@gripperopeningangle,
+ delta angle=360-\RA@endeff@gripperopeningangle,
+ radius=0.6*\RA@endeff@gripperradius]
+ -- ++(-1/2*\RA@endeff@gripperopeningangle:%
+ 0.4*\RA@endeff@gripperradius)
+ -- cycle;
+ },
+ /robotarm/.cd,
+ draw annotations/.is if=RA@robotarm@drawannotations,
+ draw annotations=true,
+ every annotation/.style={},
+ every length annotation/.style={},
+ every length annotation arrow/.style={draw,->},
+ every length annotation node/.style={circle,inner sep=0.5pt},
+ every length annotation help line/.style={draw,help lines},
+ every angle annotation/.style={},
+ every angle annotation arrow/.style={draw,->},
+ every angle annotation node/.style={},
+ every angle annotation help line/.style={draw,help lines},
+ base link/.code=\pgfkeys{/robotarm/base link/.cd,#1},
+ link/.code=\pgfkeys{/robotarm/link/.cd,#1},
+ end effector/.code=\pgfkeys{/robotarm/end effector/.cd,#1},
+ geometry/.code=\pgfkeys{/robotarm/geometry/.cd,#1},
+ config/.code=\pgfkeys{/robotarm/config/.cd,#1},
+ spacing/.code=\pgfkeys{/robotarm/annotations/spacing/.cd,#1},
+ labels/.code=\pgfkeys{/robotarm/annotations/labels/.cd,#1},
+ styles/.code=\pgfkeys{/robotarm/styles/.cd,#1},
+ /robotarm/geometry/.cd,
+ a0/.initial=0,
+ a/.initial=2,
+ r/.initial=0.25,
+ w/.initial=0.4,
+ /robotarm/config/q/.initial=0,
+ /robotarm/frames/.cd,
+ in link 0/.style={},
+ in end effector/.style={
+ /robotarm/frames/in link \RA@robotarm@numlinks,
+ shift={%
+ (\pgfkeysvalueof{/robotarm/geometry/a\RA@robotarm@numlinks},0)},
+ },
+ in world/.style={
+ shift={(0,-\RA@baselink@height)}
+ },
+ /robotarm/styles/.cd,
+ world/.style={pattern=north west lines},
+ link/.style={
+ draw,
+ fill=lightgray,
+ },
+ link 0/.style={/robotarm/styles/link},
+ /robotarm/annotations/.cd,
+ spacing/.cd,
+ a/.initial=3,
+ q/.initial=1/2,
+ /robotarm/annotations/.cd,
+ labels/.cd,
+ a/.initial=a,
+ q/.initial=q,
+}
+\tikzset{
+ link style/.style={/robotarm/styles/link},
+ world style/.style={/robotarm/styles/world},
+}
+% \end{macrocode}
+% \begin{macro}{\robotarmset}
+% \begin{macrocode}
+\newcommand\robotarmset[1]{%
+ \pgfkeys{/robotarm/.cd,#1}%
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\robotArmLink}
+% \begin{macrocode}
+\newcommand\robotArmLink[1][]{
+ \begingroup
+ \pgfkeys{/robotarm/link/.cd,#1}
+
+ \pgfkeys{/robotarm/link/draw link}
+ \pgfkeys{/robotarm/link/draw joint}
+ \endgroup
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\robotArmEndEffector}
+% \begin{macrocode}
+\newcommand\robotArmEndEffector[1][]{
+ \begingroup
+ \pgfkeys{/robotarm/end effector/.cd,#1}
+
+ \pgfkeys{/robotarm/end effector/draw link}
+ \pgfkeys{/robotarm/end effector/draw joint}
+ \pgfkeys{/robotarm/end effector/draw end effector}
+
+ \endgroup
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\robotArmBaseLink}
+% \begin{macrocode}
+\newcommand\robotArmBaseLink[1][]{
+ \begingroup
+ \pgfkeys{/robotarm/base link/.cd,#1}
+
+ \pgfkeys{/robotarm/base link/draw world}
+ \pgfkeys{/robotarm/base link/draw base link}
+ \endgroup
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macro}{\robotArm}
+% \begin{macrocode}
+\newcommand\robotArm[2][]{
+ \pgfmathtruncatemacro\RA@robotarm@numlinks{#2}
+ \def\@tmpkeys{}
+ \foreach \@link [remember=\@link as \@prevlink (initially 0)] in %
+ {1,...,\RA@robotarm@numlinks}{
+ \xdef\@tmpkeys{\@tmpkeys%
+ /robotarm/geometry/a\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/geometry/a},%
+ /robotarm/geometry/r\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/geometry/r},%
+ /robotarm/geometry/w\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/geometry/w},%
+ /robotarm/config/q\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/config/q},%
+ /robotarm/styles/link \@link/.style={/robotarm/styles/link},%
+ /robotarm/annotations/labels/a\@link/.initial={%
+ $\pgfkeysvalueof{/robotarm/annotations/labels/a}_{\@link}$},%
+ /robotarm/annotations/labels/q\@link/.initial={%
+ $\pgfkeysvalueof{/robotarm/annotations/labels/q}_{\@link}$},%
+ /robotarm/annotations/spacing/a\@link/.initial={%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/a}},%
+ /robotarm/annotations/spacing/q\@link/.initial={%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/q}},%
+ }
+ }
+ \expandafter\pgfkeys\expandafter{\@tmpkeys}
+ \pgfkeys{/robotarm/.cd,#1}
+ \def\@tmpkeys{}
+ \foreach \@link [remember=\@link as \@prevlink (initially 0)] in %
+ {1,...,\RA@robotarm@numlinks}{
+ \xdef\@tmpkeys{\@tmpkeys%
+ /robotarm/frames/in link \@link/.style={%
+ /robotarm/frames/in link \@prevlink,
+ /tikz/shift={%
+ (\pgfkeysvalueof{/robotarm/geometry/a\@prevlink},0)},
+ /tikz/rotate={\pgfkeysvalueof{/robotarm/config/q\@link}},
+ },
+ }
+ }
+ \expandafter\pgfkeys\expandafter{\@tmpkeys}
+
+ \begin{scope}[/robotarm/frames/in link 0,
+ link style/.style={/robotarm/styles/link 0}]
+ \robotArmBaseLink
+ \end{scope}
+
+ \foreach\link@num in {1,...,\RA@robotarm@numlinks}{
+ \begin{scope}[/robotarm/frames/in link \link@num,
+ link style/.style={/robotarm/styles/link \link@num}]
+
+ \ifnum\link@num<\RA@robotarm@numlinks
+ \robotArmLink[
+ joint radius=\pgfkeysvalueof{/robotarm/geometry/r\link@num},
+ length=\pgfkeysvalueof{/robotarm/geometry/a\link@num},
+ width=\pgfkeysvalueof{/robotarm/geometry/w\link@num},
+ ]
+ \else
+ \robotArmEndEffector[
+ joint radius=\pgfkeysvalueof{/robotarm/geometry/r\link@num},
+ length=\pgfkeysvalueof{/robotarm/geometry/a\link@num},
+ width=\pgfkeysvalueof{/robotarm/geometry/w\link@num},
+ ]
+ \fi
+ \end{scope}
+ }
+ \foreach\link@num in {1,...,\RA@robotarm@numlinks}{
+ \begin{scope}[/robotarm/frames/in link \link@num]
+ \pgfmathsetmacro\link@length{\pgfkeysvalueof{%
+ /robotarm/geometry/a\link@num}}
+ \pgfmathsetmacro\link@angle{\pgfkeysvalueof{%
+ /robotarm/config/q\link@num}}
+
+ \ifRA@robotarm@drawannotations
+ \pgfmathsetmacro\link@lengthannotspacing{%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/a\link@num}*
+ \pgfkeysvalueof{/robotarm/geometry/r\link@num}}
+ \pgfmathsetmacro\link@angleannotspacing{%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/q\link@num}*
+ \link@length}
+
+ % Length annotation help lines
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation help line]
+ (0,0) -- (\link@length,0);
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation help line]
+ (0,0) -- ++ (0,{\link@lengthannotspacing +
+ 0.1*sign(\link@lengthannotspacing)});
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation help line]
+ (\link@length,0) -- ++ (0,{\link@lengthannotspacing +
+ 0.1*sign(\link@lengthannotspacing)});
+% \end{macrocode}
+% Length annotation node
+% \begin{macrocode}
+ \path (0,\link@lengthannotspacing)
+ -- coordinate[pos=0.5] (coor) ++ (\link@length,0);
+ \node[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation node]
+ at (coor) (tag)
+ {\pgfkeysvalueof{/robotarm/annotations/labels/a\link@num}};
+% \end{macrocode}
+% Length annotation arrows
+% \begin{macrocode}
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation arrow]
+ (tag) -- (0,\link@lengthannotspacing);
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation arrow]
+ (tag) -- (\link@length,\link@lengthannotspacing);
+
+ \pgfmathsetmacro\angleannotationcase{%
+ ifthenelse(\link@angle==0.0, 0, 1)}
+ \ifnum\angleannotationcase>0
+ % Angle annotation help lines
+ \path[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation help line]
+ (0,0) -- ++(-\link@angle:{\link@angleannotspacing+0.1});
+ \path[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation help line]
+ (0,0) -- ++(0:{\link@angleannotspacing+0.1});
+
+ % Angle annotation arrow
+ \path[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation arrow]
+ (0,0) ++ (-\link@angle:\link@angleannotspacing)
+ arc (-\link@angle:0:\link@angleannotspacing);
+
+ % Angle annotation node
+ \node[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation node]
+ at (-\link@angle/2:\link@angleannotspacing+0.3)
+ {\pgfkeysvalueof{/robotarm/annotations/labels/q\link@num}};
+ \fi
+ \fi
+ \end{scope}
+ }
+% \end{macrocode}
+% Install \Tikz styles for coordinate transformations.
+% \begin{macrocode}
+ \tikzset{
+ in link/.style={/robotarm/frames/in link #1},
+ in base link/.style={/robotarm/frames/in link 0},
+ in end effector/.style={/robotarm/frames/in end effector},
+ in world/.style={/robotarm/frames/in world},
+ }
+}
+% \end{macrocode}
+% \end{macro}
+% \begin{macrocode}
+\makeatother
+%</robotarm-package>
+% \end{macrocode}
+% \Finale
+\endinput \ No newline at end of file
diff --git a/macros/latex/contrib/robotarm/robotarm.pdf b/macros/latex/contrib/robotarm/robotarm.pdf
new file mode 100644
index 0000000000..ab9689f9d9
--- /dev/null
+++ b/macros/latex/contrib/robotarm/robotarm.pdf
Binary files differ
diff --git a/macros/latex/contrib/robotarm/robotarm.sty b/macros/latex/contrib/robotarm/robotarm.sty
new file mode 100644
index 0000000000..5fb7f730aa
--- /dev/null
+++ b/macros/latex/contrib/robotarm/robotarm.sty
@@ -0,0 +1,375 @@
+%%
+%% This is file `robotarm.sty',
+%% generated with the docstrip utility.
+%%
+%% The original source files were:
+%%
+%% robotarm.dtx (with options: `robotarm-package')
+%%
+%% This is a generated file.
+%%
+%% Copyright (C) 2021 by M.J.W. Snippe
+%% -----------------------------------
+%%
+%% This file 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.
+%%
+%% This work has the LPPL maintenance status
+%% `author-maintained'.
+%%
+%% This work consists of the files found at github.com/max-sn/robotarm.
+%%
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{robotarm}
+ [2022/03/08 v0.1 Tikz commands to draw planar robot arms]
+
+\RequirePackage{tikz}
+
+\usetikzlibrary{patterns}
+
+\makeatletter
+
+\newif\ifRA@robotarm@drawannotations
+
+\pgfkeys{
+ /robotarm/base link/.cd,
+ width/.code={\pgfmathsetmacro\RA@baselink@width{#1}},
+ width=0.6,
+ height/.code={\pgfmathsetmacro\RA@baselink@height{#1}},
+ height=0.3,
+ world width/.code={\pgfmathsetmacro\RA@baselink@worldwidth{#1}},
+ world width=1.0,
+ world height/.code={\pgfmathsetmacro\RA@baselink@worldheight{#1}},
+ world height=0.3,
+ draw base link/.code={%
+ \path[link style]
+ (-1/2*\RA@baselink@width,0)
+ arc (180:0:1/2*\RA@baselink@width)
+ -- ++ (0, -\RA@baselink@height)
+ -- ++ (-\RA@baselink@width, 0)
+ -- cycle;
+ },
+ draw world/.code={%
+ \path[world style]
+ (-1/2*\RA@baselink@worldwidth,-\RA@baselink@height)
+ arc (180:360:{1/2*\RA@baselink@worldwidth}
+ and {\RA@baselink@worldheight}) -- cycle;
+ \path[draw, world style]
+ (-1/2*\RA@baselink@worldwidth,-\RA@baselink@height)
+ -- ++(\RA@baselink@worldwidth,0);
+ },
+ /robotarm/link/.cd,
+ width/.code={\pgfmathsetmacro\RA@link@width{#1}},
+ width=0.4,
+ length/.code={\pgfmathsetmacro\RA@link@length{#1}},
+ length=2.0,
+ joint radius/.code={\pgfmathsetmacro\RA@link@jointradius{#1}},
+ joint radius=0.25,
+ draw link/.code={%
+ \path[link style]
+ (0,1/2*\RA@link@width)
+ -- ++ ( \RA@link@length, 0)
+ arc (90:-90:1/2*\RA@link@width)
+ -- ++ (-\RA@link@length, 0)
+ arc (270:90:1/2*\RA@link@width)
+ -- cycle;
+ },
+ draw joint/.code={%
+ \path[link style]
+ (0,0) circle (\RA@link@jointradius);
+ \path[link style]
+ (0,0) circle (1/3*\RA@link@jointradius);
+ },
+ /robotarm/end effector/.cd,
+ width/.code={\pgfmathsetmacro\RA@endeff@width{#1}},
+ width=0.4,
+ length/.code={\pgfmathsetmacro\RA@endeff@length{#1}},
+ length=2,
+ joint radius/.code={\pgfmathsetmacro\RA@endeff@jointradius{#1}},
+ joint radius=0.25,
+ gripper radius/.code={\pgfmathsetmacro\RA@endeff@gripperradius{#1}},
+ gripper radius=0.3,
+ gripper opening angle/.code={%
+ \pgfmathsetmacro\RA@endeff@gripperopeningangle{#1}},
+ gripper opening angle=60,
+ draw joint/.code={%
+ \path[link style]
+ (0,0) circle (\RA@endeff@jointradius);
+ \path[link style]
+ (0,0) circle (1/3*\RA@endeff@jointradius);
+ },
+ draw link/.code={%
+ \pgfmathsetmacro{\link@startangle}{%
+ 180-asin(1/2*\RA@endeff@width/\RA@endeff@gripperradius)}
+ \pgfmathsetmacro{\link@endangle}{%
+ 180+asin(1/2*\RA@endeff@width/\RA@endeff@gripperradius)}
+
+ \path[link style]
+ (\RA@endeff@length, 0)
+ ++ (\link@startangle:\RA@endeff@gripperradius)
+ arc (\link@startangle:\link@endangle:\RA@endeff@gripperradius)
+ -- (0,0|-0,-1/2*\RA@endeff@width)
+ arc (-90:90:1/2*\RA@endeff@width)
+ -- cycle;
+ },
+ draw end effector/.code={
+ \draw[link style]
+ (\RA@endeff@length, 0)
+ ++ (-1/2*\RA@endeff@gripperopeningangle:%
+ \RA@endeff@gripperradius)
+ arc [start angle=-1/2*\RA@endeff@gripperopeningangle,
+ delta angle=-360+\RA@endeff@gripperopeningangle,
+ radius=\RA@endeff@gripperradius]
+ -- ++(180+1/2*\RA@endeff@gripperopeningangle:%
+ 0.4*\RA@endeff@gripperradius)
+ arc [start angle=1/2*\RA@endeff@gripperopeningangle,
+ delta angle=360-\RA@endeff@gripperopeningangle,
+ radius=0.6*\RA@endeff@gripperradius]
+ -- ++(-1/2*\RA@endeff@gripperopeningangle:%
+ 0.4*\RA@endeff@gripperradius)
+ -- cycle;
+ },
+ /robotarm/.cd,
+ draw annotations/.is if=RA@robotarm@drawannotations,
+ draw annotations=true,
+ every annotation/.style={},
+ every length annotation/.style={},
+ every length annotation arrow/.style={draw,->},
+ every length annotation node/.style={circle,inner sep=0.5pt},
+ every length annotation help line/.style={draw,help lines},
+ every angle annotation/.style={},
+ every angle annotation arrow/.style={draw,->},
+ every angle annotation node/.style={},
+ every angle annotation help line/.style={draw,help lines},
+ base link/.code=\pgfkeys{/robotarm/base link/.cd,#1},
+ link/.code=\pgfkeys{/robotarm/link/.cd,#1},
+ end effector/.code=\pgfkeys{/robotarm/end effector/.cd,#1},
+ geometry/.code=\pgfkeys{/robotarm/geometry/.cd,#1},
+ config/.code=\pgfkeys{/robotarm/config/.cd,#1},
+ spacing/.code=\pgfkeys{/robotarm/annotations/spacing/.cd,#1},
+ labels/.code=\pgfkeys{/robotarm/annotations/labels/.cd,#1},
+ styles/.code=\pgfkeys{/robotarm/styles/.cd,#1},
+ /robotarm/geometry/.cd,
+ a0/.initial=0,
+ a/.initial=2,
+ r/.initial=0.25,
+ w/.initial=0.4,
+ /robotarm/config/q/.initial=0,
+ /robotarm/frames/.cd,
+ in link 0/.style={},
+ in end effector/.style={
+ /robotarm/frames/in link \RA@robotarm@numlinks,
+ shift={%
+ (\pgfkeysvalueof{/robotarm/geometry/a\RA@robotarm@numlinks},0)},
+ },
+ in world/.style={
+ shift={(0,-\RA@baselink@height)}
+ },
+ /robotarm/styles/.cd,
+ world/.style={pattern=north west lines},
+ link/.style={
+ draw,
+ fill=lightgray,
+ },
+ link 0/.style={/robotarm/styles/link},
+ /robotarm/annotations/.cd,
+ spacing/.cd,
+ a/.initial=3,
+ q/.initial=1/2,
+ /robotarm/annotations/.cd,
+ labels/.cd,
+ a/.initial=a,
+ q/.initial=q,
+}
+\tikzset{
+ link style/.style={/robotarm/styles/link},
+ world style/.style={/robotarm/styles/world},
+}
+\newcommand\robotarmset[1]{%
+ \pgfkeys{/robotarm/.cd,#1}%
+}
+\newcommand\robotArmLink[1][]{
+ \begingroup
+ \pgfkeys{/robotarm/link/.cd,#1}
+
+ \pgfkeys{/robotarm/link/draw link}
+ \pgfkeys{/robotarm/link/draw joint}
+ \endgroup
+}
+\newcommand\robotArmEndEffector[1][]{
+ \begingroup
+ \pgfkeys{/robotarm/end effector/.cd,#1}
+
+ \pgfkeys{/robotarm/end effector/draw link}
+ \pgfkeys{/robotarm/end effector/draw joint}
+ \pgfkeys{/robotarm/end effector/draw end effector}
+
+ \endgroup
+}
+\newcommand\robotArmBaseLink[1][]{
+ \begingroup
+ \pgfkeys{/robotarm/base link/.cd,#1}
+
+ \pgfkeys{/robotarm/base link/draw world}
+ \pgfkeys{/robotarm/base link/draw base link}
+ \endgroup
+}
+\newcommand\robotArm[2][]{
+ \pgfmathtruncatemacro\RA@robotarm@numlinks{#2}
+ \def\@tmpkeys{}
+ \foreach \@link [remember=\@link as \@prevlink (initially 0)] in %
+ {1,...,\RA@robotarm@numlinks}{
+ \xdef\@tmpkeys{\@tmpkeys%
+ /robotarm/geometry/a\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/geometry/a},%
+ /robotarm/geometry/r\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/geometry/r},%
+ /robotarm/geometry/w\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/geometry/w},%
+ /robotarm/config/q\@link/.initial=%
+ \pgfkeysvalueof{/robotarm/config/q},%
+ /robotarm/styles/link \@link/.style={/robotarm/styles/link},%
+ /robotarm/annotations/labels/a\@link/.initial={%
+ $\pgfkeysvalueof{/robotarm/annotations/labels/a}_{\@link}$},%
+ /robotarm/annotations/labels/q\@link/.initial={%
+ $\pgfkeysvalueof{/robotarm/annotations/labels/q}_{\@link}$},%
+ /robotarm/annotations/spacing/a\@link/.initial={%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/a}},%
+ /robotarm/annotations/spacing/q\@link/.initial={%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/q}},%
+ }
+ }
+ \expandafter\pgfkeys\expandafter{\@tmpkeys}
+ \pgfkeys{/robotarm/.cd,#1}
+ \def\@tmpkeys{}
+ \foreach \@link [remember=\@link as \@prevlink (initially 0)] in %
+ {1,...,\RA@robotarm@numlinks}{
+ \xdef\@tmpkeys{\@tmpkeys%
+ /robotarm/frames/in link \@link/.style={%
+ /robotarm/frames/in link \@prevlink,
+ /tikz/shift={%
+ (\pgfkeysvalueof{/robotarm/geometry/a\@prevlink},0)},
+ /tikz/rotate={\pgfkeysvalueof{/robotarm/config/q\@link}},
+ },
+ }
+ }
+ \expandafter\pgfkeys\expandafter{\@tmpkeys}
+
+ \begin{scope}[/robotarm/frames/in link 0,
+ link style/.style={/robotarm/styles/link 0}]
+ \robotArmBaseLink
+ \end{scope}
+
+ \foreach\link@num in {1,...,\RA@robotarm@numlinks}{
+ \begin{scope}[/robotarm/frames/in link \link@num,
+ link style/.style={/robotarm/styles/link \link@num}]
+
+ \ifnum\link@num<\RA@robotarm@numlinks
+ \robotArmLink[
+ joint radius=\pgfkeysvalueof{/robotarm/geometry/r\link@num},
+ length=\pgfkeysvalueof{/robotarm/geometry/a\link@num},
+ width=\pgfkeysvalueof{/robotarm/geometry/w\link@num},
+ ]
+ \else
+ \robotArmEndEffector[
+ joint radius=\pgfkeysvalueof{/robotarm/geometry/r\link@num},
+ length=\pgfkeysvalueof{/robotarm/geometry/a\link@num},
+ width=\pgfkeysvalueof{/robotarm/geometry/w\link@num},
+ ]
+ \fi
+ \end{scope}
+ }
+ \foreach\link@num in {1,...,\RA@robotarm@numlinks}{
+ \begin{scope}[/robotarm/frames/in link \link@num]
+ \pgfmathsetmacro\link@length{\pgfkeysvalueof{%
+ /robotarm/geometry/a\link@num}}
+ \pgfmathsetmacro\link@angle{\pgfkeysvalueof{%
+ /robotarm/config/q\link@num}}
+
+ \ifRA@robotarm@drawannotations
+ \pgfmathsetmacro\link@lengthannotspacing{%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/a\link@num}*
+ \pgfkeysvalueof{/robotarm/geometry/r\link@num}}
+ \pgfmathsetmacro\link@angleannotspacing{%
+ \pgfkeysvalueof{/robotarm/annotations/spacing/q\link@num}*
+ \link@length}
+
+ % Length annotation help lines
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation help line]
+ (0,0) -- (\link@length,0);
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation help line]
+ (0,0) -- ++ (0,{\link@lengthannotspacing +
+ 0.1*sign(\link@lengthannotspacing)});
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation help line]
+ (\link@length,0) -- ++ (0,{\link@lengthannotspacing +
+ 0.1*sign(\link@lengthannotspacing)});
+ \path (0,\link@lengthannotspacing)
+ -- coordinate[pos=0.5] (coor) ++ (\link@length,0);
+ \node[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation node]
+ at (coor) (tag)
+ {\pgfkeysvalueof{/robotarm/annotations/labels/a\link@num}};
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation arrow]
+ (tag) -- (0,\link@lengthannotspacing);
+ \path[/robotarm/every annotation,
+ /robotarm/every length annotation,
+ /robotarm/every length annotation arrow]
+ (tag) -- (\link@length,\link@lengthannotspacing);
+
+ \pgfmathsetmacro\angleannotationcase{%
+ ifthenelse(\link@angle==0.0, 0, 1)}
+ \ifnum\angleannotationcase>0
+ % Angle annotation help lines
+ \path[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation help line]
+ (0,0) -- ++(-\link@angle:{\link@angleannotspacing+0.1});
+ \path[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation help line]
+ (0,0) -- ++(0:{\link@angleannotspacing+0.1});
+
+ % Angle annotation arrow
+ \path[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation arrow]
+ (0,0) ++ (-\link@angle:\link@angleannotspacing)
+ arc (-\link@angle:0:\link@angleannotspacing);
+
+ % Angle annotation node
+ \node[/robotarm/every annotation,
+ /robotarm/every angle annotation,
+ /robotarm/every angle annotation node]
+ at (-\link@angle/2:\link@angleannotspacing+0.3)
+ {\pgfkeysvalueof{/robotarm/annotations/labels/q\link@num}};
+ \fi
+ \fi
+ \end{scope}
+ }
+ \tikzset{
+ in link/.style={/robotarm/frames/in link #1},
+ in base link/.style={/robotarm/frames/in link 0},
+ in end effector/.style={/robotarm/frames/in end effector},
+ in world/.style={/robotarm/frames/in world},
+ }
+}
+\makeatother
+\endinput
+%%
+%% End of file `robotarm.sty'.