From a9067eb46b845f70c9282bad59fbe6e8dba0e515 Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Fri, 20 Dec 2013 13:57:39 -0800 Subject: Initial commit --- .dir-locals.el | 33 ++ .gitignore | 50 ++ COPYING | 674 ++++++++++++++++++++++ INSTALL | 319 +++++++++++ Makefile.am | 23 + README | 115 ++++ configure.ac | 109 ++++ examples/simple.ttt | Bin 0 -> 507079 bytes m4/ax_cxx_compile_stdcxx_11.m4 | 133 +++++ m4/boost.m4 | 1239 ++++++++++++++++++++++++++++++++++++++++ src/Makefile.am | 97 ++++ src/automobile.cpp | 403 +++++++++++++ src/automobile.h | 30 + src/csv-inl.h | 58 ++ src/csv.cpp | 48 ++ src/csv.h | 71 +++ src/main.cpp | 137 +++++ src/main.h | 44 ++ src/measurement-inl.h | 62 ++ src/measurement.cpp | 68 +++ src/measurement.h | 93 +++ src/noise-inl.h | 51 ++ src/noise.cpp | 73 +++ src/noise.h | 72 +++ src/vrep-inl.h | 118 ++++ src/vrep.cpp | 72 +++ src/vrep.h | 104 ++++ src/vrepFfi-inl.h | 133 +++++ src/vrepFfi.cpp | 68 +++ src/vrepFfi.h | 158 +++++ 30 files changed, 4655 insertions(+) create mode 100644 .dir-locals.el create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 INSTALL create mode 100644 Makefile.am create mode 100644 README create mode 100644 configure.ac create mode 100644 examples/simple.ttt create mode 100644 m4/ax_cxx_compile_stdcxx_11.m4 create mode 100644 m4/boost.m4 create mode 100644 src/Makefile.am create mode 100644 src/automobile.cpp create mode 100644 src/automobile.h create mode 100644 src/csv-inl.h create mode 100644 src/csv.cpp create mode 100644 src/csv.h create mode 100644 src/main.cpp create mode 100644 src/main.h create mode 100644 src/measurement-inl.h create mode 100644 src/measurement.cpp create mode 100644 src/measurement.h create mode 100644 src/noise-inl.h create mode 100644 src/noise.cpp create mode 100644 src/noise.h create mode 100644 src/vrep-inl.h create mode 100644 src/vrep.cpp create mode 100644 src/vrep.h create mode 100644 src/vrepFfi-inl.h create mode 100644 src/vrepFfi.cpp create mode 100644 src/vrepFfi.h diff --git a/.dir-locals.el b/.dir-locals.el new file mode 100644 index 0000000..d7ec655 --- /dev/null +++ b/.dir-locals.el @@ -0,0 +1,33 @@ +;; .dir-locals.el -- directory-local variables for the car plugin +;; Copyright (C) 2013 Galois, Inc. +;; +;; This library is free software: you can redistribute it and/or modify it under +;; the terms of the GNU General Public License as published by the Free Software +;; Foundation, either version 3 of the License, or (at your option) any later +;; version. +;; +;; This library is distributed in the hope that it will be useful, but WITHOUT +;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +;; FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +;; details. +;; +;; You should have received a copy of the GNU General Public License along with +;; this library. If not, see . +;; +;; To contact Galois, complete the Web form at +;; or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, +;; Oregon, 97204-1622. + + +((nil . ((fill-column . 80))) + (autoconf-mode . ((indent-tabs-mode . nil))) + (makefile-automake-mode . ((indent-tabs-mode . t))) + (c++-mode . ((c-file-style . "bsd") + (c-basic-offset . 4) + (indent-tabs-mode . nil))) + ;; This is not a polyglot library, so open .h files in C++ mode. + (c-mode . ((mode . c++) + (c-file-style . "bsd") + (c-basic-offset . 4) + (indent-tabs-mode . nil))) + (text-mode . ((indent-tabs-mode . nil)))) diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..495866c --- /dev/null +++ b/.gitignore @@ -0,0 +1,50 @@ +# .gitignore for the V-REP automobile plugin -*- conf -*- + +# Editor backup files +*~ +\#* +.\#* + +# autoscan +autoscan.log +configure.scan + +# aclocal +aclocal.m4 +autom4te.cache/ +m4/libtool.m4 +m4/lt*.m4 + +# autoconf +configure + +# autoheader +config.h.in + +# libtoolize +ltmain.sh + +# automake +Makefile.in +ar-lib +config.guess +config.sub +depcomp +install-sh +missing + +# configure +.deps/ +Makefile +config.h +config.log +config.status +libtool +ppamltracer.pc +stamp-* + +# make +.libs/ +*.la +*.lo +*.o diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/INSTALL b/INSTALL new file mode 100644 index 0000000..6733fd6 --- /dev/null +++ b/INSTALL @@ -0,0 +1,319 @@ +Installation Instructions +************************* + +Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, Inc. +Copyright (C) 2013 Galois, Inc. + +Copying and distribution of this file, with or without modification, are +permitted in any medium without royalty provided the copyright notice and this +notice are preserved. This file is offered as-is, without warranty of any kind. + +Basic Installation +================== + +Briefly, the shell commands + + export VREP=/path/to/vrep/installation + ./configure + make + make install + +should configure, build, and install this package. + +The `configure' shell script attempts to guess correct values for various +system-dependent variables used during compilation. It uses those values to +create a `Makefile' in the top-level directory of the package, as well as the +`src' subdirectory. It also creates a `config.h' file containing +system-dependent definitions. Finally, it creates a shell script +`config.status' that you can run in the future to recreate the current +configuration, and a file `config.log' containing compiler output (useful mainly +for debugging `configure'). + +It can also use an optional file (typically called `config.cache' and enabled +with `--cache-file=config.cache' or simply `-C') that saves the results of its +tests to speed up reconfiguring. Caching is disabled by default to prevent +problems with accidental use of stale cache files. + +If you need to do unusual things to compile the package, please try to figure +out how `configure' could check whether to do them, and mail diffs or +instructions to the address given in the `README' so they can be considered for +the next release. If you are using the cache, and at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + +The file `configure.ac' is used to create `configure' by a program called +`autoconf'. You need `configure.ac' if you want to change it or regenerate +`configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. If you have not done so already, install V-REP and the Boost file system + library. + + 2. Export the environment variable `VREP' such that it points to the top-level + directory of your V-REP installation. + + 3. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. + + Running `configure' might take a while. While running, it prints + some messages telling which features it is checking for. + + 4. Type `make' to compile the package. + + 5. Type `make install' to install the programs and any data files and + documentation. + + 6. You can remove the program object files from the source code directory by + typing `make clean'. To also remove the files that `configure' created (so + you can compile the package for a different kind of computer), type `make + distclean'. There is also a `make maintainer-clean' target, but that is + intended mainly for the package's developers. If you use it, you may have + to get all sorts of other programs in order to regenerate files that came + with the distribution. + + 7. You can also type `make uninstall' to remove the installed files again. + +Compilers and Options +===================== + +Some systems require unusual options for compilation or linking that the +`configure' script does not know about. Run `./configure --help' for details on +some of the pertinent environment variables. + +You can give `configure' initial values for configuration parameters by setting +variables in the command line or in the environment. Here is an example: + + ./configure CC=c99 CFLAGS=-g LIBS=-lposix + +Compiling For Multiple Architectures +==================================== + +You can compile the package for more than one kind of computer at the same time, +by placing the object files for each architecture in their own directory. To do +this, you can use GNU `make'. `cd' to the directory where you want the object +files and executables to go and run the `configure' script. `configure' +automatically checks for the source code in the directory that `configure' is in +and in `..'. This is known as a "VPATH" build. + +With a non-GNU `make', it is safer to compile the package for one architecture +at a time in the source code directory. After you have installed the package +for one architecture, use `make distclean' before reconfiguring for another +architecture. + +On Mac OS X 10.5 and later systems, you can create libraries and executables +that work on multiple system types--known as "fat" or "universal" binaries--by +specifying multiple `-arch' options to the compiler but only a single `-arch' +option to the preprocessor. Like this: + + ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ + CPP="gcc -E" CXXCPP="g++ -E" + +This is not guaranteed to produce working output in all cases, you may have to +build one architecture at a time and combine the results using the `lipo' tool +if you have problems. + +Installation Names +================== + +By default, `make install' installs the package's libraries under +`/usr/local/lib'. You can specify an installation prefix other than +`/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX +must be an absolute file name. + +You can specify separate installation prefixes for architecture-specific files +and architecture-independent files. If you pass the option +`--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for +installing programs and libraries. Documentation and other data files still use +the regular prefix. + +In addition, if you use an unusual directory layout you can give options like +`--bindir=DIR' to specify different values for particular kinds of files. Run +`configure --help' for a list of the directories you can set and what kinds of +files go in them. In general, the default for these options is expressed in +terms of `${prefix}', so that specifying just `--prefix' will affect all of the +other directory specifications that were not explicitly provided. + +The most portable way to affect installation locations is to pass the correct +locations to `configure'; however, many packages provide one or both of the +following shortcuts of passing variable assignments to the `make install' +command line to change installation locations without having to reconfigure or +recompile. + +The first method involves providing an override variable for each affected +directory. For example, `make install prefix=/alternate/directory' will choose +an alternate location for all directory configuration variables that were +expressed in terms of `${prefix}'. Any directories that were specified during +`configure', but not in terms of `${prefix}', must each be overridden at install +time for the entire installation to be relocated. The approach of makefile +variable overrides for each directory variable is required by the GNU Coding +Standards, and ideally causes no recompilation. However, some platforms have +known limitations with the semantics of shared libraries that end up requiring +recompilation when using this method, particularly noticeable in packages that +use GNU Libtool. + +The second method involves providing the `DESTDIR' variable. For example, `make +install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before +all installation names. The approach of `DESTDIR' overrides is not required by +the GNU Coding Standards, and does not work on platforms that have drive +letters. On the other hand, it does better at avoiding recompilation issues, +and works well even when some directory options were not specified in terms of +`${prefix}' at `configure' time. + +Optional Features +================= + +This package offers the ability to configure how verbose the execution of `make' +will be. For these packages, running `./configure --enable-silent-rules' sets +the default to minimal output, which can be overridden with `make V=1'; while +running `./configure --disable-silent-rules' sets the default to verbose, which +can be overridden with `make V=0'. + +Particular systems +================== + +On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not +installed, it is recommended to use the following options in order to use an +ANSI C compiler: + + ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" + +and if that doesn't work, install pre-built binaries of GCC for HP-UX. + +HP-UX `make' updates targets which have the same time stamps as their +prerequisites, which makes it generally unusable when shipped generated files +such as `configure' are involved. Use GNU `make' instead. + +On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its +`' header file. The option `-nodtk' can be used as a workaround. If +GNU CC is not installed, it is therefore recommended to try + + ./configure CC="cc" + +and if that doesn't work, try + + ./configure CC="cc -nodtk" + +On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains +several dysfunctional programs; working variants of these programs are available +in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ +`/usr/bin'. + +On Haiku, software installed for all users goes in `/boot/common', not +`/usr/local'. It is recommended to use the following options: + + ./configure --prefix=/boot/common + +Specifying the System Type +========================== + +There may be some features `configure' cannot figure out automatically, but +needs to determine by the type of machine the package will run on. Usually, +assuming the package is built to be run on the _same_ architectures, `configure' +can figure that out, but if it prints a message saying it cannot guess the +machine type, give it the `--build=TYPE' option. TYPE can either be a short +name for the system type, such as `sun4', or a canonical name which has the +form: + + CPU-COMPANY-SYSTEM + +where SYSTEM can have one of these forms: + + OS + KERNEL-OS + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't need to +know the machine type. + +If you are _building_ compiler tools for cross-compiling, you should use the +option `--target=TYPE' to select the type of system they will produce code for. + +If you want to _use_ a cross compiler, that generates code for a platform +different from the build platform, you should specify the "host" platform (i.e., +that on which the generated programs will eventually be run) with `--host=TYPE'. + +Sharing Defaults +================ + +If you want to set default values for `configure' scripts to share, you can +create a site shell script called `config.site' that gives default values for +variables like `CC', `cache_file', and `prefix'. `configure' looks for +`PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it +exists. Or, you can set the `CONFIG_SITE' environment variable to the location +of the site script. A warning: not all `configure' scripts look for a site +script. + +Defining Variables +================== + +Variables not defined in a site shell script can be set in the environment +passed to `configure'. However, some packages may run configure again during +the build, and the customized values of these variables may be lost. In order +to avoid this problem, you should set them in the `configure' command line, +using `VAR=value'. For example: + + ./configure CC=/usr/local2/bin/gcc + +causes the specified `gcc' to be used as the C compiler (unless it is +overridden in the site shell script). + +Unfortunately, this technique does not work for `CONFIG_SHELL' due to +an Autoconf bug. Until the bug is fixed you can use this workaround: + + CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash + +`configure' Invocation +====================== + +`configure' recognizes the following options to control how it operates. + +`--help' +`-h' + Print a summary of all of the options to `configure', and exit. + +`--help=short' +`--help=recursive' + Print a summary of the options unique to this package's + `configure', and exit. The `short' variant lists options used + only in the top level, while the `recursive' variant lists options + also present in any nested packages. + +`--version' +`-V' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`--cache-file=FILE' + Enable the cache: use and save the results of the tests in FILE, + traditionally `config.cache'. FILE defaults to `/dev/null' to + disable caching. + +`--config-cache' +`-C' + Alias for `--cache-file=config.cache'. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--prefix=DIR' + Use DIR as the installation prefix. *note Installation Names:: + for more details, including other options available for fine-tuning + the installation locations. + +`--no-create' +`-n' + Run the configure checks, but stop before creating any output + files. + +`configure' also accepts some other, not widely useful, options. Run +`configure --help' for more details. + diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 0000000..aaef76e --- /dev/null +++ b/Makefile.am @@ -0,0 +1,23 @@ +# Makefile.am -- automake script for the car plugin +# Copyright (C) 2013 Galois, Inc. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see . +# +# To contact Galois, complete the Web form at +# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, +# Oregon, 97204-1622. + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = src diff --git a/README b/README new file mode 100644 index 0000000..8d424b9 --- /dev/null +++ b/README @@ -0,0 +1,115 @@ + ppaml-vrep-automobile-plugin, v1.0.0 + +This package provides a data collection plugin for the V-REP robotics simulator +. The plugin is targeted at data collection +following the model described at +, but it may +be useful for other projects as well. + +For detailed installation instructions, see the INSTALL file. + +For examples of use, see the examples directory. + +Once you have installed the library and restarted V-REP, you'll have at your +disposal five new Lua functions: + + - simExtAutomobileInit(string directoryName, number L, number h, number a, + number b, number theta0, number max_distance, + number max_intensity) + Initializes the plugin. Consequently, you must call this at least once + during your run, and we strongly recommend you do so before collecting any + data. :) The parameters are: + + - directoryName: The base directory for the output data. If the + directory does not exist, the plugin will create it. If the directory + does exist, the plugin will remove anything in it that looks like data + from a previous run. + + - L, h, a, b, theta0: Model parameters as described in the paper. + Specifically: + + - L: Distance between front and rear axles. + + - h: Distance between center of rear axle and encoder on left rear + wheel. In examples/simple.ttt, this parameter is zero, as no + encoder is used; instead, we measure position directly at the + center of the rear axle. + + - a, b: Distance between the rear axle and the lidar sensor, + expressed as a 2D vector. The basis vectors point in line with the + car and forward (for a) and in line with the axle and to the left + side of the vehicle (for b). + + - theta0: Initial angle of the car, with 0 defined as due east and + increasing counterclockwise (i.e., in the positive k̂ direction). + + - max_distance, max_intensity: Lidar parameters. max_distance should be + set to the distance between the lidar sensors' apertures and their far + clip planes; in examples/simple.ttt, this is 10. max_intensity is + entirely dependent on what code you're using to postprocess the data; + we've had it set at 32768, but you can pick whatever you want without + incident. + + - simExtAutomobileRequestNoise(table2 xy, table2 angle, table2 speed, + table2 steeringAngle, table2 distance, + table2 intensity) + Requests that, in addition to the gathered data, the plugin also generate a + data set with artificial Gaussian noise added. Should you wish to use this + function, we strongly recommend you only call it once per run. The + parameters are two-element numeric tables describing the mean and standard + deviation for the noise applied to each measurement. + + - simExtAutomobileSavePose(number simulationTime, number x, number y, + number theta) + Records a pose (position and angle). You should call this repeatedly to + save multiple poses over the course of a simulation. + + - simExtAutomobileSaveControls(number simulationTime, number speed, + number steeringAngle) + Records measurements taken from control surfaces of the car--speed and + steering angle of the right front wheel. (This model has Ackermann + steering; hence, the two front wheels will generally not be oriented at + equal angles.) You should call this repeatedly to save multiple data over + the course of a simulation. + + - simExtAutomobileSaveLaserPair(number simulationTime, table leftDepthBuffer, + table rightDepthBuffer, table leftImage, + table rightImage) + Records measurements from the lidar. You should call this repeatedbly to + save multiple data over the course of a simulation. So that you may + simulate a lidar with a wider angle than V-REP's distance sensor part + supports, you can pass two inputs, which will be concatenated in the plugin + before being written to the file. Your input tables may be of any length, + but they must be the same length on each call to this function throughout a + single run--should you fail to maintainf this invariant, the plugin will + crash with a C++ exception, bringing down V-REP with it. + +The output directory tree will look like this: + + output_dir + ├── ground + │   ├── slam_control.csv + │   ├── slam_gps.csv + │   ├── slam_laser.csv + │   └── slam_sensor.csv + ├── noisy + │   ├── slam_control.csv + │   ├── slam_gps.csv + │   ├── slam_laser.csv + │   └── slam_sensor.csv + └── properties.csv + +The properties.csv file contains run properties written with +simExtAutomobileInit. The ground subdirectory contains ground truth data; the +noisy subdirectory contains data with additive noise. In each subdirectory, +you'll find + + - slam_sensor.csv: A "table of contents" file that describes which sensor was + sampled at what time. + + - slam_gps.csv: All poses saved with simExtAutomobileSavePose. + + - slam_sensor.csv: All data saved with simExtAutomobileSaveControls. + + - slam_laser.csv: All lidar measurements saved with + simExtAutomobileSaveLaserPair. diff --git a/configure.ac b/configure.ac new file mode 100644 index 0000000..1bf6e65 --- /dev/null +++ b/configure.ac @@ -0,0 +1,109 @@ +# configure.ac -- autoconf script for the car plugin +# Copyright (C) 2013 Galois, Inc. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see . +# +# To contact Galois, complete the Web form at +# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, +# Oregon, 97204-1622. + +# Fire up Autoconf. +AC_PREREQ([2.69]) +AC_INIT([libv_repExtAutomobile], [1.0.0], [bbarenblat@galois.com]) +AC_CANONICAL_TARGET + +# This package will build but not function on OS X, so fail fast if we're on +# Darwin. +case "$target_os" in + darwin*) + AC_MSG_ERROR([this plugin will not function on OS X]) + ;; +esac + +# Fire up Automake. +AM_INIT_AUTOMAKE([-Wall -Wno-gnu -Wno-override -Werror foreign no-dist-gzip dist-bzip2]) +AC_CONFIG_MACRO_DIR([m4]) + +# Build quietly. +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) + +# Build a C++ library. +AC_CONFIG_SRCDIR([config.h.in]) +AC_CONFIG_HEADERS([config.h]) +AC_PROG_CXX +AX_CXX_COMPILE_STDCXX_11([noext],[mandatory]) +# Automake 1.12 seems to require this, but automake 1.11 doesn't recognize it. +m4_ifdef([AM_PROG_AR], [AM_PROG_AR]) +LT_INIT +AC_PROG_LN_S + +# Dependencies +AC_ARG_VAR([VREP], [path to V-REP installation]) +if test -z "$VREP"; then + AC_MSG_ERROR([empty VREP environment variable; please set it to the path to the V-REP installation directory]) +fi +VREP_CXXFLAGS=-I$VREP/programming/include +AC_SUBST([VREP]) +AC_SUBST([VREP_CXXFLAGS]) + +BOOST_REQUIRE +BOOST_FILESYSTEM +BOOST_OPTIONAL([1.34]) + +# C++11 initializer list syntax is nice! Sadly, it is not universally +# supported. Notably, Clang <3.1 lacks support for initializer lists, and a +# number of systems--e.g., Debian Wheezy machines--have pre-3.1 Clang. +# TODO: Once Clang 3.0 and earlier disappear from the ecosystem, get rid of +# HAVE_CXX11_INITIALIZER_LISTS and make this check fatal on error. +AC_LANG_PUSH([C++]) +AC_MSG_CHECKING([for initializer list support]) +# Double brackets go around the argument to AC_LANG_SOURCE, lest m4 replace the +# square brackets in the C++ code. +AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[#include +int main(int argc, char *argv[]) { + std::vector test {1, 2, 3}; + return 0; +}]])], + [AC_DEFINE( + [HAVE_CXX11_INITIALIZER_LISTS], + [1], + [Define to 1 if your compiler supports C++11 initializer lists.]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) +AC_LANG_POP([C++]) + +# Same for lambda expressions. +AC_LANG_PUSH([C++]) +AC_MSG_CHECKING([for C++11 closure support]) +AC_COMPILE_IFELSE( + [AC_LANG_SOURCE([[int main(int argc, char *argv[]) { + auto test = [](int &n){ n++; }; + return 0; +}]])], + [AC_DEFINE( + [HAVE_CXX11_CLOSURES], + [1], + [Define to 1 if your compiler supports C++11 closure syntax.]) + AC_MSG_RESULT([yes])], + [AC_MSG_RESULT([no])]) +AC_LANG_POP([C++]) + +# Generate Makefiles. +AC_CONFIG_FILES([ + Makefile + src/Makefile]) + +# All done. +AC_OUTPUT diff --git a/examples/simple.ttt b/examples/simple.ttt new file mode 100644 index 0000000..d95dca7 Binary files /dev/null and b/examples/simple.ttt differ diff --git a/m4/ax_cxx_compile_stdcxx_11.m4 b/m4/ax_cxx_compile_stdcxx_11.m4 new file mode 100644 index 0000000..af37acd --- /dev/null +++ b/m4/ax_cxx_compile_stdcxx_11.m4 @@ -0,0 +1,133 @@ +# ============================================================================ +# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_11.html +# ============================================================================ +# +# SYNOPSIS +# +# AX_CXX_COMPILE_STDCXX_11([ext|noext],[mandatory|optional]) +# +# DESCRIPTION +# +# Check for baseline language coverage in the compiler for the C++11 +# standard; if necessary, add switches to CXXFLAGS to enable support. +# +# The first argument, if specified, indicates whether you insist on an +# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g. +# -std=c++11). If neither is specified, you get whatever works, with +# preference for an extended mode. +# +# The second argument, if specified 'mandatory' or if left unspecified, +# indicates that baseline C++11 support is required and that the macro +# should error out if no mode with that support is found. If specified +# 'optional', then configuration proceeds regardless, after defining +# HAVE_CXX11 if and only if a supporting mode is found. +# +# LICENSE +# +# Copyright (c) 2008 Benjamin Kosnik +# Copyright (c) 2012 Zack Weinberg +# Copyright (c) 2013 Roy Stogner +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. This file is offered as-is, without any +# warranty. + +#serial 3 + +m4_define([_AX_CXX_COMPILE_STDCXX_11_testbody], [ + template + struct check + { + static_assert(sizeof(int) <= sizeof(T), "not big enough"); + }; + + typedef check> right_angle_brackets; + + int a; + decltype(a) b; + + typedef check check_type; + check_type c; + check_type&& cr = static_cast(c); + + auto d = a; +]) + +AC_DEFUN([AX_CXX_COMPILE_STDCXX_11], [dnl + m4_if([$1], [], [], + [$1], [ext], [], + [$1], [noext], [], + [m4_fatal([invalid argument `$1' to AX_CXX_COMPILE_STDCXX_11])])dnl + m4_if([$2], [], [ax_cxx_compile_cxx11_required=true], + [$2], [mandatory], [ax_cxx_compile_cxx11_required=true], + [$2], [optional], [ax_cxx_compile_cxx11_required=false], + [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX_11])])dnl + AC_LANG_PUSH([C++])dnl + ac_success=no + AC_CACHE_CHECK(whether $CXX supports C++11 features by default, + ax_cv_cxx_compile_cxx11, + [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [ax_cv_cxx_compile_cxx11=yes], + [ax_cv_cxx_compile_cxx11=no])]) + if test x$ax_cv_cxx_compile_cxx11 = xyes; then + ac_success=yes + fi + + m4_if([$1], [noext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=gnu++11 -std=gnu++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + + m4_if([$1], [ext], [], [dnl + if test x$ac_success = xno; then + for switch in -std=c++11 -std=c++0x; do + cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx11_$switch]) + AC_CACHE_CHECK(whether $CXX supports C++11 features with $switch, + $cachevar, + [ac_save_CXXFLAGS="$CXXFLAGS" + CXXFLAGS="$CXXFLAGS $switch" + AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_11_testbody])], + [eval $cachevar=yes], + [eval $cachevar=no]) + CXXFLAGS="$ac_save_CXXFLAGS"]) + if eval test x\$$cachevar = xyes; then + CXXFLAGS="$CXXFLAGS $switch" + ac_success=yes + break + fi + done + fi]) + AC_LANG_POP([C++]) + if test x$ax_cxx_compile_cxx11_required = xtrue; then + if test x$ac_success = xno; then + AC_MSG_ERROR([*** A compiler with support for C++11 language features is required.]) + fi + else + if test x$ac_success = xno; then + HAVE_CXX11=0 + AC_MSG_NOTICE([No compiler with C++11 support was found]) + else + HAVE_CXX11=1 + AC_DEFINE(HAVE_CXX11,1, + [define if the compiler supports basic C++11 syntax]) + fi + + AC_SUBST(HAVE_CXX11) + fi +]) diff --git a/m4/boost.m4 b/m4/boost.m4 new file mode 100644 index 0000000..c8eb65a --- /dev/null +++ b/m4/boost.m4 @@ -0,0 +1,1239 @@ +# boost.m4: Locate Boost headers and libraries for autoconf-based projects. +# Copyright (C) 2007, 2008, 2009, 2010, 2011 Benoit Sigoure +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Additional permission under section 7 of the GNU General Public +# License, version 3 ("GPLv3"): +# +# If you convey this file as part of a work that contains a +# configuration script generated by Autoconf, you may do so under +# terms of your choice. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +m4_define([_BOOST_SERIAL], [m4_translit([ +# serial 18 +], [# +], [])]) + +# Original sources can be found at http://github.com/tsuna/boost.m4 +# You can fetch the latest version of the script by doing: +# wget http://github.com/tsuna/boost.m4/raw/master/build-aux/boost.m4 + +# ------ # +# README # +# ------ # + +# This file provides several macros to use the various Boost libraries. +# The first macro is BOOST_REQUIRE. It will simply check if it's possible to +# find the Boost headers of a given (optional) minimum version and it will +# define BOOST_CPPFLAGS accordingly. It will add an option --with-boost to +# your configure so that users can specify non standard locations. +# If the user's environment contains BOOST_ROOT and --with-boost was not +# specified, --with-boost=$BOOST_ROOT is implicitly used. +# For more README and documentation, go to http://github.com/tsuna/boost.m4 +# Note: THESE MACROS ASSUME THAT YOU USE LIBTOOL. If you don't, don't worry, +# simply read the README, it will show you what to do step by step. + +m4_pattern_forbid([^_?(BOOST|Boost)_]) + + +# _BOOST_SED_CPP(SED-PROGRAM, PROGRAM, +# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]) +# -------------------------------------------------------- +# Same as AC_EGREP_CPP, but leave the result in conftest.i. +# +# SED-PROGRAM is *not* overquoted, as in AC_EGREP_CPP. It is expanded +# in double-quotes, so escape your double quotes. +# +# It could be useful to turn this into a macro which extracts the +# value of any macro. +m4_define([_BOOST_SED_CPP], +[AC_LANG_PREPROC_REQUIRE()dnl +AC_REQUIRE([AC_PROG_SED])dnl +AC_LANG_CONFTEST([AC_LANG_SOURCE([[$2]])]) +AS_IF([dnl eval is necessary to expand ac_cpp. +dnl Ultrix and Pyramid sh refuse to redirect output of eval, so use subshell. +dnl Beware of Windows end-of-lines, for instance if we are running +dnl some Windows programs under Wine. In that case, boost/version.hpp +dnl is certainly using "\r\n", but the regular Unix shell will only +dnl strip `\n' with backquotes, not the `\r'. This results in +dnl boost_cv_lib_version='1_37\r' for instance, which breaks +dnl everything else. +dnl Cannot use 'dnl' after [$4] because a trailing dnl may break AC_CACHE_CHECK +(eval "$ac_cpp conftest.$ac_ext") 2>&AS_MESSAGE_LOG_FD | + tr -d '\r' | + $SED -n -e "$1" >conftest.i 2>&1], + [$3], + [$4]) +rm -rf conftest* +])# AC_EGREP_CPP + + + +# BOOST_REQUIRE([VERSION], [ACTION-IF-NOT-FOUND]) +# ----------------------------------------------- +# Look for Boost. If version is given, it must either be a literal of the form +# "X.Y.Z" where X, Y and Z are integers (the ".Z" part being optional) or a +# variable "$var". +# Defines the value BOOST_CPPFLAGS. This macro only checks for headers with +# the required version, it does not check for any of the Boost libraries. +# On # success, defines HAVE_BOOST. On failure, calls the optional +# ACTION-IF-NOT-FOUND action if one was supplied. +# Otherwise aborts with an error message. +AC_DEFUN([BOOST_REQUIRE], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_PROG_GREP])dnl +echo "$as_me: this is boost.m4[]_BOOST_SERIAL" >&AS_MESSAGE_LOG_FD +boost_save_IFS=$IFS +boost_version_req=$1 +IFS=. +set x $boost_version_req 0 0 0 +IFS=$boost_save_IFS +shift +boost_version_req=`expr "$[1]" '*' 100000 + "$[2]" '*' 100 + "$[3]"` +boost_version_req_string=$[1].$[2].$[3] +AC_ARG_WITH([boost], + [AS_HELP_STRING([--with-boost=DIR], + [prefix of Boost $1 @<:@guess@:>@])])dnl +AC_ARG_VAR([BOOST_ROOT],[Location of Boost installation])dnl +# If BOOST_ROOT is set and the user has not provided a value to +# --with-boost, then treat BOOST_ROOT as if it the user supplied it. +if test x"$BOOST_ROOT" != x; then + if test x"$with_boost" = x; then + AC_MSG_NOTICE([Detected BOOST_ROOT; continuing with --with-boost=$BOOST_ROOT]) + with_boost=$BOOST_ROOT + else + AC_MSG_NOTICE([Detected BOOST_ROOT=$BOOST_ROOT, but overridden by --with-boost=$with_boost]) + fi +fi +AC_SUBST([DISTCHECK_CONFIGURE_FLAGS], + ["$DISTCHECK_CONFIGURE_FLAGS '--with-boost=$with_boost'"])dnl +boost_save_CPPFLAGS=$CPPFLAGS + AC_CACHE_CHECK([for Boost headers version >= $boost_version_req_string], + [boost_cv_inc_path], + [boost_cv_inc_path=no +AC_LANG_PUSH([C++])dnl +m4_pattern_allow([^BOOST_VERSION$])dnl + AC_LANG_CONFTEST([AC_LANG_PROGRAM([[#include +#if !defined BOOST_VERSION +# error BOOST_VERSION is not defined +#elif BOOST_VERSION < $boost_version_req +# error Boost headers version < $boost_version_req +#endif +]])]) + # If the user provided a value to --with-boost, use it and only it. + case $with_boost in #( + ''|yes) set x '' /opt/local/include /usr/local/include /opt/include \ + /usr/include C:/Boost/include;; #( + *) set x "$with_boost/include" "$with_boost";; + esac + shift + for boost_dir + do + # Without --layout=system, Boost (or at least some versions) installs + # itself in /include/boost-. This inner loop helps to + # find headers in such directories. + # + # Any ${boost_dir}/boost-x_xx directories are searched in reverse version + # order followed by ${boost_dir}. The final '.' is a sentinel for + # searching $boost_dir" itself. Entries are whitespace separated. + # + # I didn't indent this loop on purpose (to avoid over-indented code) + boost_layout_system_search_list=`cd "$boost_dir" 2>/dev/null \ + && ls -1 | "${GREP}" '^boost-' | sort -rn -t- -k2 \ + && echo .` + for boost_inc in $boost_layout_system_search_list + do + if test x"$boost_inc" != x.; then + boost_inc="$boost_dir/$boost_inc" + else + boost_inc="$boost_dir" # Uses sentinel in boost_layout_system_search_list + fi + if test x"$boost_inc" != x; then + # We are going to check whether the version of Boost installed + # in $boost_inc is usable by running a compilation that + # #includes it. But if we pass a -I/some/path in which Boost + # is not installed, the compiler will just skip this -I and + # use other locations (either from CPPFLAGS, or from its list + # of system include directories). As a result we would use + # header installed on the machine instead of the /some/path + # specified by the user. So in that precise case (trying + # $boost_inc), make sure the version.hpp exists. + # + # Use test -e as there can be symlinks. + test -e "$boost_inc/boost/version.hpp" || continue + CPPFLAGS="$CPPFLAGS -I$boost_inc" + fi + AC_COMPILE_IFELSE([], [boost_cv_inc_path=yes], [boost_cv_version=no]) + if test x"$boost_cv_inc_path" = xyes; then + if test x"$boost_inc" != x; then + boost_cv_inc_path=$boost_inc + fi + break 2 + fi + done + done +AC_LANG_POP([C++])dnl + ]) + case $boost_cv_inc_path in #( + no) + boost_errmsg="cannot find Boost headers version >= $boost_version_req_string" + m4_if([$2], [], [AC_MSG_ERROR([$boost_errmsg])], + [AC_MSG_NOTICE([$boost_errmsg])]) + $2 + ;;#( + yes) + BOOST_CPPFLAGS= + ;;#( + *) + AC_SUBST([BOOST_CPPFLAGS], ["-I$boost_cv_inc_path"])dnl + ;; + esac + if test x"$boost_cv_inc_path" != xno; then + AC_DEFINE([HAVE_BOOST], [1], + [Defined if the requested minimum BOOST version is satisfied]) + AC_CACHE_CHECK([for Boost's header version], + [boost_cv_lib_version], + [m4_pattern_allow([^BOOST_LIB_VERSION$])dnl + _BOOST_SED_CPP([/^boost-lib-version = /{s///;s/\"//g;p;q;}], + [#include +boost-lib-version = BOOST_LIB_VERSION], + [boost_cv_lib_version=`cat conftest.i`])]) + # e.g. "134" for 1_34_1 or "135" for 1_35 + boost_major_version=`echo "$boost_cv_lib_version" | sed 's/_//;s/_.*//'` + case $boost_major_version in #( + '' | *[[!0-9]]*) + AC_MSG_ERROR([invalid value: boost_major_version=$boost_major_version]) + ;; + esac +fi +CPPFLAGS=$boost_save_CPPFLAGS +])# BOOST_REQUIRE + +# BOOST_STATIC() +# -------------- +# Add the "--enable-static-boost" configure argument. If this argument is given +# on the command line, static versions of the libraries will be looked up. +AC_DEFUN([BOOST_STATIC], + [AC_ARG_ENABLE([static-boost], + [AS_HELP_STRING([--enable-static-boost], + [Prefer the static boost libraries over the shared ones [no]])], + [enable_static_boost=yes], + [enable_static_boost=no])])# BOOST_STATIC + +# BOOST_FIND_HEADER([HEADER-NAME], [ACTION-IF-NOT-FOUND], [ACTION-IF-FOUND]) +# -------------------------------------------------------------------------- +# Wrapper around AC_CHECK_HEADER for Boost headers. Useful to check for +# some parts of the Boost library which are only made of headers and don't +# require linking (such as Boost.Foreach). +# +# Default ACTION-IF-NOT-FOUND: Fail with a fatal error unless Boost couldn't be +# found in the first place, in which case by default a notice is issued to the +# user. Presumably if we haven't died already it's because it's OK to not have +# Boost, which is why only a notice is issued instead of a hard error. +# +# Default ACTION-IF-FOUND: define the preprocessor symbol HAVE_ in +# case of success # (where HEADER-NAME is written LIKE_THIS, e.g., +# HAVE_BOOST_FOREACH_HPP). +AC_DEFUN([BOOST_FIND_HEADER], +[AC_REQUIRE([BOOST_REQUIRE])dnl +if test x"$boost_cv_inc_path" = xno; then + m4_default([$2], [AC_MSG_NOTICE([Boost not available, not searching for $1])]) +else +AC_LANG_PUSH([C++])dnl +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +AC_CHECK_HEADER([$1], + [m4_default([$3], [AC_DEFINE(AS_TR_CPP([HAVE_$1]), [1], + [Define to 1 if you have <$1>])])], + [m4_default([$2], [AC_MSG_ERROR([cannot find $1])])]) +CPPFLAGS=$boost_save_CPPFLAGS +AC_LANG_POP([C++])dnl +fi +])# BOOST_FIND_HEADER + + +# BOOST_FIND_LIB([LIB-NAME], [PREFERRED-RT-OPT], [HEADER-NAME], [CXX-TEST], +# [CXX-PROLOGUE]) +# ------------------------------------------------------------------------- +# Look for the Boost library LIB-NAME (e.g., LIB-NAME = `thread', for +# libboost_thread). Check that HEADER-NAME works and check that +# libboost_LIB-NAME can link with the code CXX-TEST. The optional argument +# CXX-PROLOGUE can be used to include some C++ code before the `main' +# function. +# +# Invokes BOOST_FIND_HEADER([HEADER-NAME]) (see above). +# +# Boost libraries typically come compiled with several flavors (with different +# runtime options) so PREFERRED-RT-OPT is the preferred suffix. A suffix is one +# or more of the following letters: sgdpn (in that order). s = static +# runtime, d = debug build, g = debug/diagnostic runtime, p = STLPort build, +# n = (unsure) STLPort build without iostreams from STLPort (it looks like `n' +# must always be used along with `p'). Additionally, PREFERRED-RT-OPT can +# start with `mt-' to indicate that there is a preference for multi-thread +# builds. Some sample values for PREFERRED-RT-OPT: (nothing), mt, d, mt-d, gdp +# ... If you want to make sure you have a specific version of Boost +# (eg, >= 1.33) you *must* invoke BOOST_REQUIRE before this macro. +AC_DEFUN([BOOST_FIND_LIB], +[AC_REQUIRE([BOOST_REQUIRE])dnl +AC_REQUIRE([_BOOST_FIND_COMPILER_TAG])dnl +AC_REQUIRE([BOOST_STATIC])dnl +AC_REQUIRE([_BOOST_GUESS_WHETHER_TO_USE_MT])dnl +if test x"$boost_cv_inc_path" = xno; then + AC_MSG_NOTICE([Boost not available, not searching for the Boost $1 library]) +else +dnl The else branch is huge and wasn't intended on purpose. +AC_LANG_PUSH([C++])dnl +AS_VAR_PUSHDEF([Boost_lib], [boost_cv_lib_$1])dnl +AS_VAR_PUSHDEF([Boost_lib_LDFLAGS], [boost_cv_lib_$1_LDFLAGS])dnl +AS_VAR_PUSHDEF([Boost_lib_LDPATH], [boost_cv_lib_$1_LDPATH])dnl +AS_VAR_PUSHDEF([Boost_lib_LIBS], [boost_cv_lib_$1_LIBS])dnl +BOOST_FIND_HEADER([$3]) +boost_save_CPPFLAGS=$CPPFLAGS +CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS" +# Now let's try to find the library. The algorithm is as follows: first look +# for a given library name according to the user's PREFERRED-RT-OPT. For each +# library name, we prefer to use the ones that carry the tag (toolset name). +# Each library is searched through the various standard paths were Boost is +# usually installed. If we can't find the standard variants, we try to +# enforce -mt (for instance on MacOSX, libboost_threads.dylib doesn't exist +# but there's -obviously- libboost_threads-mt.dylib). +AC_CACHE_CHECK([for the Boost $1 library], [Boost_lib], + [Boost_lib=no + case "$2" in #( + mt | mt-) boost_mt=-mt; boost_rtopt=;; #( + mt* | mt-*) boost_mt=-mt; boost_rtopt=`expr "X$2" : 'Xmt-*\(.*\)'`;; #( + *) boost_mt=; boost_rtopt=$2;; + esac + if test $enable_static_boost = yes; then + boost_rtopt="s$boost_rtopt" + fi + # Find the proper debug variant depending on what we've been asked to find. + case $boost_rtopt in #( + *d*) boost_rt_d=$boost_rtopt;; #( + *[[sgpn]]*) # Insert the `d' at the right place (in between `sg' and `pn') + boost_rt_d=`echo "$boost_rtopt" | sed 's/\(s*g*\)\(p*n*\)/\1\2/'`;; #( + *) boost_rt_d='-d';; + esac + # If the PREFERRED-RT-OPT are not empty, prepend a `-'. + test -n "$boost_rtopt" && boost_rtopt="-$boost_rtopt" + $boost_guess_use_mt && boost_mt=-mt + # Look for the abs path the static archive. + # $libext is computed by Libtool but let's make sure it's non empty. + test -z "$libext" && + AC_MSG_ERROR([the libext variable is empty, did you invoke Libtool?]) + boost_save_ac_objext=$ac_objext + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include <$3> +$5], [$4])]) +dnl Optimization hacks: compiling C++ is slow, especially with Boost. What +dnl we're trying to do here is guess the right combination of link flags +dnl (LIBS / LDFLAGS) to use a given library. This can take several +dnl iterations before it succeeds and is thus *very* slow. So what we do +dnl instead is that we compile the code first (and thus get an object file, +dnl typically conftest.o). Then we try various combinations of link flags +dnl until we succeed to link conftest.o in an executable. The problem is +dnl that the various TRY_LINK / COMPILE_IFELSE macros of Autoconf always +dnl remove all the temporary files including conftest.o. So the trick here +dnl is to temporarily change the value of ac_objext so that conftest.o is +dnl preserved accross tests. This is obviously fragile and I will burn in +dnl hell for not respecting Autoconf's documented interfaces, but in the +dnl mean time, it optimizes the macro by a factor of 5 to 30. +dnl Another small optimization: the first argument of AC_COMPILE_IFELSE left +dnl empty because the test file is generated only once above (before we +dnl start the for loops). + AC_COMPILE_IFELSE([], + [ac_objext=do_not_rm_me_plz], + [AC_MSG_ERROR([cannot compile a test that uses Boost $1])]) + ac_objext=$boost_save_ac_objext + boost_failed_libs= +# Don't bother to ident the 6 nested for loops, only the 2 innermost ones +# matter. +for boost_tag_ in -$boost_cv_lib_tag ''; do +for boost_ver_ in -$boost_cv_lib_version ''; do +for boost_mt_ in $boost_mt -mt ''; do +for boost_rtopt_ in $boost_rtopt '' -d; do + for boost_lib in \ + boost_$1$boost_tag_$boost_mt_$boost_rtopt_$boost_ver_ \ + boost_$1$boost_tag_$boost_rtopt_$boost_ver_ \ + boost_$1$boost_tag_$boost_mt_$boost_ver_ \ + boost_$1$boost_tag_$boost_ver_ + do + # Avoid testing twice the same lib + case $boost_failed_libs in #( + *@$boost_lib@*) continue;; + esac + # If with_boost is empty, we'll search in /lib first, which is not quite + # right so instead we'll try to a location based on where the headers are. + boost_tmp_lib=$with_boost + test x"$with_boost" = x && boost_tmp_lib=${boost_cv_inc_path%/include} + for boost_ldpath in "$boost_tmp_lib/lib" '' \ + /opt/local/lib* /usr/local/lib* /opt/lib* /usr/lib* \ + "$with_boost" C:/Boost/lib /lib* + do + test -e "$boost_ldpath" || continue + boost_save_LDFLAGS=$LDFLAGS + # Are we looking for a static library? + case $boost_ldpath:$boost_rtopt_ in #( + *?*:*s*) # Yes (Non empty boost_ldpath + s in rt opt) + Boost_lib_LIBS="$boost_ldpath/lib$boost_lib.$libext" + test -e "$Boost_lib_LIBS" || continue;; #( + *) # No: use -lboost_foo to find the shared library. + Boost_lib_LIBS="-l$boost_lib";; + esac + boost_save_LIBS=$LIBS + LIBS="$Boost_lib_LIBS $LIBS" + test x"$boost_ldpath" != x && LDFLAGS="$LDFLAGS -L$boost_ldpath" +dnl First argument of AC_LINK_IFELSE left empty because the test file is +dnl generated only once above (before we start the for loops). + _BOOST_AC_LINK_IFELSE([], + [Boost_lib=yes], [Boost_lib=no]) + ac_objext=$boost_save_ac_objext + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + if test x"$Boost_lib" = xyes; then + # Check or used cached result of whether or not using -R or -rpath makes sense. + # Some implementations of ld, such as for Mac OSX, require -rpath but + # -R is the flag known to work on other systems. + # https://github.com/tsuna/boost.m4/issues/19 + AC_CACHE_VAL([boost_cv_rpath_link_ldflag], + [for boost_cv_rpath_link_ldflag in -Wl,-R, -Wl,-rpath,; do + LDFLAGS="$boost_save_LDFLAGS -L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + LIBS="$boost_save_LIBS $Boost_lib_LIBS" + _BOOST_AC_LINK_IFELSE([], + [boost_rpath_link_ldflag_found=yes + break], + [boost_rpath_link_ldflag_found=no]) + done + AS_IF([test "x$boost_rpath_link_ldflag_found" != "xyes"], + [AC_MSG_ERROR([Unable to determine whether to use -R or -rpath])]) + LDFLAGS=$boost_save_LDFLAGS + LIBS=$boost_save_LIBS + ]) + Boost_lib_LDFLAGS="-L$boost_ldpath $boost_cv_rpath_link_ldflag$boost_ldpath" + Boost_lib_LDPATH="$boost_ldpath" + break 6 + else + boost_failed_libs="$boost_failed_libs@$boost_lib@" + fi + done + done +done +done +done +done +rm -f conftest.$ac_objext +]) +case $Boost_lib in #( + no) _AC_MSG_LOG_CONFTEST + AC_MSG_ERROR([cannot find the flags to link with Boost $1]) + ;; +esac +AC_SUBST(AS_TR_CPP([BOOST_$1_LDFLAGS]), [$Boost_lib_LDFLAGS])dnl +AC_SUBST(AS_TR_CPP([BOOST_$1_LDPATH]), [$Boost_lib_LDPATH])dnl +AC_SUBST([BOOST_LDPATH], [$Boost_lib_LDPATH])dnl +AC_SUBST(AS_TR_CPP([BOOST_$1_LIBS]), [$Boost_lib_LIBS])dnl +CPPFLAGS=$boost_save_CPPFLAGS +AS_VAR_POPDEF([Boost_lib])dnl +AS_VAR_POPDEF([Boost_lib_LDFLAGS])dnl +AS_VAR_POPDEF([Boost_lib_LDPATH])dnl +AS_VAR_POPDEF([Boost_lib_LIBS])dnl +AC_LANG_POP([C++])dnl +fi +])# BOOST_FIND_LIB + + +# --------------------------------------- # +# Checks for the various Boost libraries. # +# --------------------------------------- # + +# List of boost libraries: http://www.boost.org/libs/libraries.htm +# The page http://beta.boost.org/doc/libs is useful: it gives the first release +# version of each library (among other things). + +# BOOST_DEFUN(LIBRARY, CODE) +# -------------------------- +# Define BOOST_ as a macro that runs CODE. +# +# Use indir to avoid the warning on underquoted macro name given to AC_DEFUN. +m4_define([BOOST_DEFUN], +[m4_indir([AC_DEFUN], + m4_toupper([BOOST_$1]), +[m4_pushdef([BOOST_Library], [$1])dnl +$2 +m4_popdef([BOOST_Library])dnl +]) +]) + +# BOOST_ARRAY() +# ------------- +# Look for Boost.Array +BOOST_DEFUN([Array], +[BOOST_FIND_HEADER([boost/array.hpp])]) + + +# BOOST_ASIO() +# ------------ +# Look for Boost.Asio (new in Boost 1.35). +BOOST_DEFUN([Asio], +[AC_REQUIRE([BOOST_SYSTEM])dnl +BOOST_FIND_HEADER([boost/asio.hpp])]) + + +# BOOST_BIND() +# ------------ +# Look for Boost.Bind +BOOST_DEFUN([Bind], +[BOOST_FIND_HEADER([boost/bind.hpp])]) + + +# BOOST_CHRONO() +# ------------------ +# Look for Boost.Chrono +BOOST_DEFUN([Chrono], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then +BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([chrono], [$1], + [boost/chrono.hpp], + [boost::chrono::thread_clock d;]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + AC_SUBST([BOOST_FILESYSTEM_LIBS], ["$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"]) +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS + +])# BOOST_CHRONO + + +# BOOST_CONVERSION() +# ------------------ +# Look for Boost.Conversion (cast / lexical_cast) +BOOST_DEFUN([Conversion], +[BOOST_FIND_HEADER([boost/cast.hpp]) +BOOST_FIND_HEADER([boost/lexical_cast.hpp]) +])# BOOST_CONVERSION + + +# BOOST_CRC() +# ----------- +# Look for Boost.CRC +BOOST_DEFUN([CRC], +[BOOST_FIND_HEADER([boost/crc.hpp]) +])# BOOST_CRC + + +# BOOST_DATE_TIME([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Date_Time. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Date_Time], +[BOOST_FIND_LIB([date_time], [$1], + [boost/date_time/posix_time/posix_time.hpp], + [boost::posix_time::ptime t;]) +])# BOOST_DATE_TIME + + +# BOOST_FILESYSTEM([PREFERRED-RT-OPT]) +# ------------------------------------ +# Look for Boost.Filesystem. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +# Do not check for boost/filesystem.hpp because this file was introduced in +# 1.34. +BOOST_DEFUN([Filesystem], +[# Do we have to check for Boost.System? This link-time dependency was +# added as of 1.35.0. If we have a version <1.35, we must not attempt to +# find Boost.System as it didn't exist by then. +if test $boost_major_version -ge 135; then +BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +boost_filesystem_save_LIBS=$LIBS +boost_filesystem_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +BOOST_FIND_LIB([filesystem], [$1], + [boost/filesystem/path.hpp], [boost::filesystem::path p;]) +if test $enable_static_boost = yes && test $boost_major_version -ge 135; then + AC_SUBST([BOOST_FILESYSTEM_LIBS], ["$BOOST_FILESYSTEM_LIBS $BOOST_SYSTEM_LIBS"]) +fi +LIBS=$boost_filesystem_save_LIBS +LDFLAGS=$boost_filesystem_save_LDFLAGS +])# BOOST_FILESYSTEM + + +# BOOST_FOREACH() +# --------------- +# Look for Boost.Foreach +BOOST_DEFUN([Foreach], +[BOOST_FIND_HEADER([boost/foreach.hpp])]) + + +# BOOST_FORMAT() +# -------------- +# Look for Boost.Format +# Note: we can't check for boost/format/format_fwd.hpp because the header isn't +# standalone. It can't be compiled because it triggers the following error: +# boost/format/detail/config_macros.hpp:88: error: 'locale' in namespace 'std' +# does not name a type +BOOST_DEFUN([Format], +[BOOST_FIND_HEADER([boost/format.hpp])]) + + +# BOOST_FUNCTION() +# ---------------- +# Look for Boost.Function +BOOST_DEFUN([Function], +[BOOST_FIND_HEADER([boost/function.hpp])]) + + +# BOOST_GEOMETRY() +# ---------------- +# Look for Boost.Geometry (new since 1.47.0). +BOOST_DEFUN([Geometry], +[BOOST_FIND_HEADER([boost/geometry.hpp]) +])# BOOST_GEOMETRY + + +# BOOST_GRAPH([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Graphs. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Graph], +[BOOST_FIND_LIB([graph], [$1], + [boost/graph/adjacency_list.hpp], [boost::adjacency_list<> g;]) +])# BOOST_GRAPH + + +# BOOST_IOSTREAMS([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.IOStreams. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([IOStreams], +[BOOST_FIND_LIB([iostreams], [$1], + [boost/iostreams/device/file_descriptor.hpp], + [boost::iostreams::file_descriptor fd; fd.close();]) +])# BOOST_IOSTREAMS + + +# BOOST_HASH() +# ------------ +# Look for Boost.Functional/Hash +BOOST_DEFUN([Hash], +[BOOST_FIND_HEADER([boost/functional/hash.hpp])]) + + +# BOOST_LAMBDA() +# -------------- +# Look for Boost.Lambda +BOOST_DEFUN([Lambda], +[BOOST_FIND_HEADER([boost/lambda/lambda.hpp])]) + + +# BOOST_LOG([PREFERRED-RT-OPT]) +# ----------------------------- +# Look for Boost.Log For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log], +[BOOST_FIND_LIB([log], [$1], + [boost/log/core/core.hpp], + [boost::log::attribute a; a.get_value();]) +])# BOOST_LOG + + +# BOOST_LOG_SETUP([PREFERRED-RT-OPT]) +# ----------------------------------- +# Look for Boost.Log For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Log_Setup], +[AC_REQUIRE([BOOST_LOG])dnl +BOOST_FIND_LIB([log_setup], [$1], + [boost/log/utility/init/from_settings.hpp], + [boost::log::basic_settings bs; bs.empty();]) +])# BOOST_LOG_SETUP + + +# BOOST_MATH() +# ------------ +# Look for Boost.Math +# TODO: This library isn't header-only but it comes in multiple different +# flavors that don't play well with BOOST_FIND_LIB (e.g, libboost_math_c99, +# libboost_math_c99f, libboost_math_c99l, libboost_math_tr1, +# libboost_math_tr1f, libboost_math_tr1l). This macro must be fixed to do the +# right thing anyway. +BOOST_DEFUN([Math], +[BOOST_FIND_HEADER([boost/math/special_functions.hpp])]) + + +# BOOST_MULTIARRAY() +# ------------------ +# Look for Boost.MultiArray +BOOST_DEFUN([MultiArray], +[BOOST_FIND_HEADER([boost/multi_array.hpp])]) + + +# BOOST_NUMERIC_CONVERSION() +# -------------------------- +# Look for Boost.NumericConversion (policy-based numeric conversion) +BOOST_DEFUN([Numeric_Conversion], +[BOOST_FIND_HEADER([boost/numeric/conversion/converter.hpp]) +])# BOOST_NUMERIC_CONVERSION + + +# BOOST_OPTIONAL() +# ---------------- +# Look for Boost.Optional +BOOST_DEFUN([Optional], +[BOOST_FIND_HEADER([boost/optional.hpp])]) + + +# BOOST_PREPROCESSOR() +# -------------------- +# Look for Boost.Preprocessor +BOOST_DEFUN([Preprocessor], +[BOOST_FIND_HEADER([boost/preprocessor/repeat.hpp])]) + + +# BOOST_UNORDERED() +# ----------------- +# Look for Boost.Unordered +BOOST_DEFUN([Unordered], +[BOOST_FIND_HEADER([boost/unordered_map.hpp])]) + + +# BOOST_UUID() +# ------------ +# Look for Boost.Uuid +BOOST_DEFUN([Uuid], +[BOOST_FIND_HEADER([boost/uuid/uuid.hpp])]) + + +# BOOST_PROGRAM_OPTIONS([PREFERRED-RT-OPT]) +# ----------------------------------------- +# Look for Boost.Program_options. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Program_Options], +[BOOST_FIND_LIB([program_options], [$1], + [boost/program_options.hpp], + [boost::program_options::options_description d("test");]) +])# BOOST_PROGRAM_OPTIONS + + + +# _BOOST_PYTHON_CONFIG(VARIABLE, FLAG) +# ------------------------------------ +# Save VARIABLE, and define it via `python-config --FLAG`. +# Substitute BOOST_PYTHON_VARIABLE. +m4_define([_BOOST_PYTHON_CONFIG], +[AC_SUBST([BOOST_PYTHON_$1], + [`python-config --$2 2>/dev/null`])dnl +boost_python_save_$1=$$1 +$1="$$1 $BOOST_PYTHON_$1"]) + + +# BOOST_PYTHON([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.Python. For the documentation of PREFERRED-RT-OPT, +# see the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Python], +[_BOOST_PYTHON_CONFIG([CPPFLAGS], [includes]) +_BOOST_PYTHON_CONFIG([LDFLAGS], [ldflags]) +_BOOST_PYTHON_CONFIG([LIBS], [libs]) +m4_pattern_allow([^BOOST_PYTHON_MODULE$])dnl +BOOST_FIND_LIB([python], [$1], + [boost/python.hpp], + [], [BOOST_PYTHON_MODULE(empty) {}]) +CPPFLAGS=$boost_python_save_CPPFLAGS +LDFLAGS=$boost_python_save_LDFLAGS +LIBS=$boost_python_save_LIBS +])# BOOST_PYTHON + + +# BOOST_REF() +# ----------- +# Look for Boost.Ref +BOOST_DEFUN([Ref], +[BOOST_FIND_HEADER([boost/ref.hpp])]) + + +# BOOST_REGEX([PREFERRED-RT-OPT]) +# ------------------------------- +# Look for Boost.Regex. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Regex], +[BOOST_FIND_LIB([regex], [$1], + [boost/regex.hpp], + [boost::regex exp("*"); boost::regex_match("foo", exp);]) +])# BOOST_REGEX + + +# BOOST_SERIALIZATION([PREFERRED-RT-OPT]) +# --------------------------------------- +# Look for Boost.Serialization. For the documentation of PREFERRED-RT-OPT, see +# the documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Serialization], +[BOOST_FIND_LIB([serialization], [$1], + [boost/archive/text_oarchive.hpp], + [std::ostream* o = 0; // Cheap way to get an ostream... + boost::archive::text_oarchive t(*o);]) +])# BOOST_SERIALIZATION + + +# BOOST_SIGNALS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Signals. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Signals], +[BOOST_FIND_LIB([signals], [$1], + [boost/signal.hpp], + [boost::signal s;]) +])# BOOST_SIGNALS + + +# BOOST_SIGNALS2() +# ---------------- +# Look for Boost.Signals2 (new since 1.39.0). +BOOST_DEFUN([Signals2], +[BOOST_FIND_HEADER([boost/signals2.hpp]) +])# BOOST_SIGNALS2 + + +# BOOST_SMART_PTR() +# ----------------- +# Look for Boost.SmartPtr +BOOST_DEFUN([Smart_Ptr], +[BOOST_FIND_HEADER([boost/scoped_ptr.hpp]) +BOOST_FIND_HEADER([boost/shared_ptr.hpp]) +]) + + +# BOOST_STATICASSERT() +# -------------------- +# Look for Boost.StaticAssert +BOOST_DEFUN([StaticAssert], +[BOOST_FIND_HEADER([boost/static_assert.hpp])]) + + +# BOOST_STRING_ALGO() +# ------------------- +# Look for Boost.StringAlgo +BOOST_DEFUN([String_Algo], +[BOOST_FIND_HEADER([boost/algorithm/string.hpp]) +]) + + +# BOOST_SYSTEM([PREFERRED-RT-OPT]) +# -------------------------------- +# Look for Boost.System. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. This library was introduced in Boost +# 1.35.0. +BOOST_DEFUN([System], +[BOOST_FIND_LIB([system], [$1], + [boost/system/error_code.hpp], + [boost::system::error_code e; e.clear();]) +])# BOOST_SYSTEM + + +# BOOST_TEST([PREFERRED-RT-OPT]) +# ------------------------------ +# Look for Boost.Test. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Test], +[m4_pattern_allow([^BOOST_CHECK$])dnl +BOOST_FIND_LIB([unit_test_framework], [$1], + [boost/test/unit_test.hpp], [BOOST_CHECK(2 == 2);], + [using boost::unit_test::test_suite; + test_suite* init_unit_test_suite(int argc, char ** argv) + { return NULL; }]) +])# BOOST_TEST + + +# BOOST_THREADS([PREFERRED-RT-OPT]) +# --------------------------------- +# Look for Boost.Thread. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +# FIXME: Provide an alias "BOOST_THREAD". +BOOST_DEFUN([Threads], +[dnl Having the pthread flag is required at least on GCC3 where +dnl boost/thread.hpp would complain if we try to compile without +dnl -pthread on GNU/Linux. +AC_REQUIRE([_BOOST_PTHREAD_FLAG])dnl +boost_threads_save_LIBS=$LIBS +boost_threads_save_LDFLAGS=$LDFLAGS +boost_threads_save_CPPFLAGS=$CPPFLAGS +# Link-time dependency from thread to system was added as of 1.49.0. +if test $boost_major_version -ge 149; then +BOOST_SYSTEM([$1]) +fi # end of the Boost.System check. +m4_pattern_allow([^BOOST_SYSTEM_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS" +# Yes, we *need* to put the -pthread thing in CPPFLAGS because with GCC3, +# boost/thread.hpp will trigger a #error if -pthread isn't used: +# boost/config/requires_threads.hpp:47:5: #error "Compiler threading support +# is not turned on. Please set the correct command line options for +# threading: -pthread (Linux), -pthreads (Solaris) or -mthreads (Mingw32)" +CPPFLAGS="$CPPFLAGS $boost_cv_pthread_flag" + +# When compiling for the Windows platform, the threads library is named +# differently. +case $host_os in + (*mingw*) + BOOST_FIND_LIB([thread_win32], [$1], + [boost/thread.hpp], [boost::thread t; boost::mutex m;]) + BOOST_THREAD_LDFLAGS=$BOOST_THREAD_WIN32_LDFLAGS + BOOST_THREAD_LDPATH=$BOOST_THREAD_WIN32_LDPATH + BOOST_THREAD_LIBS=$BOOST_THREAD_WIN32_LIBS + ;; + (*) + BOOST_FIND_LIB([thread], [$1], + [boost/thread.hpp], [boost::thread t; boost::mutex m;]) + ;; +esac + +BOOST_THREAD_LIBS="$BOOST_THREAD_LIBS $BOOST_SYSTEM_LIBS $boost_cv_pthread_flag" +BOOST_THREAD_LDFLAGS="$BOOST_SYSTEM_LDFLAGS" +BOOST_CPPFLAGS="$BOOST_CPPFLAGS $boost_cv_pthread_flag" +LIBS=$boost_threads_save_LIBS +LDFLAGS=$boost_threads_save_LDFLAGS +CPPFLAGS=$boost_threads_save_CPPFLAGS +])# BOOST_THREADS + + +# BOOST_TOKENIZER() +# ----------------- +# Look for Boost.Tokenizer +BOOST_DEFUN([Tokenizer], +[BOOST_FIND_HEADER([boost/tokenizer.hpp])]) + + +# BOOST_TRIBOOL() +# --------------- +# Look for Boost.Tribool +BOOST_DEFUN([Tribool], +[BOOST_FIND_HEADER([boost/logic/tribool_fwd.hpp]) +BOOST_FIND_HEADER([boost/logic/tribool.hpp]) +]) + + +# BOOST_TUPLE() +# ------------- +# Look for Boost.Tuple +BOOST_DEFUN([Tuple], +[BOOST_FIND_HEADER([boost/tuple/tuple.hpp])]) + + +# BOOST_TYPETRAITS() +# -------------------- +# Look for Boost.TypeTraits +BOOST_DEFUN([TypeTraits], +[BOOST_FIND_HEADER([boost/type_traits.hpp])]) + + +# BOOST_UTILITY() +# --------------- +# Look for Boost.Utility (noncopyable, result_of, base-from-member idiom, +# etc.) +BOOST_DEFUN([Utility], +[BOOST_FIND_HEADER([boost/utility.hpp])]) + + +# BOOST_VARIANT() +# --------------- +# Look for Boost.Variant. +BOOST_DEFUN([Variant], +[BOOST_FIND_HEADER([boost/variant/variant_fwd.hpp]) +BOOST_FIND_HEADER([boost/variant.hpp])]) + +# BOOST_POINTERCONTAINER() +# ------------------------ +# Look for Boost.PointerContainer +BOOST_DEFUN([Pointer_Container], +[BOOST_FIND_HEADER([boost/ptr_container/ptr_deque.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_list.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_vector.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_array.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_set.hpp]) +BOOST_FIND_HEADER([boost/ptr_container/ptr_map.hpp]) +])# BOOST_POINTERCONTAINER + +# BOOST_WAVE([PREFERRED-RT-OPT]) +# ------------------------------ +# NOTE: If you intend to use Wave/Spirit with thread support, make sure you +# call BOOST_THREADS first. +# Look for Boost.Wave. For the documentation of PREFERRED-RT-OPT, see the +# documentation of BOOST_FIND_LIB above. +BOOST_DEFUN([Wave], +[AC_REQUIRE([BOOST_FILESYSTEM])dnl +AC_REQUIRE([BOOST_DATE_TIME])dnl +boost_wave_save_LIBS=$LIBS +boost_wave_save_LDFLAGS=$LDFLAGS +m4_pattern_allow([^BOOST_((FILE)?SYSTEM|DATE_TIME|THREAD)_(LIBS|LDFLAGS)$])dnl +LIBS="$LIBS $BOOST_SYSTEM_LIBS $BOOST_FILESYSTEM_LIBS $BOOST_DATE_TIME_LIBS \ +$BOOST_THREAD_LIBS" +LDFLAGS="$LDFLAGS $BOOST_SYSTEM_LDFLAGS $BOOST_FILESYSTEM_LDFLAGS \ +$BOOST_DATE_TIME_LDFLAGS $BOOST_THREAD_LDFLAGS" +BOOST_FIND_LIB([wave], [$1], + [boost/wave.hpp], + [boost::wave::token_id id; get_token_name(id);]) +LIBS=$boost_wave_save_LIBS +LDFLAGS=$boost_wave_save_LDFLAGS +])# BOOST_WAVE + + +# BOOST_XPRESSIVE() +# ----------------- +# Look for Boost.Xpressive (new since 1.36.0). +BOOST_DEFUN([Xpressive], +[BOOST_FIND_HEADER([boost/xpressive/xpressive.hpp])]) + + +# ----------------- # +# Internal helpers. # +# ----------------- # + + +# _BOOST_PTHREAD_FLAG() +# --------------------- +# Internal helper for BOOST_THREADS. Based on ACX_PTHREAD: +# http://autoconf-archive.cryp.to/acx_pthread.html +AC_DEFUN([_BOOST_PTHREAD_FLAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_LANG_PUSH([C++])dnl +AC_CACHE_CHECK([for the flags needed to use pthreads], [boost_cv_pthread_flag], +[ boost_cv_pthread_flag= + # The ordering *is* (sometimes) important. Some notes on the + # individual items follow: + # (none): in case threads are in libc; should be tried before -Kthread and + # other compiler flags to prevent continual compiler warnings + # -lpthreads: AIX (must check this before -lpthread) + # -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h) + # -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able) + # -llthread: LinuxThreads port on FreeBSD (also preferred to -pthread) + # -pthread: GNU Linux/GCC (kernel threads), BSD/GCC (userland threads) + # -pthreads: Solaris/GCC + # -mthreads: MinGW32/GCC, Lynx/GCC + # -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it + # doesn't hurt to check since this sometimes defines pthreads too; + # also defines -D_REENTRANT) + # ... -mt is also the pthreads flag for HP/aCC + # -lpthread: GNU Linux, etc. + # --thread-safe: KAI C++ + case $host_os in #( + *solaris*) + # On Solaris (at least, for some versions), libc contains stubbed + # (non-functional) versions of the pthreads routines, so link-based + # tests will erroneously succeed. (We need to link with -pthreads/-mt/ + # -lpthread.) (The stubs are missing pthread_cleanup_push, or rather + # a function called by this macro, so we could check for that, but + # who knows whether they'll stub that too in a future libc.) So, + # we'll just look for -pthreads and -lpthread first: + boost_pthread_flags="-pthreads -lpthread -mt -pthread";; #( + *) + boost_pthread_flags="-lpthreads -Kthread -kthread -llthread -pthread \ + -pthreads -mthreads -lpthread --thread-safe -mt";; + esac + # Generate the test file. + AC_LANG_CONFTEST([AC_LANG_PROGRAM([#include ], + [pthread_t th; pthread_join(th, 0); + pthread_attr_init(0); pthread_cleanup_push(0, 0); + pthread_create(0,0,0,0); pthread_cleanup_pop(0);])]) + for boost_pthread_flag in '' $boost_pthread_flags; do + boost_pthread_ok=false +dnl Re-use the test file already generated. + boost_pthreads__save_LIBS=$LIBS + LIBS="$LIBS $boost_pthread_flag" + AC_LINK_IFELSE([], + [if grep ".*$boost_pthread_flag" conftest.err; then + echo "This flag seems to have triggered warnings" >&AS_MESSAGE_LOG_FD + else + boost_pthread_ok=:; boost_cv_pthread_flag=$boost_pthread_flag + fi]) + LIBS=$boost_pthreads__save_LIBS + $boost_pthread_ok && break + done +]) +AC_LANG_POP([C++])dnl +])# _BOOST_PTHREAD_FLAG + + +# _BOOST_gcc_test(MAJOR, MINOR) +# ----------------------------- +# Internal helper for _BOOST_FIND_COMPILER_TAG. +m4_define([_BOOST_gcc_test], +["defined __GNUC__ && __GNUC__ == $1 && __GNUC_MINOR__ == $2 && !defined __ICC @ gcc$1$2"])dnl + + +# _BOOST_FIND_COMPILER_TAG() +# -------------------------- +# Internal. When Boost is installed without --layout=system, each library +# filename will hold a suffix that encodes the compiler used during the +# build. The Boost build system seems to call this a `tag'. +AC_DEFUN([_BOOST_FIND_COMPILER_TAG], +[AC_REQUIRE([AC_PROG_CXX])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_CACHE_CHECK([for the toolset name used by Boost for $CXX], [boost_cv_lib_tag], +[boost_cv_lib_tag=unknown +if test x$boost_cv_inc_path != xno; then + AC_LANG_PUSH([C++])dnl + # The following tests are mostly inspired by boost/config/auto_link.hpp + # The list is sorted to most recent/common to oldest compiler (in order + # to increase the likelihood of finding the right compiler with the + # least number of compilation attempt). + # Beware that some tests are sensible to the order (for instance, we must + # look for MinGW before looking for GCC3). + # I used one compilation test per compiler with a #error to recognize + # each compiler so that it works even when cross-compiling (let me know + # if you know a better approach). + # Known missing tags (known from Boost's tools/build/v2/tools/common.jam): + # como, edg, kcc, bck, mp, sw, tru, xlc + # I'm not sure about my test for `il' (be careful: Intel's ICC pre-defines + # the same defines as GCC's). + for i in \ + _BOOST_gcc_test(4, 8) \ + _BOOST_gcc_test(4, 7) \ + _BOOST_gcc_test(4, 6) \ + _BOOST_gcc_test(4, 5) \ + _BOOST_gcc_test(4, 4) \ + _BOOST_gcc_test(4, 3) \ + _BOOST_gcc_test(4, 2) \ + _BOOST_gcc_test(4, 1) \ + _BOOST_gcc_test(4, 0) \ + "defined __GNUC__ && __GNUC__ == 3 && !defined __ICC \ + && (defined WIN32 || defined WINNT || defined _WIN32 || defined __WIN32 \ + || defined __WIN32__ || defined __WINNT || defined __WINNT__) @ mgw" \ + _BOOST_gcc_test(3, 4) \ + _BOOST_gcc_test(3, 3) \ + "defined _MSC_VER && _MSC_VER >= 1500 @ vc90" \ + "defined _MSC_VER && _MSC_VER == 1400 @ vc80" \ + _BOOST_gcc_test(3, 2) \ + "defined _MSC_VER && _MSC_VER == 1310 @ vc71" \ + _BOOST_gcc_test(3, 1) \ + _BOOST_gcc_test(3, 0) \ + "defined __BORLANDC__ @ bcb" \ + "defined __ICC && (defined __unix || defined __unix__) @ il" \ + "defined __ICL @ iw" \ + "defined _MSC_VER && _MSC_VER == 1300 @ vc7" \ + _BOOST_gcc_test(2, 95) \ + "defined __MWERKS__ && __MWERKS__ <= 0x32FF @ cw9" \ + "defined _MSC_VER && _MSC_VER < 1300 && !defined UNDER_CE @ vc6" \ + "defined _MSC_VER && _MSC_VER < 1300 && defined UNDER_CE @ evc4" \ + "defined __MWERKS__ && __MWERKS__ <= 0x31FF @ cw8" + do + boost_tag_test=`expr "X$i" : 'X\([[^@]]*\) @ '` + boost_tag=`expr "X$i" : 'X[[^@]]* @ \(.*\)'` + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if $boost_tag_test +/* OK */ +#else +# error $boost_tag_test +#endif +]])], [boost_cv_lib_tag=$boost_tag; break], []) + done +AC_LANG_POP([C++])dnl + case $boost_cv_lib_tag in #( + # Some newer (>= 1.35?) versions of Boost seem to only use "gcc" as opposed + # to "gcc41" for instance. + *-gcc | *'-gcc ') :;; #( Don't re-add -gcc: it's already in there. + gcc*) + boost_tag_x= + case $host_os in #( + darwin*) + if test $boost_major_version -ge 136; then + # The `x' added in r46793 of Boost. + boost_tag_x=x + fi;; + esac + # We can specify multiple tags in this variable because it's used by + # BOOST_FIND_LIB that does a `for tag in -$boost_cv_lib_tag' ... + boost_cv_lib_tag="$boost_tag_x$boost_cv_lib_tag -${boost_tag_x}gcc" + ;; #( + unknown) + AC_MSG_WARN([[could not figure out which toolset name to use for $CXX]]) + boost_cv_lib_tag= + ;; + esac +fi])dnl end of AC_CACHE_CHECK +])# _BOOST_FIND_COMPILER_TAG + + +# _BOOST_GUESS_WHETHER_TO_USE_MT() +# -------------------------------- +# Compile a small test to try to guess whether we should favor MT (Multi +# Thread) flavors of Boost. Sets boost_guess_use_mt accordingly. +AC_DEFUN([_BOOST_GUESS_WHETHER_TO_USE_MT], +[# Check whether we do better use `mt' even though we weren't ask to. +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#if defined _REENTRANT || defined _MT || defined __MT__ +/* use -mt */ +#else +# error MT not needed +#endif +]])], [boost_guess_use_mt=:], [boost_guess_use_mt=false]) +]) + +# _BOOST_AC_LINK_IFELSE(PROGRAM, [ACTION-IF-TRUE], [ACTION-IF-FALSE]) +# ------------------------------------------------------------------- +# Fork of _AC_LINK_IFELSE that preserves conftest.o across calls. Fragile, +# will break when Autoconf changes its internals. Requires that you manually +# rm -f conftest.$ac_objext in between to really different tests, otherwise +# you will try to link a conftest.o left behind by a previous test. +# Used to aggressively optimize BOOST_FIND_LIB (see the big comment in this +# macro). +# +# Don't use "break" in the actions, as it would short-circuit some code +# this macro runs after the actions. +m4_define([_BOOST_AC_LINK_IFELSE], +[m4_ifvaln([$1], [AC_LANG_CONFTEST([$1])])dnl +rm -f conftest$ac_exeext +boost_save_ac_ext=$ac_ext +boost_use_source=: +# If we already have a .o, re-use it. We change $ac_ext so that $ac_link +# tries to link the existing object file instead of compiling from source. +test -f conftest.$ac_objext && ac_ext=$ac_objext && boost_use_source=false && + _AS_ECHO_LOG([re-using the existing conftest.$ac_objext]) +AS_IF([_AC_DO_STDERR($ac_link) && { + test -z "$ac_[]_AC_LANG_ABBREV[]_werror_flag" || + test ! -s conftest.err + } && test -s conftest$ac_exeext && { + test "$cross_compiling" = yes || + $as_executable_p conftest$ac_exeext +dnl FIXME: use AS_TEST_X instead when 2.61 is widespread enough. + }], + [$2], + [if $boost_use_source; then + _AC_MSG_LOG_CONFTEST + fi + $3]) +ac_objext=$boost_save_ac_objext +ac_ext=$boost_save_ac_ext +dnl Delete also the IPA/IPO (Inter Procedural Analysis/Optimization) +dnl information created by the PGI compiler (conftest_ipa8_conftest.oo), +dnl as it would interfere with the next link command. +rm -f core conftest.err conftest_ipa8_conftest.oo \ + conftest$ac_exeext m4_ifval([$1], [conftest.$ac_ext])[]dnl +])# _BOOST_AC_LINK_IFELSE + +# Local Variables: +# mode: autoconf +# End: diff --git a/src/Makefile.am b/src/Makefile.am new file mode 100644 index 0000000..ae311c6 --- /dev/null +++ b/src/Makefile.am @@ -0,0 +1,97 @@ +# Makefile.am -- automake script for the car plugin +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, +# 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, +# Inc. +# Copyright (C) 2013 Galois, Inc. +# +# This program is free software: you can redistribute it and/or modify it under +# the terms of the GNU General Public License as published by the Free Software +# Foundation, either version 3 of the License, or (at your option) any later +# version. +# +# This program is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this program. If not, see . +# +# To contact Galois, complete the Web form at +# or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, +# Oregon, 97204-1622. + +# We're building a library that gets loaded by dlopen, not a standard .so. +AM_LDFLAGS = \ + -avoid-version -module -shared -export-dynamic + +lib_LTLIBRARIES = libv_repExtAutomobile.la +libv_repExtAutomobile_la_SOURCES = \ + $(srcdir)/automobile.cpp \ + $(srcdir)/automobile.h \ + $(srcdir)/csv.cpp \ + $(srcdir)/csv.h \ + $(srcdir)/csv-inl.h \ + $(srcdir)/main.cpp \ + $(srcdir)/main.h \ + $(srcdir)/measurement.cpp \ + $(srcdir)/measurement.h \ + $(srcdir)/measurement-inl.h \ + $(srcdir)/noise.cpp \ + $(srcdir)/noise.h \ + $(srcdir)/noise-inl.h \ + $(srcdir)/vrep.cpp \ + $(srcdir)/vrep.h \ + $(srcdir)/vrep-inl.h \ + $(srcdir)/vrepFfi.cpp \ + $(srcdir)/vrepFfi.h \ + $(srcdir)/vrepFfi-inl.h +libv_repExtAutomobile_la_CPPFLAGS = \ + $(BOOST_CPPFLAGS) +libv_repExtAutomobile_la_CXXFLAGS = \ + -Wall \ + -Wextra \ + -pedantic \ + @VREP_CXXFLAGS@ +libv_repExtAutomobile_la_LDFLAGS = \ + $(AM_LDFLAGS) \ + -export-symbols-regex '^v_rep' \ + $(BOOST_FILESYSTEM_LDFLAGS) +libv_repExtAutomobile_la_LIBADD = \ + $(BOOST_FILESYSTEM_LIBS) + +# In addition to these sources, we also need to bundle a special object built +# from code in the V-REP distribution. Ideally, I'd just add that source file +# to 'libv_repExtAutomobile_la_SOURCES', but it's not exactly +# standards-compliant and generates a ton of warnings. To get around this, use +# per-object flags emulation (see "Per-Object Flags Emulation" in the Automake +# manual). +libv_repExtAutomobile_la_LIBADD += libv_repLib.la +noinst_LTLIBRARIES = libv_repLib.la +libv_repLib_la_SOURCES = @VREP@/programming/common/v_repLib.cpp +libv_repLib_la_CXXFLAGS = @VREP_CXXFLAGS@ + +# Override install and uninstall targets to stick the libraries in the V-REP +# directory. +install-libLTLIBRARIES: $(lib_LTLIBRARIES) + @$(NORMAL_INSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + list2=; for p in $$list; do \ + if test -f $$p; then \ + list2="$$list2 $$p"; \ + else :; fi; \ + done; \ + test -z "$$list2" || { \ + echo " $(MKDIR_P) '$(VREP)'"; \ + $(MKDIR_P) "$(VREP)" || exit 1; \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install --no-warn $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(VREP)'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install --no-warn $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(VREP)"; \ + } +uninstall-libLTLIBRARIES: + @$(NORMAL_UNINSTALL) + @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ + for p in $$list; do \ + $(am__strip_dir) \ + echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(VREP)/$$f'"; \ + $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(VREP)/$$f"; \ + done diff --git a/src/automobile.cpp b/src/automobile.cpp new file mode 100644 index 0000000..365c96b --- /dev/null +++ b/src/automobile.cpp @@ -0,0 +1,403 @@ +/* automobile.cpp -- recording data about the car + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +/* This module assumes only one car is recording data at once. Thus, it follows + * a singleton object pattern. To keep everything a bit simpler, the state + * variables live in an anonymous namespace, and the functions simply mutate + * them as appropriate. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "automobile.h" +#include "noise.h" +#include "vrepFfi.h" + +#ifndef HAVE_CXX11_INITIALIZER_LISTS +# include +# include +#endif + + +namespace { + + // Paths to the output files + namespace path { + + std::string dataDir = "/tmp"; + + const std::string groundDir = "/ground"; + const std::string noisyDir = "/noisy"; + + const std::string properties = "/properties.csv"; + const std::string sensor = "/slam_sensor.csv"; + const std::string pose = "/slam_gps.csv"; + const std::string control = "/slam_control.csv"; + const std::string laser = "/slam_laser.csv"; + + } + + // Run specifications + struct Properties : public csv::Datum { + inline Properties(float L, float h, float a, float b, float theta0) + : L(L), h(h), a(a), b(b), theta0(theta0) { + } + inline virtual std::string csvHeader() const; + virtual std::string csv() const; + inline virtual unsigned int nCols() const; + // Distance between front and rear axles + float L; + // Distance between center of rear axle and encoder on left rear wheel + float h; + // Lengthwise distance between the rear axle and the lidar + float a; + // Widthwise distance between the rear axle and the lidar + float b; + // Initial angle of the car + float theta0; + }; + + // Individual sample records + struct Sample : public csv::Datum { + inline explicit Sample(const Pose &); + inline explicit Sample(const ControlSignals &); + inline explicit Sample(const LidarDatum &); + inline virtual std::string csvHeader() const; + inline virtual std::string csv() const; + inline virtual unsigned int nCols() const; + float time; + unsigned short sensorId; + }; + + + // Lidar specifications // + namespace laser { + + float MAX_DISTANCE = 10.; + float MAX_INTENSITY = 32768.; + + } + + + // Noise // + namespace noise { + + bool requested = false; + + // Dummy noise source that provides no noise + GaussianNoiseSource none(0., 0.); + + // Noise sources for the various measurements (can be set via Lua) + boost::optional> position; + boost::optional> angle; + boost::optional> speed; + boost::optional> steeringAngle; + boost::optional> distance; + boost::optional> intensity; + + } + + + // Prototypes // + + // Lua callbacks + typedef simVoid LuaFunc(SLuaCallBack *); + LuaFunc init; + LuaFunc setNoiseParameters; + LuaFunc savePose; + LuaFunc saveControls; + LuaFunc saveLaser; + + inline void savePropertiesFile(const Properties &); + + template + inline void saveDatum(const std::string &subdir, + const std::string &filename, const CsvDatum &); + + void outputDatum(const std::string &filePath, const csv::Datum &); + +} + + +// Registering // + +void registerLuaFunctions() { + vrep::exposeFunction< + std::string, + float, + float, + float, + float, + float, + float, + float>( + "simExtAutomobileInit", + "simExtAutomobileInit(string directoryName, number L, number h, number a, number b, number theta0, number max_distance, number max_intensity)", + init); + vrep::exposeFunction< + std::vector, // x and y + std::vector, // angle + std::vector, // speed + std::vector, // steering angle + std::vector, // distance + std::vector>( // intensity + "simExtAutomobileRequestNoise", + "simExtAutomobileRequestNoise(table2 xy, table2 angle, table2 speed, table2 steeringAngle, table2 distance, table2 intensity)", + setNoiseParameters); + vrep::exposeFunction( + "simExtAutomobileSavePose", + "simExtAutomobileSavePose(number simulationTime, number x, number y, number theta)", + savePose); + vrep::exposeFunction( + "simExtAutomobileSaveControls", + "simExtAutomobileSaveControls(number simulationTime, number speed, number steeringAngle)", + saveControls); + /* V-REP's depth sensor part has a maximum field of view narrower than 180 + * degrees. To compensate, we instead use two 90-degree depth sensors and + * combine the results here. */ + vrep::exposeFunction< + float, + std::vector, std::vector, // depths + std::vector, std::vector>( // grayscale images + "simExtAutomobileSaveLaserPair", + "simExtAutomobileSaveLaserPair(number simulationTime, table leftDepthBuffer, table rightDepthBuffer, table leftImage, table rightImage)", + saveLaser); +} + + +// Callbacks // +namespace { + + std::string Properties::csvHeader() const { +# ifdef HAVE_CXX11_INITIALIZER_LISTS + return csv::fromContainer( + std::vector {"L", "h", "a", "b", "InitialAngle"}); +# else + return csv::fromContainer( + makeList(nCols(), "L", "h", "a", "b", + "InitialAngle")); +# endif + } + + std::string Properties::csv() const { +# ifdef HAVE_CXX11_INITIALIZER_LISTS + return csv::fromContainer( + std::vector {L, h, a, b, theta0}); +# else + return csv::fromContainer( + makeList(nCols(), L, h, a, b, theta0)); +# endif + } + + unsigned int Properties::nCols() const { + return 5; + } + + Sample::Sample(const Pose &pose) + : time(pose.time), sensorId(1) { + } + + Sample::Sample(const ControlSignals &signals) + : time(signals.time), sensorId(2) { + } + + Sample::Sample(const LidarDatum &datum) + : time(datum.time), sensorId(3) { + } + + std::string Sample::csvHeader() const { + return "Time,Sensor"; + } + + std::string Sample::csv() const { + return std::to_string(time) + "," + std::to_string(sensorId); + } + + unsigned int Sample::nCols() const { + return 2; + } + + simVoid init(SLuaCallBack *const simCall) { + // Clean data from previous runs. + boost::filesystem::remove_all(path::dataDir + path::groundDir); + boost::filesystem::remove_all(path::dataDir + path::noisyDir); + boost::filesystem::remove(path::dataDir + path::properties); + // Save the passed directory as the base directory for the output. + vrep::LuaCall call(simCall); + path::dataDir = call.expectAtom(); + // Save the passed properties in the properties file. + const float L = call.expectAtom(); + const float h = call.expectAtom(); + const float a = call.expectAtom(); + const float b = call.expectAtom(); + const float theta0 = call.expectAtom(); + savePropertiesFile(Properties(L, h, a, b, theta0)); + // Save the maximum distance and intensity settings. + laser::MAX_DISTANCE = call.expectAtom(); + laser::MAX_INTENSITY = call.expectAtom(); + // Reset the noise settings. + noise::requested = false; + const std::array> *const, 6> sources = + {{&noise::position, &noise::angle, &noise::speed, + &noise::steeringAngle, &noise::intensity, &noise::distance}}; + for (boost::optional> *const source : sources) { + *source = boost::none; + } + } + + simVoid setNoiseParameters(SLuaCallBack *const simCall) { + vrep::LuaCall call(simCall); + const std::array> *const, 6> sources = + {{&noise::position, &noise::angle, &noise::speed, + &noise::steeringAngle, &noise::intensity, &noise::distance}}; + for (boost::optional> *const source : sources) { + *source = gaussian(call.expectTable()); + } + noise::requested = true; + } + + simVoid savePose(SLuaCallBack *const simCall) { + // Build the pose. + vrep::LuaCall call(simCall); + const float time = call.expectAtom(); + const float x = call.expectAtom(); + const float y = call.expectAtom(); + const float theta = call.expectAtom(); + const Pose pose(time, x, y, theta); + // Record it. + saveDatum(path::groundDir, path::pose, pose); + if (noise::requested) { + saveDatum(path::noisyDir, path::pose, + addNoise(pose, noise::position.get_value_or(noise::none), + noise::angle.get_value_or(noise::none))); + } + } + + simVoid saveControls(SLuaCallBack *const simCall) { + // Build the control systems object. + vrep::LuaCall call(simCall); + const float time = call.expectAtom(); + const float speed = call.expectAtom(); + const float angle = call.expectAtom(); + const ControlSignals signals(time, speed, angle); + // Record it. + saveDatum(path::groundDir, path::control, signals); + if (noise::requested) { + saveDatum(path::noisyDir, path::control, + addNoise(signals, noise::speed.get_value_or(noise::none), + noise::steeringAngle.get_value_or(noise::none))); + } + } + + simVoid saveLaser(SLuaCallBack *const simCall) { + // Get the arguments and reconstruct the full lidar measurements. + vrep::LuaCall call(simCall); + const float time = call.expectAtom(); + std::vector distance = call.expectTable(); + const std::vector distanceRight = call.expectTable(); + distance.insert(distance.end(), + distanceRight.begin(), distanceRight.end()); + std::vector image = call.expectTable(); + const std::vector imageRight = call.expectTable(); + image.insert(image.end(), imageRight.begin(), imageRight.end()); + // Process the lidar measurements. +# ifdef HAVE_CXX11_CLOSURES + std::for_each(distance.begin(), distance.end(), + [](float &d) { d *= laser::MAX_DISTANCE; }); + std::for_each(image.begin(), image.end(), + [](float &i) { i *= laser::MAX_INTENSITY; }); +# else + for (float &d : distance) { + d *= laser::MAX_DISTANCE; + } + for (float &i : image) { + i *= laser::MAX_INTENSITY; + } +# endif + // Build the lidar datum and record it. + const LidarDatum datum(time, distance, image); + saveDatum(path::groundDir, path::laser, datum); + if (noise::requested) { + saveDatum(path::noisyDir, path::laser, + addNoise(datum, noise::distance.get_value_or(noise::none), + noise::intensity.get_value_or(noise::none))); + } + } + + void savePropertiesFile(const Properties &properties) { + boost::filesystem::create_directories(path::dataDir); + outputDatum(path::dataDir + path::properties, properties); + } + + template + void saveDatum(const std::string &subdir, const std::string &filename, + const CsvDatum &datum) { + const std::string logDir = path::dataDir + subdir; + boost::filesystem::create_directories(logDir); + outputDatum(logDir + filename, datum); + outputDatum(logDir + path::sensor, Sample(datum)); + } + + void outputDatum(const std::string &filePath, const csv::Datum &datum) { + const std::string header = datum.csvHeader(); + std::fstream file(filePath, + std::ios::in | std::ios::out | std::ios::app); + // Ensure we're writing correctly-formatted data. + std::string firstLine; + std::getline(file, firstLine); + if (file.eof() && firstLine.empty()) { + // The file was empty, so write in the header. + file.clear(); + file << header << std::endl; + } else if (firstLine != header) { + /* The file was nonempty, but the first line did not match the + * expected header. This might occur if an external program + * modifies the file in between our writes, but more likely, we've + * got a bug somewhere that is causing us to write different data + * sets to the same file. */ + throw std::logic_error( + std::string("CSV header mismatch: expected `") + + header + + "', but got `" + + firstLine + + "'"); + } else { + /* The file was nonempty, and the headers matched what we expected. + * We're good to go. */ + } + // Write the datum. + file << datum.csv() << std::endl; + } + +} diff --git a/src/automobile.h b/src/automobile.h new file mode 100644 index 0000000..0d3d2c1 --- /dev/null +++ b/src/automobile.h @@ -0,0 +1,30 @@ +/* automobile.h -- recording data about the car + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_AUTOMOBILE_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_AUTOMOBILE_H + +#ifdef HAVE_CONFIG_H +# include +#endif + +void registerLuaFunctions(); + +#endif diff --git a/src/csv-inl.h b/src/csv-inl.h new file mode 100644 index 0000000..c1b7cb9 --- /dev/null +++ b/src/csv-inl.h @@ -0,0 +1,58 @@ +/* csv-inl.h -- CSV utilities + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_CSV_INL_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_CSV_INL_H + +namespace csv { + + template + std::string fromContainer(const SequenceContainer &columns) { + std::ostringstream line; + for (typename SequenceContainer::const_iterator col = columns.begin(); + col != columns.end(); + col++) { + if (col != columns.begin()) { + line << ","; + } + line << *col; + } + return line.str(); + } + +} + +#ifndef HAVE_CXX11_INITIALIZER_LISTS + + template + std::list makeList(typename std::list::size_type size, ...) { + std::list result; + va_list args; + va_start(args, size); + for (typename std::list::size_type i = 0; i < size; i++) { + result.push_back(va_arg(args, T)); + } + va_end(args); + return result; + } + +#endif + +#endif diff --git a/src/csv.cpp b/src/csv.cpp new file mode 100644 index 0000000..88d08b3 --- /dev/null +++ b/src/csv.cpp @@ -0,0 +1,48 @@ +/* csv.h -- CSV utilities + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifndef HAVE_CXX11_INITIALIZER_LISTS +# include +# include +# include +#endif + +#include "csv.h" + +#ifndef HAVE_CXX11_INITIALIZER_LISTS + + std::list makeList(typename std::list::size_type size, ...) { + std::list result; + va_list args; + va_start(args, size); + for (typename std::list::size_type i = 0; + i < static_cast::size_type>(size); + i++) { + result.push_back(va_arg(args, double)); + } + va_end(args); + return result; + } + +#endif diff --git a/src/csv.h b/src/csv.h new file mode 100644 index 0000000..fd46646 --- /dev/null +++ b/src/csv.h @@ -0,0 +1,71 @@ +/* csv.h -- CSV utilities + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_CSV_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_CSV_H + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#ifndef HAVE_CXX11_INITIALIZER_LISTS +# include +# include +#endif + +namespace csv { + + // Interface: Any datum which can be converted to a CSV string. + struct Datum { + virtual std::string csvHeader() const = 0; + virtual std::string csv() const = 0; + virtual unsigned int nCols() const = 0; + }; + + /* Converts a sequence of objects to a CSV string. It uses stringstreams + * internally, so all data in the sequence will get converted to strings + * using operator<<; however, no escaping will occur. */ + template + std::string fromContainer(const SequenceContainer &); + +} + +#ifndef HAVE_CXX11_INITIALIZER_LISTS + + /* Without C++11 initializer list syntax, creating containers to pass to + * csv::fromContainer is really ugly. This function makes it substantially + * nicer, at the cost of forcing you to manually specify the length of the + * container (an unfortunate varargs limitation). */ + template + std::list makeList(typename std::list::size_type, ...); + + /* floats get promoted to doubles in a va_list, so they need special + * handling. */ + template<> + std::list makeList(typename std::list::size_type, ...); + +#endif + +#include "csv-inl.h" + +#endif diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..6deb436 --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,137 @@ +/* main.cpp -- plugin entry points + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include +#include + +#include +#include + +#include "automobile.h" +#include "main.h" +#include "vrep.h" +#include "vrepFfi.h" + +namespace { + + const unsigned char PLUGIN_VERSION = 1; + + // The V-REP library that will get loaded at runtime + const std::string VREP_LIBRARY_NAME = "libv_rep.so"; + LIBRARY vrepLibrary; + + + // Prototypes // + + /* The library we think we're loading might not actually be the right + * library. */ + class BadLibraryError : public std::runtime_error { + public: + explicit inline BadLibraryError(); + }; + + // We might be using a too-old V-REP. + class TooOldVrepError : public std::runtime_error { + public: + explicit inline TooOldVrepError(const simInt version); + }; + + /* Loads the V-REP library and ensures it has the correct set of symbols. + * Throws 'std::exception' if an error occurs. */ + // This function is declared inline because it is only used once. + inline void loadAndValidateVrepLibrary(); + + /* Throws 'std::exception' if the current version of V-REP is strictly less + than the 'simInt' passed. */ + // This function is declared inline because it is only used once. + inline void requireVrepVersion(const simInt); +} + +unsigned char v_repStart(void *, int) { + try { + loadAndValidateVrepLibrary(); + // If we needed a specific version of V-REP, we'd check it here with + // 'requireVrepVersion'. + vrep::InterfaceLockGuard lockInterface; + // Register functions. + registerLuaFunctions(); + // Returning zero indicates a failure condition. + static_assert(PLUGIN_VERSION != 0, "Plugin version must be nonzero"); + return PLUGIN_VERSION; + } catch (const std::exception& error) { + // Loading the plugin failed. Return 0 to indicate failure. + return 0; + } +} + +void v_repEnd() { + unloadVrepLibrary(vrepLibrary); +} + +void *v_repMessage(int, int *, void *, int *) { + return nullptr; +} + +namespace { + + void loadAndValidateVrepLibrary() { + try { + // Load the V-REP library out of the V-REP directory. + const std::string vrepLibraryPath = + boost::filesystem::current_path().string() + + "/" + VREP_LIBRARY_NAME; + vrepLibrary = loadVrepLibrary(vrepLibraryPath.c_str()); + // Make sure we can actually get code out of the V-REP library. + if (getVrepProcAddresses(vrepLibrary) == 0) { + throw BadLibraryError(); + } + } catch (const std::exception& e) { + // Problems occurred loading the library; unload it before leaving. + unloadVrepLibrary(vrepLibrary); + throw e; + } + } + + void requireVrepVersion(const simInt expected) { + simInt actual; + VREP(simGetIntegerParameter(sim_intparam_program_version, &actual)); + if (actual < expected) { + throw TooOldVrepError(expected); + } + } + + BadLibraryError::BadLibraryError() + : std::runtime_error("could not find all required functions in " + + VREP_LIBRARY_NAME) { + } + + TooOldVrepError::TooOldVrepError(const simInt version) + : std::runtime_error("plugin requires V-REP >= " + + std::to_string(version)) { + } + +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..4960210 --- /dev/null +++ b/src/main.h @@ -0,0 +1,44 @@ +/* main.h -- main plugin interface + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_MAIN_H_ +#define PPAML_VREP_AUTOMOBILE_PLUGIN_MAIN_H_ + +#ifdef HAVE_CONFIG_H +# include +#endif + +/* This interface is defined by V-REP itself. See + * . */ + +#ifdef __cplusplus +extern "C" { +#endif + + unsigned char v_repStart(void *pointer, int integer); + void v_repEnd(); + void *v_repMessage(int message, int *auxiliary_data, void *custom_data, + int *reply_data); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/src/measurement-inl.h b/src/measurement-inl.h new file mode 100644 index 0000000..9762cd1 --- /dev/null +++ b/src/measurement-inl.h @@ -0,0 +1,62 @@ +/* measurement-inl.h -- data sets we gather + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_MEASUREMENT_INL_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_MEASUREMENT_INL_H + +std::string Pose::csvHeader() const { + return csvHeader_; +} + +std::string Pose::csv() const { +# ifdef HAVE_CXX11_INITIALIZER_LISTS + return csv::fromContainer(std::vector {time, y, x, theta}); +# else + return csv::fromContainer(makeList(nCols(), time, y, x, theta)); +# endif +} + +unsigned int Pose::nCols() const { + return 4; +} + +std::string ControlSignals::csvHeader() const { + return csvHeader_; +} + +std::string ControlSignals::csv() const { +# ifdef HAVE_CXX11_INITIALIZER_LISTS + return csv::fromContainer( + std::vector {time, speed, steeringAngle}); +# else + return csv::fromContainer( + makeList(nCols(), time, speed, steeringAngle)); +# endif +} + +unsigned int ControlSignals::nCols() const { + return 3; +} + +unsigned int LidarDatum::nCols() const { + return 1 + distance.size() + intensity.size(); +} + +#endif diff --git a/src/measurement.cpp b/src/measurement.cpp new file mode 100644 index 0000000..bcf20c3 --- /dev/null +++ b/src/measurement.cpp @@ -0,0 +1,68 @@ +/* measurement.cpp -- data sets we gather + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include + +#include "csv.h" +#include "measurement.h" + +const std::string Pose::csvHeader_ = "TimeGPS,GPSLat,GPSLon,Orientation"; + +const std::string ControlSignals::csvHeader_ = "Time_VS,Velocity,Steering"; + +std::string LidarDatum::csvHeader() const { + std::string result; + const std::string timeLaserHeader = "TimeLaser"; + const std::string distanceHeader = "Laser"; + const std::string intensityHeader = "Intensity"; + result.reserve(timeLaserHeader.size() + + distance.size() * (1 + distanceHeader.size()) + + intensity.size() * (1 + intensityHeader.size())); + result.append(timeLaserHeader); + for (std::vector::size_type i = 0; i < distance.size(); i++) { + result.append(","); + result.append(distanceHeader); + } + for (std::vector::size_type i = 0; i < intensity.size(); i++) { + result.append(","); + result.append(intensityHeader); + } + return result; +} + +std::string LidarDatum::csv() const { + std::string result = std::to_string(time); + /* Yes, there are double braces in the initializer on the next line. See + * . */ + const std::array, 2> dataSets = {{distance, intensity}}; + for (const std::vector &data : dataSets) { + if (! data.empty()) { + result.append(","); + result.append(csv::fromContainer(data)); + } + } + return result; +} diff --git a/src/measurement.h b/src/measurement.h new file mode 100644 index 0000000..bad199c --- /dev/null +++ b/src/measurement.h @@ -0,0 +1,93 @@ +/* measurement.h -- data sets we gather + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_MEASUREMENT_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_MEASUREMENT_H + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "csv.h" + +// Base class for time-series data +struct Datum { + inline Datum(float time) + : time(time) { + } + float time; +}; + + +// Datum definitions // + +class Pose : public Datum, public csv::Datum { +public: + inline Pose(float time, float x, float y, float theta) + : ::Datum(time), x(x), y(y), theta(theta) { + } + float x; + float y; + float theta; + inline virtual std::string csvHeader() const; + inline virtual std::string csv() const; + inline virtual unsigned int nCols() const; + +protected: + static const std::string csvHeader_; +}; + + +class ControlSignals : public Datum, public csv::Datum { +public: + inline ControlSignals(float time, float speed, float steeringAngle) + : ::Datum(time), speed(speed), steeringAngle(steeringAngle) { + } + float speed; + float steeringAngle; + inline virtual std::string csvHeader() const; + inline virtual std::string csv() const; + inline virtual unsigned int nCols() const; + +protected: + static const std::string csvHeader_; +}; + + +class LidarDatum : public Datum, public csv::Datum { +public: + inline LidarDatum(float time, std::vector distance, + std::vector intensity) + : ::Datum(time), distance(distance), intensity(intensity) { + } + std::vector distance; + std::vector intensity; + virtual std::string csvHeader() const; + inline virtual std::string csv() const; + inline virtual unsigned int nCols() const; +}; + + +#include "measurement-inl.h" + +#endif diff --git a/src/noise-inl.h b/src/noise-inl.h new file mode 100644 index 0000000..5013a3c --- /dev/null +++ b/src/noise-inl.h @@ -0,0 +1,51 @@ +/* noise-inl.h -- noisy data + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_NOISE_INL_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_NOISE_INL_H + +#ifdef HAVE_CONFIG_H +# include +#endif + +template +GaussianNoiseSource::GaussianNoiseSource(RealType mean, + RealType stddev) + : generator(), distribution(mean, stddev) { + generator.seed(std::random_device()()); +} + +template +RealType GaussianNoiseSource::get() { + return distribution(generator); +} + +GaussianNoiseSource gaussian(const std::vector params) { + if (params.size() != 2) { + throw std::invalid_argument(std::string() + + "expected two-element vector of distribution parameters " + + "(got " + std::to_string(params.size()) + "-element " + + "vector instead"); + } else { + return GaussianNoiseSource(params[0], params[1]); + } +} + +#endif diff --git a/src/noise.cpp b/src/noise.cpp new file mode 100644 index 0000000..bee0224 --- /dev/null +++ b/src/noise.cpp @@ -0,0 +1,73 @@ +/* noise.h -- noisy data + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#ifdef HAVE_CXX11_CLOSURES +# include +#endif + +#include "measurement.h" +#include "noise.h" + +Pose addNoise(const Pose &pose, + GaussianNoiseSource &positionNoise, + GaussianNoiseSource &angleNoise) { + Pose result = pose; + result.x += positionNoise.get(); + result.y += positionNoise.get(); + result.theta += angleNoise.get(); + return result; +} + +ControlSignals addNoise(const ControlSignals &signals, + GaussianNoiseSource &speedNoise, + GaussianNoiseSource &steeringAngleNoise) { + ControlSignals result = signals; + result.speed += speedNoise.get(); + result.steeringAngle += steeringAngleNoise.get(); + return result; +} + +LidarDatum addNoise(const LidarDatum &datum, + GaussianNoiseSource &distanceNoise, + GaussianNoiseSource &intensityNoise) { + LidarDatum result = datum; +# ifdef HAVE_CXX11_CLOSURES + std::for_each(result.distance.begin(), result.distance.end(), + [&distanceNoise](float &d) { + d += distanceNoise.get(); + }); + std::for_each(result.intensity.begin(), result.intensity.end(), + [&intensityNoise](float &i) { + i += intensityNoise.get(); + }); +# else + for (float &d : result.distance) { + d += distanceNoise.get(); + } + for (float &i : result.intensity) { + i += intensityNoise.get(); + } +# endif + return result; +} diff --git a/src/noise.h b/src/noise.h new file mode 100644 index 0000000..e0b9980 --- /dev/null +++ b/src/noise.h @@ -0,0 +1,72 @@ +/* noise.h -- noisy data + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_NOISE_H +#define PPAML_VREP_AUTOMOBILE_PLUGIN_NOISE_H + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include "csv.h" +#include "measurement.h" + + +// Noise sources // + +template +class GaussianNoiseSource { +public: + inline GaussianNoiseSource(RealType mean, RealType stddev); + inline RealType get(); + +private: + std::mt19937 generator; + std::normal_distribution distribution; +}; + +/* Convenience function to construct a GaussianNoiseSource from a + * two-element float vector representing mean and standard deviation. + * Throws a std::invalid_argument if the vector is of the wrong + * length. */ +inline GaussianNoiseSource gaussian(const std::vector); + + +// Noisy values // + +// Adds noise to a value. +Pose addNoise(const Pose &, GaussianNoiseSource &positionNoise, + GaussianNoiseSource &angleNoise); +ControlSignals addNoise(const ControlSignals &, + GaussianNoiseSource &speedNoise, + GaussianNoiseSource &steeringAngleNoise); +LidarDatum addNoise(const LidarDatum &, + GaussianNoiseSource &distanceNoise, + GaussianNoiseSource &intensityNoise); + + +#include "noise-inl.h" + +#endif diff --git a/src/vrep-inl.h b/src/vrep-inl.h new file mode 100644 index 0000000..84d8ef0 --- /dev/null +++ b/src/vrep-inl.h @@ -0,0 +1,118 @@ +/* vrep-inl.h -- convenience code to interface with V-REP + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_VREP_INL_H_ +#define PPAML_VREP_AUTOMOBILE_PLUGIN_VREP_INL_H_ + +namespace vrep { + + // class InterfaceLockGuard + + InterfaceLockGuard::InterfaceLockGuard() { + lock(); + } + + InterfaceLockGuard::InterfaceLockGuard(const InterfaceLockGuard &other) { + copyState(other); + } + + InterfaceLockGuard &InterfaceLockGuard::operator=( + const InterfaceLockGuard &other) { + copyState(other); + return *this; + } + + InterfaceLockGuard::InterfaceLockGuard(InterfaceLockGuard &&other) { + moveState(other); + } + + InterfaceLockGuard &InterfaceLockGuard::operator=( + InterfaceLockGuard &&other) { + moveState(other); + return *this; + } + + void InterfaceLockGuard::lock() { + VREP(simLockInterface(true)); + isLocked = true; + } + + void InterfaceLockGuard::unlock() { + VREP(simLockInterface(false)); + isLocked = false; + } + + + // class Error + + Error::Error(const std::string &whatArg) + : std::runtime_error(whatArg) { + } + + Error::Error(const char *whatArg) + : Error(std::string(whatArg)) { + } + + + // template class FunctionError + + template + FunctionError::FunctionError(const std::string &invocation, + const T result) + : Error("V-REP function invocation " + + invocation + + " failed, returning " + + std::to_string(result)) { + } + + template + FunctionError::FunctionError(const char *invocation, const T result) + : FunctionError(std::string(invocation), result) { + } + + + // template T checkFunction(T, const char[]) + + template + T checkFunction(T result, const char invocation[]) { + if (isSuccess(result)) { + return result; + } else { + throw vrep::FunctionError(invocation, result); + } + } + + + // template bool isSuccess(const T) + + template<> + bool isSuccess(const simInt val) { + return val != -1; + } + + template<> + bool isSuccess(const simVoid *const val) { + return val != nullptr; + } + +} + +#endif + diff --git a/src/vrep.cpp b/src/vrep.cpp new file mode 100644 index 0000000..2043b45 --- /dev/null +++ b/src/vrep.cpp @@ -0,0 +1,72 @@ +/* vrep.cpp -- convenience code to interface with V-REP + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include + +#include "vrep.h" + +namespace vrep { + + InterfaceLockGuard::~InterfaceLockGuard() noexcept { + if (isLocked) { + /* Throwing an exception from a destructor is a bad, bad idea. See + * /More Effective C++/ #14. */ + try { + unlock(); + } catch (const Error& error) { + /* Unlocking failed, so we're kind of screwed at this point. We + * can't even display a dialog to the user noting the failure, + * because the interface is locked! *sigh* Just give up and do + * nothing. */ + } + } + } + + void InterfaceLockGuard::copyState(const InterfaceLockGuard &other) { + if (isLocked) { + unlock(); + } + if (other.isLocked) { + lock(); + } else { + isLocked = false; + } + } + + void InterfaceLockGuard::moveState(InterfaceLockGuard &other) { + if (isLocked) { + unlock(); + } + if (other.isLocked) { + lock(); + other.unlock(); + } else { + isLocked = false; + } + } + +} diff --git a/src/vrep.h b/src/vrep.h new file mode 100644 index 0000000..7a1bac0 --- /dev/null +++ b/src/vrep.h @@ -0,0 +1,104 @@ +/* vrep.h -- convenience code to interface with V-REP + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_VREP_H_ +#define PPAML_VREP_AUTOMOBILE_PLUGIN_VREP_H_ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include +#include + +#include + +/* All the convenience code lives in the 'vrep' namespace to distinguish it from + * the actual V-REP functions, which all are prefixed with 'sim'. */ +namespace vrep { + + // A RAII wrapper for 'simLockInterface'. + class InterfaceLockGuard { + public: + inline InterfaceLockGuard(); + ~InterfaceLockGuard() noexcept; + // Copying + inline InterfaceLockGuard(const InterfaceLockGuard &); + inline InterfaceLockGuard &operator=(const InterfaceLockGuard &); + // Moving + inline InterfaceLockGuard(InterfaceLockGuard &&); + inline InterfaceLockGuard &operator=(InterfaceLockGuard &&); + + private: + inline void lock(); + inline void unlock(); + void copyState(const InterfaceLockGuard &); + void moveState(InterfaceLockGuard &); + + bool isLocked; + }; + + + // Error handling // + + // The class for all errors which occur when interfacing with V-REP. + class Error : public std::runtime_error { + public: + explicit inline Error(const std::string &whatArg); + explicit inline Error(const char *whatArg); + }; + + // An error signaling a failed V-REP function invocation. + template + class FunctionError : public Error { + public: + FunctionError(const std::string &invocation, const T result); + inline FunctionError(const char *invocation, const T result); + }; + +/* A nice macro to convert failed V-REP function invocations to + * 'FunctionError's. Simply wrap your V-REP function interface--e.g., + * + * simInt x = VREP(simGetIntegerParameter(foo, &bar)); + * + * --and you'll be off to the races. 'x' will be assigned the result of the + * invocation if and only if the invocation succeeded; otherwise, a + * 'FunctionError' describing the failed invocation will be thrown. + * + * This needs to be a macro so that it can include the code of the failed + * invocation itself. */ +#define VREP(invocation) vrep::checkFunction((invocation), #invocation) + + template + T checkFunction(T result, const char invocation[]); + + /* Returns 'true' iff the passed value signifies a successful V-REP function + * invocation. */ + template + inline bool isSuccess(const T); + template<> inline bool isSuccess(const simInt); + template<> inline bool isSuccess(const simVoid *); +} + +#include "vrep-inl.h" + +#endif diff --git a/src/vrepFfi-inl.h b/src/vrepFfi-inl.h new file mode 100644 index 0000000..554d954 --- /dev/null +++ b/src/vrepFfi-inl.h @@ -0,0 +1,133 @@ +/* vrepFfi-inl.h -- exposing functions to V-REP + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_VREPFFI_INL_H_ +#define PPAML_VREP_AUTOMOBILE_PLUGIN_VREPFFI_INL_H_ + +namespace vrep { + + namespace { + + // Converting a variadic template type to a Lua type list // + + std::forward_list toLuaTypes() { + return std::forward_list(); + } + + template + std::forward_list toLuaTypes() { + std::forward_list luaTypes = toLuaTypes(); + luaTypes.push_front(LuaType::id); + return luaTypes; + } + + template + std::forward_list toLuaTypes() { + std::forward_list luaTypes = toLuaTypes(); + luaTypes.push_front(LuaType::id); + return luaTypes; + } + + } + + + // Exposing C++ functions to Lua // + + template + void exposeFunction(const std::string name, const std::string callTips, + simVoid (*const f)(SLuaCallBack *)) { + // Compute the Lua signature. + std::vector luaTypes; + luaTypes.push_back(0); + for (int type : toLuaTypes()) { + luaTypes.push_back(type); + // We just added an argument. + luaTypes[0]++; + } + // Register the function with Lua. + VREP(simRegisterCustomLuaFunction(name.c_str(), callTips.c_str(), + luaTypes.data(), f)); + } + + + // Extracting Lua arguments from the callback structure // + + template + T LuaCall::expectAtom() { + ensureNextArgType(LuaType::id); + const T result = unsafeGetAtom(); + argIdx++; + return result; + } + + template + std::vector LuaCall::expectTable() { + ensureNextArgType(LuaType>::id); + const std::vector result = unsafeGetTable(); + argIdx++; + return result; + } + + template + std::vector LuaCall::unsafeGetTable() { + // Determine how long the table is. + size_t tableLen; + if (simCall->inputArgTypeAndSize[2 * argIdx] & sim_lua_arg_table) { + tableLen = simCall->inputArgTypeAndSize[2 * argIdx + 1]; + } else { + tableLen = 1; + } + // Build the result. + std::vector result(tableLen); + for (size_t i = 0; i < tableLen; i++) { + result[i] = unsafeGetAtom(); + } + return result; + } + + template<> + bool LuaCall::unsafeGetAtom() { + return *cursorBool++; + } + + template<> + int LuaCall::unsafeGetAtom() { + return *cursorInt++; + } + + template<> + float LuaCall::unsafeGetAtom() { + return *cursorFloat++; + } + + + // Error handling // + + MarshalingError::MarshalingError(const std::string &whatArg) + : Error(whatArg) { + } + + MarshalingError::MarshalingError(const char *whatArg) + : MarshalingError(std::string(whatArg)) { + } + +} + +#endif diff --git a/src/vrepFfi.cpp b/src/vrepFfi.cpp new file mode 100644 index 0000000..4641bbf --- /dev/null +++ b/src/vrepFfi.cpp @@ -0,0 +1,68 @@ +/* vrepFfi.cpp -- exposing functions to V-REP + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include + +#include "vrepFfi.h" + +namespace vrep { + + // Extracting Lua arguments from the callback structure // + + LuaCall::LuaCall(SLuaCallBack *simCall) + : simCall(simCall), argIdx(0), cursorBool(simCall->inputBool), + cursorInt(simCall->inputInt), cursorFloat(simCall->inputFloat), + cursorChar(simCall->inputChar) { + } + + void LuaCall::ensureNextArgType(const int expected) { + const int nextType = simCall->inputArgTypeAndSize[2 * argIdx]; + if (nextType != expected) { + throw MarshalingError("unexpected Lua argument (expected type " + + std::to_string(expected) + + ", got type " + + std::to_string(nextType) + + ")"); + } + } + + template<> + std::string LuaCall::unsafeGetAtom() { + // Determine how long the string is. Lua uses '@' as its sentinel. + size_t len; + simChar *sentinel = std::strchr(cursorChar, '@'); + if (sentinel) { + len = sentinel - cursorChar; + } else { + len = std::strlen(cursorChar); + } + // Build the 'std::string'. + const std::string result = std::string(cursorChar, len); + cursorChar += len + (sentinel ? 1 : 0); + return result; + } + +} diff --git a/src/vrepFfi.h b/src/vrepFfi.h new file mode 100644 index 0000000..0dbab1e --- /dev/null +++ b/src/vrepFfi.h @@ -0,0 +1,158 @@ +/* vrepFfi.h -- exposing functions to V-REP + * Copyright (C) 2013 Galois, Inc. + * + * This library is free software: you can redistribute it and/or modify it under + * the terms of the GNU General Public License as published by the Free Software + * Foundation, either version 3 of the License, or (at your option) any later + * version. + * + * This library is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS + * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more + * details. + * + * You should have received a copy of the GNU General Public License along with + * this library. If not, see . + * + * To contact Galois, complete the Web form at + * or write to Galois, Inc., 421 Southwest 6th Avenue, Suite 300, Portland, + * Oregon, 97204-1622. */ + +#ifndef PPAML_VREP_AUTOMOBILE_PLUGIN_VREPFFI_H_ +#define PPAML_VREP_AUTOMOBILE_PLUGIN_VREPFFI_H_ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include +#include +#include + +#include + +#include "vrep.h" + +namespace vrep { + + namespace { + + // C-Lua type equivalences // + + template + struct LuaTypeWrapper { + static const int id = idVal; + static inline T isNextArg(const SLuaCallBack *); + }; + + template + struct LuaType; + + template<> + struct LuaType + : public LuaTypeWrapper { + }; + + template<> + struct LuaType : public LuaTypeWrapper { + typedef simBool LuaT; + }; + + template<> + struct LuaType : public LuaTypeWrapper { + typedef simInt LuaT; + }; + + template<> + struct LuaType + : public LuaTypeWrapper { + typedef simFloat LuaT; + }; + + template<> + struct LuaType + : public LuaTypeWrapper { + typedef simChar LuaT; + }; + + template + struct LuaType> + : public LuaTypeWrapper, + sim_lua_arg_table | LuaType::id> { + typedef typename LuaType::LuaT LuaT; + }; + + + // Converting a variadic template type to a Lua type list // + + std::forward_list toLuaTypes(); + + template + std::forward_list toLuaTypes(); + + template + std::forward_list toLuaTypes(); + } + + + // Exposing C++ functions to Lua // + + template + void exposeFunction(const std::string name, const std::string callTips, + simVoid (*const f)(SLuaCallBack *)); + + + // Extracting Lua arguments from the callback structure // + + /* A class layered on 'SLuaCallBack' for handling calls from Lua into C++. + * Watch out--interacting with this class at all outside of a C++ function + * exposed to Lua will almost certainly cause undefined behavior! */ + class LuaCall { + public: + LuaCall(SLuaCallBack *); + + template + T expectAtom(); + + template + std::vector expectTable(); + + private: + void ensureNextArgType(const int expected); + + template + T unsafeGetAtom(); + + template + std::vector unsafeGetTable(); + + SLuaCallBack *const simCall; + size_t argIdx; + simBool *cursorBool; + simInt *cursorInt; + simFloat *cursorFloat; + simChar *cursorChar; + }; + template<> inline bool LuaCall::unsafeGetAtom(); + template<> inline int LuaCall::unsafeGetAtom(); + template<> inline float LuaCall::unsafeGetAtom(); + template<> std::string LuaCall::unsafeGetAtom(); + + + // Error handling // + + // An error signaling a failed marshal from Lua to C++. + class MarshalingError : public Error { + public: + explicit inline MarshalingError(const std::string &whatArg); + explicit inline MarshalingError(const char *whatArg); + }; + +} + +#include "vrepFfi-inl.h" + +#endif -- cgit v1.2.3