diff --git a/Examples/Environments/gridworld_demo.ikc b/Examples/Environments/gridworld_demo.ikc new file mode 100755 index 000000000..496e63f50 --- /dev/null +++ b/Examples/Environments/gridworld_demo.ikc @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/CannyEdgeDetector_test.ikc b/Examples/ImageProcessing/CannyEdgeDetector_test.ikc new file mode 100755 index 000000000..9a57e510f --- /dev/null +++ b/Examples/ImageProcessing/CannyEdgeDetector_test.ikc @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/ColorTransform_test.ikc b/Examples/ImageProcessing/ColorTransform_test.ikc new file mode 100755 index 000000000..d18f8b085 --- /dev/null +++ b/Examples/ImageProcessing/ColorTransform_test.ikc @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/Convolution_test.ikc b/Examples/ImageProcessing/Convolution_test.ikc new file mode 100755 index 000000000..73658b315 --- /dev/null +++ b/Examples/ImageProcessing/Convolution_test.ikc @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/EdgeDetectors_test.ikc b/Examples/ImageProcessing/EdgeDetectors_test.ikc new file mode 100755 index 000000000..c58b17ab1 --- /dev/null +++ b/Examples/ImageProcessing/EdgeDetectors_test.ikc @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/GaborFilter_test.ikc b/Examples/ImageProcessing/GaborFilter_test.ikc new file mode 100755 index 000000000..570cb61ed --- /dev/null +++ b/Examples/ImageProcessing/GaborFilter_test.ikc @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/GaussianEdgeDetector_test.ikc b/Examples/ImageProcessing/GaussianEdgeDetector_test.ikc new file mode 100755 index 000000000..d1b93b94a --- /dev/null +++ b/Examples/ImageProcessing/GaussianEdgeDetector_test.ikc @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/HarrisDetector_test.ikc b/Examples/ImageProcessing/HarrisDetector_test.ikc new file mode 100755 index 000000000..2324c1255 --- /dev/null +++ b/Examples/ImageProcessing/HarrisDetector_test.ikc @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/Morphology_test.ikc b/Examples/ImageProcessing/Morphology_test.ikc new file mode 100755 index 000000000..d1ba6ffec --- /dev/null +++ b/Examples/ImageProcessing/Morphology_test.ikc @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ImageProcessing/SobelEdgeDetector_test.ikc b/Examples/ImageProcessing/SobelEdgeDetector_test.ikc new file mode 100755 index 000000000..821863109 --- /dev/null +++ b/Examples/ImageProcessing/SobelEdgeDetector_test.ikc @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ikc-Features/batch.ikc b/Examples/ikc-Features/batch.ikc new file mode 100755 index 000000000..fb408b2b5 --- /dev/null +++ b/Examples/ikc-Features/batch.ikc @@ -0,0 +1,37 @@ + + + + + + This is an advanced example that illustrates how batch processing works in Ikaros + + This file will run five instances of Ikaros sequentially with the different + parameters set by the target attributes. As a result, five files will be created + and will each contain a sequence of numbers generated by a function generator with + different offset values. + + The batch elements defines attributes that will be set in the outer group and + subsequently inherited by modules defined within the group. In this example, + the module F will inherit the value of the attribute"offset" and the module OUT will + inherit the attribute "filename" + + To run this test, make sure that the execution runs in batch mode and stops by using + for example the following at the command line to stop after 100 ticks: + + IKAROS batch.ikc -B -s100 + + Otherwise Ikaros will run only the first instance of the batch in an endless loop. + + + + + + + + + + + + + + diff --git a/Examples/ikc-Features/double_randomizer.ikc b/Examples/ikc-Features/double_randomizer.ikc new file mode 100755 index 000000000..1b1e923f3 --- /dev/null +++ b/Examples/ikc-Features/double_randomizer.ikc @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ikc-Features/group.ikc b/Examples/ikc-Features/group.ikc new file mode 100755 index 000000000..0c10e66f1 --- /dev/null +++ b/Examples/ikc-Features/group.ikc @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Examples/ikc-Features/including_file.ikc b/Examples/ikc-Features/including_file.ikc new file mode 100755 index 000000000..6f8674b0a --- /dev/null +++ b/Examples/ikc-Features/including_file.ikc @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Licence.txt b/Licence.txt new file mode 100755 index 000000000..5b6e7c66c --- /dev/null +++ b/Licence.txt @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) 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 +this service 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 make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. 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. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute 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 and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +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 +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the 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 a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, 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. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE 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. + + 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 +convey 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 2 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, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision 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, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This 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 Library General +Public License instead of this License. diff --git a/README.md b/README.md new file mode 100755 index 000000000..0a6a0e5ad --- /dev/null +++ b/README.md @@ -0,0 +1,45 @@ +Ikaros ReadMe +============= + +Version 1.4 +----------- +This is the eleventh public distribution of the Ikaros kernel together with a number of functional modules. This version is mainly intended for potential developers and not for more general use. The current distribution includes versions for OX X, Linux and Windows. + +Installation instructions and other documentation can be found on the web site: + + http://www.ikaros-project.org/ + + +The Ikaros Project +------------------ +The Ikaros projected started in early 2001 and its goal is to develop an open infrastructure for system level modeling of the brain including databases of experimental data, computational models and functional brain data. The system makes heavy use of the emerging standards for Internet based information and makes all information accessible through an open web-based interface. + +The main components of the IKAROS systems are: + +- A platform independent simulation kernel +- A set of computational brain models +- A set of I/O modules for interfacing with data files and peripheral such as robots or video cameras +- Tools for building systems of interconnected models +- A plug-in architecture that allows new models to be added to the system +- A database with data from learning experiments that can be used for validation of the computational models. + +Further information on the project can be found at: + + http://www.ikaros-project.org/ + + +Distribution +------------ +This software can be downloaded from the Ikaros site: + + http://www.ikaros-project.org/ + +IKAROS is distributed under the GNU GPL licence. +See the file Licence.txt for further information. + + +Author +------ +Christian Balkenius +christian.balkenius@lucs.lu.se + diff --git a/Source/IKAROS.h b/Source/IKAROS.h new file mode 100755 index 000000000..e92301fb3 --- /dev/null +++ b/Source/IKAROS.h @@ -0,0 +1,489 @@ +// +// IKAROS.h Kernel code for the IKAROS project +// Version 1.3 +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created July 13, 2001 +// + +#ifndef IKAROS +#define IKAROS + + +#define VERSION "1.3" + +#include "IKAROS_System.h" +#include "Kernel/IKAROS_Timer.h" +#include "Kernel/IKAROS_Socket.h" +#include "Kernel/IKAROS_Utils.h" +#include "Kernel/IKAROS_Math.h" +#include "Kernel/IKAROS_Serial.h" +#include "Kernel/IKAROS_Threads.h" +#include "Kernel/IKAROS_XML.h" + +// Messages to use with Notify + +const int msg_fatal_error = 1; +const int msg_exception = 2; +const int msg_warning = 3; +const int msg_print = 4; +const int msg_end_of_file = 5; +const int msg_terminate = 6; +const int msg_verbose = 7; + +// Print modes for Notify + +const int print_silent = 0; +const int print_normal = msg_print; +const int print_verbose = msg_verbose; + +// Size constant + +const int unknown_size = -1; + +// Binding constants - type constants + +const int bind_float = 0; +const int bind_int = 1; +const int bind_bool = 2; +const int bind_list = 3; +const int bind_array = 4; +const int bind_matrix = 5; + + +class Module; +class Kernel; +class WebUI; + + + +// +// Parameter is used during the creation of a module to set internal values +// + + +class Parameter +{ +public: + Kernel * kernel; + XMLElement * xml; + + Parameter(Kernel * k, XMLElement * x) + { + kernel = k; + xml = x; + } + + ~Parameter() + { + } +}; + + + +// +// Binding is used to bind a name to a variable +// + +/* + Binding types: sent as + OUTPUT float ** [[]] + matrix float ** [[]] + float float * [[]] + int int * [[]] + bool bool * [[]] 0/1 + */ + +class Binding +{ +public: + Module * module; + const char * name; + void * value; + int size_x; // size for scalar [float, int, bool] = (0, 0) for array = (n, 1), for matrix = (n, m) + int size_y; + int type; + Binding * next; + + Binding(Module * m, const char * n, int t, void * v, int sx, int sy, Binding * nxt) : + module(m), name(n), value(v), size_x(sx), size_y(sy), type(t), next(nxt) + { } + + ~Binding() + { } +}; + + + +// +// Class is used to hold pointers to module creators +// + +typedef Module * (*ModuleCreator)(Parameter *); + + + +class ModuleClass +{ +private: + ModuleCreator module_creator; +public: + const char * name; + const char * path; + ModuleClass * next; + + ModuleClass(const char * n, ModuleCreator mc, const char * p, ModuleClass * nxt = NULL); + ~ModuleClass(); + + const char * GetClassPath(const char * class_name); + friend Module * CreateModule(ModuleClass * c, const char * class_name, const char * n, Parameter * p); // Return a module of class class_name initialized with parameters in p and attributes in a +}; + + + +// +// Module_IO is used internally by Module and Kernel to represent the input and output connections of a module +// + +class Module_IO +{ +public: + int sizex; // no of columns *** temporarily made public for WebUI *** + int sizey; // no of rows + float *** matrix; // matrix version of data; array of pointers to columns; Array of matrixes in 0.8.0 for delays +private: + Module_IO(Module_IO * nxt, Module * m, const char * n, int x=unknown_size, int y=1); // Create output from module m with name n and size x and y + ~Module_IO(); // Deletes the data + + void Allocate(); + void SetSize(int x, int y=1); + void DelayOutputs(); + + + Module_IO * next; + Module * module; + const char * name; + float ** data; // Array in 0.8.0 for delays + int size; // should equal sizex*sizey + int max_delay; // maximum number of arrays/matrices + + friend class Kernel; + friend class Connection; + friend class Module; + friend class WebUI; +}; + + + +// +// Module is the base class for all simulation modules +// + +class Module +{ +public: + const char * GetName(); // Get the name of the module assigned during creation + const char * GetFullName(); // Get the name of the module with all enclosing groups + const char * GetClassName(); + + long GetTickLength(); // Get length of tick in ms for real time mode + long GetTick(); + + float * GetInputArray(const char * name, bool required=true); // Get a pointer to the input array of this module with a certain name + float * GetOutputArray(const char * name, bool required=true); // Get a pointer to the output array of this module with a certain name + + float ** GetInputMatrix(const char * name, bool required=true); // Get a pointer to the input matrix of this module with a certain name + float ** GetOutputMatrix(const char * name, bool required=true); // Get a pointer to the output matrix of this module with a certain name + + int GetInputSize(const char * input_name); // Get the size of an input array (size_x * size_y if two-dimensional) + int GetInputSizeX(const char * name); // Get the horizontal size of an input array + int GetInputSizeY(const char * name); // Get the vertical size of an input array (1 if one-dimensional) + + int GetOutputSize(const char * name); // Get the size of an output array (size_x * size_y if two-dimensional) + int GetOutputSizeX(const char * name); // Get the horizontal size of an output array + int GetOutputSizeY(const char * name); // Get the vertical size of an output array (1 if one-dimensional) + + bool InputConnected(const char * name); // True if input receives at least one connection + bool OutputConnected(const char * name); // True if output is connected to at least one module + + virtual void SetSizes(); // Calculate and set the sizes of unknown output arrays (OVERRIDE IN SUBCLASSES) + virtual void Init() + {} // Init memory for internal data (OVERRIDE IN SUBCLASSES) + virtual void Tick() + {} // Update state of the module (OVERRIDE IN SUBCLASSES) + + void Notify(int msg); // Send message to the kernel (for example terminate or error, using constants defined above) + void Notify(int msg, const char *format, ...); // Send message to the kernel and print a massage to the user + +protected: + void AddInput(const char * name); + void AddOutput(const char * name, int size_x=unknown_size, int size_y=1); // Allocate output + void AddIOFromIKC(); + void SetOutputSize(const char * name, int size_x, int size_y=1); // Set the output size for an output of unknown size; it is an error to change the output size + + Module(Parameter * p); // Creates the module and possibly init connections from ikc file (MUST BE CALLED FROM SUBCLASS CREATOR) + + virtual ~Module(); + + // Get values from parameters in XML tree - implements the semantics of the ikc file format + + const char * GetList(const char * n); // Get list of values for parameter + const char * GetDefault(const char * n); // Get default value for parameter + const char * GetValue(const char * n); // Search through XML for parameter and return its value or NULL + float GetFloatValue(const char * n, float d=0); // Search through XML for parameter and return its value as a float or default value d if not found + int GetIntValue(const char * n, int d=0); // Search through XML for parameter and return its value as a float or default value d if not found + bool GetBoolValue(const char * n, bool d=false); // Search through XML for parameter and return its value as a float or default value d if not found + int GetIntValueFromList(const char * n, const char * list=NULL); // Search through XML for parameter and then search list for the index of the value in the parameter; return 0 if not foun + float * GetArray(const char * n, int size); // Search through XML for parameter and return its value as an array + float ** GetMatrix(const char * n, int sizex, int sizey); // Search through XML for parameter and return its value as a matrix + int * GetIntArray(const char * n, int & size); + + // Bind values to names and get values from XML tree if possible + + void Bind(float & v, const char * n); // Bind a floating point value to a name + void Bind(int & v, const char * n); // Bind int OR list value to name + void Bind(bool & v, const char * n); // Bind boolean + void Bind(float * & v, int size, const char * n); // Bind array + void Bind(float ** & v, int sizex, int sizey, const char * n); // Bind matrix + + XMLElement * xml; + +private: + Module * next; // Next module in list + Module * next_in_threadGroup; // Next module in ThreadGroup + + const char * class_name; + const char * instance_name; + char * full_instance_name; + + Kernel * kernel; + + Module_IO * input_list; // List of inputs + Module_IO * output_list; // List of outputs + Binding * bindings; + + int period; // How often should the module tick + int phase; // Phase when the module ticks + + Timer * timer; // Statistics variables + float time; + float ticks; + + void DelayOutputs(); + + Module_IO * GetModule_IO(Module_IO * list, const char * name); + void AllocateOutputs(); // Allocate memory for outputs + + friend class Kernel; + friend class Module_IO; + friend class Connection; + friend class ThreadGroup; + + friend Module * CreateModule(ModuleClass * c, const char * class_name, const char * n, Parameter * p); + friend class WebUI; +}; + + + +// +// Connection is used internally by Kernel to store pointers to data in Module_IO that are copied during Propagate() +// + +class Connection +{ // Connection contains info about data flow between modules +private: + Connection * next; // Next connection in list + Module_IO * source_io; + int source_offset; + Module_IO * target_io; + int target_offset; + int size; // The size of the data to be copied + int delay; + + Connection(Connection * n, Module_IO * sio, int so, Module_IO * tio, int to, int s, int d = 1); + ~Connection(); + + void Propagate(long tick); + + friend class Kernel; + friend class WebUI; +}; + + + +// +// ThreadGroup contains a linked list of modules that are executed in the same thread +// + +class ThreadGroup +{ +public: + Kernel * kernel; + ThreadGroup * next; + Module * modules; + Module * last_module; // Last module in list + + int period; // How often should the thread be started + int phase; // Phase when the thread should start + + Thread * thread; + + void AddModule(Module * m); // Try to add module to this or next thread; return false if it is necessary to create a new thread + + ThreadGroup(Kernel * k); + ~ThreadGroup(); + + void Start(long tick); + void Stop(long tick); + void Tick(); +}; + + + +// +// Kernel is the main object and points to data structures for modules and connections +// + +class Kernel +{ +public: + FILE * logfile; + const char * ikaros_dir; + char * ikc_dir; + char * ikc_file_name; + + Options * options; + + Kernel(Options * opt); + ~Kernel(); + + void AddClass(const char * name, ModuleCreator mcc, const char * path = NULL); // Add a new class of modules to the kernel + + void Notify(int msg, const char * format, ...); + + bool Terminate(); // True if the simulation should end + void Run(); // Run the simulation until kernel receives notification; for example end-of-file from a module + + void Init(); // Call Init() for all modules + void Tick(); // Call Tick() for all modules + + void AddModule(Module * m); // Add a module to the simulation + Module * GetModule(const char * n); // Find a module based on its name + + const char * GetBatchValue(const char * n); // Get a value from a batch element with the target n and the current batch rank + + bool GetSource(XMLElement * group, Module * &m, Module_IO * &io, const char * source_module_name, const char * source_name); + bool GetBinding(Module * &m, int &type, void * &value_ptr, int & sx, int & sy, const char * source_module_name, const char * source_name); + + int Connect(Module_IO * sio, Module_IO * tio, const char * delay, int extra_delay = 0); + int Connect(XMLElement * group_xml, Module * sm, Module_IO * sio, const char * tm_name, const char * t_name, const char * delay, int extra_delay = 0); + + XMLElement * BuildClassGroup(XMLElement * xml, const char * current_class = NULL); + void BuildGroup(XMLElement * xml, const char * current_class = NULL); + void ReadXML(); + + bool InputConnected(Module * m, const char * input_name); + bool OutputConnected(Module * m, const char * output_name); + + long GetTick() + { + return tick; + } + + long GetTickLength() + { + return tick_length; + } + + void ListInfo(); + void ListModulesAndConnections(); + void ListScheduling(); + void ListThreads(); + void ListClasses(); + void ListProfiling(); + void PrintTiming(); // Print total timing information + +private: + ModuleClass * classes; // List of module classes + long tick; // Updated every iteration + long max_ticks; // Max iterations, stop after these many ticks + + long tick_length; // Desired length (in ms) of each tick + Timer * timer; // Global timer + float total_time; // Total execution time at termination + + int print_mode; // How much to print + + XMLDocument * xmlDoc; + + Module * modules; // List of modules + Connection * connections; // List of connections + bool useThreads; + + ThreadGroup * threadGroups; // List of ThreadGroups + + bool nan_checks; // Look for NANs in all outputs efter every tick - slow; use only for debugging + + // Execution Control + + int module_count; + int period_count; + int phase_count; + + bool end_of_file_reached; // Flags set on notification from modules + bool fatal_error_occured; + bool terminate; + + bool sizeChangeFlag; + + void CheckInputs(); // Check that memory for all connected inputs have been allocated + void CheckOutputs(); // Check that all outputs are correctly set + + bool Preceedes(Module * a, Module * b); + void SortModules(); // Sort modules in precedence order + void CalculateDelays(); // Calculate the maximum delay from each output + + void InitInputs(); // Allocate memory for inputs in all modules + void InitOutputs(); // Calculate and set output sizes that were not set at module creation; called by Init() + void AllocateOutputs(); // Allocate memory for outputs + void InitModules(); // Init all modules; called by Init() + + int CalculateInputSize(Module_IO * i); // Calculate the size of the input using connections to it + int CalculateInputSizeX(Module_IO * i); // Calculate the size of the input using connections to it + int CalculateInputSizeY(Module_IO * i); // Calculate the size of the input using connections to it + + void NotifySizeChange(); + + void Propagate(); // Copy output data to input for all modules + void DelayOutputs(); + + void CheckNAN(); // Test for NANs in module outputs + + friend class Module; + friend class Module_IO; + friend class ThreadGroup; + friend class WebUI; +}; + + + +#endif + + diff --git a/Source/IKAROS_System.h b/Source/IKAROS_System.h new file mode 100755 index 000000000..5ea73f6b1 --- /dev/null +++ b/Source/IKAROS_System.h @@ -0,0 +1,190 @@ +// +// IKAROS_System.h Definition of the target system for which to compile +// +// Copyright (C) 2001-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// +// Created: August 22, 2002 +// + + + +// +// Target system can be set using a compiler flag, e.g., -DMAC_OS_X or -DWINDOWS +// Alternatively, the appropriate #define below can be uncommented +// + +//#define MINIMAL +//#define MAC_OS_X +//#define LINUX +//#define WINDOWS +//#define WINDOWS32 + + +// +// IKAROSPATH is the path to the Ikaros root directory relative to the Ikaros binary +// OR the absolute path to the Ikaros root directory. A relative path is useful when +// Ikaros is run from within an IDE. An absolut path MUST be set if the full path +// is not used when starting Ikaros. This is the case when the search path for +// executable files includes the directory with the Ikaros binary. +// +// An absolute path can be set using a compiler flag, for example: +// -DIKAROSPATH="\"/home/me/Ikaros.1.3/\"" +// -DIKAROSPATH="C:\\Users\\me\\ikaros\\" (Windows) +// + +#ifndef IKAROSPATH +#define IKAROSPATH "../" +#endif + + +// +// Minimal Defines +// + +// If Ikaros does not compile, try starting with the minmal version by declaring MINIMAL +// This will compile a minmal Ikaros version without support for sockets, WebUI, or threads. +// The minimal version is plain C++ using only the standard libraries and should compile on +// any system. + +#ifdef MINIMAL +#define PLATFORM "MINIMAL-UNKOWN" +//#define POSIX +//#define USE_BSD_SOCKET +//#define USE_LIBJPEG +//#define USE_THREADS +//#define USE_BLAS +//#define USE_MPI +#endif + + + +// +// Linux Defines +// + +#ifdef LINUX +#define PLATFORM "LINUX" +#define POSIX +#define USE_BSD_SOCKET +//#define USE_QUICKTIME +#define USE_LIBJPEG +//#define USE_V4L2 +//#define USE_KEEPON +#define USE_THREADS +#define USE_BLAS +#define USE_LIBPNG +//#define USE_MPI +//#define USE_THREADED_WEBUI +#endif + + + +// +// Mac OS X Defines +// + +#ifdef MAC_OS_X +#define PLATFORM "MAC OS X" +#define POSIX +#define USE_BSD_SOCKET +#define USE_QUICKTIME +//#define USE_QUICKTIME_OLD +#define USE_LIBJPEG +#define USE_LIBPNG +//#define USE_VDSP +#define USE_VIMAGE +#define USE_VFORCE +#define USE_BLAS +#define USE_LAPACK +#define USE_THREADS +#define USE_MPI +//#define USE_THREADED_WEBUI // 1.3 +#endif + + + +// +// Windows Defines +// + +#ifdef WINDOWS +#define PLATFORM "WINDOWS" + +#define USE_WIN_SOCKET +#define USE_LIBJPEG +#define USE_THREADS +//#define USE_LIBPNG +//#define USE_BLAS +#define USE_WIN_SERIAL +//#define USE_THREADED_WEBUI +#include // Include chdir +#define chdir _chdir +#define getcwd _getcwd + +#define M_PI 3.14159265358979323846264338328f +#undef min +#undef max + +#ifdef WINDOWS32 +//#define vsnprintf _vsnprintf +#define snprintf _snprintf +#define PATH_MAX 255 +#endif +//#define POSIX +//#define USE_QUICKTIME +//#define USE_MPI +#endif + +#if defined(_MSC_VER) +#define _CRT_SECURE_NO_DEPRECATE (1) +#define _CRT_NONSTDC_NO_DEPRECATE +#pragma warning( disable : 4305) +#pragma warning( disable : 4244) +#pragma warning( disable : 4290) +#endif + + +// +// Unix includes (some distributions lack PATH_MAX) +// + +#ifdef LINUX +#include +#endif + +#ifdef MAC_OS_X +#include +#endif + + +// Include the socket header file if some socket library is used + +#ifdef USE_BSD_SOCKET +#define USE_SOCKET +#endif +#ifdef USE_WIN_SOCKET +#define USE_SOCKET +#endif + +// Fix for missing MSG_NOSIGNAL in OS X to pass compilation + +#ifdef MAC_OS_X +#define MSG_NOSIGNAL 0 +#endif diff --git a/Source/Kernel/IKAROS.cc b/Source/Kernel/IKAROS.cc new file mode 100755 index 000000000..057100bcf --- /dev/null +++ b/Source/Kernel/IKAROS.cc @@ -0,0 +1,2557 @@ +// +// IKAROS.cc Kernel code for the IKAROS project +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created July 13, 2001 +// +// Revision History: +// +// 2002-01-27 Added support for sizing of output arrays depending on input sizes +// 2002-02-06 Added x, y of each array instead of width +// 2002-02-10 Added new XML support that does not depend on expat for better portability +// 2002-02-16 Additional support for matrices: GetInputMatrix() and GetOutputMatrix() +// to make image processing easier +// 2002-03-15 Added socket for UI communication +// 2002-05-20 Added new communication protocol +// 2002-10-06 Minor changes in parameter class +// 2003-01-23 Bug in InitInputs() fixed +// 2003-08-09 Now catches ctrl-C to shut down gracefully +// +// 2004-03-02 Version 0.8.0 created +// 2004-11-15 New print and error functions; now use Notify(msg, ...) for both errors and printing +// 2004-11-27 Added defines around CTRL-C handler +// 2005-01-17 Changed Data to Array +// 2005-01-18 Completed timing functions +// 2005-08-31 All communication code moved to WebUI +// 2006-01-20 Major cleanup of the code; most system specific code moved out of the kernel +// 2006-02-10 Extended error handling +// 2006-05-05 Even more extended error handling; more informative error messages +// 2006-08-31 Most Windows-specific code included +// 2006-12-12 Fixed potential memory leaks caused by old XML parser +// 2007-01-10 Added new XML handling and new module creation for ikc files + +// 2007-05-10 Version 1.0.0 created +// 2007-07-05 Malloc debugging added +// 2008-12-28 All legacy support and deprecated functions removed to simplify XML cleanup + +#include "IKAROS.h" + +#include +#include +#include +#include +#include +#include +#include + +#ifdef WINDOWS +#include +#else +#include +#endif + +#ifdef WINDOWS32 +#include +#undef GetClassName +#else +#include +#endif + +#include // for std::bad_alloc +#include + + + +using namespace ikaros; +bool global_fatal_error = false; // Must be global because it is used before the kernel is created +bool global_terminate = false; // Used to flag that CTRL-C has been received + + +//#define USE_MALLOC_DEBUG + +#ifndef USE_MALLOC_DEBUG + +void* operator new (std::size_t size) throw (std::bad_alloc) +{ + void *p=calloc(size, sizeof(char)); + if (p==0) // did calloc succeed? + throw std::bad_alloc(); + return p; +} + +void operator delete (void *p) throw() +{ + free(p); +} + +#endif + +// +// USE_MALLOC_DEBUG checks all memory allocations (Currently OS X only). +// + +#ifdef USE_MALLOC_DEBUG + +#include + +const int mem_max_blocks = 100000; // Ikaros will exit if storage is exhausted +unsigned long mem_allocated = 0; +int mem_block_allocated_count = 0; +int mem_block_deleted_count = 0; +void * mem_block[mem_max_blocks]; +size_t mem_size[mem_max_blocks]; +bool mem_block_deleted[mem_max_blocks]; + +void * +operator new (std::size_t size) throw (std::bad_alloc) +{ + void *p=calloc(size, sizeof(char)); + if (p==0) // did calloc succeed? + throw std::bad_alloc(); + + mem_block[mem_block_allocated_count] = p; + mem_size[mem_block_allocated_count] = size; + mem_block_deleted[mem_block_allocated_count] = false; + mem_block_allocated_count++; + + if(mem_block_allocated_count > mem_max_blocks) + { + printf("OUT OF MEMORY\n"); + exit(1); + } + + return p; +} + +void * +operator new [] (std::size_t size) throw (std::bad_alloc) +{ + return operator new(size); +} + +void +operator delete (void *p) throw() +{ + if(p == NULL) // this is ok + return; + + // Look for block (backwards to allow several allocation of the same memory) + + for(int i=mem_block_allocated_count; i>=0; i--) + if(mem_block[i] == p) + { + if(mem_block_deleted[i]) + { + printf("Attempting to delete already deleted memory [%d]: %p\n", i, p); + return; + } + + else + { + mem_block[i] == NULL; + mem_block_deleted[i] = true; + mem_block_deleted_count++; + mem_allocated -= malloc_size(p); + + free(p); + return; + } + } + + printf("Attempting to delete memory not allocated with new: %p\n", p); +} + +void +operator delete [] (void *p) throw() +{ + operator delete (p); +} + +void +dump_memory() +{ + printf("Allocated Memory\n"); + printf("=======================\n"); + int cnt = 0; + for(int i=0; i%lu]\t", i, mem_block[i], mem_size[i], malloc_size(mem_block[i])); + for(unsigned int j=0; jGetClassPath(class_name); + else + return NULL; +} + +Module * +CreateModule(ModuleClass * c, const char * class_name, const char * module_name, Parameter * p) +{ + if (c == NULL) + return NULL; + + else if (equal_strings(c->name, class_name)) + { + Module * m = (*c->module_creator)(p); + if(!m->input_list && !m->output_list) + m->AddIOFromIKC(); + return m; + } + else + return CreateModule(c->next, class_name, module_name, p); +} + +void +Module_IO::Allocate() +{ + if (sizex == unknown_size || sizey == unknown_size) + { + if (module != NULL) + module->Notify(msg_fatal_error, "Attempting to allocate io (\"%s\") with unknown size for module \"%s\" (%s). Check that all required inputs are connected.\n", name, module->GetName(), module->GetClassName()); + return; + } + if (module != NULL) module->Notify(msg_verbose, "Allocating data of size %d.\n", size); + data = new float * [max_delay]; + matrix = new float ** [max_delay]; + for (int d=0; dNotify(msg_verbose, " Deleting Module_IO \"%s\".\n", name); + } + else + { + if (module != NULL) module->Notify(msg_verbose, " Deleting Module_IO\n"); + } + if (matrix) + for (int d=0; dNotify(msg_warning, "Module_IO::SetSize: Attempt to resize data array \"%s\" of module \"%s\" (%s) (%d <= %d). Ignored.\n", name, module->GetName(), module->GetClassName(), size, s); + return; + } + if (s == size) + return; + if (s == 0) + return; + if (module != NULL) module->Notify(msg_verbose, "Allocating memory for input/output \"%s\" of module \"%s\" (%s) with size %d and max_delay = %d (in SetSize).\n", name, module->instance_name, module->GetClassName(), s, max_delay); + sizex = x; + sizey = y; + size = x*y; + if (module != NULL && module->kernel != NULL) + module->kernel->NotifySizeChange(); +} + +void +Module_IO::DelayOutputs() +{ + for (int d=max_delay-1; d>0; d--) + copy_matrix(matrix[d], matrix[d-1], sizex, sizey); +} + +Module::~Module() +{ + Notify(msg_verbose, " Deleting Module \"%s\".\n", instance_name); + destroy_string(full_instance_name); + delete timer; + delete input_list; + delete output_list; + delete next; +} + +void +Module::AddInput(const char * name) +{ + if (GetModule_IO(input_list, name) != NULL) + { + Notify(msg_warning, "Input \"%s\" of module \"%s\" (%s) already exists.\n", name, GetName(), GetClassName()); + return; + } + input_list = new Module_IO(input_list, this, name); + Notify(msg_verbose, " Adding input \"%s\".\n", name); +} + +void +Module::AddOutput(const char * name, int sizeX, int sizeY) +{ + if (GetModule_IO(output_list, name) != NULL) + { + Notify(msg_warning, "Output \"%s\" of module \"%s\" (%s) already exists.\n", name, GetName(), GetClassName()); + return; + } + output_list = new Module_IO(output_list, this, name, sizeX, sizeY); + Notify(msg_verbose, " Adding output \"%s\" of size %d x %d to module \"%s\" (%s).\n", name, sizeX, sizeY, GetName(), GetClassName()); +} + +const char * +Module::GetName() +{ + return instance_name; +} + +const char * +Module::GetFullName() +{ + return full_instance_name; +} + +const char * +Module::GetClassName() +{ + return class_name; +} + +long +Module::GetTickLength() +{ + return kernel->GetTickLength(); +} + +long +Module::GetTick() +{ + return kernel->GetTick(); +} + +const char * +Module::GetList(const char * n) // TODO: Check that this compicated procedure is really necessary; join with GetDefault and GetValue +{ + const char * module_name = GetName(); + + // loop up the group hierarchy + for (XMLElement * parent = xml->GetParentElement(); parent != NULL; parent = parent->GetParentElement()) + { + // Look for parameter element that redefines the attribute name + for (XMLElement * parameter = parent->GetContentElement("parameter"); parameter != NULL; parameter = parameter->GetNextElement("parameter")) + { + if(equal_strings(parameter->GetAttribute("name"), n)) + { + const char * d = parameter->GetAttribute("values"); + if(d) + return d; + } + + const char * t = parameter->GetAttribute("target"); + if (equal_strings(parameter->GetAttribute("target"), n)) + { + // we have found our parameter + // it controls this module if module name is set to the name of this module or if it is not set = relates to all modules + const char * tm = parameter->GetAttribute("module"); + if (tm == NULL || (equal_strings(tm, module_name))) + { + // use default if it exists + const char * d = parameter->GetAttribute("values"); + if(d) + return d; + + // the parameter element redefines our parameter name; get the new name + const char * newname = parameter->GetAttribute("name"); + if (newname == NULL) + { + Notify(msg_fatal_error, "A parameter element with target \"%s\" lacks a name attribute.\n", t); + return NULL; + } + // we have the new name; set it and see if it is defined in the current group element + n = newname; + } + } + } + + // It was not found here; shift module name to that of the current group and continue up the group hierarchy... + module_name = parent->GetAttribute("name"); + } + return NULL; // No list value was found +} + +const char * +Module::GetDefault(const char * n) +{ + const char * module_name = GetName(); + + // loop up the group hierarchy + for (XMLElement * parent = xml->GetParentElement(); parent != NULL; parent = parent->GetParentElement()) + { + // Look for parameter element that redefines the attribute name + for (XMLElement * parameter = parent->GetContentElement("parameter"); parameter != NULL; parameter = parameter->GetNextElement("parameter")) + { + if(equal_strings(parameter->GetAttribute("name"), n)) + { + const char * d = parameter->GetAttribute("default"); + if(d) + return d; + } + + const char * t = parameter->GetAttribute("target"); + if (equal_strings(parameter->GetAttribute("target"), n)) + { + // we have found our parameter + // it controls this module if module name is set to the name of this module or if it is not set = relates to all modules + const char * tm = parameter->GetAttribute("module"); + if (tm == NULL || (equal_strings(tm, module_name))) + { + // use default if it exists + const char * d = parameter->GetAttribute("default"); + if(d) + return d; + + // the parameter element redefines our parameter name; get the new name + const char * newname = parameter->GetAttribute("name"); + if (newname == NULL) + { + Notify(msg_fatal_error, "A parameter element with target \"%s\" lacks a name attribute.\n", t); + return NULL; + } + // we have the new name; set it and see if it is defined in the current group element + n = newname; + } + } + } + + // It was not found here; shift module name to that of the current group and continue up the group hierarchy... + module_name = parent->GetAttribute("name"); + } + return NULL; // No default value was found +} + + + +const char * +Module::GetValue(const char * n) // This function implements attribute inheritance with renaming through the parameter element +{ + const char * module_name = GetName(); + // Check for local value in this element + const char * value = xml->GetAttribute(n); + if (value != NULL) + return value; + // not found here, loop up the group hierarchy + for (XMLElement * parent = xml->GetParentElement(); parent != NULL; parent = parent->GetParentElement()) + { + // Look for parameter element that redefines the attribute name + for (XMLElement * parameter = parent->GetContentElement("parameter"); parameter != NULL; parameter = parameter->GetNextElement("parameter")) + { + // const char * t = parameter->GetAttribute("target"); + if (equal_strings(parameter->GetAttribute("target"), n)) + { + // we have found our parameter + // it controls this module if module name is set to the name of this module or if it is not set = relates to all modules + const char * tm = parameter->GetAttribute("module"); + if (tm == NULL || (equal_strings(tm, module_name))) + { + // the parameter element redefines our parameter name; get the new name + const char * newname = parameter->GetAttribute("name"); + if (newname == NULL) + { + // Notify(msg_fatal_error, "A parameter element with target \"%s\" lacks a name attribute.\n", t); + return GetDefault(n); + } + // we have the new name; set it and see if it is defined in the current group element + n = newname; + } + } + } + value = parent->GetAttribute(n); + if (value != NULL) + return value; + // It was not found here; shift module name to that of the current group and continue up the group hierarchy... + module_name = parent->GetAttribute("name"); + } + + // No value was found, check if we are in batch mode and look for batch a value + + value = kernel->GetBatchValue(n); + if (value != NULL) + return value; + + // As a last step, look for default instead + + return GetDefault(n); +} + +float +Module::GetFloatValue(const char * n, float d) +{ + return string_to_float(GetValue(n), d); +} + +int +Module::GetIntValue(const char * n, int d) +{ + return string_to_int(GetValue(n), d); +} + +static bool +tobool(const char * v) +{ + if (!v) return false; + if (!strcmp(v, "true")) return true; + if (!strcmp(v, "True")) return true; + if (!strcmp(v, "TRUE")) return true; + if (!strcmp(v, "yes")) return true; + if (!strcmp(v, "Yes")) return true; + if (!strcmp(v, "YES")) return true; + if (!strcmp(v, "1")) return true; + if (!strcmp(v, "false")) return false; + if (!strcmp(v, "False")) return false; + if (!strcmp(v, "FALSE")) return false; + if (!strcmp(v, "no")) return false; + if (!strcmp(v, "No")) return false; + if (!strcmp(v, "NO")) return false; + if (!strcmp(v, "0")) return false; + return false; +} + +bool +Module::GetBoolValue(const char * n, bool d) +{ + const char * v = GetValue(n); + if (v == NULL) + return d; + else + return tobool(v); +} + +static int +findindex(const char * name, const char * list) +{ + int ix = 0; + int lp = 0; + while (true) + { + // try to match name in list + int np = 0; + while (list[lp] && list[lp] != '/' && name[np] == list[lp]) + { + np++; + lp++; + } + // name matches, return index + if ((list[lp] == '/' || list[lp] == 0) && name[np] == 0) + return ix; + // skip to next name + ix++; + while (list[lp] && list[lp] != '/') + lp++; + // no match + if (list[lp] == 0) + return -1; + // prepare for next match + lp++; + } +} + + + +int +Module::GetIntValueFromList(const char * n, const char * list) +{ + const char * l = GetList(n); + if(!l) + l = list; + if(!l) + { + Notify(msg_warning, "List values not defined for \"%s\".\n", n); + return 0; + } + const char * v = GetValue(n); + if (!v) + return 0; + else + { + int ix = findindex(v, l); + + if(ix == -1) + { + Notify(msg_warning, "List value \"%s\" is not defined. Using default value.\n", v); + return 0; + } + else + return ix; + } +} + + + +float * +Module::GetArray(const char * n, int size) +{ + bool too_few = false; + float * a = create_array(size); + const char * v = GetValue(n); + if (v == NULL) + return a; + for (int i=0; inext) + if (equal_strings(name, i->name)) + return i; + return NULL; +} + + + +void +Module::AllocateOutputs() +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + i->Allocate(); +} + +void +Module::DelayOutputs() +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + i->DelayOutputs(); +} + +float * +Module::GetInputArray(const char * name, bool required) +{ + for (Module_IO * i = input_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + { + if (i->data == NULL) + { + if(required) + Notify(msg_fatal_error, "Input array \"%s\" of module \"%s\" (%s) has no allocated data. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; + } + else + return i->data[0]; + } + Notify(msg_warning, "Input array \"%s\" of module \"%s\" (%s) does not exist. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; +} + +float * +Module::GetOutputArray(const char * name, bool required) +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + { + if (i->data == NULL) + { + if(required) + Notify(msg_fatal_error, "Output array \"%s\" of module \"%s\" (%s) has no allocated data. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; + } + else + return i->data[0]; + } + Notify(msg_warning, "Output array \"%s\" of module \"%s\" (%s) does not exist. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; +} + +float ** +Module::GetInputMatrix(const char * name, bool required) +{ + for (Module_IO * i = input_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + { + if (i->matrix == NULL) + { + if(required) + Notify(msg_fatal_error, "Input matrix \"%s\" of module \"%s\" (%s) has no allocated data. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; + } + else + return i->matrix[0]; + } + Notify(msg_warning, "Input matrix \"%s\" of module \"%s\" (%s) does not exist. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; +} + +float ** +Module::GetOutputMatrix(const char * name, bool required) +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + { + if (i->matrix == NULL) + { + if(required) + Notify(msg_fatal_error, "Output matrix \"%s\" of module \"%s\" (%s) has no allocated data. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; + } + else + return i->matrix[0]; + } + Notify(msg_warning, "Output matrix \"%s\" of module \"%s\" (%s) does not exist. Returning NULL.\n", name, GetName(), GetClassName()); + return NULL; +} + +int +Module::GetInputSize(const char * input_name) +{ + // Find the Module_IO for this input + for (Module_IO * i = input_list; i != NULL; i = i->next) + if (equal_strings(input_name, i->name)) + { + if (i->size != unknown_size) + return i->size; + else if (kernel != NULL) + return kernel->CalculateInputSize(i); + else + break; + } + Notify(msg_fatal_error, "Cannot calculate input size for \"%s\" of module \"%s\" (%s).\n", input_name, instance_name, class_name); + return unknown_size; +} + +int +Module::GetInputSizeX(const char * input_name) +{ + // Find the Module_IO for this input + for (Module_IO * i = input_list; i != NULL; i = i->next) + if (equal_strings(input_name, i->name)) + { + if (i->sizex != unknown_size) + return i->sizex; + else if (kernel != NULL) + return kernel->CalculateInputSizeX(i); + else + break; + } + Notify(msg_fatal_error, "Cannot calculate input x size for \"%s\" of module \"%s\" (%s).\n", input_name, instance_name, class_name); + return unknown_size; +} + +int +Module::GetInputSizeY(const char * input_name) +{ + // Find the Module_IO for this input + for (Module_IO * i = input_list; i != NULL; i = i->next) + if (equal_strings(input_name, i->name)) + { + if (i->sizex != unknown_size) // Yes, sizeX is correct + return i->sizey; + else if (kernel != NULL) + return kernel->CalculateInputSizeY(i); + else + break; + } + Notify(msg_fatal_error, "Cannot calculate input y size for \"%s\" of module \"%s\" (%s).\n", input_name, instance_name, class_name); + return unknown_size; +} + +int +Module::GetOutputSize(const char * name) +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + return i->size; + return 0; +} + +int +Module::GetOutputSizeX(const char * name) +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + return i->sizex; + return 0; +} + +int +Module::GetOutputSizeY(const char * name) +{ + for (Module_IO * i = output_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + return i->sizey; + return 0; +} + +bool +Module::InputConnected(const char * name) +{ + return kernel->InputConnected(this, name); +} + +bool +Module::OutputConnected(const char * name) +{ + return kernel->OutputConnected(this, name); +} + +void +Module::SetOutputSize(const char * name, int x, int y) +{ + if (x < -1 || y < -1) + { + Notify(msg_warning, "Attempting to set negative size of %s.%s \n", this->instance_name, name); + return; + } + for (Module_IO * i = output_list; i != NULL; i = i->next) + if (equal_strings(name, i->name)) + i->SetSize(x, y); +} + +Module::Module(Parameter * p) +{ + next = NULL; + next_in_threadGroup = NULL; + input_list = NULL; + output_list = NULL; + bindings = NULL; + timer = new Timer(); + time = 0; + ticks = 0; + kernel = p->kernel; + xml = p->xml; + instance_name = GetValue("name"); + class_name = xml->GetAttribute("class"); + period = GetIntValue("period", 1); + phase = GetIntValue("phase", 0); + + // Compute full name + + char n[1024] = ""; + const char * group[128]; + int i=0; + for (XMLElement * parent = xml->GetParentElement(); parent != NULL; parent = parent->GetParentElement()) + if(parent->GetAttribute("name") && i<100) + group[i++] = parent->GetAttribute("name"); + for(int j=i-1; j>=0; j--) + { + append_string(n, group[j], 1024); + if(j>0) append_string(n, ":", 1024); + } + full_instance_name = create_string(n); +} + +void +Module::AddIOFromIKC() +{ + if(!xml->GetParentElement()) + return; + + for(XMLElement * e=xml->GetParentElement()->GetContentElement("input"); e != NULL; e = e->GetNextElement("input")) + AddInput(e->GetAttribute("name")); + + for(XMLElement * e=xml->GetParentElement()->GetContentElement("output"); e != NULL; e = e->GetNextElement("output")) + AddOutput(e->GetAttribute("name")); +} + +// Default SetSizes sets output sizes from IKC file based on size_set, size_param, and size attributes + +void +Module::SetSizes() +{ + if(xml->GetParentElement()) + { + const char * sizearg; + const char * arg; + for(XMLElement * e=xml->GetParentElement()->GetContentElement("output"); e != NULL; e = e->GetNextElement("output")) + { + const char * output_name = e->GetAttribute("name"); + if((sizearg = e->GetAttribute("size_set"))) + { + char * l = create_string(sizearg); + char * ll = l; + // strip blanks + int i=0, j=0; + while(l[i] != 0) + { + if(l[j] == ' ') + j++; + else + l[i++]=l[j++]; + } + char * s = l; + char * input; + input = strsep(&s, ","); + while(input) + { + int sx = GetInputSizeX(input); + int sy = GetInputSizeY(input); + if(sx != unknown_size) + SetOutputSize(output_name, sx, sy); + input = strsep(&s, ","); + } + destroy_string(ll); + } + + else + { + int s = unknown_size; + int sx = unknown_size; + int sy = unknown_size; + + if((sizearg = e->GetAttribute("size_param")) && (arg = GetValue(sizearg))) + s = string_to_int(arg); + + if((sizearg = e->GetAttribute("size_param_x")) && (arg = GetValue(sizearg))) + sx = string_to_int(arg); + + if((sizearg = e->GetAttribute("size_param_y")) && (arg = GetValue(sizearg))) + sy = string_to_int(arg); + + if((sizearg = e->GetAttribute("size"))) + s = string_to_int(sizearg); + + if((sizearg = e->GetAttribute("size_x"))) + sx = string_to_int(sizearg); + + if((sizearg = e->GetAttribute("size_y"))) + sy = string_to_int(sizearg); + + if(s != unknown_size) + { + sx = s; + sy = 1; + } + + SetOutputSize(output_name, sx, sy); + } + } + } +} + + + +void +Module::Notify(int msg) +{ + if (kernel != NULL) + kernel->Notify(msg, "\n"); + else if (msg == msg_fatal_error) + global_fatal_error = true; +} + +void +Module::Notify(int msg, const char *format, ...) +{ + char message[512]; + int n = 0; + if (message == NULL) + { + global_fatal_error = true; + return; + } + va_list args; + va_start(args, format); + vsnprintf(&message[n], 512, format, args); + va_end(args); + if (kernel != NULL) + { + kernel->Notify(msg, message); + } + else if (msg == msg_fatal_error) + { + global_fatal_error = true; + printf("IKAROS: ERROR: %s", message); + } +} + +Connection::Connection(Connection * n, Module_IO * sio, int so, Module_IO * tio, int to, int s, int d) +{ + source_io = sio; + source_offset = so; + target_io = tio; + target_offset = to; + size = s; + delay = d; + next = n; +} + +Connection::~Connection() +{ + if (source_io != NULL && source_io->module != NULL) + source_io->module->Notify(msg_verbose, " Deleting Connection.\n"); + delete next; +} + +void +Connection::Propagate(long tick) +{ + if (delay == 0) + return; + // Return if both modules will not start in this tick - necessary when using threads + if (tick % source_io->module->period != source_io->module->phase) + return; + if (tick % target_io->module->period != target_io->module->phase) + return; + if (source_io != NULL && source_io->module != NULL) + source_io->module->Notify(msg_verbose, " Propagating %s.%s -> %s.%s (%p -> %p) size = %d\n", source_io->module->GetName(), source_io->name, target_io->module->GetName(), target_io->name, source_io->data, target_io->data, size); + for (int i=0; idata[0][i+target_offset] = source_io->data[delay-1][i+source_offset]; +} + +void +ThreadGroup::AddModule(Module * m) +{ + // Add module if thread is empty + if (modules == NULL) + { + kernel->Notify(msg_verbose, "Adding module %s to new thread group\n", m->GetName()); + modules = m; + last_module = m; + period = m->period; + phase = m->phase; + return; + } + + // Check if any module already in the group preceedes the new one + + bool p = false; + for(Module * pm = modules; pm != NULL; pm = pm->next_in_threadGroup) + p = p | kernel->Preceedes(pm, m); + + // Check for the case where this module preceedes a module that will be added to the group in the future + + if(!p) + for(Module * pm = modules; pm != NULL; pm = pm->next_in_threadGroup) + for(Module * nm = m->next; nm != NULL; nm = nm->next) + if(kernel->Preceedes(pm, nm) && kernel->Preceedes(m, nm)) + { + p = true; + break; + } + + // Add module if this module should run in same thread as the other (and last) modules + if (p) + { + if(m->period != period) + { + kernel->Notify(msg_fatal_error, "Module %s do not have the correct period for thread group (Should be %d rather than %d)\n", m->GetName(), period, m->period); + return; + } + + kernel->Notify(msg_verbose, "Adding module %s to thread groups after %s\n", m->GetName(), last_module->GetName()); + last_module->next_in_threadGroup = m; + last_module = m; + return; + } + // Add to a new group if this was the last one + if (next == NULL) + { + next = new ThreadGroup(kernel); + next->AddModule(m); + return; + } + // Try to add the module to the next group + next->AddModule(m); +} + +ThreadGroup::ThreadGroup(Kernel * k) +{ + kernel = k; + next = NULL; + modules = NULL; + last_module = NULL; + period = 1; + phase = 0; + thread = new Thread(); +} + +ThreadGroup::~ThreadGroup() +{ + delete thread; + delete next; +} + +static void * +ThreadGroup_Tick(void * group) +{ + ((ThreadGroup *)group)->Tick(); + return NULL; +} + +void +ThreadGroup::Start(long tick) +{ + // Test if group should be started + if (tick % period == phase) + { + if (thread->Create(ThreadGroup_Tick, (void*)this)) + printf("Thread Creation Failed!\n"); + } +} + +void +ThreadGroup::Stop(long tick) +{ + // Test if group should be joined + if ((tick + 1) % period == phase) + { + thread->Join(); + } +} + +void +ThreadGroup::Tick() +{ + for (Module * m = modules; m != NULL; m = m->next_in_threadGroup) + { + m->timer->Restart(); + m->Tick(); + m->time += m->timer->GetTime(); + m->ticks += 1; + } +} + +Kernel::Kernel(Options * opt) +{ + options = opt; + useThreads = options->GetOption('t') || options->GetOption('T'); + max_ticks = string_to_int(options->GetArgument('s'), -1); + tick_length = string_to_int(options->GetArgument('r'), 0); + nan_checks = options->GetOption('n'); + + print_mode = print_normal; + if (options->GetOption('q')) + print_mode = print_silent; + if (options->GetOption('v')) + print_mode = print_verbose; + + tick = 0; + xmlDoc = NULL; + classes = NULL; + modules = NULL; + connections = NULL; + module_count = 0; + period_count = 0; + phase_count = 0; + end_of_file_reached = false; + fatal_error_occured = false; + terminate = false; + sizeChangeFlag = false; + threadGroups = NULL; + + logfile = NULL; + timer = new Timer(); + + // Compute ikaros root path + + ikaros_dir = NULL; + if(is_absolute_path(IKAROSPATH)) + ikaros_dir = create_string(IKAROSPATH); + else if(options->GetBinaryDirectory() != NULL) + ikaros_dir = create_formatted_string("%s%s", options->GetBinaryDirectory(), IKAROSPATH); + else + Notify(msg_fatal_error, "The Ikaros root directory could not be established. Please set an absolute IKAROSPATH in IKAROS_System.h\n"); + + // Compute ikc path and name + + ikc_dir = options->GetFileDirectory(); + ikc_file_name = options->GetFileName(); + + // Seed random number generator + + if(options->GetOption('z')) +#ifdef WINDOWS32 + srand(string_to_int(options->GetArgument('z'))); +#else + srandom(string_to_int(options->GetArgument('z'))); +#endif +} + +Kernel::~Kernel() +{ + Notify(msg_verbose, "Deleting Kernel.\n"); + Notify(msg_verbose, " Deleting Connections.\n"); + delete connections; + Notify(msg_verbose, " Deleting Modules.\n"); + delete modules; + Notify(msg_verbose, " Deleting Thread Groups.\n"); + delete threadGroups; + Notify(msg_verbose, " Deleting Classes.\n"); + delete classes; + + delete timer; + delete xmlDoc; + delete ikaros_dir; + + Notify(msg_verbose, "Deleting Kernel Complete.\n"); + if (logfile) fclose(logfile); + +#ifdef USE_MALLOC_DEBUG + dump_memory(); // dump blocks that are still allocated +#endif +} + +void +Kernel::AddClass(const char * name, ModuleCreator mc, const char * path) +{ + if (path == NULL) + { + Notify(msg_warning, "Path to ikc file is missing for class \"%s\".\n", name); + classes = new ModuleClass(name, mc, NULL, classes); // Add class anyway + return; + } + + char * path_to_ikc_file = NULL; + + // Test for backward compatibility and remove initial paths if needed + + path_to_ikc_file = create_formatted_string("%s%s%s.ikc", ikaros_dir, path, name); + + classes = new ModuleClass(name, mc, path_to_ikc_file, classes); + destroy_string(path_to_ikc_file); +} + +bool +Kernel::Terminate() +{ + if (max_ticks != -1 && tick >= max_ticks) + { + Notify(msg_verbose, "Max ticks reached.\n"); + return true; + } + return end_of_file_reached || fatal_error_occured || global_fatal_error || terminate || global_terminate; +} + +void +Kernel::Run() +{ + if (fatal_error_occured || global_fatal_error) + { + Notify(msg_fatal_error, "Terminating because a fatal error occured.\n"); + throw 4; + } + if (max_ticks == 0) + return; + + Notify(msg_print, "Start\n"); + + // Synchronize with master process if one is indicated in the IKC file + if(xmlDoc) + { + const char * ip = xmlDoc->xml->GetAttribute("masterip"); + if(ip) + { + Socket s; + char rr[100]; + int port = string_to_int(xmlDoc->xml->GetAttribute("masterport"), 9000); + printf("Waiting for master: %s:%d\n", ip, port); + fflush(stdout); + if(!s.Get(ip, port, "*", rr, 100)) + { + printf("Master not running.\n"); + exit(-1); // No master + } + } + } + + timer->Restart(); + while (!Terminate()) + { + Tick(); + if (tick_length > 0) + { + float lag = timer->WaitUntil(float(tick*tick_length)); + if (lag > 0.1) Notify(msg_warning, "Lagging %.2f ms at tick = %ld\n", lag, tick); + } + } +} + +void +Kernel::PrintTiming() +{ + total_time = timer->GetTime()/1000; // in seconds + if (max_ticks != 0) + Notify(msg_print, "Stop (%ld ticks, %.2f s, %.2f ticks/s, %.3f s/tick)\n", tick, total_time, float(tick)/total_time, total_time/float(tick)); +} + +void +Kernel::Propagate() +{ + for (Connection * c = connections; c != NULL; c = c->next) + c->Propagate(tick); +} + +void +Kernel::CheckNAN() +{ + for (Module * m = modules; m != NULL; m = m->next) + { + for (Module_IO * i = m->output_list; i != NULL; i = i->next) + { + for(int j=0; jsizex*i->sizey; j++) + { + float v = i->matrix[0][0][j]; + if((v) != (v)) + { + Notify(msg_fatal_error, "NAN in output \"%s\" of module \"%s\" (%s).\n", i->name, i->module->instance_name, i->module->GetClassName()); + break; + } + } + } + } +} + +void +Kernel::CheckInputs() +{ + for (Module * m = modules; m != NULL; m = m->next) + { + for (Module_IO * i = m->input_list; i != NULL; i = i->next) + if (i->size == unknown_size) + { + // Check if connected + bool connected = false; + for (Connection * c = connections; c != NULL; c = c->next) + if (c->target_io == i) + connected = true; + if (connected) + { + Notify(msg_fatal_error, "Size of input \"%s\" of module \"%s\" (%s) could not be resolved.\n", i->name, i->module->instance_name, i->module->GetClassName()); + } + else + i->size = 0; // ok if not connected + } + } +} + +void +Kernel::CheckOutputs() +{ + for (Module * m = modules; m != NULL; m = m->next) + { + for (Module_IO * i = m->output_list; i != NULL; i = i->next) + if (i->size == unknown_size) + { + // Check if connected + bool connected = false; + for (Connection * c = connections; c != NULL; c = c->next) + if (c->source_io == i) + connected = true; + if (connected) + { + Notify(msg_fatal_error, "Size of output \"%s\" of module \"%s\" (%s) could not be resolved.\n", i->name, i->module->instance_name, i->module->GetClassName()); + } + } + } +} + +void +Kernel::InitInputs() +{ + for (Connection * c = connections; c != NULL; c = c->next) + { + if (c->source_io->size == unknown_size) + { + Notify(msg_fatal_error, "Output \"%s\" of module \"%s\" (%s) has unknown size.\n", c->source_io->name, c->source_io->module->instance_name, c->source_io->module->GetClassName()); + } + else if (c->delay == 0) + { + Notify(msg_verbose, "Short-circuiting zero-delay connection from \"%s\" of module \"%s\" (%s)\n", c->source_io->name, c->source_io->module->instance_name, c->source_io->module->GetClassName()); + // already connected to 0 or longer delay? + if (c->target_io->data != NULL) + { + Notify(msg_fatal_error, "Failed to connect zero-delay connection from \"%s\" of module \"%s\" (%s) because target is already connected.\n", c->source_io->name, c->source_io->module->instance_name, c->source_io->module->GetClassName()); + } + else + { + c->target_io->data = new float * [1]; + c->target_io->data[0] = c->source_io->data[0]; + c->target_io->matrix = new float ** [1]; + c->target_io->matrix[0] = c->source_io->matrix[0]; + c->target_io->sizex = c->source_io->sizex; + c->target_io->sizey = c->source_io->sizey; + c->target_io->size = c->source_io->size; + c->target_io->max_delay = 0; + } + } + else if(c->target_io) + { + // Check that this connection does not interfere with zero-delay connection + if (c->target_io->max_delay == 0) + { + Notify(msg_fatal_error, "Failed to connect from \"%s\" of module \"%s\" (%s) because target is already connected with zero-delay.\n", c->source_io->name, c->source_io->module->instance_name, c->source_io->module->GetClassName()); + } + // First connection to this target: initialize + if (c->target_io->size == unknown_size) // start calculation with size 0 + c->target_io->size = 0; + int target_offset = c->target_io->size; + c->target_io->size += c->source_io->size; + // Target not used previously: ok to connect anything + if (c->target_io->sizex == unknown_size) + { + Notify(msg_verbose, "New connection.\n"); + c->target_io->sizex = c->source_io->sizex; + c->target_io->sizey = c->source_io->sizey; + } + // Connect one dimensional output + else if (c->target_io->sizey == 1 && c->source_io->sizey == 1) + { + Notify(msg_verbose, "Adding additional connection.\n"); + c->target_io->sizex = c->target_io->size; + } + // Collapse matrix to array + else + { + Notify(msg_verbose, "Multiple connections to \"%s.%s\" with different no of rows. Input flattened.\n", c->target_io->module->instance_name, c->target_io->name); + c->target_io->sizex = c->target_io->size; + c->target_io->sizey = 1; + } + // Set connection variables + c->target_offset = target_offset; + c->size = c->source_io->size; + // Allocate input memory and reset + Notify(msg_verbose, "Allocating memory for input \"%s\" of module \"%s\" with size %d (%dx%d).\n", c->target_io->name, c->target_io->module->instance_name, c->target_io->size, c->target_io->sizex, c->target_io->sizey); + c->target_io->SetSize(c->target_io->sizex, c->target_io->sizey); + c->target_io->Allocate(); + } + } +} + +void +Kernel::InitOutputs() +{ + do + { + sizeChangeFlag = false; + for (Module * m = modules; m != NULL; m = m->next) + m->SetSizes(); + if (sizeChangeFlag) + Notify(msg_verbose, "InitOutput: Iteration with changes\n"); + else + Notify(msg_verbose, "InitOutput: Iteration with no changes\n"); + } + while (sizeChangeFlag); +} + +void +Kernel::AllocateOutputs() +{ + for (Module * m = modules; m != NULL; m = m->next) + m->AllocateOutputs(); +} + +void +Kernel::InitModules() +{ + for (Module * m = modules; m != NULL; m = m->next) + m->Init(); +} + +void +Kernel::NotifySizeChange() +{ + sizeChangeFlag = true; +} + +void +Kernel::Init() +{ + if (options->GetFilePath()) + ReadXML(); + else + Notify(msg_fatal_error, "No IKC file supplied.\n"); + SortModules(); + CalculateDelays(); + InitOutputs(); // Calculate the output sizes for outputs that have not been specified at creation + AllocateOutputs(); + InitInputs(); // Calculate the input sizes and allocate memory for the inputs or connect 0-delays + CheckOutputs(); + CheckInputs(); + if (fatal_error_occured) + return; + InitModules(); +} + +void +Kernel::Tick() +{ + Notify(msg_verbose, "Kernel::Tick()\n"); + Propagate(); + DelayOutputs(); + if (useThreads) + { + for (ThreadGroup * g = threadGroups; g != NULL; g = g->next) + g->Start(tick); + for (ThreadGroup * g = threadGroups; g != NULL; g = g->next) + g->Stop(tick); + } + else if (print_mode < msg_verbose) + { + for (Module * m = modules; m != NULL; m = m->next) + if (tick % m->period == m->phase) + { + m->timer->Restart(); + m->Tick(); + m->time += m->timer->GetTime(); + m->ticks += 1; + } + } + else + { + for (Module * m = modules; m != NULL; m = m->next) + if (tick % m->period == m->phase) + { + m->timer->Restart(); + Notify(msg_verbose, "%s::Tick (%s) Start\n", m->GetName(), m->GetClassName()); + m->Tick(); + Notify(msg_verbose, "%s::Tick (%s) End\n", m->GetName(), m->GetClassName()); + m->time += m->timer->GetTime(); + m->ticks += 1; + } + + } + + if(nan_checks) + CheckNAN(); + + tick++; +} + +void +Kernel::DelayOutputs() +{ + for (Module * m = modules; m != NULL; m = m->next) + m->DelayOutputs(); +} + +void +Kernel::AddModule(Module * m) +{ + if (!m) return; + m->next = modules; + modules = m; + m->kernel = this; +} + + + +Module * +Kernel::GetModule(const char * n) +{ + for (Module * m = modules; m != NULL; m = m->next) + if (equal_strings(n, m->instance_name)) + return m; + return NULL; +} + + + +bool +Kernel::GetSource(XMLElement * group, Module * &m, Module_IO * &io, const char * source_module_name, const char * source_name) +{ + for (XMLElement * xml = group->GetContentElement(); xml != NULL; xml = xml->GetNextElement()) + if (xml->IsElement("module") && (equal_strings(xml->GetAttribute("name"), source_module_name) || equal_strings(source_module_name, "*"))) + { + m = (Module *)(xml->aux); + if (m != NULL) + io = m->GetModule_IO(m->output_list, source_name); + if (m != NULL && io != NULL) + return true; + return false; + } + else if (xml->IsElement("group") && equal_strings(xml->GetAttribute("name"), source_module_name)) // Translate output name + { + for (XMLElement * output = xml->GetContentElement("output"); output != NULL; output = output->GetNextElement("output")) + { + const char * n = output->GetAttribute("name"); + if (n == NULL) + return false; + if (equal_strings(n, source_name) || equal_strings(n, "*")) + { + const char * new_module = output->GetAttribute("sourcemodule"); + const char * new_source = output->GetAttribute("source"); + if (new_source == NULL) + new_source = source_name; // retain name + return GetSource(xml, m, io, new_module, new_source); + } + } + } + + return false; +} + + + +static const char * +find_nth_element(const char * s, int n) +{ + if(s==NULL) + return NULL; + + int l = int(strlen(s)); + if(l==0) + return NULL; + + int i=0; + while(i < l && s[i] <= ' ') + i++; + + for(int c=1; c<=n; c++) + { + if(s[i] > ' ' && c==n) + { + int j=0; + while((i+j < l) && (s[i+j] > ' ')) + j++; + return create_string_head(&s[i], j); + } + while(i < l && s[i] > ' ') + i++; + while(i < l && s[i] <= ' ') + i++; + } + + return NULL; +} + + + +const char * +Kernel::GetBatchValue(const char * n) +{ + int rank = string_to_int(options->GetArgument('b')); + + XMLElement * xml = xmlDoc->xml->GetElement("group"); + if (xml == NULL) + return NULL; + + for (XMLElement * xml_node = xml->GetContentElement(); xml_node != NULL; xml_node = xml_node->GetNextElement("batch")) + if(equal_strings(xml_node->GetAttribute("target"), n)) + { + if(rank == 0) + rank = string_to_int(xml_node->GetAttribute("rank")); + + if(rank == 0) + return NULL; + + const char * value = find_nth_element(xml_node->GetAttribute("values"), rank); + printf("IKAROS: %s = \"%s\"\n", xml_node->GetAttribute("target"), value); + return value; + } + + return NULL; +} + + + +bool +Kernel::GetBinding(Module * &m, int &type, void * &value_ptr, int & sx, int & sy, const char * source_module_name, const char * source_name) +{ + m = GetModule(source_module_name); + if(!m) + { + Notify(msg_warning, "Could not find binding. Module \"%s\" does not exist\n", source_module_name); + return false; + } + for(Binding * b = m->bindings; b != NULL; b = b->next) + if(equal_strings(source_name, b->name)) + { + type = b->type; + value_ptr = b->value; + sx = b->size_x; + sy = b->size_y; + return true; + } + + Notify(msg_warning, "Could not find binding. Binding \"%s\" of module \"%s\" does not exist\n", source_name, source_module_name); + return false; +} + + + +bool +Kernel::Preceedes(Module * a, Module * b) +{ + // Base case + for (Connection * c = connections; c != NULL; c = c->next) + if (c->delay == 0 && c->source_io->module == a && c->target_io->module == b) + return true; + // Transitivity test + for (Connection * c = connections; c != NULL; c = c->next) + if (c->delay == 0 && c->source_io->module == a && Preceedes(c->target_io->module, b)) + return true; + return false; +} + + + +int +Kernel::CalculateInputSize(Module_IO * i) +{ + // The input size has not yet been determined; use the connection list to calculate it + // Scan through the connection list to find the size of the input + // The size is the sum of the sizes of all outputs connected to this input + // The input size is unspecified if one of the outputs has unknown size + int s = 0; + for (Connection * c = connections; c != NULL; c = c->next) + { + if (c->target_io == i) + { + if (c->source_io->size == unknown_size) + return unknown_size; + else + s += c->source_io->size; + } + } + return s; +} + +int +Kernel::CalculateInputSizeX(Module_IO * i) +{ + // The input size has not yet been determined; use the connection list to calculate it + // Scan through the connection list to find the size of the input + // For matrices, there can only be one input + // The input size is unspecified if one of the outputs has unknown size + int s = 0; + for (Connection * c = connections; c != NULL; c = c->next) + { + if (c->target_io == i) + { + if (c->source_io->sizex == unknown_size) + return unknown_size; + else if (s == 0) + s = c->source_io->sizex; + else + return CalculateInputSize(i); + } + } + return s; +} + +int +Kernel::CalculateInputSizeY(Module_IO * i) +{ + // The input size has not yet been determined; use the connection list to calculate it + // Scan through the connection list to find the size of the input + // For matrices, there can only be one input + // The input size is unspecified if one of the outputs has unknown size + int s = 0; + for (Connection * c = connections; c != NULL; c = c->next) + { + if (c->target_io == i) + { + if (c->source_io->sizey == unknown_size) + return unknown_size; + else if (s == 0) + s = c->source_io->sizey; + else + return 1; + } + } + return s; +} + +void +Kernel::SortModules() +{ + // For statistics only + for (Module * m = modules; m != NULL; m = m->next) + { + phase_count = (m->phase < phase_count ? phase_count : m->phase); + period_count = (m->period < period_count ? period_count : m->period); + module_count++; + } + if (phase_count > period_count) + period_count = phase_count; + // Build a new sorted list of modules (precedence order) using selection sort + Module * sorted_modules = NULL; + while (modules != NULL) + { + // Find smallest module + Module * sm = modules; + for (Module * m = modules; m != NULL; m = m->next) + { + if (Preceedes(sm, m)) + sm = m; + } + // Remove from list + if (sm == modules) // First + { + modules = modules->next; + sm->next = sorted_modules; + sorted_modules = sm; + } + else + { + // Find prev (double linked list would have been better) + Module * psm = NULL; + for (psm = modules; psm->next != sm; psm = psm->next) + ; + psm->next = sm->next; + sm->next = sorted_modules; + sorted_modules = sm; + } + } + modules = sorted_modules; + // Check for loops + for (Module * m = modules; m != NULL; m = m->next) + if (Preceedes(m, m)) + Notify(msg_fatal_error, "Module \"%s\" (%s) has a zero-delay connection to itself.\n", m->GetName(), m->GetClassName()); + // Create Thread Groups + threadGroups = new ThreadGroup(this); + for (Module * m = modules; m != NULL; m = m->next) + threadGroups->AddModule(m); +} + +void +Kernel::CalculateDelays() +{ + for (Connection * c = connections; c != NULL; c = c->next) + { + if (c->delay > c->source_io->max_delay) + c->source_io->max_delay = c->delay; + } +} + +bool +Kernel::InputConnected(Module * m, const char * input_name) // TODO: Test it *** +{ + return m->GetInputArray(input_name, false) != NULL; + /* + if (connections == NULL) + return false; + for (Connection * c = connections; c != NULL; c = c->next) + if (c->target_io->module == m && equal_strings(input_name, c->target_io->name)) + return true; + return false; + */ +} + +bool +Kernel::OutputConnected(Module * m, const char * output_name) +{ + if (connections == NULL) + return false; + for (Connection * c = connections; c != NULL; c = c->next) + if (c->source_io->module == m && m->GetModule_IO(m->output_list, output_name) == c->source_io) + return true; + return false; +} + +void +Kernel::ListInfo() +{ + if (!options->GetOption('i')) return; + Notify(msg_print, "\n"); + Notify(msg_print, "Ikaros version %s\n", VERSION); + Notify(msg_print, "\n"); + Notify(msg_print, "%s\n", PLATFORM); +#ifdef POSIX + Notify(msg_print, "POSIX\n"); +#endif +#ifdef USE_BSD_SOCKET + Notify(msg_print, "BSD-socket\n"); +#endif +#ifdef USE_WIN_SOCKET + Notify(msg_print, "WIN-socket\n"); +#endif +#ifdef USE_LIBJPEG + Notify(msg_print, "libjpeg\n"); +#endif +#ifdef USE_THREADS + Notify(msg_print, "threads\n"); +#endif +#ifdef USE_BLAS + Notify(msg_print, "BLAS\n"); +#endif +#ifdef USE_QUICKTIME + Notify(msg_print, "Quicktime\n"); +#endif +#ifdef USE_VIMAGE + Notify(msg_print, "vImage\n"); +#endif +#ifdef USE_VFORCE + Notify(msg_print, "vForce\n"); +#endif +#ifdef USE_VDSP + Notify(msg_print, "vDSP\n"); +#endif +#ifdef USE_MPI + Notify(msg_print, "MPI\n"); +#endif + Notify(msg_print, "\n"); + Notify(msg_print, "ikc file name: %s\n", ikc_file_name); + Notify(msg_print, "ikc file directory: %s\n", ikc_dir); + Notify(msg_print, "ikaros root directory: %s\n", ikaros_dir); +} + +void +Kernel::ListModulesAndConnections() +{ + if (!options->GetOption('m') && !options->GetOption('a')) return; + Notify(msg_print, "\n"); + Notify(msg_print, "Modules:\n"); + Notify(msg_print, "\n"); + for (Module * m = modules; m != NULL; m = m->next) + { + // Notify(msg_print, " %s (%s) [%d, %d]:\n", m->name, m->class_name, m->period, m->phase); + Notify(msg_print, " %s (%s) [%d, %d]:\n", m->GetFullName(), m->class_name, m->period, m->phase); + for (Module_IO * i = m->input_list; i != NULL; i = i->next) + if(i->data) + Notify(msg_print, " %-10s\t(Input) \t%6d%6d%12p\n", i->name, i->sizex, i->sizey, (i->data == NULL ? NULL : i->data[0])); + else + Notify(msg_print, " %-10s\t(Input) \t no connection\n", i->name); + for (Module_IO * i = m->output_list; i != NULL; i = i->next) + Notify(msg_print, " %-10s\t(Output)\t%6d%6d%12p\t(%d)\n", i->name, i->sizex, i->sizey, (i->data == NULL ? NULL : i->data[0]), i->max_delay); + Notify(msg_print, "\n"); + } + Notify(msg_print, "Connections:\n"); + Notify(msg_print, "\n"); + for (Connection * c = connections; c != NULL; c = c->next) + if (c->delay == 0) + Notify(msg_print, " %s.%s[%d..%d] == %s.%s[%d..%d] (%d)\n", + c->source_io->module->instance_name, c->source_io->name, 0, c->source_io->size-1, + c->target_io->module->instance_name, c->target_io->name, 0, c->source_io->size-1, + c->delay); + else if (c->size > 1) + Notify(msg_print, " %s.%s[%d..%d] -> %s.%s[%d..%d] (%d)\n", + c->source_io->module->instance_name, c->source_io->name, c->source_offset, c->source_offset+c->size-1, + c->target_io->module->instance_name, c->target_io->name, c->target_offset, c->target_offset+c->size-1, + c->delay); + else + Notify(msg_print, " %s.%s[%d] -> %s.%s[%d] (%d)\n", + c->source_io->module->instance_name, c->source_io->name, c->source_offset, + c->target_io->module->instance_name, c->target_io->name, c->target_offset, + c->delay); + Notify(msg_print, "\n"); +} + +void +Kernel::ListThreads() +{ + if (!options->GetOption('T') && !(options->GetOption('a') && options->GetOption('t'))) return; + Notify(msg_print, "\n"); + Notify(msg_print,"ThreadManagers:\n"); + Notify(msg_print, "\n"); + int tt = 0; + for (ThreadGroup * t = threadGroups; t != NULL; t = t->next) + { + Notify(msg_print,"ThreadManager %d [Period:%d, Phase:%d]\n", tt++, t->period, t->phase); + for (Module * m = t->modules; m != NULL; m=m->next_in_threadGroup) + Notify(msg_print,"\tModule: %s\n", m->GetName()); + } + Notify(msg_print, "\n"); +} + +void +Kernel::ListScheduling() +{ + if (!options->GetOption('l') && !options->GetOption('a')) return; + Notify(msg_print, "Scheduling:\n"); + Notify(msg_print, "\n"); + for (int t=0; tnext) + if (t % m->period == m->phase) + Notify(msg_print," %02d.%02d: %s (%s)\n", t, tm++, m->GetName(), m->GetClassName()); + } + + Notify(msg_print, "\n"); + Notify(msg_print, "\n"); +} + +void +Kernel::ListClasses() +{ + if (!options->GetOption('c')) return; + int i = 0; + Notify(msg_print, "\n"); + Notify(msg_print, "Classes:\n"); + for (ModuleClass * c = classes; c != NULL; c = c->next) + { + Notify(msg_print, "\t%s\n", c->name); + i++; + } + Notify(msg_print, "No of modules: %d.\n", i); +} + +void +Kernel::ListProfiling() +{ + if (!options->GetOption('p')) return; + // Calculate Total Time + float total_module_time = 0; + for (Module * m = modules; m != NULL; m = m->next) + total_module_time += m->time; + Notify(msg_print, "\n"); + Notify(msg_print, "Time (ms):\n"); + Notify(msg_print, "-------------------\n"); + Notify(msg_print, "Modules: %10.2f\n", total_module_time); + Notify(msg_print, "Other: %10.2f\n", 1000*total_time-total_module_time); + Notify(msg_print, "-------------------\n"); + Notify(msg_print, "Total: %10.2f\n", 1000*total_time); + Notify(msg_print, "\n"); + if (total_module_time == 0) + return; + Notify(msg_print, "Time in Each Module:\n"); + Notify(msg_print, "\n"); + Notify(msg_print, "%-20s%-20s%10s%10s%10s\n", "Module", "Class", "Count", "Avg (ms)", "Time %"); + Notify(msg_print, "----------------------------------------------------------------------\n"); + for (Module * m = modules; m != NULL; m = m->next) + if (m->ticks > 0) + Notify(msg_print, "%-20s%-20s%10.0f%10.2f%10.1f\n", m->GetName(), m->GetClassName(), m->ticks, (m->time/m->ticks), 100*(m->time/total_module_time)); + else + Notify(msg_print, "%-20s%-20s% ---f\n", m->GetName(), m->GetClassName()); + Notify(msg_print, "----------------------------------------------------------------------\n"); + if (useThreads) + Notify(msg_print, "Note: Time is real-time, not time in thread.\n"); + Notify(msg_print, "\n"); +} + +void +Kernel::Notify(int msg, const char * format, ...) +{ + switch (msg) + { + case msg_fatal_error: + fatal_error_occured = true; + break; + case msg_end_of_file: + end_of_file_reached = true; + break; + case msg_terminate: + terminate = true; + break; + default: + break; + } + if (msg > print_mode) + return; + char message[512]; + int n = 0; + switch (msg) + { + case msg_fatal_error: + n = snprintf(message, 512, "ERROR: "); + break; + case msg_end_of_file: + n = snprintf(message, 512, "END-OF-FILE: "); + break; + case msg_terminate: + n = snprintf(message, 512, "TERMINATE. "); + break; + case msg_warning: + n = snprintf(message, 512, "WARNING: "); + break; + default: + break; + } + va_list args; + va_start(args, format); + vsnprintf(&message[n], 512, format, args); + va_end(args); + printf("IKAROS: %s", message); + if(message[strlen(message)] != '\n') + printf("\n"); + if (logfile != NULL) + fprintf(logfile, "%5ld: %s", tick, message); // Print in both places +} + + + +// Create one or several connections with different delays between two ModuleIOs + +int +Kernel::Connect(Module_IO * sio, Module_IO * tio, const char * delay, int extra_delay) +{ + int c = 0; + char * dstring = create_string(delay); + + if(!dstring || (!strchr(dstring, ':') && !strchr(dstring, ','))) + { + int d = string_to_int(dstring, 1); + connections = new Connection(connections, sio, 0, tio, unknown_size, unknown_size, d+extra_delay); + c++; + } + + else // parse delay string for multiple delays + { + char * d = create_string(dstring); + char * p = strtok(d, ","); + while (p != NULL) + { + int a, b, n; + n = sscanf(p, "%d:%d", &a, &b); + if(n==1) + b = a; + + for(int i=a; i<=b; i++) + { + connections = new Connection(connections, sio, 0, tio, unknown_size, unknown_size, i+extra_delay); + c++; + } + p = strtok(NULL, ","); + } + destroy_string(d); + } + + destroy_string(dstring); + return c; +} + + + +int +Kernel::Connect(XMLElement * group_xml, Module * sm, Module_IO * sio, const char * tm_name, const char * t_name, const char * delay, int extra_delay) +{ + int c = 0; // no of generated connections + + // iterate over all modules + + for (XMLElement * xml_module = group_xml->GetContentElement("module"); xml_module != NULL; xml_module = xml_module->GetNextElement("module")) + if(equal_strings(tm_name, "*") || equal_strings(tm_name, xml_module->GetAttribute("name"))) // also matches anonymous module as it should + { + Module * tm = (Module *)(xml_module->aux); + if (tm) + { + Module_IO * tio = tm->GetModule_IO(tm->input_list, t_name); + if(sio == NULL) + Notify(msg_fatal_error, "Could not make connection. Source missing\n."); + else if(tio == NULL) + Notify(msg_fatal_error, "Could not make connection. Target \"%s\" of module \"%s\" missing.\n", t_name, tm_name); + else + c += Connect(sio, tio, delay, extra_delay); + } + } + + bool connection_made = false; + for (XMLElement * xml_group = group_xml->GetContentElement("group"); xml_group != NULL; xml_group = xml_group->GetNextElement("group")) + if(equal_strings(tm_name, "*") || equal_strings(tm_name, xml_group->GetAttribute("name"))) // Found group + { + // iterate over all input elements + for (XMLElement * xml_input = xml_group->GetContentElement("input"); xml_input != NULL; xml_input = xml_input->GetNextElement("input")) + if(equal_strings(t_name, xml_input->GetAttribute("name"))) // Found input with target + { + connection_made = true; + const char * tm = xml_input->GetAttribute("targetmodule"); + const char * t = xml_input->GetAttribute("target"); + int d = string_to_int(xml_input->GetAttribute("delay")); // TODO: We should merge d with the range in d instead + if(!equal_strings(t,"")) + c += Connect(xml_group, sm, sio, tm, (t ? t : t_name), delay, d+extra_delay); // TODO: Extra delay should be replaced with a merge interval function + else + c++; // ignore connections if both are nil + } + } + + if(!connection_made) // look of wildcard connections + for (XMLElement * xml_group = group_xml->GetContentElement("group"); xml_group != NULL; xml_group = xml_group->GetNextElement("group")) + if(equal_strings(tm_name, "*") || equal_strings(tm_name, xml_group->GetAttribute("name"))) // Found group + { + // iterate over all input elements + for (XMLElement * xml_input = xml_group->GetContentElement("input"); xml_input != NULL; xml_input = xml_input->GetNextElement("input")) + if(equal_strings("*", xml_input->GetAttribute("name"))) // Found input with target + { + const char * tm = xml_input->GetAttribute("targetmodule"); + const char * t = xml_input->GetAttribute("target"); + int d = string_to_int(xml_input->GetAttribute("delay")); + + if(!equal_strings(t,"")) + c += Connect(xml_group, sm, sio, tm, (t ? t : t_name), delay, d+extra_delay); // TODO: Extra delay should be replaced with a merge interval function + else + c++; // ignore connections if both are nil + } + } + + return c; +} + + + +// Check if class file exists and return path if valid + +static const char * +file_exists(const char * path) +{ + if (path != NULL) + { + FILE * t = fopen(path, "rb"); + bool exists = (t != NULL); + if (t) fclose(t); + return (exists ? path : NULL); + } + + return NULL; +} + + + +// Read class file (or included file) and merge with the current XML-tree + +XMLElement * +Kernel::BuildClassGroup(XMLElement * xml_node, const char * class_name) +{ + char include_file[PATH_MAX] =""; + const char * filename = file_exists(append_string(copy_string(include_file, class_name, PATH_MAX), ".ikc", PATH_MAX)); + filename = (filename ? filename : file_exists(classes->GetClassPath(class_name))); + if(!filename) + { + Notify(msg_warning, "Class file for class \"%s\" could not be found.\n", class_name); + return xml_node; + } + + XMLDocument * cDoc = new XMLDocument(filename); + XMLElement * cgroup = cDoc->xml; + cDoc->xml = NULL; + delete cDoc; + + // 1. Replace the module element with the group element of the included file + + cgroup->next = xml_node->next; + if (xml_node->prev == NULL) + xml_node->GetParentElement()->content = cgroup; + else + xml_node->prev->next = cgroup; + cgroup->parent = xml_node->parent; + + // 2. Copy attributes + + for(XMLNode * n = xml_node->attributes; n != NULL; n=n->next) + cgroup->SetAttribute(((XMLAttribute *)n)->name, ((XMLAttribute *)n)->value); + delete xml_node->attributes; + xml_node->attributes = NULL; + + // 3. Copy elements + + XMLNode * last = cgroup->content; + if (last == NULL) + cgroup->content = xml_node->content; + else + { + while (last->next != NULL) + last = last->next; + last->next = xml_node->content; + } + xml_node->content = NULL; + + // 4. Build the class group + + BuildGroup(cgroup, class_name); + + // 5. Delete original element and replace it with the newly merged group + + xml_node->next = NULL; + delete xml_node; + + return cgroup; +} + + + +// Parse XML for a group + +static int group_number = 0; + +void +Kernel::BuildGroup(XMLElement * group_xml, const char * current_class) +{ + const char * name = group_xml->GetAttribute("name"); + if(name == NULL) + group_xml->SetAttribute("name", create_formatted_string("Group-%d", group_number++)); + + for (XMLElement * xml_node = group_xml->GetContentElement(); xml_node != NULL; xml_node = xml_node->GetNextElement()) + if (xml_node->IsElement("module")) // Add module + { + char * class_name = create_string(xml_node->GetAttribute("class")); + if (!equal_strings(class_name, current_class)) // Check that we are not in a class file + { + xml_node = BuildClassGroup(xml_node, class_name); + } + + else if (class_name != NULL) // Create the module using standard class + { + Parameter * parameter = new Parameter(this, xml_node); + Module * m = CreateModule(classes, class_name, xml_node->GetAttribute("name"), parameter); + delete parameter; + if (m == NULL) + Notify(msg_warning, "Could not create module: Class \"%s\" does not exist.\n", class_name); + if (useThreads && m->phase != 0) + Notify(msg_fatal_error, "phase != 0 not yet supported in threads."); + xml_node->aux = (void *)m; + AddModule(m); + } + destroy_string(class_name); + } + else if (xml_node->IsElement("group")) // Add group + BuildGroup(xml_node); + + // Create connections in group + + for (XMLElement * xml_connection = group_xml->GetContentElement("connection"); xml_connection != NULL; xml_connection = xml_connection->GetNextElement("connection")) + { + const char * sm_name = xml_connection->GetAttribute("sourcemodule"); + const char * s_name = xml_connection->GetAttribute("source"); + const char * tm_name = xml_connection->GetAttribute("targetmodule"); + const char * t_name = xml_connection->GetAttribute("target"); + const char * delay = xml_connection->GetAttribute("delay"); + + Module * sm; + Module_IO * sio; + int c = 0; + if (GetSource(group_xml, sm, sio, sm_name, s_name)) + c = Connect(group_xml, sm, sio, tm_name, t_name, delay); + else + Notify(msg_fatal_error, "Connection source %s.%s not found.\n", sm_name, s_name); + + if(c == 0) + Notify(msg_fatal_error, "Connection target %s.%s not found.\n", tm_name, t_name); + } +} + + + +void +Kernel::ReadXML() +{ + if (ikc_file_name[0] == 0) + { + Notify(msg_fatal_error, "Empty file name.\n"); + return; + } + char path[PATH_MAX]; + copy_string(path, ikc_dir, PATH_MAX); + append_string(path, ikc_file_name, PATH_MAX); + Notify(msg_print, "Reading XML file \"%s\".\n", ikc_file_name); + if (chdir(ikc_dir) < 0) + { + Notify(msg_fatal_error, "The directory \"%s\" could not be found.\n", ikc_dir); + return; + } + xmlDoc = new XMLDocument(ikc_file_name, options->GetOption('X')); + if (xmlDoc->xml == NULL) + { + Notify(msg_fatal_error, "Could not read (or find) \"%s\".\n", ikc_file_name); + return; + } + XMLElement * xml = xmlDoc->xml->GetElement("group"); + if (xml == NULL) + { + Notify(msg_fatal_error, "Did not find element in IKC/XML file \"%s\".\n", ikc_file_name); + return; + } + // Build The Main Group + + BuildGroup(xml); + if (options->GetOption('x')) + xmlDoc->Print(stdout); +} + diff --git a/Source/Kernel/IKAROS_ColorTables.h b/Source/Kernel/IKAROS_ColorTables.h new file mode 100755 index 000000000..68ebad0b3 --- /dev/null +++ b/Source/Kernel/IKAROS_ColorTables.h @@ -0,0 +1,807 @@ +// +// IKAROS_ColorTables.h Color tables for JPEG images +// +// Copyright (C) 20098 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#ifndef IKAROS_COLORTABLES +#define IKAROS_COLORTABLES + +int LUT_spectrum[256][3] = +{ +{255, 0, 0}, +{255, 6, 0}, +{255, 12, 0}, +{255, 18, 0}, +{255, 24, 0}, +{255, 30, 0}, +{255, 36, 0}, +{255, 42, 0}, +{255, 48, 0}, +{255, 54, 0}, +{255, 60, 0}, +{255, 66, 0}, +{255, 72, 0}, +{255, 78, 0}, +{255, 84, 0}, +{255, 90, 0}, +{255, 96, 0}, +{255, 102, 0}, +{255, 108, 0}, +{255, 114, 0}, +{255, 120, 0}, +{255, 126, 0}, +{255, 132, 0}, +{255, 138, 0}, +{255, 144, 0}, +{255, 150, 0}, +{255, 156, 0}, +{255, 162, 0}, +{255, 168, 0}, +{255, 174, 0}, +{255, 180, 0}, +{255, 186, 0}, +{255, 192, 0}, +{255, 198, 0}, +{255, 204, 0}, +{255, 210, 0}, +{255, 216, 0}, +{255, 222, 0}, +{255, 228, 0}, +{255, 234, 0}, +{255, 240, 0}, +{255, 246, 0}, +{255, 252, 0}, +{252, 255, 0}, +{246, 255, 0}, +{240, 255, 0}, +{234, 255, 0}, +{228, 255, 0}, +{222, 255, 0}, +{216, 255, 0}, +{210, 255, 0}, +{204, 255, 0}, +{198, 255, 0}, +{192, 255, 0}, +{186, 255, 0}, +{180, 255, 0}, +{174, 255, 0}, +{168, 255, 0}, +{162, 255, 0}, +{156, 255, 0}, +{150, 255, 0}, +{144, 255, 0}, +{138, 255, 0}, +{132, 255, 0}, +{126, 255, 0}, +{120, 255, 0}, +{114, 255, 0}, +{108, 255, 0}, +{102, 255, 0}, +{96, 255, 0}, +{90, 255, 0}, +{84, 255, 0}, +{78, 255, 0}, +{72, 255, 0}, +{66, 255, 0}, +{60, 255, 0}, +{54, 255, 0}, +{48, 255, 0}, +{42, 255, 0}, +{36, 255, 0}, +{30, 255, 0}, +{24, 255, 0}, +{18, 255, 0}, +{12, 255, 0}, +{6, 255, 0}, +{0, 255, 0}, +{0, 255, 6}, +{0, 255, 12}, +{0, 255, 18}, +{0, 255, 24}, +{0, 255, 30}, +{0, 255, 36}, +{0, 255, 42}, +{0, 255, 48}, +{0, 255, 54}, +{0, 255, 60}, +{0, 255, 66}, +{0, 255, 72}, +{0, 255, 78}, +{0, 255, 84}, +{0, 255, 90}, +{0, 255, 96}, +{0, 255, 102}, +{0, 255, 108}, +{0, 255, 114}, +{0, 255, 120}, +{0, 255, 126}, +{0, 255, 132}, +{0, 255, 138}, +{0, 255, 144}, +{0, 255, 150}, +{0, 255, 156}, +{0, 255, 162}, +{0, 255, 168}, +{0, 255, 174}, +{0, 255, 180}, +{0, 255, 186}, +{0, 255, 192}, +{0, 255, 198}, +{0, 255, 204}, +{0, 255, 210}, +{0, 255, 216}, +{0, 255, 222}, +{0, 255, 228}, +{0, 255, 234}, +{0, 255, 240}, +{0, 255, 246}, +{0, 255, 252}, +{0, 252, 255}, +{0, 246, 255}, +{0, 240, 255}, +{0, 234, 255}, +{0, 228, 255}, +{0, 222, 255}, +{0, 216, 255}, +{0, 210, 255}, +{0, 204, 255}, +{0, 198, 255}, +{0, 192, 255}, +{0, 186, 255}, +{0, 180, 255}, +{0, 174, 255}, +{0, 168, 255}, +{0, 162, 255}, +{0, 156, 255}, +{0, 150, 255}, +{0, 144, 255}, +{0, 138, 255}, +{0, 132, 255}, +{0, 126, 255}, +{0, 120, 255}, +{0, 114, 255}, +{0, 108, 255}, +{0, 102, 255}, +{0, 96, 255}, +{0, 90, 255}, +{0, 84, 255}, +{0, 78, 255}, +{0, 72, 255}, +{0, 66, 255}, +{0, 60, 255}, +{0, 54, 255}, +{0, 48, 255}, +{0, 42, 255}, +{0, 36, 255}, +{0, 30, 255}, +{0, 24, 255}, +{0, 18, 255}, +{0, 12, 255}, +{0, 6, 255}, +{0, 0, 255}, +{6, 0, 255}, +{12, 0, 255}, +{18, 0, 255}, +{24, 0, 255}, +{30, 0, 255}, +{36, 0, 255}, +{42, 0, 255}, +{48, 0, 255}, +{54, 0, 255}, +{60, 0, 255}, +{66, 0, 255}, +{72, 0, 255}, +{78, 0, 255}, +{84, 0, 255}, +{90, 0, 255}, +{96, 0, 255}, +{102, 0, 255}, +{108, 0, 255}, +{114, 0, 255}, +{120, 0, 255}, +{126, 0, 255}, +{132, 0, 255}, +{138, 0, 255}, +{144, 0, 255}, +{150, 0, 255}, +{156, 0, 255}, +{162, 0, 255}, +{168, 0, 255}, +{174, 0, 255}, +{180, 0, 255}, +{186, 0, 255}, +{192, 0, 255}, +{198, 0, 255}, +{204, 0, 255}, +{210, 0, 255}, +{216, 0, 255}, +{222, 0, 255}, +{228, 0, 255}, +{234, 0, 255}, +{240, 0, 255}, +{246, 0, 255}, +{252, 0, 255}, +{255, 0, 252}, +{255, 0, 246}, +{255, 0, 240}, +{255, 0, 234}, +{255, 0, 228}, +{255, 0, 222}, +{255, 0, 216}, +{255, 0, 210}, +{255, 0, 204}, +{255, 0, 198}, +{255, 0, 192}, +{255, 0, 186}, +{255, 0, 180}, +{255, 0, 174}, +{255, 0, 168}, +{255, 0, 162}, +{255, 0, 156}, +{255, 0, 150}, +{255, 0, 144}, +{255, 0, 138}, +{255, 0, 132}, +{255, 0, 126}, +{255, 0, 120}, +{255, 0, 114}, +{255, 0, 108}, +{255, 0, 102}, +{255, 0, 96}, +{255, 0, 90}, +{255, 0, 84}, +{255, 0, 78}, +{255, 0, 72}, +{255, 0, 66}, +{255, 0, 60}, +{255, 0, 54}, +{255, 0, 48}, +{255, 0, 42}, +{255, 0, 36}, +{255, 0, 30}, +{255, 0, 24}, +{255, 0, 18}, +{255, 0, 12}, +{255, 0, 6}, +{255, 0, 0} +}; + + +int LUT_green[256][3] = +{ +{0, 0, 0}, +{0, 1, 0}, +{0, 2, 0}, +{0, 3, 0}, +{0, 4, 0}, +{0, 5, 0}, +{0, 6, 0}, +{0, 7, 0}, +{0, 8, 0}, +{0, 9, 0}, +{0, 10, 0}, +{0, 11, 0}, +{0, 12, 0}, +{0, 13, 0}, +{0, 14, 0}, +{0, 15, 0}, +{0, 16, 0}, +{0, 17, 0}, +{0, 18, 0}, +{0, 19, 0}, +{0, 20, 0}, +{0, 21, 0}, +{0, 22, 0}, +{0, 23, 0}, +{0, 24, 0}, +{0, 25, 0}, +{0, 26, 0}, +{0, 27, 0}, +{0, 28, 0}, +{0, 29, 0}, +{0, 30, 0}, +{0, 31, 0}, +{0, 32, 0}, +{0, 33, 0}, +{0, 34, 0}, +{0, 35, 0}, +{0, 36, 0}, +{0, 37, 0}, +{0, 38, 0}, +{0, 39, 0}, +{0, 40, 0}, +{0, 41, 0}, +{0, 42, 0}, +{0, 43, 0}, +{0, 44, 0}, +{0, 45, 0}, +{0, 46, 0}, +{0, 47, 0}, +{0, 48, 0}, +{0, 49, 0}, +{0, 50, 0}, +{0, 51, 0}, +{0, 52, 0}, +{0, 53, 0}, +{0, 54, 0}, +{0, 55, 0}, +{0, 56, 0}, +{0, 57, 0}, +{0, 58, 0}, +{0, 59, 0}, +{0, 60, 0}, +{0, 61, 0}, +{0, 62, 0}, +{0, 63, 0}, +{0, 64, 0}, +{0, 65, 0}, +{0, 66, 0}, +{0, 67, 0}, +{0, 68, 0}, +{0, 69, 0}, +{0, 70, 0}, +{0, 71, 0}, +{0, 72, 0}, +{0, 73, 0}, +{0, 74, 0}, +{0, 75, 0}, +{0, 76, 0}, +{0, 77, 0}, +{0, 78, 0}, +{0, 79, 0}, +{0, 80, 0}, +{0, 81, 0}, +{0, 82, 0}, +{0, 83, 0}, +{0, 84, 0}, +{0, 85, 0}, +{0, 86, 0}, +{0, 87, 0}, +{0, 88, 0}, +{0, 89, 0}, +{0, 90, 0}, +{0, 91, 0}, +{0, 92, 0}, +{0, 93, 0}, +{0, 94, 0}, +{0, 95, 0}, +{0, 96, 0}, +{0, 97, 0}, +{0, 98, 0}, +{0, 99, 0}, +{0, 100, 0}, +{0, 101, 0}, +{0, 102, 0}, +{0, 103, 0}, +{0, 104, 0}, +{0, 105, 0}, +{0, 106, 0}, +{0, 107, 0}, +{0, 108, 0}, +{0, 109, 0}, +{0, 110, 0}, +{0, 111, 0}, +{0, 112, 0}, +{0, 113, 0}, +{0, 114, 0}, +{0, 115, 0}, +{0, 116, 0}, +{0, 117, 0}, +{0, 118, 0}, +{0, 119, 0}, +{0, 120, 0}, +{0, 121, 0}, +{0, 122, 0}, +{0, 123, 0}, +{0, 124, 0}, +{0, 125, 0}, +{0, 126, 0}, +{0, 127, 0}, +{0, 128, 0}, +{0, 129, 0}, +{0, 130, 0}, +{0, 131, 0}, +{0, 132, 0}, +{0, 133, 0}, +{0, 134, 0}, +{0, 135, 0}, +{0, 136, 0}, +{0, 137, 0}, +{0, 138, 0}, +{0, 139, 0}, +{0, 140, 0}, +{0, 141, 0}, +{0, 142, 0}, +{0, 143, 0}, +{0, 144, 0}, +{0, 145, 0}, +{0, 146, 0}, +{0, 147, 0}, +{0, 148, 0}, +{0, 149, 0}, +{0, 150, 0}, +{0, 151, 0}, +{0, 152, 0}, +{0, 153, 0}, +{0, 154, 0}, +{0, 155, 0}, +{0, 156, 0}, +{0, 157, 0}, +{0, 158, 0}, +{0, 159, 0}, +{0, 160, 0}, +{0, 161, 0}, +{0, 162, 0}, +{0, 163, 0}, +{0, 164, 0}, +{0, 165, 0}, +{0, 166, 0}, +{0, 167, 0}, +{0, 168, 0}, +{0, 169, 0}, +{0, 170, 0}, +{0, 171, 0}, +{0, 172, 0}, +{0, 173, 0}, +{0, 174, 0}, +{0, 175, 0}, +{0, 176, 0}, +{0, 177, 0}, +{0, 178, 0}, +{0, 179, 0}, +{0, 180, 0}, +{0, 181, 0}, +{0, 182, 0}, +{0, 183, 0}, +{0, 184, 0}, +{0, 185, 0}, +{0, 186, 0}, +{0, 187, 0}, +{0, 188, 0}, +{0, 189, 0}, +{0, 190, 0}, +{0, 191, 0}, +{0, 192, 0}, +{0, 193, 0}, +{0, 194, 0}, +{0, 195, 0}, +{0, 196, 0}, +{0, 197, 0}, +{0, 198, 0}, +{0, 199, 0}, +{0, 200, 0}, +{0, 201, 0}, +{0, 202, 0}, +{0, 203, 0}, +{0, 204, 0}, +{0, 205, 0}, +{0, 206, 0}, +{0, 207, 0}, +{0, 208, 0}, +{0, 209, 0}, +{0, 210, 0}, +{0, 211, 0}, +{0, 212, 0}, +{0, 213, 0}, +{0, 214, 0}, +{0, 215, 0}, +{0, 216, 0}, +{0, 217, 0}, +{0, 218, 0}, +{0, 219, 0}, +{0, 220, 0}, +{0, 221, 0}, +{0, 222, 0}, +{0, 223, 0}, +{0, 224, 0}, +{0, 225, 0}, +{0, 226, 0}, +{0, 227, 0}, +{0, 228, 0}, +{0, 229, 0}, +{0, 230, 0}, +{0, 231, 0}, +{0, 232, 0}, +{0, 233, 0}, +{0, 234, 0}, +{0, 235, 0}, +{0, 236, 0}, +{0, 237, 0}, +{0, 238, 0}, +{0, 239, 0}, +{0, 240, 0}, +{0, 241, 0}, +{0, 242, 0}, +{0, 243, 0}, +{0, 244, 0}, +{0, 245, 0}, +{0, 246, 0}, +{0, 247, 0}, +{0, 248, 0}, +{0, 249, 0}, +{0, 250, 0}, +{0, 251, 0}, +{0, 252, 0}, +{0, 253, 0}, +{0, 254, 0}, +{0, 255, 0} +}; + +int LUT_fire[256][3] = +{ +{0, 0, 31}, +{0, 0, 34}, +{0, 0, 38}, +{0, 0, 42}, +{0, 0, 46}, +{0, 0, 49}, +{0, 0, 53}, +{0, 0, 57}, +{0, 0, 61}, +{0, 0, 65}, +{0, 0, 69}, +{0, 0, 74}, +{0, 0, 78}, +{0, 0, 82}, +{0, 0, 87}, +{0, 0, 91}, +{1, 0, 96}, +{4, 0, 100}, +{7, 0, 104}, +{10, 0, 108}, +{13, 0, 113}, +{16, 0, 117}, +{19, 0, 121}, +{22, 0, 125}, +{25, 0, 130}, +{28, 0, 134}, +{31, 0, 138}, +{34, 0, 143}, +{37, 0, 147}, +{40, 0, 151}, +{43, 0, 156}, +{46, 0, 160}, +{49, 0, 165}, +{52, 0, 168}, +{55, 0, 171}, +{58, 0, 175}, +{61, 0, 178}, +{64, 0, 181}, +{67, 0, 185}, +{70, 0, 188}, +{73, 0, 192}, +{76, 0, 195}, +{79, 0, 199}, +{82, 0, 202}, +{85, 0, 206}, +{88, 0, 209}, +{91, 0, 213}, +{94, 0, 216}, +{98, 0, 220}, +{101, 0, 220}, +{104, 0, 221}, +{107, 0, 222}, +{110, 0, 223}, +{113, 0, 224}, +{116, 0, 225}, +{119, 0, 226}, +{122, 0, 227}, +{125, 0, 224}, +{128, 0, 222}, +{131, 0, 220}, +{134, 0, 218}, +{137, 0, 216}, +{140, 0, 214}, +{143, 0, 212}, +{146, 0, 210}, +{148, 0, 206}, +{150, 0, 202}, +{152, 0, 199}, +{154, 0, 195}, +{156, 0, 191}, +{158, 0, 188}, +{160, 0, 184}, +{162, 0, 181}, +{163, 0, 177}, +{164, 0, 173}, +{166, 0, 169}, +{167, 0, 166}, +{168, 0, 162}, +{170, 0, 158}, +{171, 0, 154}, +{173, 0, 151}, +{174, 0, 147}, +{175, 0, 143}, +{177, 0, 140}, +{178, 0, 136}, +{179, 0, 132}, +{181, 0, 129}, +{182, 0, 125}, +{184, 0, 122}, +{185, 0, 118}, +{186, 0, 114}, +{188, 0, 111}, +{189, 0, 107}, +{190, 0, 103}, +{192, 0, 100}, +{193, 0, 96}, +{195, 0, 93}, +{196, 1, 89}, +{198, 3, 85}, +{199, 5, 82}, +{201, 7, 78}, +{202, 8, 74}, +{204, 10, 71}, +{205, 12, 67}, +{207, 14, 64}, +{208, 16, 60}, +{209, 19, 56}, +{210, 21, 53}, +{212, 24, 49}, +{213, 27, 45}, +{214, 29, 42}, +{215, 32, 38}, +{217, 35, 35}, +{218, 37, 31}, +{220, 40, 27}, +{221, 43, 23}, +{223, 46, 20}, +{224, 48, 16}, +{226, 51, 12}, +{227, 54, 8}, +{229, 57, 5}, +{230, 59, 4}, +{231, 62, 3}, +{233, 65, 3}, +{234, 68, 2}, +{235, 70, 1}, +{237, 73, 1}, +{238, 76, 0}, +{240, 79, 0}, +{241, 81, 0}, +{243, 84, 0}, +{244, 87, 0}, +{246, 90, 0}, +{247, 92, 0}, +{249, 95, 0}, +{250, 98, 0}, +{252, 101, 0}, +{252, 103, 0}, +{252, 105, 0}, +{253, 107, 0}, +{253, 109, 0}, +{253, 111, 0}, +{254, 113, 0}, +{254, 115, 0}, +{255, 117, 0}, +{255, 119, 0}, +{255, 121, 0}, +{255, 123, 0}, +{255, 125, 0}, +{255, 127, 0}, +{255, 129, 0}, +{255, 131, 0}, +{255, 133, 0}, +{255, 134, 0}, +{255, 136, 0}, +{255, 138, 0}, +{255, 140, 0}, +{255, 141, 0}, +{255, 143, 0}, +{255, 145, 0}, +{255, 147, 0}, +{255, 148, 0}, +{255, 150, 0}, +{255, 152, 0}, +{255, 154, 0}, +{255, 155, 0}, +{255, 157, 0}, +{255, 159, 0}, +{255, 161, 0}, +{255, 162, 0}, +{255, 164, 0}, +{255, 166, 0}, +{255, 168, 0}, +{255, 169, 0}, +{255, 171, 0}, +{255, 173, 0}, +{255, 175, 0}, +{255, 176, 0}, +{255, 178, 0}, +{255, 180, 0}, +{255, 182, 0}, +{255, 184, 0}, +{255, 186, 0}, +{255, 188, 0}, +{255, 190, 0}, +{255, 191, 0}, +{255, 193, 0}, +{255, 195, 0}, +{255, 197, 0}, +{255, 199, 0}, +{255, 201, 0}, +{255, 203, 0}, +{255, 205, 0}, +{255, 206, 0}, +{255, 208, 0}, +{255, 210, 0}, +{255, 212, 0}, +{255, 213, 0}, +{255, 215, 0}, +{255, 217, 0}, +{255, 219, 0}, +{255, 220, 0}, +{255, 222, 0}, +{255, 224, 0}, +{255, 226, 0}, +{255, 228, 0}, +{255, 230, 0}, +{255, 232, 0}, +{255, 234, 0}, +{255, 235, 4}, +{255, 237, 8}, +{255, 239, 13}, +{255, 241, 17}, +{255, 242, 21}, +{255, 244, 26}, +{255, 246, 30}, +{255, 248, 35}, +{255, 248, 42}, +{255, 249, 50}, +{255, 250, 58}, +{255, 251, 66}, +{255, 252, 74}, +{255, 253, 82}, +{255, 254, 90}, +{255, 255, 98}, +{255, 255, 105}, +{255, 255, 113}, +{255, 255, 121}, +{255, 255, 129}, +{255, 255, 136}, +{255, 255, 144}, +{255, 255, 152}, +{255, 255, 160}, +{255, 255, 167}, +{255, 255, 175}, +{255, 255, 183}, +{255, 255, 191}, +{255, 255, 199}, +{255, 255, 207}, +{255, 255, 215}, +{255, 255, 223}, +{255, 255, 227}, +{255, 255, 231}, +{255, 255, 235}, +{255, 255, 239}, +{255, 255, 243}, +{255, 255, 247}, +{255, 255, 251}, +{255, 255, 255}, +{255, 255, 255}, +{255, 255, 255}, +{255, 255, 255}, +{255, 255, 255}, +{255, 255, 255}, +{255, 255, 255}, +{255, 255, 255} +}; + +#endif diff --git a/Source/Kernel/IKAROS_Math.cc b/Source/Kernel/IKAROS_Math.cc new file mode 100755 index 000000000..08c93370f --- /dev/null +++ b/Source/Kernel/IKAROS_Math.cc @@ -0,0 +1,3286 @@ +// +// IKAROS_Math.cc Various math functions for IKAROS +// +// Copyright (C) 2006-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#include "IKAROS_System.h" +#include "IKAROS_Math.h" +#include "IKAROS_Utils.h" + +#include +#include + +//#include // FIXME: Remove + +// includes for image processing (JPEG) + +#include +extern "C" +{ +#include "jpeglib.h" +#include +} + + + + +#ifdef MAC_OS_X +#include +#endif + +#ifdef LINUX +#define MAXFLOAT 3.402823466e+38f +#ifdef USE_BLAS +extern "C" +{ +#include "gsl/gsl_blas.h" +} +#endif +#endif + +#ifdef WINDOWS +#define MAXFLOAT 3.402823466e+38f +#ifdef USE_BLAS +extern "C" +{ +#include "gsl/gsl_blas.h" +} +#endif +#endif + +#ifdef WINDOWS32 +#define M_PI 3.14159265358979323846264338328f +#undef min +#undef max +#endif + +namespace ikaros +{ + extern const float maxfloat = MAXFLOAT; + extern const float pi = M_PI; + extern const float sqrt2pi = sqrt(2*pi); + + float eps(float x) + { + return nextafterf(fabsf(x), MAXFLOAT)-fabsf(x); + } + + // misc scalar functions + + // MARK: - + // MARK: functions + + float trunc(float x) + { +#ifdef WINDOWS32 + return (float)((int)x); +#else + return ::truncf((int)x); +#endif + } + float exp(float x) + { + return ::expf(x); + } + float pow(float x, float y) + { + return ::powf(x, y); + } + float log(float x) + { + return ::logf(x); + } + float log10(float x) + { + return ::log10f(x); + } + float sin(float x) + { + return ::sinf(x); + } + float cos(float x) + { + return ::cosf(x); + } + float tan(float x) + { + return ::tanf(x); + } + float asin(float x) + { + return ::asinf(x); + } + float acos(float x) + { + return ::acosf(x); + } + float atan(float x) + { + return ::atanf(x); + } + float atan2(float x, float y) + { + return ::atan2f(x, y); + } + float * + atan2(float * r, float * a, float * b, int size) + { +#ifdef USE_VFORCE + vvatan2f(r, a, b, &size); +#else + for (int i=0; i= 1.0); + + w = sqrt((-2.0f * log(w))/w); + y1 = x1 * w; + //y2 = x2 * w; + + return mean+sigma*y1; + } + + + + // MARK: - + // MARK: sqr + + // sqr + int + sqr(int x) + { + return x*x; + } + + float + sqr(float x) + { + return x*x; + } + + float * + sqr(float * a, int size) + { + sqr(a, a, size); + return a; + } + + float ** + sqr(float ** a, int sizex, int sizey) + { + sqr(*a, sizex*sizey); + return a; + } + + float * + sqr(float * r, float * a, int size) + { +#ifdef USE_VDSP + vDSP_vsq(a, 1, r, 1, size); +#else + for (int i=0; i y ? x : y); + } + + float + max(float x, float y) + { + return (x > y ? x : y); + } + + float + max(float * a, int size) + { +#ifdef USE_VDSP + float r; + vDSP_maxv(a, 1, &r, size); + return r; +#else + int mi = 0; + for (int i=0; i a[mi]) + mi = i; + return a[mi]; +#endif + } + + float + max(float ** a, int sizex, int sizey) + { + return max(*a, sizex*sizey); + } + + float * + max(float * r, float * a, int size) + { +#ifdef USE_VDSP + vDSP_vmax(a, 1, r, 1, r, 1, size); +#else + for (int i=0; i r[i]) + r[i] = a[i]; +#endif + return r; + } + + float ** + max(float ** r, float ** a, int sizex, int sizey) + { + max(*r, *a, sizex*sizey); + return r; + } + + float * + max(float * r, float * a, float * b, int size) + { +#ifdef USE_VDSP + vDSP_vmax(a, 1, b, 1, r, 1, size); +#else + for (int i=0; i b[i]) + r[i] = a[i]; + else + r[i] = b[i]; +#endif + return r; + } + + float ** + max(float ** r, float ** a, float ** b, int sizex, int sizey) + { + max(*r, *a, *b, sizex*sizey); + return r; + } + + int + arg_max(float * a, int size) + { + if (size < 1) + return -1; + float m = a[0]; + float t; + int mi = 0; + for (int i=1; i m) + { + mi = i; + m = t; + } + return mi; + } + + void + arg_max(int & x, int & y, float ** a, int sizex, int sizey) + { + float t; + float max = a[y][x]; + for (int j=0; j max) + { + x = i; + y = j; + max = t; + } + } + + // minmax + float * + minmax(float & min, float & max, float * a, int size) + { + min = *a; + max = *a; + float t; + for (int i=0; i max) + max = t; + else if (t < min) + min = t; + return a; + } + + float ** + minmax(float & min, float & max, float ** a, int sizex, int sizey) + { + minmax(min, max, *a, sizex*sizey); + return a; + } + + // MARK: - + // MARK: mean + + // mean + float + mean(float * a, int size) + { +#ifdef USE_VDSP + float r; + vDSP_meanv(a, 1, &r, size); + return r; +#else + float s = 0; + for (int i=0; i high) + return high; + else + return x; + } + + float * + clip(float * a, float low, float high, int size) + { +#ifdef USE_VDSP + vDSP_vclip(a, 1, &low, &high, a, 1, size); +#else + for (int i=0; i high) + a[i] = high; +#endif + return a; + } + + float ** + clip(float ** a, float low, float high, int sizex, int sizey) + { + clip(*a, low, high, sizex*sizey); + return a; + } + + float * + clip(float * r, float * a, float low, float high, int size) + { +#ifdef USE_VDSP + vDSP_vclip(a, 1, &low, &high, r, 1, size); +#else + for (int i=0; i high) + r[i] = high; + else + r[i] = a[i]; +#endif + return r; + } + + float ** + clip(float ** r, float ** a, float low, float high, int sizex, int sizey) + { + clip(*r, *a, low, high, sizex*sizey); + return r; + } + + // MARK: - + // MARK: add and subtract + + // add + float + add(float * a, int size) // sum a + { + float r = 0; +#ifdef USE_VDSP + vDSP_sve(a, 1, &r, size); +#else + for (int i=0; i=0; k--) + { + s += (*aj++) * (*bki); + bki += sizex; + } + r[j][i] = s; + } + } +#endif + if(a!=aa) + destroy_matrix(aa); + + if(b!=bb) + destroy_matrix(bb); + + return r; + } + + // dot - scalar product + float + dot(float * a, float * b, int size) + { +#ifdef USE_BLAS + return cblas_sdot(size, a, 1, b, 1); +#elif defined USE_VDSP + float r = 0; + vDSP_dotpr(a, 1, b, 1, &r, size); + return r; +#else + float r = 0; + for (int i=0; i abs(m[p][j])) + p = i; + + if(pivots) + pivots[j] = p; + + if(m[p][j] != 0) + { + if(p != j) + { + swap_rows(m, j, p, sizex); + pd = -pd; + } + + if(j < sizey) + { + p = j+1; + double s = 1/m[j][j]; // could test for overflow here + for(int k=j+1; k=0; j--) + { + for(int i=j+1; i=0; j--) + { + int jp = pivots[j]; + if(jp != j) + swap_columns(a, j, jp, n); + } + + delete t; + return true; + } + + + bool + qr(float ** q, float ** r, float **a, int size) + { + int i,j,k; + float scale,sigma,sum,tau; + float c[size]; + float d[size]; + + copy_matrix(r, a, size, size); + + bool singular=false; + for (k=0;k 0 ? sqrt(sum) : fabsf(r[k][k]); + + r[k][k] += sigma; + c[k]=sigma*r[k][k]; + d[k] = -scale*sigma; + for (j=k+1;j< size;j++) { + for (sum=0.0,i=k;i tol) + r += 1.0; + destroy_matrix(u); + destroy_matrix(v); + destroy_array(s); + return r; + } + + + + // inv inverts the square matrix b using lu decomposition and store the results in a + + bool + inv(float ** a, float ** b, int size) + { + int * pivots = new int [size]; + copy_matrix(a, b, size, size); + lu(a, size, size, NULL, pivots); + bool r = inv_lu(a, pivots, size); + delete pivots; + return r; + } + + + + // pinv calculates the psuedoinverse of b using singular value decomposition + // the results is stored in a that has size sizex * sizey + // the size of matrix b is sizey x sizex + + void + pinv(float ** a, float ** b, int sizex, int sizey) + { + int sizemin = min(sizex, sizey); + float ** u = create_matrix(sizex, sizex); + float ** v = create_matrix(sizey, sizey); + float * s = create_array(sizemin); + svd(u, s, v, b, sizey, sizex); + float ** S = create_matrix(sizex, sizey); + for(int i=0; i epsilon? + S[i][i] = 1/s[i]; + + transpose(u, sizex); + multiply(S, v, S, sizex, sizey, sizey); + multiply(a, S, u, sizex, sizey, sizex); + destroy_matrix(u); + destroy_matrix(v); + destroy_matrix(S); + destroy_array(s); + } + + + + // chol calculates the Cholesky decomposition of a symmetric positive definite matrix a + + float ** + chol(float ** r, float ** a, int size, bool & posdef) + { + posdef = true; + + for(int j=0; j=0; i--) + { + float v = 0.0; + for(int k = i; k x) + x = y; + } + + // Accumulation of right-hand transformations + + for (i=n-1;i>=0;i--) + { + if (g != 0.0) { + h = u[i][i+1] * g; + + for (j=l;j=0;i--) + { + l = i + 1; + g = q[i]; + for (j=l;j=0;k--) + { + iter = 0; + + test_f_splitting: + + for (l=k;l>=0;l--) + { + if (fabs(e[l]) <= eps) goto test_f_convergence; + if (fabs(q[l-1]) <= eps) goto cancellation; + } + + // Cancellation of e[l] if l > 0 + + cancellation: + + c = 0.0; + s = 1.0; + l1 = l - 1; + for (i=l;i<=k;i++) + { + f = s * e[i]; + e[i] *= c; + if (fabs(f) <= eps) goto test_f_convergence; + g = q[i]; + h = q[i] = hypotf(f, g); + c = g / h; + s = -f / h; + + for (j=0;j 30) + { + retval = k; + break; + } + + x = q[l]; + y = q[k-1]; + g = e[k-1]; + h = e[k]; + f = ((y-z)*(y+z) + (g-h)*(g+h)) / (2*h*y); + g = hypotf(f, 1.0); + f = ((x-z)*(x+z) + h*(y/((f<0)?(f-g):(f+g))-h))/x; + + // QR transformation + + c = s = 1.0; + for (i=l+1;i<=k;i++) + { + g = e[i]; + y = q[i]; + h = s * g; + g *= c; + e[i-1] = z = hypotf(f, h); + c = f / z; + s = h / z; + f = x * c + g * s; + g = -x * s + g * c; + h = y * s; + y *= c; + + for (j=0;j 1); + + for (k=0;k (m+n)/2) + { + for (i=0;i sizey) + { + // Transpose a and switch u and v in calls below + + float ** mt = transpose(create_matrix(sizey, sizex), m, sizey, sizex); + k = svd_implementation(v, s, u, mt, sizey, sizex); + destroy_matrix(mt); + return k; + } + + else + { + return svd_implementation(u, s, v, m, sizex, sizey); + } + } + + + // conversion + // MARK: - + // MARK: conversion + + int + lround(float x) + { +#ifdef WINDOWS32 + if ( x >= (int)x + 0.5f ) + return (int)x + 1; + else + return (int)x; +#else + return int(::lroundf(x)); +#endif + } + + void + float_to_byte(unsigned char * r, float * a, float min, float max, int size) + { +#ifdef USE_VIMAGE + struct vImage_Buffer src = + { + a, 1, size, size*sizeof(float) + }; + struct vImage_Buffer dest = + { + r, 1, size, size*sizeof(float) + }; + vImage_Error err = vImageConvert_PlanarFtoPlanar8 (&src, &dest, max, min, 0); + if (err < 0) printf("IKAROS_Math:float_to_byte vImage_Error = %ld\n", err); +#else + for (int i=0; i max) + r[i] = 255; + else + r[i] = int(255.0*(a[i]-min)/(max-min)); +#endif + } + + void + byte_to_float(float * r, unsigned char * a, float min, float max, int size) + { + for (int i=0; i= rs) + return i; + } + + return size-1; + } + + void + select_boltzmann(int & x, int & y, float ** m, int sizex, int sizey, float T) + { + double sum = 0; + double alpha = 1/T; + for (int j=0; j= rs) + { + x = i; + y = j; + return; + } + + x = sizex-1; + y = sizey-1; + } + + // Simple minded recursive implementation + // + // FIXME: It will not follow a gradient along the edges of the matrix/image *** + void + ascend_gradient(int & x, int & y, float ** m, int sizex, int sizey) + { + if (x == 0) return; + if (y == 0) return; + if (x == sizex-1) return; + if (y == sizey-1) return; + int mx = x; + int my = y; + for (int i=-1; i<=1; i++) + for (int j=-1; j<=1; j++) + if (m[y+j][x+i] > m[my][mx]) + { + mx = x+i; + my = y+j; + } + if (mx != x || my != y) + { + x = mx; + y = my; + ascend_gradient(x, y, m, sizex, sizey); + } + } + + void + descend_gradient(int & x, int & y, float ** m, int sizex, int sizey) + { + if (x == 0) return; + if (y == 0) return; + if (x == sizex-1) return; + if (y == sizey-1) return; + int mx = x; + int my = y; + for (int i=-1; i<=1; i++) + for (int j=-1; j<=1; j++) + if (m[y+j][x+i] < m[my][mx]) + { + mx = x+i; + my = y+j; + } + if (mx != x || my != y) + { + x = mx; + y = my; + descend_gradient(x, y, m, sizex, sizey); + } + } + + + // image file formats + // MARK: - + // MARK: image file formats + // + // these functions will be moved to a separate file in the future + // + + // create jpeg functions + + struct jpeg_destination { + struct jpeg_destination_mgr dest_mgr; + JOCTET * buffer; + size_t size; + size_t used; + }; + + + static void + dst_init(j_compress_ptr cinfo) + { + struct jpeg_destination *dst = (jpeg_destination *)cinfo->dest; + dst->used = 0; + dst->size = 2048+cinfo->image_width * cinfo->image_height * cinfo->input_components * 2; // arbitrary initial size ; 2048 for header in case of very small images + dst->buffer = (JOCTET *)malloc(dst->size * sizeof *dst->buffer); + dst->dest_mgr.next_output_byte = dst->buffer; + dst->dest_mgr.free_in_buffer = dst->size; + return; + } + + + // FIXME: Something goes wrong when dst_empty is called more than once + // Fortunately it never happens since the size set by dst_init is large enough + + static boolean + dst_empty(j_compress_ptr cinfo) + { + struct jpeg_destination *dst = (jpeg_destination *)cinfo->dest; + dst->used = dst->size - dst->dest_mgr.free_in_buffer; + dst->size *= 2; + dst->buffer = (JOCTET *)realloc(dst->buffer, dst->size * sizeof *dst->buffer); + dst->dest_mgr.next_output_byte = &dst->buffer[dst->used]; + dst->dest_mgr.free_in_buffer = dst->size - dst->used; + return true; + } + + + static void + dst_term(j_compress_ptr cinfo) + { + struct jpeg_destination *dst = (jpeg_destination *)cinfo->dest; + dst->used = dst->size - dst->dest_mgr.free_in_buffer; + return; + } + + + static void + jpeg_set_destination(j_compress_ptr cinfo, struct jpeg_destination *dst) + { + dst->dest_mgr.init_destination = dst_init; + dst->dest_mgr.empty_output_buffer = dst_empty; + dst->dest_mgr.term_destination = dst_term; + cinfo->dest = (jpeg_destination_mgr *)dst; + return; + } + + + + char * + create_jpeg(long int & size, float ** matrix, int sizex, int sizey, float minimum, float maximum) + { + if (matrix == NULL) + { + size = 0; + return NULL; + } + + JSAMPLE * image_buffer = new JSAMPLE [sizex]; + JSAMPROW row_pointer[1]; + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + struct jpeg_destination dst; + + //int row_stride; // physical row width in image buffer + + cinfo.err = jpeg_std_error(&jerr); + + jpeg_create_compress(&cinfo); // Replace with ikaros error handler later + + cinfo.image_width = sizex; //* image width and height, in pixels + cinfo.image_height = sizey; + cinfo.input_components = 1; // # of color components per pixel + cinfo.in_color_space = JCS_GRAYSCALE; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, 100, true); // Highest quality + jpeg_set_destination(&cinfo, &dst); + + // Do the compression + + jpeg_start_compress(&cinfo, true); + + //row_stride = sizex * 1; // JSAMPLEs per row in image_buffer + int j=0; + + while (cinfo.next_scanline < cinfo.image_height) + { + // Convert row to image buffer (assume max == 1 for now) + + JSAMPLE * ib = image_buffer; + if (maximum != minimum) + float_to_byte(image_buffer, matrix[j], minimum, maximum, sizex); + else + for (int i=0; i 1.0 ? 1.0 : r[j][i])); + float gg = (g[j][i] < 0.0 ? 0.0 : (g[j][i] > 1.0 ? 1.0 : g[j][i])); + float bb = (b[j][i] < 0.0 ? 0.0 : (b[j][i] > 1.0 ? 1.0 : b[j][i])); + + // clipping |= (rr != r[j][i]) || (gg != g[j][i]) || (bb != b[j][i]); + + image_buffer[x++] = int(255.0*rr); + image_buffer[x++] = int(255.0*gg); + image_buffer[x++] = int(255.0*bb); + } + + // Write to compressor + row_pointer[0] = image_buffer; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + j++; + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + delete [] image_buffer; + + size = dst.used; + return (char *)dst.buffer; + } + + + + void + destroy_jpeg(char * jpeg) + { + free(jpeg); + } + + + // decode jpeg functions + + typedef struct { + struct jpeg_source_mgr pub; // public fields + JOCTET eoi_buffer[2]; // a place to put a dummy EOI + } my_source_mgr; + + typedef my_source_mgr * my_src_ptr; + + + static void + init_source (j_decompress_ptr cinfo) + { + } + + + static boolean + fill_input_buffer (j_decompress_ptr cinfo) + { + my_src_ptr src = (my_src_ptr) cinfo->src; + + // WARNMS(cinfo, JWRN_JPEG_EOF); + + // Create a fake EOI marker + src->eoi_buffer[0] = (JOCTET) 0xFF; + src->eoi_buffer[1] = (JOCTET) JPEG_EOI; + src->pub.next_input_byte = src->eoi_buffer; + src->pub.bytes_in_buffer = 2; + + return TRUE; + } + + + static void + skip_input_data (j_decompress_ptr cinfo, long num_bytes) + { + my_src_ptr src = (my_src_ptr) cinfo->src; + + if (num_bytes > 0) { + while (num_bytes > (long) src->pub.bytes_in_buffer) { + num_bytes -= (long) src->pub.bytes_in_buffer; + (void) fill_input_buffer(cinfo); + // note we assume that fill_input_buffer will never return FALSE, so suspension need not be handled. + } + src->pub.next_input_byte += (size_t) num_bytes; + src->pub.bytes_in_buffer -= (size_t) num_bytes; + } + } + + + static void + term_source (j_decompress_ptr cinfo) + { + } + + + static void + jpeg_memory_src (j_decompress_ptr cinfo, const JOCTET * buffer, size_t bufsize) + { + my_src_ptr src; + + if (cinfo->src == NULL) // first time for this JPEG object? + { + cinfo->src = (struct jpeg_source_mgr *) + (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_PERMANENT, sizeof(my_source_mgr)); + } + + src = (my_src_ptr) cinfo->src; + src->pub.init_source = init_source; + src->pub.fill_input_buffer = fill_input_buffer; + src->pub.skip_input_data = skip_input_data; + src->pub.resync_to_restart = jpeg_resync_to_restart; // use default method + src->pub.term_source = term_source; + + src->pub.next_input_byte = buffer; + src->pub.bytes_in_buffer = bufsize; + } + + + struct my_error_mgr + { + struct jpeg_error_mgr pub; // "public" fields + jmp_buf setjmp_buffer; // for return to caller + }; + + + typedef struct my_error_mgr * my_error_ptr; + + + static void + my_error_exit (j_common_ptr cinfo) + { + my_error_ptr myerr = (my_error_ptr) cinfo->err; + (*cinfo->err->output_message) (cinfo); + longjmp(myerr->setjmp_buffer, 1); + } + + + bool + jpeg_get_info(int & sizex, int & sizey, int & planes, char * data, long int size) + { + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + if (setjmp(jerr.setjmp_buffer)) + { + jpeg_destroy_decompress(&cinfo); + sizex = 0; + sizey = 0; + planes = 0; + return false; + } + + jpeg_create_decompress(&cinfo); + jpeg_memory_src(&cinfo, (JOCTET *)data, size); + (void) jpeg_read_header(&cinfo, TRUE); + (void) jpeg_start_decompress(&cinfo); + + sizex = cinfo.output_width; + sizey = cinfo.output_height; + planes = cinfo.output_components; + return true; + } + + + void + jpeg_decode(float ** matrix, int sizex, int sizey, char * data, long int size) + { + + } + + + void + jpeg_decode(float ** red_matrix, float ** green_matrix, float ** blue_matrix, float ** intensity_matrix, int sizex, int sizey, char * data, long int size) + { + struct jpeg_decompress_struct cinfo; + struct my_error_mgr jerr; + FILE * infile = NULL; /* source file */ + JSAMPARRAY buffer; /* Output row buffer */ + int row_stride; /* physical row width in output buffer */ + + cinfo.err = jpeg_std_error(&jerr.pub); + jerr.pub.error_exit = my_error_exit; + + if (setjmp(jerr.setjmp_buffer)) + { + jpeg_destroy_decompress(&cinfo); + fclose(infile); + return; + } + + jpeg_create_decompress(&cinfo); + jpeg_memory_src(&cinfo, (JOCTET *)data, size); + + (void) jpeg_read_header(&cinfo, TRUE); + (void) jpeg_start_decompress(&cinfo); + row_stride = cinfo.output_width * cinfo.output_components; + + if(cinfo.output_components != 3) + { + printf("IKAROS_Math:jpeg_decode: ERROR Not a colot image.\n"); + return; + } + + if (cinfo.output_width != (unsigned int)(sizex) || cinfo.output_height != (unsigned int)(sizey)) + { + printf("IKAROS_Math:jpeg_decode: ERROR Incorresct size for destination.\n"); + return; + } + + buffer = (*cinfo.mem->alloc_sarray)((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1); + + // RGB Color Image + + float c255 = 1.0/255.0; + float c3 = 1.0/3.0; + while (cinfo.output_scanline < cinfo.output_height) + { + (void) jpeg_read_scanlines(&cinfo, buffer, 1); + unsigned char * buf = buffer[0]; + int ix = (cinfo.output_scanline-1); + float * r = red_matrix[ix]; + float * g = green_matrix[ix]; + float * b = blue_matrix[ix]; + float * iy = intensity_matrix[ix]; + for (int i=0; i=sizex) return; + if(y>=sizey) return; + image[y][x] = color; + } + + void + draw_line(float ** image, int sizex, int sizey, int x0, int y0, int x1, int y1, float color) + { + bool steep = abs(y1 - y0) > abs(x1 - x0); + if(steep) + { + swap(x0, y0); + swap(x1, y1); + } + + if(x0 > x1) + { + swap(x0, x1); + swap(y0, y1); + } + + int deltax = x1 - x0; + int deltay = abs(y1 - y0); + float error = 0; + float deltaerr = float(deltay) / float(deltax); + int ystep; + int y = y0; + + if(y0 < y1) + ystep = 1; + else + ystep = -1; + + for(int x=x0; x<=x1; x++) + { + if(steep) + plot(image, sizex, sizey, x, y, color); + else + plot(image, sizex, sizey, y, x, color); + + error = error + deltaerr; + + if(error >= 0.5) + { + y = y + ystep; + error = error - 1.0; + } + } + } + + + void + draw_line(float ** red_image, float ** green_image, float ** blue_image, int sizex, int sizey, int x0, int y0, int x1, int y1, float red, float green, float blue) + { + draw_line(red_image, sizex, sizey, x0, y0, x1, y1, red); + draw_line(green_image, sizex, sizey, x0, y0, x1, y1, green); + draw_line(blue_image, sizex, sizey, x0, y0, x1, y1, blue); + } + + + void + draw_circle(float ** image, int sizex, int sizey, int x0, int y0, int radius, float color) + { + int f = 1 - radius; + int ddF_x = 1; + int ddF_y = -2 * radius; + int x = 0; + int y = radius; + + plot(image, sizex, sizey, x0, y0 + radius, color); + plot(image, sizex, sizey, x0, y0 - radius, color); + plot(image, sizex, sizey, x0 + radius, y0, color); + plot(image, sizex, sizey, x0 - radius, y0, color); + + while(x < y) + { + if(f >= 0) + { + y--; + ddF_y += 2; + f += ddF_y; + } + x++; + ddF_x += 2; + f += ddF_x; + plot(image, sizex, sizey, x0 + x, y0 + y, color); + plot(image, sizex, sizey, x0 - x, y0 + y, color); + plot(image, sizex, sizey, x0 + x, y0 - y, color); + plot(image, sizex, sizey, x0 - x, y0 - y, color); + plot(image, sizex, sizey, x0 + y, y0 + x, color); + plot(image, sizex, sizey, x0 - y, y0 + x, color); + plot(image, sizex, sizey, x0 + y, y0 - x, color); + plot(image, sizex, sizey, x0 - y, y0 - x, color); + } + } + + + void + draw_circle(float ** red, float ** green, float ** blue, int sizex, int sizey, int x, int y, int radius, float r, float g, float b) + { + draw_circle(red, sizex, sizey, x, y, radius, r); + draw_circle(green, sizex, sizey, x, y, radius, g); + draw_circle(blue, sizex, sizey, x, y, radius, b); + } + +} + diff --git a/Source/Kernel/IKAROS_Math.h b/Source/Kernel/IKAROS_Math.h new file mode 100755 index 000000000..ee8e6f6ae --- /dev/null +++ b/Source/Kernel/IKAROS_Math.h @@ -0,0 +1,323 @@ +// +// IKAROS_Math.h Various math functions for IKAROS +// +// Copyright (C) 2006-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#ifndef IKAROS_MATH +#define IKAROS_MATH + +// order of sizes is ALWAYS x before y +// the sizes nearly always goes last of the arguments + +namespace ikaros +{ + + extern const float pi; + extern const float sqrt2pi; + extern const float maxfloat; + + float eps(float x); + + // misc scalar + + float exp(float x); + float pow(float x, float y); + + float log(float x); + float log10(float x); + + + float sin(float x); + float cos(float x); + float tan(float x); + float asin(float x); + float acos(float x); + float atan(float x); + + + float atan2(float x, float y); + float * atan2(float * r, float * a, float * b, int size); + float ** atan2(float ** r, float ** a, float ** b, int sizex, int sizey); + + float mod(float x, float y); + + float gaussian(float x, float sigma); + + float * gaussian(float * r, float * a, float sigma, int size); + float ** gaussian(float ** r, float ** m, float sigma, int sizex, int sizey); + + + float * gaussian(float * r, float sigma, int size); + float * gaussian(float * r, float x, float sigma, int size); + float ** gaussian(float ** r, float sigma, int sizex, int sizey); + float ** gaussian(float ** r, float x, float y, float sigma, int sizex, int sizey); + + float gaussian1(float x, float sigma); + + float * gaussian1(float * r, float * a, float sigma, int size); + float ** gaussian1(float ** r, float ** m, float sigma, int sizex, int sizey); + + float * gaussian1(float * r, float sigma, int size); + float * gaussian1(float * r, float x, float sigma, int size); + float ** gaussian1(float ** r, float sigma, int sizex, int sizey); + float ** gaussian1(float ** r, float x, float y, float sigma, int sizex, int sizey); + + float random(float low, float high); + float * random(float * r, float low, float high, int size); + float ** random(float ** r, float low, float high, int sizex, int sizey); + + int random(int high); // 0 <= int < high + + float gaussian_noise(float mean, float sigma); + + bool zero(float * a, int size); + bool zero(float ** a, int sizex, int sizey); + bool non_zero(float * a, int size); + bool non_zero(float ** a, int sizex, int sizey); + + int sqr(int x); + float sqr(float x); + float * sqr(float * a, int size); + float ** sqr(float ** r, int sizex, int sizey); + float * sqr(float * r, float * a, int size); + float ** sqr(float ** r, float ** a, int sizex, int sizey); + + + float sqrt(int x); + float sqrt(float x); + float * sqrt(float * a, int size); + float ** sqrt(float ** m, int sizex, int sizey); + float * sqrt(float * r, float * a, int size); + float ** sqrt(float ** r, float ** a, int sizex, int sizey); + + + float hypot(float x, float y); + float * hypot(float * r, float * a, float * b, int size); + float ** hypot(float ** r, float ** a, float ** b, int sizex, int sizey); + + + float dist(float * a, float * b, int size); + float dist(float ** a, float ** b, int sizex, int sizey); + + float norm(float * a, int size); + float norm(float ** a, int sizex, int sizey); + + float dist1(float * a, float * b, int size); + float dist1(float ** a, float ** b, int sizex, int sizey); + + float norm1(float * a, int size); + float norm1(float ** a, int sizex, int sizey); + + float * normalize(float * a, int size); + float ** normalize(float ** m, int sizex, int sizey); + + float * normalize1(float * a, int size); + float ** normalize1(float ** m, int sizex, int sizey); + + float * normalize_max(float * a, int size); + float ** normalize_max(float ** m, int sizex, int sizey); + + int abs(int x); + float abs(float x); + float * abs(float * a, int size); + float ** abs(float ** m, int sizex, int sizey); + float * abs(float * r, float * a, int size); + float ** abs(float ** r, float ** m, int sizex, int sizey); + + + int min(int x, int y); + float min(float x, float y); + float min(float * a, int size); + float min(float ** a, int sizex, int sizey); + float * min(float * r, float * a, int size); + float ** min(float ** r, float ** a, int sizex, int sizey); + float * min(float * r, float * a, float * b, int size); + float ** min(float ** r, float ** a, float ** b, int sizex, int sizey); + + int arg_min(float * a, int size); + void arg_min(int & x, int & y, float ** a, int sizex, int sizey); + + + int max(int x, int y); + float max(float x, float y); + float max(float * a, int size); + float max(float ** a, int sizex, int sizey); + float * max(float * r, float * a, int size); + float ** max(float ** r, float ** a, int sizex, int sizey); + float * max(float * r, float * a, float * b, int size); + float ** max(float ** r, float ** a, float ** b, int sizex, int sizey); + + int arg_max(float * a, int size); + void arg_max(int & x, int & y, float ** a, int sizex, int sizey); + + + float * minmax(float & min, float & max, float * a, int size); + float ** minmax(float & min, float & max, float ** a, int sizex, int sizey); + + float mean(float * a, int size); + float mean(float ** a, int sizex, int sizey); + + + float clip(float x, float low, float high); + float * clip(float * a, float low, float high, int size); + float ** clip(float ** a, float low, float high, int sizex, int sizey); + float * clip(float * r, float * a, float low, float high, int size); + float ** clip(float ** r, float ** a, float low, float high, int sizex, int sizey); + + + float add(float * a, int size); // sum a + float add(float ** a, int sizex, int sizey); // sum a + + float * add(float * r, float alpha, int size); // r = r + alpha + float ** add(float ** r, float alpha, int sizex, int sizey); // r = r + alpha + + float * add(float * r, float * a, int size); // r = r + a + float ** add(float ** r, float ** a, int sizex, int sizey); // r = r + a + float * add(float * r, float * a, float * b, int size); // r = a + b + float ** add(float ** r, float ** a, float ** b, int sizex, int sizey); // r = a + b + float * add(float * r, float alpha, float * a, int size); // r = r + alpha * a + float ** add(float ** r, float alpha, float ** a, int sizex, int sizey); // r = r + alpha * a + float * add(float * r, float alpha, float * a, float beta, float * b, int size); // r = alpha * a + beta * b + float ** add(float ** r, float alpha, float ** a, float beta, float ** b, int sizex, int sizey); // r = alpha * a + beta * b + float * add(float * r, float alpha, float * a, float beta, int size); // r = alpha * a + beta + float ** add(float ** r, float alpha, float ** a, float beta, int sizex, int sizey); // r = alpha * a + beta + + float * subtract(float * r, float alpha, int size); // r = r - alpha + float ** subtract(float ** r, float alpha, int sizex, int sizey); // r = r - alpha + + float * subtract(float alpha, float * r, int size); // r = alpha - r + float ** subtract(float alpha, float ** r, int sizex, int sizey); // r = alpha - r + + float * subtract(float * r, float * a, float alpha, int size); // r = a - alpha *** undocumented *** + float ** subtract(float ** r, float ** a, float alpha, int sizex, int sizey); // r = a - alpha *** undocumented *** + + + float * subtract(float * r, float * a, int size); + float ** subtract(float ** r, float ** a, int sizex, int sizey); + float * subtract(float * r, float * a, float * b, int size); + float ** subtract(float ** r, float ** a, float ** b, int sizex, int sizey); + + + float * multiply(float * a, float alpha, int size); + float ** multiply(float ** a, float alpha, int sizex, int sizey); + float * multiply(float * r, float * a, float alpha, int size); + float ** multiply(float ** r, float ** a, float alpha, int sizex, int sizey); + float * multiply(float * r, float * a, int size); + float ** multiply(float ** r, float ** a, int sizex, int sizey); + float * multiply(float * r, float * a, float * b, int size); + float ** multiply(float ** r, float ** a, float ** b, int sizex, int sizey); + + float * multiply(float * r, float ** a, float * b, int sizex, int sizey); // matrix x vector + float ** multiply(float ** r, float ** a, float ** b, int sizex, int sizey, int n); // matrix x matrix; size of result, n = columns of a = rows of b + + float dot(float * a, float * b, int size); + float dot(float ** a, float ** b, int sizex, int sizey); + + float ** outer(float ** r, float * a, float * b, int sizex, int sizey); // outer product; r[j][i] = a[i]*b[j]; sizex = sizeof(a), sizey = sizeof(b) + + float * divide(float * r, float * a, int size); + float ** divide(float ** r, float ** a, int sizex, int sizey); + float * divide(float * r, float * a, float * b, int size); + float ** divide(float ** r, float ** a, float ** b, int sizex, int sizey); + + // linear algebra + + float ** eye(float ** a, int size); // identity matrix + float ** transpose(float ** a_T, float ** a, int sizex, int sizey); + float ** transpose(float ** a, int size); // transpose square matrix in place + float det(float ** m, int size); // determinant of m + float trace(float ** m, int size); // trace of m + float rank(float ** m, int sizex, int sizey, float tol=0); // the rank of the matrix + bool inv(float ** a, float ** b, int size); // invert matrix b and store in a; returns false if singular + void pinv(float ** a, float ** b, int sizex, int sizey); // pseudoinverse of b is stored in a; sizeof(a) = sizex x sizey; sizeof(b) = sizey x sizex + float * mldivide(float * r, float ** m, float * a, int size); // left divide; solves mr = a + + void lu(float ** l, float ** u, float ** a, int sizex, int sizey); // LU-decomposition of a + bool qr(float ** q, float ** r, float ** a, int size); // QR-decomposition of a (square matrix), returns false if a is ingular + float ** chol(float ** r, float ** a, int size, bool & posdef); // Cholesky decomposition of a symmetric positive definite matrix a; posdef = false if not positive definite + float ** chol(float ** r, float ** a, int size); + int svd(float ** u, float * s, float ** v, float ** m, int sizex, int sizey); // Singular value decomposition: u*diag(s)*v' = m; m has size sizex x sizey + + + // conversion + + float trunc(float x); + int lround(float x); + void float_to_byte(unsigned char * r, float * a, float min, float max, int size); // min, max of float; byte is always 0-255 + void byte_to_float(float * r, unsigned char * a, float min, float max, int size); // min, max of float; byte is always 0-255 + + int string_to_int(const char * s, int d=0); // convert to int; use d if char is NULL + float string_to_float(const char * s, float d=0.0); // convert to float; use d if char is NULL + + char * int_to_string(char * s, int n, int i); // put the string representation of the value i into s using a maximum of n characters + char * float_to_string(char * s, float v, int decimals, int n); + + // misc + + int select_boltzmann(float * a, int size, float T); + void select_boltzmann(int & x, int & y, float ** m, int sizex, int sizey, float T); + + void ascend_gradient(int & x, int & y, float ** m, int sizex, int sizey); + void descend_gradient(int & x, int & y, float ** m, int sizex, int sizey); + + + // + // image processing + // + + float ** convolve(float ** result, float ** source, float ** kernel, int rsizex, int rsizey, int ksizex, int ksizey, float bias = 0.0); + + // ksizex and ksizey must be odd for BLAS calls to work // TODO: Check that it works otherwise as well + + float ** box_filter(float ** r, float ** a, int sizex, int sizey, int boxsize, bool scale = false, float ** t = 0); + + /* + float ** erode(float ** result, int masksize, int sizex, int sizey); + float ** dilate(float ** result, int masksize, int sizex, int sizey); + float ** open(float ** result, int masksize, int sizex, int sizey); + float ** close(float ** result, int masksize, int sizex, int sizey); + */ + + // image file formats + + char * create_jpeg(long int & size, float ** matrix, int sizex, int sizey, float minimum=0, float maximum=1); + char * create_jpeg(long int & size, float ** matrix, int sizex, int sizey, int color_table[256][3]); + char * create_jpeg(long int & size, float ** red_matrix, float ** green_matrix, float ** blue_matrix, int sizex, int sizey); + + void destroy_jpeg(char * jpeg); + + void decode_jpeg(float ** matrix, int sizex, int sizey, char * data, long int size); + void decode_jpeg(float ** red_matrix, float ** green_matrix, float ** blue_matrix, int sizex, int sizey, char * data, long int size); + + bool jpeg_get_info(int & sizex, int & sizey, int & planes, char * data, long int size); + void jpeg_decode(float ** matrix, int sizex, int sizey, char * data, long int size); // NOT IMPLEMENTED + void jpeg_decode(float ** red_matrix, float ** green_matrix, float ** blue_matrix, float ** intensity_matrix, int sizex, int sizey, char * data, long int size); + + // drawing routines + + void draw_line(float ** image, int sizex, int sizey, int x0, int y0, int x1, int x2, float color); + void draw_line(float ** red, float ** green, float ** blue, int sizex, int sizey, int x0, int y0, int x1, int x2, float r, float g, float b); + + void draw_circle(float ** image, int sizex, int sizey, int x, int y, int radius, float color); + void draw_circle(float ** red, float ** green, float ** blue, int sizex, int sizey, int x, int y, int radius, float r, float g, float b); + +} + +#endif diff --git a/Source/Kernel/IKAROS_Serial.h b/Source/Kernel/IKAROS_Serial.h new file mode 100755 index 000000000..9527c1a98 --- /dev/null +++ b/Source/Kernel/IKAROS_Serial.h @@ -0,0 +1,78 @@ +// +// IKAROS_Serial.h Serial IO utilities for the IKAROS project +// +// Copyright (C) 2006-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Edited by Birger + +#ifndef IKAROS_SERIAL +#define IKAROS_SERIAL + + +#define DEFAULT_MAX_FAILED_READS 10 + +#include "IKAROS.h" + +#include +#include + + + +class SerialException +{ +public: + const char * string; + int internal_reference; + + SerialException(const char * s, int ref = 0) : string(s), internal_reference(ref) {}; +}; + + + +class SerialData; + +class Serial +{ +public: + + Serial(); + Serial(const char * device, unsigned long baud_rate); // defaults to 8 bits, no partity, 1 stop bit + ~Serial(); + + int SendString(const char *sendbuf); + int SendBytes(const char *sendbuf, int length); + + int ReceiveUntil(char *rcvbuf, char c); + int ReceiveBytes(char *rcvbuf, int length); + + void Close(); + + void Flush(); + void FlushOut(); + void FlushIn(); + +protected: + int max_failed_reads; + +private: + SerialData * data; +}; + + +#endif + + diff --git a/Source/Kernel/IKAROS_Serial_BSD.cc b/Source/Kernel/IKAROS_Serial_BSD.cc new file mode 100755 index 000000000..04afa498f --- /dev/null +++ b/Source/Kernel/IKAROS_Serial_BSD.cc @@ -0,0 +1,244 @@ +// +// IKAROS_Serial_BSD.cc Serial IO utilities for the IKAROS project +// +// Copyright (C) 2006-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#include "IKAROS_Serial.h" + +#include +#include +#include + +#include +#include +#include + + +#ifdef MAC_OS_X +#include +#include +#endif + + + +// +// SerialData (for Unix this is simply the file descriptor) +// + +class SerialData +{ +public: + int fd; + + SerialData() : fd(-1) + {}; +}; + + + +Serial::Serial(const char * device_name, unsigned long baud_rate) +{ + struct termios options; + + max_failed_reads = DEFAULT_MAX_FAILED_READS; + + data = new SerialData(); + + data->fd = open(device_name, O_RDWR | O_NOCTTY | O_NDELAY); + if(data->fd == -1) + throw SerialException("Could not open serial device. ", errno); + + fcntl(data->fd, F_SETFL, 0); // blocking + tcgetattr(data->fd, &options); // get the current options // TODO: restore on destruction of the object + +#ifndef MAC_OS_X + if(cfsetispeed(&options, baud_rate)) + throw SerialException("Could not set baud rate for input", errno); + if(cfsetospeed(&options, baud_rate)) + throw SerialException("Could not set baud rate for output", errno); +#endif + + options.c_cflag |= (CS8 | CLOCAL | CREAD); + options.c_iflag = IGNPAR; + options.c_oflag = 0; + options.c_lflag = 0; + options.c_cc[VMIN] = 0; + options.c_cc[VTIME] = 1; // tenth of seconds allowed between bytes of serial data + // but since VMIN = 0 we will wait at most 1/10 s for data then return + tcflush(data->fd, TCIOFLUSH); + tcsetattr(data->fd, TCSANOW, &options); // set the options + +#ifdef MAC_OS_X // TODO: Check this section - was not used for original version + cfmakeraw(&options); // necessary for ioctl to function; must come after setattr + const speed_t TGTBAUD = baud_rate; + int ret = ioctl(data->fd, IOSSIOSPEED, &TGTBAUD); // sets also non-standard baud rates + if (ret) + throw SerialException("Could not set baud rate", errno); +#endif +} + + + +Serial::~Serial() +{ + Close(); + delete data; +} + + + +void +Serial::Flush() +{ + tcflush(data->fd, TCIOFLUSH); +} + + + +void +Serial::FlushOut() +{ + tcflush(data->fd, TCOFLUSH); +} + + + +void +Serial::FlushIn() +{ + tcflush(data->fd, TCOFLUSH); +} + + + +// Send a string. + +int +Serial::SendString(const char *sendbuf) +{ + if(data->fd == -1) + return 0; + return int(write(data->fd, sendbuf, strlen(sendbuf))); +} + + + +// Read characters until we recive character c + +int +Serial::ReceiveUntil(char *rcvbuf, char c) +{ + if(data->fd == -1) + return 0; + + char *bufptr = rcvbuf; + long read_bytes = 0, read_bytes_tot = 0, failed_reads = 0; + + while (failed_reads < max_failed_reads) + { + read_bytes = read(data->fd, bufptr, 1); + + if (read_bytes == 0) + { + failed_reads++; + continue; + } + + if (read_bytes > 0) + { + bufptr += read_bytes; + read_bytes_tot += read_bytes; + } + + if (read_bytes < 0) + break; + + if (bufptr[-1] == c) + break; + } + + if (read_bytes_tot == 0) + return int(read_bytes); + else + return int(read_bytes_tot); +} + + + +int +Serial::SendBytes(const char *sendbuf, int length) +{ + if(data->fd == -1) + return 0; + + long n = write(data->fd, sendbuf, length); + + if(n == -1) + printf("Could not send bytes (%d)", errno); + + return int(n); +} + + + +int +Serial::ReceiveBytes(char *rcvbuf, int length) +{ + if(data->fd == -1) + return 0; + + char *bufptr = rcvbuf; + long read_bytes = 0, read_bytes_tot = 0, failed_reads = 0; + + while (failed_reads < max_failed_reads) + { + read_bytes = read(data->fd, bufptr, length - read_bytes_tot); + + if (read_bytes == 0) + { + failed_reads++; + continue; + } + + if (read_bytes < 0) + break; + + bufptr += read_bytes; + read_bytes_tot += read_bytes; + + if (read_bytes_tot >= length) + break; + } + + if (read_bytes_tot == 0) + return int(read_bytes); + else + return int(read_bytes_tot); +} + + + +void Serial::Close() +{ + Flush(); + if(data->fd != -1) + close(data->fd); +} + diff --git a/Source/Kernel/IKAROS_Serial_WIN.cc b/Source/Kernel/IKAROS_Serial_WIN.cc new file mode 100755 index 000000000..8aad3be8c --- /dev/null +++ b/Source/Kernel/IKAROS_Serial_WIN.cc @@ -0,0 +1,365 @@ +// +// IKAROS_Serial_WIN.cc Serial IO utilities for the IKAROS project +// +// Copyright (C) 2006-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + + +#include "IKAROS_Serial.h" + +#ifdef USE_WIN_SERIAL + +//#define SHOWCOM + +#include + +//for debuging +#include +#include + +// +// SerialData (the state variables needed for the connection) +// + +class SerialData +{ +public: + char* Port; + char* Comport; + HANDLE hCom; + + SerialData() {}; + ~SerialData() {}; // FIXME: delete Port; delete Comport; +}; + + + + +Serial::Serial(const char * device_name, unsigned long baud_rate) +{ + data = new SerialData(); + +#ifdef SHOWCOM + data->Comport = new char[strlen(device_name)+1]; + strcpy(data->Comport, device_name); +#endif + +#ifdef SHOWCOM + printf("(IKAROS_Serial_Win.cc)(%s) Trying to open port", data->Comport); +#endif + + data->hCom = CreateFile(device_name, + GENERIC_READ | GENERIC_WRITE, + 0, // must be opened with exclusive-access + NULL, // no security attributes + OPEN_EXISTING, // must use OPEN_EXISTING + 0, // not overlapped I/O + NULL // hTemplate must be NULL for comm devices + ); + + if (data->hCom == INVALID_HANDLE_VALUE) + { + printf("...Faild to create serialport\n"); + printf("Ikaros is shuting down....\n"); + exit(1); + } +#ifdef SHOWCOM + printf("...Succesfully (maybe)\n"); +#endif + + DCB dcb; + +#ifdef SHOWCOM + printf("(IKAROS_Serial_Win.cc)(%s) Getting parameters", data->Comport); +#endif + + if (!GetCommState(data->hCom, &dcb)) + { + printf("...Faild to get prameters\n"); + printf("Ikaros is shutdown....\n"); + exit(1); + } + +#ifdef SHOWCOM + printf("...Succesfully\n"); +#endif + +// Settings Hardcoded. Baudrate needs to have CBR_ before the baudrate. Differs form linux +// Lunux +// dcb.BaudRate = BaudRate; // set the baud rate +// dcb.ByteSize = ByteSize; // data size, xmit, and rcv +// dcb.Parity = Parity; // no parity bit +// dcb.StopBits = StopBits; // one stop bit + +// Windows + dcb.BaudRate = baud_rate; // set the baud rate, for example CBR_57600 for windows + dcb.ByteSize = 8; // data size, xmit, and rcv + dcb.Parity = NOPARITY; // no parity bit + dcb.StopBits = ONESTOPBIT; // one stop bit + +#ifdef SHOWCOM + printf("(IKAROS_Serial_Win.cc)(%s) Setting parameters", data->Comport); + printf("%i,%i,%i,%i", baud_rate, ByteSize, Parity, StopBits); +#endif + + if (!SetCommState(data->hCom, &dcb)) + { + printf("...Faild to set prameters\n"); + printf("Ikaros is shutdown....\n"); + exit(1); + } + +#ifdef SHOWCOM + printf("...Succesfully\n"); +#endif + +#ifdef SHOWCOM + printf("(IKAROS_Serial_Win.cc)(%s) Setting Timeouts", data->Comport); +#endif + //// Creating Timeouts for Serial communication + COMMTIMEOUTS timeouts; + timeouts.ReadIntervalTimeout = 400; + timeouts.ReadTotalTimeoutMultiplier = 10; + timeouts.ReadTotalTimeoutConstant = 400; + timeouts.WriteTotalTimeoutMultiplier = 10; + timeouts.WriteTotalTimeoutConstant = 400; + + if (!SetCommTimeouts(data->hCom, &timeouts)) + { + printf("...Faild to set Timeouts\n"); + printf("Ikaros is shuting down....\n"); + exit(1); + } +#ifdef SHOWCOM + printf("...Succesfully\n"); +#endif +} + + + +Serial::~Serial() +{ + delete data; +} + + + +void +Serial::Flush() +{ + // printf("%i",tcflush(fd, TCIOFLUSH)); + FlushFileBuffers(data->hCom); +} + + + +void +Serial::FlushOut() +{ + //printf("%i",tcflush(fd, TCIOFLUSH)); + // tcflush(fd, TCOFLUSH); +} + + + +void +Serial::FlushIn() +{ + // printf("%i",tcflush(fd, TCIOFLUSH)); + // tcflush(fd, TCOFLUSH); +} + + + +int +Serial::SendString(const char * sendbuf) +{ + //flush(); + unsigned long writed = 0; + + if (!WriteFile(data->hCom, sendbuf, strlen(sendbuf), &writed, 0)) + { + printf("...Faild to set send!\n"); + return(0); + } + +#ifdef SHOWCOM + printf("Send (String)\t"); + for (int i = 0; i < strlen(sendbuf); i++) + printf("%c",sendbuf[i]); + printf("\n(%i of total %i bytes sent)\n", writed,strlen(sendbuf)); + printf("=============================\n"); +#endif + if (writed < 0) + return(0); + else + return(1); +} + + + +// Read characters until we recive a '\n' +int Serial::ReceiveUntil(char * buffer, char c) +{ + char * bufptr = buffer; + int nbytes = 0; + int counter = 0; + bool start_recive = false; + + unsigned long readed = 0; + + //while ((!ReadFile(hCom, buffer, 1, &readed, 0)) || start_recive == false) + while ((nbytes = ReadFile(data->hCom, bufptr, 1, &readed, 0))) + { + //printf("in recieve string loop %i",bufptr); + //printf("nbyte = %i and readed = %i\t read= %c\n",nbytes,readed, buffer[0]); + bufptr += readed; + if (nbytes > 0) + start_recive = true; + nbytes = 0; + counter++; + if (bufptr[-1] == c) + break; + + // Loop 50 times and then return with a error +// if (counter > 50 && start_recive == false) +// { +// // No resonse from the e-puck. Wait for 0.5 sec and then flush the buffer. +// Timer::Sleep(200); +// Flush(); +// return (-2); +// } + } + +#ifdef SHOWCOM + printf("Recive (String)\t"); + for (int i = 0; i < strlen(buffer); i++) + printf("%c",buffer[i]); + printf("\n(%i bytes recived)\n", strlen(buffer)); + printf("==================\n"); +#endif + return(strlen(buffer)); +} + + + + +int +Serial::SendBytes(const char *Command, int length) +{ + unsigned long writed = 0; + int n = WriteFile(data->hCom, Command, length, &writed, 0); +#ifdef SHOWCOM + printf("Send (Binary)\t\t"); + for (int i = 0; i < length; i++) + printf(" %x",Command[i]); + printf("\n(%i of %i total bytes sent)\n", n, length ); + printf("=========================\n"); +#endif + + if (n < 0) + return(0); + else + return(1); +} + + +int +Serial::ReceiveBytes(char *rcvbuf, int length) +{ + char * bufptr = rcvbuf; + int nbytes = 0; + int bytes_left = length; + int sum_bytes = 0; + int counter = 0; + bool start_recive = false; + + unsigned long readed = 0; + + //FlushFileBuffers(hCom); + + if (!ReadFile(data->hCom, rcvbuf, length, &readed, 0)) + { + printf("...Faild to set send!\n"); + return(false); + } + else + { + if ((int)readed != length) + { +#ifdef SHOWCOM + printf("...Timedouted!\n"); +#endif + + printf("...Timedouted!\n"); + return(false); + } + else + { +#ifdef SHOWCOM + for (int i = 0; i < length; i++) + printf("%x",buffer[i]); + printf("\n"); +#endif + return(readed); + } + } +////////////////////////////////// + +// while ((nbytes = ReadFile(hCom, buffer, length, &readed, 0)) > 0 || start_recive == false) +// { +// +// sum_bytes += nbytes; +// if (nbytes == bytes_left) +// break; +// bufptr += nbytes; +// bytes_left -= nbytes; +// if (nbytes > 0) +// start_recive = true; +// nbytes = 0; +// counter++; +// // Loop 10 times and then return with a error +// if (counter > 10 && start_recive == false) +// { +// // No resonse from the e-puck. Wait for 0.5 sec and then flush the buffer. +// Timer::Sleep(50); +// Flush(); +// return (-2); +// } +// } +// if (sum_bytes != length) +// return (-1); + +#ifdef SHOWCOM + printf("Recived (Binary)\t\t"); + for (int i = 0; i < length; i++) + printf(" %c",buffer[i]); + printf("\n(%i bytes recived)\n", sum_bytes); + printf("===================\n"); +#endif + return sum_bytes; +} + + + +void Serial::Close() +{ +} + +#endif diff --git a/Source/Kernel/IKAROS_Signal.cc b/Source/Kernel/IKAROS_Signal.cc new file mode 100755 index 000000000..b8481f6bc --- /dev/null +++ b/Source/Kernel/IKAROS_Signal.cc @@ -0,0 +1,98 @@ +// +// IKAROS_Signal.cc Signal utilities for IKAROS +// +// Copyright (C) 2006-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// NOTE: There is no .h file for IKAROS_Signal since there are no callable routines +// +// This file installs a CTRL-C handler that allows IKAROS to terminate gracefully +// In case of compile errors, this file can simply be removed. +// + +#include "IKAROS_System.h" + +#ifdef WINDOWS +#include +#include + +#include + +extern bool global_terminate; // Used to flag that CTRL-C has been received; defined in IKAROS.cc +BOOL WINAPI ConsoleHandler1(DWORD dwCtrlType) +{ + printf("\nIKAROS: Will terminate after this iteration.\n"); + global_terminate= true; + SetConsoleCtrlHandler(ConsoleHandler1,FALSE); + return true; + +} +class Signal +{ + +private: + +public: + bool install_handler() + { + if (!(SetConsoleCtrlHandler(ConsoleHandler1,TRUE))) + { + printf("Unable to install (CTRL-C) handler!\n"); + return -1; + } + return true; + } + Signal() + { + install_handler(); + } +} +INIT; +#endif + +#ifdef POSIX +#include +#include + +extern bool global_terminate; // Used to flag that CTRL-C has been received; defined in IKAROS.cc +class Signal +{ + +private: + static void Handler(int s) // Catch CTRL-C, set the terminate flag and remove the handler + { // so that next CTRL-C will terminate the process immediately + global_terminate = true; + struct sigaction sa; + sa.sa_handler = SIG_DFL; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + fflush(NULL); + printf("\nIKAROS: Will terminate after this iteration.\n"); + fflush(NULL); + } +public: + Signal() // Install the CTRL-C handler + { + struct sigaction sa; + sa.sa_handler = &Signal::Handler; + sigemptyset(&sa.sa_mask); + sigaction(SIGINT, &sa, NULL); + } +} +INIT; + +#endif + diff --git a/Source/Kernel/IKAROS_Socket.h b/Source/Kernel/IKAROS_Socket.h new file mode 100755 index 000000000..0d15fa476 --- /dev/null +++ b/Source/Kernel/IKAROS_Socket.h @@ -0,0 +1,110 @@ +// +// IKAROS_Socket.h Socket utilities for the IKAROS project +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + + +#ifndef IKAROS_SOCKET +#define IKAROS_SOCKET + +#include + +#include "IKAROS_System.h" +#include "IKAROS_Utils.h" + +#ifdef USE_SOCKET + +#define PORTNO 8000 // the default port users will be connecting to + + + +class SocketException + { + public: + char * string; + int internal_reference; + + SocketException(char * s, int ref = 0) : string(s), internal_reference(ref) + {}; + }; + + + +// +// Socket used to request data from a HTTP server in a simple way +// + +class SocketData; + +class Socket + { + public: + Socket(); + ~Socket(); + + bool SendRequest(const char * hostname, int port, const char * request); + bool Poll(); // return true if data is waiting + int ReadData(char * result, int maxlen, bool fill=false); + int Get(const char * hostname, int port, const char * request, char * result, int maxlen); + void Close(); + + private: + SocketData * data; + }; + + + +// +// The class socket implements a simple HTTP server +// + +class ServerSocketData; + +class ServerSocket + { + public: + ServerSocket(int port=PORTNO); // Create server socket on port + ~ServerSocket(); + + Dictionary header; // The current HTTP request header + bool GetRequest(bool block=false); // Check for request and read if available + + bool SendHTTPHeader(Dictionary * d = NULL, const char * response=NULL); + bool SendData(const char * buffer, long size); + bool Send(const char * format, ...); + bool Send(const float *, int sizex, int sizey); + bool SendFile(const char * filename, const char * path="", Dictionary * header = NULL); + + bool Close(); // Close reply socket + + int Port(); // Get port no + const char * Host(); // Get host name + + int errcode; // Last error + private: + ServerSocketData * data; + + bool Poll(bool block=false); // Poll for connection; return >=0 if accepted connection (or > 0 CHECK!!!) + long Read(char * buffer, int maxSize); // Read + }; + + +#endif +#endif diff --git a/Source/Kernel/IKAROS_Socket_BSD.cc b/Source/Kernel/IKAROS_Socket_BSD.cc new file mode 100755 index 000000000..a0512116b --- /dev/null +++ b/Source/Kernel/IKAROS_Socket_BSD.cc @@ -0,0 +1,593 @@ +// +// IKAROS_Socket.cc Socket utilities for the IKAROS project +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#include "IKAROS_System.h" + +#ifdef USE_BSD_SOCKET + +#include "IKAROS_Socket.h" +#include "IKAROS_Math.h" + +using namespace ikaros; + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + + +#define BACKLOG 10 // how many pending connections queue will hold +#define TIMEOUT 1000 // number of attempts to read +#define TIMEOUTDEL 1000 // number of usec to sleep before each read + + + +// +// SocketData +// + +class SocketData + { + public: + int sd; + + SocketData() : sd(-1) + {}; + }; + + + +// +// Socket - functions that gets data from a HTTP server +// + +Socket::Socket() +{ + data = new SocketData(); +} + + + +Socket::~Socket() +{ + if (data->sd != -1) close(data->sd); + delete data; +} + + + +bool +Socket::SendRequest(const char * hostname, int port, const char * request) +{ + data->sd = -1; + struct sockaddr_in localAddr, servAddr; + struct hostent *h; + + if ((h = gethostbyname(hostname)) == NULL) + return false; // unkown host + + servAddr.sin_family = h->h_addrtype; + memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); + servAddr.sin_port = htons(port); + + if ((data->sd = socket(AF_INET, SOCK_STREAM, 0)) == 0) + return false; // cannot open socket + + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + localAddr.sin_port = htons(0); + + if (bind(data->sd, (struct sockaddr *) &localAddr, sizeof(localAddr)) < 0) + return false; // cannot open port + + if (connect(data->sd, (struct sockaddr *) &servAddr, sizeof(servAddr)) <0) + return false; // cannot connect + + if (write(data->sd, request, strlen(request)) <0) + return false; // cannot send data + + return data->sd != -1; +} + + + +bool +Socket::Poll() +{ + struct timeval tv; + fd_set readfds; + tv.tv_sec = 0; + tv.tv_usec = 0; + + FD_ZERO(&readfds); + FD_SET(data->sd, &readfds); + + select(data->sd+1, &readfds, NULL, NULL, &tv); + + if (FD_ISSET(data->sd, &readfds)) + return true; + else + return false; +} + + + +int +Socket::ReadData(char * result, int maxlen, bool fill) +{ + if (data->sd == -1) + return 0; + + const int BUFFER_SIZE = 1024; + static char buffer[BUFFER_SIZE]; + + int dst=0; + ssize_t rc = 0; + do + { + ssize_t read_size = (maxlen-dst < BUFFER_SIZE ? maxlen-dst : BUFFER_SIZE); + rc = read(data->sd, buffer, read_size); + for (int i=0; i0 || fill)); + + return dst; +} + + + +int +Socket::Get(const char * hostname, int port, const char * request, char * result, int maxlen) +{ + int rc = 0; + if (SendRequest(hostname, port, request)) + rc = ReadData(result, maxlen); + Close(); + + return rc; +} + + + +void +Socket::Close() +{ + if (data->sd == -1) + return; + close(data->sd); + data->sd = -1; +} + + + +// +// ServerSocketData +// + +class ServerSocketData + { + public: + int portno; + int sockfd; // Listen on sock_fd, + int new_fd; // New connection on new_fd + int block_flags; // Original flags for blocking I/O + int request_allocated_size; + char * request; +// char argument[10][256]; +// int argcnt; + + char filepath[PATH_MAX]; + + struct sockaddr_in my_addr; // My address information + struct sockaddr_in their_addr; // Connector's address information + + ServerSocketData() { request_allocated_size = 1024; request = (char *)malloc(sizeof(char)*request_allocated_size); } + }; + + + +// +// ServerSocket +// + +ServerSocket::ServerSocket(int port) +{ + data = new ServerSocketData(); + + data->portno = port; + int yes = 1; +// data->argcnt = 0; + if ((data->sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + throw SocketException(strerror(errno), 1); + + data->my_addr.sin_family = AF_INET; // host byte order + data->my_addr.sin_port = htons(port); // short, network byte order + data->my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP + memset(&(data->my_addr.sin_zero), '\0', 8); // zero the rest of the struct + + if (setsockopt(data->sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) // To avoid (most) socket already in use errors + throw SocketException(strerror(errno), 2); + + // Call to avoid SIGPIPEs on OS X + // May not work on other platforms like Linux. In that case #ifdefs should be added around it +#ifdef MAC_OS_X + if(setsockopt(data->sockfd, SOL_SOCKET, SO_NOSIGPIPE, &yes, sizeof(int)) == -1) + throw SocketException(strerror(errno), 3); +#endif + + if (bind(data->sockfd, (struct sockaddr *)&(data->my_addr), sizeof(struct sockaddr)) == -1) + throw SocketException(strerror(errno), 4); // Socket already used + + if (listen(data->sockfd, BACKLOG) == -1) + throw SocketException(strerror(errno), 5); + + signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE so that the program does not exit; catch errors when send() returns -1 instead +} + + + +ServerSocket::~ServerSocket() +{ + close(data->sockfd); + delete data; +} + + + +bool +ServerSocket::Poll(bool block) +{ + int sin_size = sizeof(struct sockaddr_in); + if(!block) + fcntl(data->sockfd, F_SETFL, O_NONBLOCK); // temporariliy make the socket non-blocking + data->new_fd = accept(data->sockfd, (struct sockaddr *)&(data->their_addr), (socklen_t*) &sin_size); + if(!block) + fcntl(data->sockfd, F_SETFL, 0); // make the socket blocking again + return (data->new_fd != -1); +} + + + +long +ServerSocket::Read(char * buffer, int maxSize) +{ + if (data->new_fd == -1) + return 0; + + ssize_t n = 0; + bzero(buffer, maxSize); + + for (int t = 0; t < TIMEOUT; t++) + { + if ((n = recv(data->new_fd, buffer, maxSize-1, 0)) >= 0) + return n; + + usleep(TIMEOUTDEL); + } + + return n; +} + + + +// strip strips non-printing characters in the beginning and end of a string +// the tsring is modified in place and a pointer to the new beginning is returned + +static char * +strip(char * s) +{ + ssize_t t = strlen(s)-1; + while(s[t] <= ' ') + s[t--] = '\0'; + while(*s <= ' ') + s++; + return s; +} + +static char * +recode(char * s) // Replace %20 and others with a space +{ + int j = 0; + for (int i=0; s[i]; i++) + if (s[j] != '%') + s[i] = s[j++]; + else + { + s[i] = ' '; + j+=3; + } + return s; +} + + + +bool +ServerSocket::GetRequest(bool block) +{ + if (!Poll(block)) + return false; + + // Loop until CRLF CRLF is found which marks the end of the HTTP request + + char * d = data->request; + data->request[0] = '\0'; + int read_count = 0; + while(!strstr(d, "\r\n\r\n")) // check border condition *** + { + long rr = Read(&d[read_count], data->request_allocated_size-read_count); + if(rr == 0) // the connections has been closed since the beginning of the request + return false; // this can occur when a view is changed; return and ignore the request + read_count += rr; + data->request[read_count] = '\0'; + if(read_count >= data->request_allocated_size-1) + data->request = (char *)realloc(data->request, data->request_allocated_size += 1024); + } + + // Parse request and header [TODO: handle that arguments in theory can span several lines accoding to the HTTP specification; although it never happens] + + char * p = data->request; + if(!p) + { + printf("ERROR: Empty HTTP request."); + return false; + } + + header.Clear(); + + header.Set("Method", strsep(&p, " ")); + header.Set("URI", recode(strsep(&p, " "))); + header.Set("HTTP-Version", strsep(&p, "\r")); + strsep(&p, "\n"); + while(p && *p != '\r') + { + char * k = strip(strsep(&p, ":")); // Order is important! + char * v = strip(strsep(&p, "\r")); + header.Set(k, v); + strsep(&p, "\n"); + } + +// if(char * x = strpbrk(header.Get("URI"), "?#")) *x = '\0'; // Remove timestamp in request TODO: keep this later + + return true; +} + + + +bool +ServerSocket::SendHTTPHeader(Dictionary * d, const char * response) // Content length from where? +{ + if(!response) + Send("HTTP/1.1 200 OK\r\n"); + else + Send("HTTP/1.1 %s\r\n", response); + + d->Set("Server", "Ikaros/1.2"); + d->Set("Connection", "Close"); + + time_t rawtime; + time(&rawtime); + char tb[32]; + strftime(tb, sizeof(tb), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime)); // RFC 1123 really uses numeric time zones rather than GMT + + d->Set("Date", tb); + d->Set("Expires", tb); + + for(Dictionary::Iterator i = Dictionary::First(d); i.kv; ++i) + Send("%s: %s\r\n", d->GetKey(i), d->Get(i)); + + Send("\r\n"); + + return true; +} + + + +bool +ServerSocket::SendData(const char * buffer, long size) +{ + if (data->new_fd == -1) + { +// printf("### connection closed unexpectedly\n"); + return false; // Connection closed - ignore send + } + + long total = 0; + long bytesleft = size; + long n = 0; + + while (total < size) + { + n = send(data->new_fd, buffer+total, bytesleft, MSG_NOSIGNAL); // Write "handle SIGPIPE nostop print pass" in gdb to avoid break during debugging +// if (n == 0) printf("No data sent - SIGPIPEING....\n"); + if (n == -1) + { +// printf("### send returned -1\n"); + break; + } + total += n; + bytesleft -= n; + } + + if (n == -1 || bytesleft > 0) // We failed to send all data + { +// printf("### failed to send all data\n"); + Close(); // Close the socket and ignore further data + return false; + } + + return true; +} + + + +bool +ServerSocket::Send(const char * format, ...) +{ + if (data->new_fd == -1) + return false; // Connection closed - ignore send + + char buffer[1024]; + va_list args; + va_start(args, format); + + if (vsnprintf(buffer, 1024, format, args) == -1) + { + va_end(args); + return false; + } + va_end(args); + + return SendData(buffer, strlen(buffer)); +} + + + +bool +ServerSocket::Send(const float * d, int sizex, int sizey) +{ + float sx = float(sizex); + float sy = float(sizey); + + if (!SendData((char *)(&sx), sizeof(float))) + return false; + + if (!SendData((char *)(&sy), sizeof(float))) + return false; + + if (!SendData((char *)d, sizex*sizey*sizeof(float))) + return false; + + return true; +} + + + +bool +ServerSocket::SendFile(const char * filename, const char * path, Dictionary * hdr) +{ + if (filename == NULL) return false; + + copy_string(data->filepath, path, PATH_MAX); + append_string(data->filepath, filename, PATH_MAX); + FILE * f = fopen(data->filepath, "r+b"); + + if (f == NULL) return false; + + fseek(f, 0, SEEK_END); + size_t len = ftell(f); + fseek(f, 0, SEEK_SET); + + Dictionary * h = (hdr ? hdr : new Dictionary()); + + h->Set("Connection", "Close"); // TODO: check if socket uses persistent connections + char length[256]; + h->Set("Content-Length", int_to_string(length, (int)len, 256)); + h->Set("Server", "Ikaros/1.2"); + + if(strend(filename, ".html")) + h->Set("Content-Type", "text/html"); + else if(strend(filename, ".css")) + h->Set("Content-Type", "text/css"); + else if(strend(filename, ".js")) + h->Set("Content-Type", "text/javascript"); + else if(strend(filename, ".jpg")) + h->Set("Content-Type", "image/jpeg"); + else if(strend(filename, ".jpeg")) + h->Set("Content-Type", "image/jpeg"); + else if(strend(filename, ".gif")) + h->Set("Content-Type", "image/gif"); + else if(strend(filename, ".png")) + h->Set("Content-Type", "image/png"); + else if(strend(filename, ".svg")) + h->Set("Content-Type", "image/svg+xml"); + else if(strend(filename, ".xml")) + h->Set("Content-Type", "text/xml"); + else if(strend(filename, ".ico")) + h->Set("Content-Type", "image/ico"); // TODO: Check this + + SendHTTPHeader(h); + + char * s = new char[len]; + fread(s, len, 1, f); + SendData(s, len); + fclose(f); + delete [] s; + + if(!hdr) + delete h; + + return true; +} + + + +bool +ServerSocket::Close() +{ + if (data->new_fd == -1) return true; // Connection already closed + + if (close(data->new_fd) == -1) + { + errcode = errno; + return false; + } + data->new_fd = -1; + + return true; +} + + + +int +ServerSocket::Port() +{ + return data->portno; +} + + + +const char * +ServerSocket::Host() +{ + static char hostname[256]; + if (gethostname(hostname, 256) == 0) // everything ok + return hostname; + else + return "unkown-host"; +} + +#endif diff --git a/Source/Kernel/IKAROS_Socket_WIN.cc b/Source/Kernel/IKAROS_Socket_WIN.cc new file mode 100755 index 000000000..82dd1a9c2 --- /dev/null +++ b/Source/Kernel/IKAROS_Socket_WIN.cc @@ -0,0 +1,566 @@ +// +// IKAROS_Socket.cc Socket utilities for the IKAROS project +// +// Copyright (C) 2001-2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#include "IKAROS.h" +#include "IKAROS_Socket.h" +#include "IKAROS_Math.h" + +#ifdef USE_WIN_SOCKET + +#include +#include +#include + +#include +#include +#include + +#define BACKLOG 10 // how many pending connections queue will hold +#define TIMEOUT 1000 // number of attempts to read +#define TIMEOUTDEL 1000 // number of usec to sleep before each read + +#define usleep(x) Sleep(x/1000) +#define bzero(b,len) (memset((b), '\0', (len)), (void) 0) + + + +// +// SocketData +// + +class SocketData +{ + +public: + int sd; + + SocketData() : sd(-1) + {}; +}; + + + +// +// Socket - functions that gets data from a HTTP server +// + +Socket::Socket() +{ + // The magic windows socket word + WSADATA wsaData; + WSAStartup(0x0101, &wsaData); + data = new SocketData(); +} + + + +Socket::~Socket() +{ + if (data->sd != -1) closesocket(data->sd); + + delete data; +} + + + +bool +Socket::SendRequest(const char * hostname, int port, const char * request) +{ + data->sd = -1; + + struct sockaddr_in localAddr, servAddr; + + struct hostent *h; + if ((h = gethostbyname(hostname)) == NULL) + return false; // unkown host + servAddr.sin_family = h->h_addrtype; + memcpy((char *) &servAddr.sin_addr.s_addr, h->h_addr_list[0], h->h_length); + servAddr.sin_port = htons(port); + if ((data->sd = socket(AF_INET, SOCK_STREAM, 0)) == 0) + return false; // cannot open socket + localAddr.sin_family = AF_INET; + localAddr.sin_addr.s_addr = htonl(INADDR_ANY); + localAddr.sin_port = htons(0); + if (bind(data->sd, (struct sockaddr *) &localAddr, sizeof(localAddr)) < 0) + return false; // cannot open port + if (connect(data->sd, (struct sockaddr *) &servAddr, sizeof(servAddr)) <0) + return false; // cannot connect + if (send(data->sd, request, strlen(request),0) <0) + return false; // cannot send data + return data->sd != -1; +} + + + +bool +Socket::Poll() +{ + struct timeval tv; + fd_set readfds; + tv.tv_sec = 0; + tv.tv_usec = 0; + + FD_ZERO(&readfds); + FD_SET((u_int)data->sd, (u_int)&readfds); + + select(data->sd+1, &readfds, NULL, NULL, &tv); + + if (FD_ISSET(data->sd, &readfds)) + return true; + else + return false; +} + + + +int +Socket::ReadData(char * result, int maxlen, bool fill) +{ + if (data->sd == -1) + return 0; + const int BUFFER_SIZE = 1024; + static char buffer[BUFFER_SIZE]; + int dst=0; + int rc = 0; + do + { + int read_size = (maxlen-dst < BUFFER_SIZE ? maxlen-dst : BUFFER_SIZE); + rc = recv(data->sd, buffer, read_size,0); + + for (int i=0; i0 || fill)); + return dst; +} + + + +int +Socket::Get(const char * hostname, int port, const char * request, char * result, int maxlen) +{ + int rc = 0; + if (SendRequest(hostname, port, request)) + rc = ReadData(result, maxlen); + Close(); + return rc; +} + + + +void +Socket::Close() +{ + if (data->sd == -1) + return; + closesocket(data->sd); + data->sd = -1; +} + + + +// +// ServerSocketData +// + +class ServerSocketData +{ + +public: + int portno; + int sockfd; // Listen on sock_fd, + int new_fd; // New connection on new_fd + int block_flags; // Original flags for blocking I/O +// char request[1024]; + int request_allocated_size; + char * request; + + char argument[10][256]; + int argcnt; + + char filepath[PATH_MAX]; + + struct sockaddr_in my_addr; // My address information + struct sockaddr_in their_addr; // Connector's address information + + ServerSocketData() { request_allocated_size = 1024; request = (char *)malloc(sizeof(char)*request_allocated_size); } +}; + + + +// +// ServerSocket +// + +ServerSocket::ServerSocket(int port) +{ + // The magic windows socket word + WSADATA wsaData; + WSAStartup(0x0101, &wsaData); + + data = new ServerSocketData(); + + data->portno = port; + data->argcnt = 0; + + if ((data->sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) + throw SocketException(strerror(errno), 1); + + data->my_addr.sin_family = AF_INET; // host byte order + data->my_addr.sin_port = htons(port); // short, network byte order + data->my_addr.sin_addr.s_addr = htonl(INADDR_ANY); // automatically fill with my IP + + memset(&(data->my_addr.sin_zero), '\0', 8); // zero the rest of the struct + + // Not implemented. Not sure if this is used in windows. + //int yes = 1; + //if (setsockopt(data->sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) // To avoid (most) socket already in use errors + // throw SocketException(strerror(errno), 2); + + if (bind(data->sockfd, (struct sockaddr *)&(data->my_addr), sizeof(struct sockaddr)) == -1) + throw SocketException(strerror(errno), 3); // Socket already used + + if (listen(data->sockfd, BACKLOG) == -1) + throw SocketException(strerror(errno), 4); + +#ifdef POSIX + signal(SIGPIPE, SIG_IGN); // ignore SIGPIPE; catch errors when send() returns -1 instead + +#endif +} + +ServerSocket::~ServerSocket() +{ + WSACleanup(); + // close ?? + delete data; +} + +bool +ServerSocket::Poll(bool block) +{ + // make the socket non-blocking + int iMode = 1; + if(!block) + ioctlsocket(data->sockfd, FIONBIO, (u_long FAR*) &iMode); // temporariliy make the socket non-blocking + data->new_fd = accept(data->sockfd, NULL, NULL); + iMode = 0; + if(!block) + ioctlsocket(data->sockfd, FIONBIO, (u_long FAR*) &iMode); // temporariliy make the socket non-blocking + return (data->new_fd != -1); +} + + + +long +ServerSocket::Read(char * buffer, int maxSize) +{ + if (data->new_fd == -1) + return 0; + + long n = 0; + + bzero(buffer, maxSize); + + for (int t = 0; t < TIMEOUT; t++) + { + if ((n = recv(data->new_fd, buffer, maxSize-1, 0)) >= 0) + return n; + + usleep(TIMEOUTDEL); + } + + return n; +} + + + +// strip strips non-printing characters in the beginning and end of a string +// the tsring is modified in place and a pointer to the new beginning is returned + +static char * +strip(char * s) +{ + int t = strlen(s)-1; + while(s[t] <= ' ') + s[t--] = '\0'; + while(*s <= ' ') + s++; + return s; +} + +static char * +recode(char * s) // Replace %20 and others with a space +{ + int j = 0; + for (int i=0; s[i]; i++) + if (s[j] != '%') + s[i] = s[j++]; + else + { + s[i] = ' '; + j+=3; + } + return s; +} + + + +bool +ServerSocket::GetRequest(bool block) +{ + if (!Poll(block)) + return false; + + // Loop until CRLF CRLF is found which marks the end of the HTTP request + + char * d = data->request; + data->request[0] = '\0'; + int read_count = 0; + while(!strstr(d, "\r\n\r\n")) // check border condition *** + { + long rr = Read(&d[read_count], data->request_allocated_size-read_count); + if(rr == 0) // the connections has been closed since the beginning of the request + return false; // this can occur when a view is changed; return and ignore the request + read_count += rr; + data->request[read_count] = '\0'; + if(read_count >= data->request_allocated_size-1) + data->request = (char *)realloc(data->request, data->request_allocated_size += 1024); + } + + // Parse request and header [TODO: handle that arguments in theory can span several lines accoding to the HTTP specification; although it never happens] + + char * p = data->request; + if(!p) + { + printf("ERROR: Empty HTTP request."); + return false; + } + + header.Clear(); + + header.Set("Method", strsep(&p, " ")); + header.Set("URI", recode(strsep(&p, " "))); + header.Set("HTTP-Version", strsep(&p, "\r")); + strsep(&p, "\n"); + while(p && *p != '\r') + { + char * k = strip(strsep(&p, ":")); // Order is important! + char * v = strip(strsep(&p, "\r")); + header.Set(k, v); + strsep(&p, "\n"); + } + +// if(char * x = strpbrk(header.Get("URI"), "?#")) *x = '\0'; // Remove timestamp in request TODO: keep this later + + return true; +} + + + +bool +ServerSocket::SendHTTPHeader(Dictionary * d, const char * response) +{ + if(!response) + Send("HTTP/1.1 200 OK\r\n"); + else + Send("HTTP/1.1 %s\r\n", response); + + d->Set("Server", "Ikaros/1.2"); + d->Set("Connection", "Close"); + + time_t rawtime; + time(&rawtime); + char tb[32]; + strftime(tb, sizeof(tb), "%a, %d %b %Y %H:%M:%S GMT", gmtime(&rawtime)); // RFC 1123 really uses numeric time zones rather than GMT + + d->Set("Date", tb); + d->Set("Expires", tb); + + for(Dictionary::Iterator i = Dictionary::First(d); i.kv; ++i) + Send("%s: %s\r\n", d->GetKey(i), d->Get(i)); + + Send("\r\n"); + + return true; +} + + + +bool +ServerSocket::SendData(const char * buffer, long size) +{ + if (data->new_fd == -1) return false; // Connection closed - ignore send + long total = 0; + long bytesleft = size; + long n = 0; + while (total < size) + { + n = send(data->new_fd, buffer+total, bytesleft, 0); + if (n == -1) break; + total += n; + bytesleft -= n; + } + if (n == -1 || bytesleft > 0) // We failed to send all data + { +// perror("ServerSocket::SendData Failed"); + Close(); // Close the socket and ignore further data + return false; + } + return true; +} + + + +bool +ServerSocket::Send(const char * format, ...) +{ + if (data->new_fd == -1) return false; // Connection closed - ignore send + char buffer[1024]; + va_list args; + va_start(args, format); + + if (vsnprintf(buffer, 1024, format, args) == -1) + { + va_end(args); + return false; + } + va_end(args); + bool r = SendData(buffer, strlen(buffer)); + return r; +} + + + +bool +ServerSocket::Send(const float * data, int sizex, int sizey) +{ + float sx = float(sizex); + float sy = float(sizey); + + if (!SendData((char *)(&sx), sizeof(float))) + return false; + + if (!SendData((char *)(&sy), sizeof(float))) + return false; + + if (!SendData((char *)data, sizex*sizey*sizeof(float))) + return false; + + return true; +} + + + +bool +ServerSocket::SendFile(const char * filename, const char * path, Dictionary * hdr) +{ + if (filename == NULL) return false; + + copy_string(data->filepath, path, PATH_MAX); + append_string(data->filepath, filename, PATH_MAX); + FILE * f = fopen(data->filepath, "r+b"); + + if (f == NULL) return false; + + fseek(f, 0, SEEK_END); + int len = ftell(f); + fseek(f, 0, SEEK_SET); + + Dictionary * h = (hdr ? hdr : new Dictionary()); + + h->Set("Connection", "Close"); // TODO: check if socket uses persistent connections + char length[256]; + h->Set("Content-Length", ikaros::int_to_string(length, len, 256)); + h->Set("Server", "Ikaros/1.2"); + + if(strend(filename, ".html")) + h->Set("Content-Type", "text/html"); + else if(strend(filename, ".css")) + h->Set("Content-Type", "text/css"); + else if(strend(filename, ".js")) + h->Set("Content-Type", "text/javascript"); + else if(strend(filename, ".jpg")) + h->Set("Content-Type", "image/jpeg"); + else if(strend(filename, ".jpeg")) + h->Set("Content-Type", "image/jpeg"); + else if(strend(filename, ".gif")) + h->Set("Content-Type", "image/gif"); + else if(strend(filename, ".png")) + h->Set("Content-Type", "image/png"); + else if(strend(filename, ".svg")) + h->Set("Content-Type", "image/svg+xml"); + else if(strend(filename, ".ico")) + h->Set("Content-Type", "image/ico"); // TODO: CHECK THIS + + SendHTTPHeader(h); + + char * s = new char[len]; + fread(s, len, 1, f); + SendData(s, len); + fclose(f); + delete [] s; + + if(!hdr) + delete h; + + return true; +} + + + +bool +ServerSocket::Close() +{ + if (data->new_fd == -1) return true; // Connection already closed + if (closesocket(data->new_fd) == -1) + { + errcode = errno; + return false; + } + data->new_fd = -1; + return true; +} + + + +int +ServerSocket::Port() +{ + return data->portno; +} + + + +const char * +ServerSocket::Host() +{ + static char hostname[256]; + if (gethostname(hostname, 256) == 0) // everything ok + return hostname; + else + return "unkown-host"; +} + +#endif + diff --git a/Source/Kernel/IKAROS_Threads.h b/Source/Kernel/IKAROS_Threads.h new file mode 100755 index 000000000..53792c30a --- /dev/null +++ b/Source/Kernel/IKAROS_Threads.h @@ -0,0 +1,43 @@ +// +// IKAROS_Threads.h Thread utilities for the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#include "IKAROS_System.h" + +#ifndef IKAROS_THREADS +#define IKAROS_THREADS + +class ThreadData; + +class Thread +{ +private: + ThreadData * data; +public: + int Create(void *(*func)(void *), void *arg); + int Join(); + + Thread(); + ~Thread(); +}; + +#endif + diff --git a/Source/Kernel/IKAROS_Threads_none.cc b/Source/Kernel/IKAROS_Threads_none.cc new file mode 100755 index 000000000..62f195fa8 --- /dev/null +++ b/Source/Kernel/IKAROS_Threads_none.cc @@ -0,0 +1,60 @@ +// +// IKAROS_Threads_none.cc Thread utilities for the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// This file defines a dummy class for systems that lacks thread support +// + +#include "IKAROS_System.h" + +#ifndef USE_THREADS + +#include "IKAROS_Threads.h" + +int +Thread::Create(void *(*func)(void *), void *arg) +{ + // Since we have no threads we will simply call the function immediately + + func(arg); + return 0; +} + + + +int +Thread::Join() +{ + // There is nothing to join + + return 0; +} + + + +Thread::Thread() +{} + + + +Thread::~Thread() +{} + +#endif diff --git a/Source/Kernel/IKAROS_Threads_pthread.cc b/Source/Kernel/IKAROS_Threads_pthread.cc new file mode 100755 index 000000000..0300fe958 --- /dev/null +++ b/Source/Kernel/IKAROS_Threads_pthread.cc @@ -0,0 +1,74 @@ +// +// IKAROS_Threads.cc Thread utilities for the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Wrapper for pthread - use this file for systems that supports pthread +// + +#include "IKAROS_System.h" + +#ifdef USE_THREADS + +#include "IKAROS_Threads.h" + +#include + +class ThreadData +{ +public: + pthread_t thread; + int thread_id; +}; + + + +int +Thread::Create(void *(*func)(void *), void *arg) +{ + return (data->thread_id = pthread_create( &(data->thread), NULL, func, arg)); +} + + + +int +Thread::Join() +{ + data->thread_id = -1; + return pthread_join(data->thread, NULL); +} + + + +Thread::Thread() +{ + data = new ThreadData(); + data->thread_id = -1; +} + + + +Thread::~Thread() +{ + if (data->thread_id != -1) + pthread_join(data->thread, NULL); + delete data; +} + +#endif diff --git a/Source/Kernel/IKAROS_Timer.h b/Source/Kernel/IKAROS_Timer.h new file mode 100755 index 000000000..a6d793726 --- /dev/null +++ b/Source/Kernel/IKAROS_Timer.h @@ -0,0 +1,44 @@ +// +// IKAROS_Timer.h Timer utilities for the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// + +#ifndef IKAROS_TIMER +#define IKAROS_TIMER + +class TimerData; + +class Timer +{ +private: + TimerData * data; +public: + void Restart(); // Start the timer + float GetTime(); // Get the time (in milliseconds) since the timer was created or restarted + float WaitUntil(float time); // Suspend execution until time; return timing lag (in milliseconds) + + Timer(); + ~Timer(); + + static void Sleep(float time); // Sleep this many milliseconds +}; + +#endif + diff --git a/Source/Kernel/IKAROS_Timer_POSIX.cc b/Source/Kernel/IKAROS_Timer_POSIX.cc new file mode 100755 index 000000000..683cd9bf3 --- /dev/null +++ b/Source/Kernel/IKAROS_Timer_POSIX.cc @@ -0,0 +1,95 @@ +// +// IKAROS_Timer.h Timer utilities for the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// This file implements a timer class using the POSIX timing functions +// + +#include "IKAROS_System.h" + +#ifdef POSIX + +#include "IKAROS_Timer.h" + +#include +#include +#include + +class TimerData +{ +public: + struct timeval start_time; +}; + + + +void +Timer::Restart() +{ + gettimeofday(&(data->start_time), NULL); +} + + + +float +Timer::GetTime() +{ + struct timeval stop_time; + gettimeofday(&stop_time, NULL); + long sec_diff = stop_time.tv_sec - data->start_time.tv_sec; + long usec_diff = stop_time.tv_usec - data->start_time.tv_usec; + return 1E3*float(sec_diff) + float(usec_diff)/1E3; // difference in milliseconds +} + + + +float +Timer::WaitUntil(float time) +{ + float dt; +// if(time - t > 1.2) sleep(long(t-0.2)); + + while ((dt = GetTime()-time) < 0) ; + return dt; +} + + + +Timer::Timer() +{ + data = new TimerData(); + Restart(); +} + + + +Timer::~Timer() +{ + delete data; +} + + + +void Timer::Sleep(float time) +{ + usleep(useconds_t(1000*time)); +} + +#endif diff --git a/Source/Kernel/IKAROS_Timer_WIN.cc b/Source/Kernel/IKAROS_Timer_WIN.cc new file mode 100755 index 000000000..61bc622f5 --- /dev/null +++ b/Source/Kernel/IKAROS_Timer_WIN.cc @@ -0,0 +1,91 @@ +// +// IKAROS_Timer.h Timer utilities for the IKAROS project +// +// Copyright (C) 2006 Birger Johansson +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// This file implements a timer class using windows multimedia timing +// This file uses the libwinmm.a libary in the lib directory +// + +#include "IKAROS_System.h" + +#ifdef WINDOWS + +#include "IKAROS_Timer.h" +#include "windows.h" + +#define usleep(x) ::Sleep(x/1000) + +class TimerData +{ +public: + DWORD startTime; + UINT period; +}; + +void +Timer::Restart() +{ + data->startTime = timeGetTime(); +} + +float +Timer::GetTime() +{ + return (timeGetTime() - data->startTime); +} + +float +Timer::WaitUntil(float time) +{ + float dt; +// if(time - t > 1.2) sleep(long(t-0.2)); + + while ((dt = GetTime()-time) < 0) ; + return dt; +} + +Timer::Timer() +{ + data = new TimerData(); + // Set the highest resolution for the multimedia timer + TIMECAPS tc; + // Retrieve timer caps, which contain resolution range + timeGetDevCaps(&tc, sizeof tc); + // Store period in a member variable so that we can restore it when program terminates + data->period = tc.wPeriodMin; + // Set resolution with this call + timeBeginPeriod(tc.wPeriodMin); + + Restart(); +} + +Timer::~Timer() +{ + timeEndPeriod(data->period); + delete data; +} + +void Timer::Sleep(float time) +{ + usleep(long(1000*time)); +} + +#endif + diff --git a/Source/Kernel/IKAROS_Timer_none.h b/Source/Kernel/IKAROS_Timer_none.h new file mode 100755 index 000000000..efd7ac7c6 --- /dev/null +++ b/Source/Kernel/IKAROS_Timer_none.h @@ -0,0 +1,72 @@ +// +// IKAROS_Timer.h Timer utilities for the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// This file defines a dummy class for systems that lacks timer support +// + +#include "KAROS_System.h" + +#include "IKAROS_Timer.h" + + +class TimerData + {}; + + + +void +Timer::Restart() +{ +} + + + +float +Timer::GetTime() +{ + return 0; +} + + + +float +Timer::WaitUntil(float time) +{ + return 0; +} + + + +Timer::Timer() +{ +} + + + +Timer::~Timer() +{ +} + + + +static void Sleep(float time) +{ +} diff --git a/Source/Kernel/IKAROS_Utils.cc b/Source/Kernel/IKAROS_Utils.cc new file mode 100755 index 000000000..d053dad36 --- /dev/null +++ b/Source/Kernel/IKAROS_Utils.cc @@ -0,0 +1,803 @@ +// +// IKAROS_Utils.cc Various utilities for the IKAROS project +// +// Copyright (C) 2001-2008 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: July 17 2001 +// +#include "IKAROS_Utils.h" +#include "IKAROS_System.h" + +#ifdef WINDOWS +#include +#else +#include +#endif + +#include +#include +#include +#include +#include + + +#if defined USE_VDSP +#include +#endif + + + + +char * +create_string(const char * c) +{ + if (c) + { + char * p = strcpy(new char [strlen(c)+1], c); + return p; + } + else + return NULL; +} + +char * +create_string_head(const char * c, int n) +{ + if (c) + { + int l = int(strlen(c)); + + if(n > l) + n = l; + + char * p = strncpy(new char [n+1], c, n); // FIXME: replace with create string *** + p[n] = 0; + return p; + } + else + return NULL; +} + +char * +create_string_tail(const char * c, int i) +{ + if (c) + { + int l = int(strlen(c)); + + if(i > l) + return NULL; + + char * p = strncpy(new char [l-i+1], &c[i], l-i); // FIXME: replace with create string *** + p[l-i] = 0; + return p; + } + else + return NULL; +} + +char * +create_formatted_string(const char *format, ...) +{ + const int max_string = 1024; + static char temp[max_string]; + va_list args; + va_start(args, format); + vsnprintf(temp, max_string, format, args); + va_end(args); + int length = int(strlen(temp))+1; + char * p = strncpy(new char [length], temp, length); // FIXME: replace with create string *** + return p; +} + +void +destroy_string(char * c) +{ + delete [] c; +} + +bool +equal_strings(const char * a, const char * b) +{ + if (a == b) // Identical string or both NULL + return true; + if (a == NULL || b == NULL) // only one is NULL, they can't be equal + return false; + return !strcmp(a, b); // Do the usual comparison +} + +bool +strstart(const char * s1, const char *s2) // does s1 start with s2 +{ + while(*s2) + if(*s2++ != *s1++) + return false; + return true; +} + +bool +strend(const char * s1, const char * s2) // does 1s end with s2 +{ + int i1 = int(strlen(s1))-1; + int i2 = int(strlen(s2))-1; + do + { + if(s1[i1--] != s2[i2--]) + return false; + } + while(i1 && i2); + return true; +} + +char * +copy_string(char * dest, const char * src, int len) +{ + int size; + + if (!len) + return dest; + + if(!src) // NULL is treated as an empty string + { + dest[0] = '\0'; + return dest; + } + + size = int(strlen(src)); + if (size >= len) + size = len-1; + memcpy(dest, src, size); + dest[size] = '\0'; + return dest; +} + +char * +append_string(char * dest, const char * a, int len) +{ + if(!len || !a) + return dest; + + int used = int(strlen(dest)); + + int size = int(strlen(a)); + if(used+size >= len) + size = len-used-1; + memcpy(dest+used, a, size); + dest[used+size] = '\0'; + + return dest; +} + +#ifdef WINDOWS32 +/* + * Get next token from string *stringp, where tokens are possibly-empty + * strings separated by characters from delim. + * + * Writes NULs into the string at *stringp to end tokens. + * delim need not remain constant from call to call. + * On return, *stringp points past the last NUL written (if there might + * be further tokens), or is NULL (if there are definitely no more tokens). + * + * If *stringp is NULL, strsep returns NULL. + */ +char* strsep(char **stringp, const char *delim) +{ + char *s; + const char *spanp; + int c, sc; + char *tok; + + if ((s = *stringp) == NULL) + return (NULL); + for (tok = s;;) { + c = *s++; + spanp = delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = 0; + *stringp = s; + return (tok); + } + } while (sc != 0); + } +} + +#endif + +bool +is_path(const char * p) +{ + if(!p) + return false; + + for(unsigned int i=0; i 0) + ss[e--] ='\0'; + + for (; isspace(*v) && *v != '\0'; v++) ; + + while(sscanf(v, "%*f")!=-1) + { + row_elements++; + for (; !isspace(*v) && *v != ',' && *v != ';' && *v != '\0'; v++) ; + if(*v==',') v++; + for (; isspace(*v) && *v != '\0'; v++) ; + if(*v==';') + { + v++; + if(row_elements > sx) + sx = row_elements; + row_elements = 0; + sy++; + } + for (; isspace(*v) && *v != '\0'; v++) ; + } + if(row_elements > sx) + sx = row_elements; + + float ** m = create_matrix(sx, sy); + + v = ss; + int j=0; + int i=0; + while(sscanf(v, "%f", &m[j][i])!=-1) + { + i++; + for (; !isspace(*v) && *v != ',' && *v != ';' && *v != '\0'; v++) ; + if(*v==',') v++; + for (; isspace(*v) && *v != '\0'; v++) ; + if(*v==';') + { + v++; + i = 0; + j++; + } + for (; isspace(*v) && *v != '\0'; v++) ; + } + + destroy_string(ss); + + sizex = sx; + sizey = sy; + + return m; +} + + + +float * +reset_array(float * a, int size) +{ +#ifdef USE_VDSP + vDSP_vclr(a, 1, size); +#else + for (int i=0; i0 && bin_path[i] != '/' && bin_path[i] !='\\'; i--) ; + binary_dir = create_string_head(bin_path, i+1); + destroy_string(bin_path); + } + + // Compute file directory and name + + if(file_arg != NULL) + { + if(is_absolute_path(file_arg)) + file_path = create_string(file_arg); + else + file_path = create_formatted_string("%s/%s", working_dir, file_arg); + + int i; + for(i=int(strlen(file_path))-1; i>0 && file_path[i] != '/' && file_path[i] !='\\'; i--) ; + file_dir = create_string_head(file_path, i+1); + file_name = create_string_tail(file_path, i+1); + } +} + +Options::~Options() +{ + for (int i=0; i<255; i++) + destroy_string(argument[i]); + + destroy_string(binary_dir); + destroy_string(file_path); + destroy_string(file_dir); + destroy_string(file_name); +} + +void +Options::SetOption(char c, char * arg) +{ + option[int(c)] = true; + argument[int(c)] = arg; +} + +void +Options::ResetOption(char c) +{ + option[int(c)] = false; +} + +bool +Options::GetOption(char c) +{ + return option[int(c)]; +} + +char * +Options::GetArgument(char c) +{ + return argument[int(c)]; +} + +char * +Options::GetWorkingDirectory() +{ + return working_dir; +} + +char * +Options::GetBinaryDirectory() +{ + return binary_dir; +} + +char * +Options::GetFilePath() +{ + return file_path; +} + +char * +Options::GetFileDirectory() +{ + return file_dir; +} + +char * +Options::GetFileName() +{ + return file_name; +} + +void +Options::Print() +{ + printf("Options:\n"); + for (int i=0; i<255; i++) + if (option[i]) + { + printf("-%c", i); + if (argument[i]) + printf(" %s", argument[i]); + printf("\n"); + } + if (file_name) + { + printf("File Dir: %s\n", file_dir); + printf("File Name: %s\n", file_name); + } +} + + + +// Dictionary + +Dictionary::KeyValue::KeyValue(const char * k, const char * v, KeyValue * first) +{ + key = create_string(k); + value = create_string(v); + next = first; + prev = NULL; + + if(next != NULL) + next->prev = this; +} + +Dictionary::KeyValue::~KeyValue() +{ + destroy_string(key); + destroy_string(value); +} + +Dictionary::Dictionary() +{ + first = NULL; + last = NULL; +} + +Dictionary::~Dictionary() +{ + Clear(); +} + +void +Dictionary::Clear() +{ + for(KeyValue * kv = first; kv != NULL;) + { + KeyValue * n = kv->next; + delete kv; + kv = n; + } + first = NULL; + last = NULL; +} + +void +Dictionary::Set(const char * k, const char * v) +{ + for(KeyValue * kv = first; kv != NULL; kv = kv->next) + if(equal_strings(k, kv->key)) + { + destroy_string(kv->value); + kv->value = create_string(v); + return; + } + + first = new KeyValue(k, v, first); +} + +const char * +Dictionary::Get(const char * k) +{ + for(KeyValue * kv = first; kv != NULL; kv = kv->next) + if(equal_strings(k, kv->key)) + return kv->value; + return NULL; +} + +void +Dictionary::Print() +{ + for(KeyValue * kv = first; kv != NULL; kv = kv->next) + printf("\"%s\" : \"%s\"\n", kv->key, kv->value); +} + +const char * +Dictionary::Get(Dictionary::Iterator i) +{ + return i.kv->value; +} + +const char * +Dictionary::GetKey(Dictionary::Iterator i) +{ + return i.kv->key; +} diff --git a/Source/Kernel/IKAROS_Utils.h b/Source/Kernel/IKAROS_Utils.h new file mode 100755 index 000000000..5f9e120c4 --- /dev/null +++ b/Source/Kernel/IKAROS_Utils.h @@ -0,0 +1,194 @@ +// +// IKAROS_Utils.h Various utilities for the IKAROS project +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: July 17 2001 +// + +#ifndef IKAROS_UTILS +#define IKAROS_UTILS + +#include // for NULL + +// Basic string functions + +char * create_string(const char * c); // copy string c +char * create_string_head(const char * c, int n); // copy at most n characters +char * create_string_tail(const char * c, int i); // copy starting at character i +char * create_formatted_string(const char * format, ...); +void destroy_string(char * c); + +char * copy_string(char * dest, const char * src, int len); // copy src into dest, len is max size of dest; return dest +char * append_string(char * dest, const char * a, int len); // append a to dest, len is max size of dest, return dest + +bool equal_strings(const char * a, const char * b); + +bool strstart(const char * s1, const char *s2); // does s1 start with s2 +bool strend(const char * s1, const char * s2); // does 1s end with s2 + +#ifdef WINDOWS32 +char* strsep(char **stringp, const char *delim); +#endif + +// File path operations + +bool is_path(const char * p); +bool is_absolute_path(const char * p); + +// Array and matrix functions + +const int MATLAB = 1024; +const int DIM = 2048; + +void print_array(const char * name, float * a, int size, int decimals=2); +void print_matrix(const char * name, float ** m, int sizex, int sizey, int decimals=2); + +float * create_array(int size); +float * create_array(const char * s, int & size); + +float ** create_matrix(int sizex, int sizey); +float ** create_matrix(const char * s, int & sizex, int & sizey); +float *** create_matrix(int sizex, int sizey, int sizez); +float **** create_matrix(int sizex, int sizey, int sizez, int sizet); + + +void destroy_array(float * a); +void destroy_matrix(float ** m); +void destroy_matrix(float *** m); +void destroy_matrix(float **** m); + +float * copy_array(float * r, float * a, int size); +float ** copy_matrix(float ** r, float ** a, int sizex, int sizey); + +float * reset_array(float * a, int size); +float ** reset_matrix(float ** m, int sizex, int sizey); + +float * set_array(float * a, float v, int size); +float ** set_matrix(float ** m, float v, int sizex, int sizey); + +// Delay Line + +class DelayLine +{ +public: + int size; + int pos; + float * data; + + DelayLine(int s) : size(s), pos(0) + { + data = new float[s]; + } // s > 0; s = 1 is no delay + ~DelayLine() + { + delete [] data; + } + void put(float v) + { + data[pos] = v; + pos = (pos + 1) % size; + } + float get() + { + return data[(pos + 1) % size]; + } +}; + + + +// Options + +class Options +{ +public: + Options(int argc, char *argv[]); + ~Options(); + + void SetOption(char c, char * arg = 0); + bool GetOption(char c); + char * GetArgument(char c); + void ResetOption(char c); + + char * GetWorkingDirectory(); + char * GetBinaryDirectory(); + + char * GetFilePath(); + char * GetFileDirectory(); + char * GetFileName(); + + void Print(); +private: + bool option[256]; + char * argument[256]; + char working_dir[1024]; + char * binary_dir; + char * file_path; + char * file_dir; + char * file_name; +}; + + +// Dictionary + +class Dictionary + { + public: + + class KeyValue + { + public: + KeyValue * prev; + KeyValue * next; + char * key; + char * value; + + KeyValue(const char * k, const char * v, KeyValue * first); + ~KeyValue(); + }; + + class Iterator + { + public: + KeyValue * kv; + Iterator(KeyValue * e = NULL): kv(e) {} + Iterator * operator++() { if(kv) kv = kv->next; return this; } + }; + + KeyValue * first; + KeyValue * last; + + Dictionary(); + ~Dictionary(); + + void Clear(); + void Set(const char * k, const char * v); + const char * Get(const char * k); + + const char * Get(Iterator i); + const char * GetKey(Iterator i); + + void Print(); + + static Iterator First(Dictionary * d) { return (d ? Iterator(d->first): NULL); } + }; + + +#endif + diff --git a/Source/Kernel/IKAROS_XML.cc b/Source/Kernel/IKAROS_XML.cc new file mode 100755 index 000000000..a45bcafd2 --- /dev/null +++ b/Source/Kernel/IKAROS_XML.cc @@ -0,0 +1,835 @@ +// +// Ikaros_XML.cc +// XMLParser +// +// Version 1.0.2 +// +// Copyright (C) 2001-2009 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created 2006-03-05. +// + +#include "IKAROS_XML.h" +#include "IKAROS_Utils.h" + +#include +#include +#include + + + +void +XMLNode::Print(FILE * f, int d) +{ + if (next != NULL) + next->Print(f, d); +} + + + +XMLElement * +XMLNode::GetElement(const char * element_name) +{ + if (next != NULL) + return next->GetElement(element_name); + else + return NULL; +} + + + +void +XMLNode::SetPrev(XMLNode * p) +{ + this->prev = p; + if(this->next) + this->next->SetPrev(this); +} + + + +XMLNode * +XMLNode::Disconnect() +{ + if(prev != NULL) + prev->next = next; + else if(parent != NULL) + ((XMLElement *)parent)->content = next; + + parent = NULL; + prev = NULL; + next = NULL; + + return this; +} + + + +XMLCharacterData::XMLCharacterData(char * s, bool cd, XMLNode * n) : + XMLNode() +{ + data = s; + cdata = cd; + next = n; +} + + + +XMLCharacterData::~XMLCharacterData() +{ + destroy_string(data); +} + + + +void +XMLCharacterData::Print(FILE * f, int d) +{ + if (cdata) fprintf(f, ""); + if (next != NULL) + next->Print(f, d); +} + + + +XMLComment::XMLComment(char * s, XMLNode * n) : + XMLNode() +{ + data = s; + next = n; +} + + + +XMLComment::~XMLComment() +{ + destroy_string(data); +} + + + +void +XMLComment::Print(FILE * f, int d) +{ + fprintf(f, "", data); + if (next != NULL) + next->Print(f, d); +} + + + +XMLAttribute::XMLAttribute(char * nm, char * v, int q, XMLNode * n) : + XMLNode() +{ + name = nm; + value = v; + quote = q; + next = n; +} + + + +XMLAttribute::~XMLAttribute() +{ + destroy_string(name); + destroy_string(value); +} + + + +void +XMLAttribute::Print(FILE * f, int d) +{ + fprintf(f, " %s=%c%s%c", name, quote, value, quote); + + if (next != NULL) + next->Print(f, d); +} + + + +XMLElement::XMLElement(XMLNode * p, char * nm, XMLAttribute * a, bool e) : + XMLNode() +{ + parent = p; + name = nm; + attributes = a; + empty = e; + content = NULL; + next = NULL; +} + + + +XMLElement::XMLElement(XMLNode * p, char * nm, XMLAttribute * a, bool e, XMLNode * c, XMLNode * n) : + XMLNode() +{ + parent = p; + name = nm; + attributes = a; + empty = e; + content = c; + next = n; +} + + + +XMLElement::~XMLElement() +{ + destroy_string(name); + delete attributes; + delete content; +} + + + +void +XMLElement::Print(FILE * f, int d) +{ + if(empty) + { + fprintf(f, "<%s", name); + if (attributes != NULL) + attributes->Print(f, d); + fprintf(f, "/>"); + if (next != NULL) + next->Print(f, d); + return; + } + + fprintf(f, "<%s", name); + if (attributes != NULL) + attributes->Print(f, d); + fprintf(f, ">"); + if(content != NULL) + content->Print(f, d+1); + fprintf(f, "", name); + if (next != NULL) + next->Print(f, d); +} + + + +void +XMLElement::SetPrev(XMLNode * p) +{ + if(content) + content->SetPrev(NULL); + if(attributes) + attributes->SetPrev(NULL); + XMLNode::SetPrev(p); +} + + + +const char * +XMLElement::GetAttribute(const char * attribute_name) +{ + for (XMLAttribute * a = attributes; a != NULL; a = (XMLAttribute *)(a->next)) + if (!strcmp(a->name, attribute_name)) + return a->value; + return NULL; +} + + + +void +XMLElement::SetAttribute(const char * attribute_name, const char * value) +{ + for (XMLAttribute * a = attributes; a != NULL; a = (XMLAttribute *)(a->next)) + if (!strcmp(a->name, attribute_name)) + { + destroy_string(a->value); + a->value = create_string(value); + return; + } + + attributes = new XMLAttribute(create_string(attribute_name), create_string(value), '\"', attributes); + if(attributes->next != NULL) + attributes->next->prev = attributes; + attributes->parent = this; +} + + + +// Finds the next element with the supplied name or any element if element_name == NULL +XMLElement * +XMLElement::GetElement(const char * element_name) +{ + if (IsElement(element_name)) + return this; + else if (next != NULL) + return GetNextElement(element_name); + + return NULL; +} + + +// Finds the first element with a particular name in the contents of the current element +XMLElement * +XMLElement::GetContentElement(const char * element_name) +{ + if (content != NULL) + return content->GetElement(element_name); + else + return NULL; +} + + + +XMLElement * +XMLElement::GetNextElement(const char * element_name) +{ + if(next) + return next->GetElement(element_name); + else + return NULL; + +/* + for (XMLNode * xml = next; xml != NULL; xml = xml->next) + if (xml->IsElement(element_name)) + return (XMLElement *)(xml); + + return NULL; +*/ +} + + + +XMLElement * +XMLElement::GetParentElement() +{ + return (XMLElement *)parent; +} + + + +XMLProcessingInstruction::XMLProcessingInstruction(char * nm, char * c, XMLNode * n) : + XMLNode() +{ + name = nm; + content = c; + next = n; +} + + + +XMLProcessingInstruction::~XMLProcessingInstruction() +{ + destroy_string(name); + destroy_string(content); +} + + + +void +XMLProcessingInstruction::Print(FILE * f, int d) +{ + fprintf(f, ""); + if (next != NULL) + next->Print(f, d); + return; +} + + + +XMLDocument::XMLDocument(const char * filename, bool debug) +{ + debug_mode = debug; + action = ""; + action_line = 0; + + f = fopen(filename, "rb"); + + if (f==NULL) + { + printf("Could not open \"%s\".\n", filename); + return; + } + + line = 1; + character = 1; + + try + { + prolog = Parse(NULL); + prolog->SetPrev(NULL); + + // Find root + + XMLNode * xml_node = prolog; + while(!xml_node->IsElement()) + { + if(xml_node->next == NULL) + throw "XML contains no root element"; + xml_node = xml_node->next; + } + xml = (XMLElement *)xml_node; + + // Disconnect prolog before root element + + if(xml->prev != NULL) + xml->prev->next = NULL; + xml->prev = NULL; + + if(prolog == xml) + prolog = NULL; + + // Delete data after root (should never have been parsed) + + delete xml->next; + xml->next = NULL; + + } + catch (const char * msg) + { + printf("%s: ", filename); + printf("%s at line %d, position %d", msg, line, character); + if (action_line != 0) + printf(" while %s at line %d\n", action, action_line); + else + printf("\n"); + exit(1); + } + + fclose(f); +} + + + +XMLDocument::~XMLDocument() +{ + delete xml; + delete prolog; +} + + + +bool +XMLDocument::Match(const char c, bool skip) +{ + long p = ftell(f); + if (feof(f)) return false; // REPORT ERROR ******** + bool r = (fgetc(f) == c); + fseek(f, p, SEEK_SET); + if (skip) Skip("##", 1); + return r; +} + + + +bool +XMLDocument::Match(const char * s, bool skip) +{ + long p = ftell(f); + int i = 0; + for (; s[i]; i++) + { + if (feof(f)) break; // REPORT ERROR ******** + if (fgetc(f) != s[i]) break; + } + fseek(f, p, SEEK_SET); + + if (skip && !s[i]) Skip("##", i); + + return !s[i]; +} + + + +void +XMLDocument::Skip(const char * t, int n) +{ + for (int i=0; i= max_buffer) throw "Buffer overflow"; + for (int i=0; i 0 ? buffer : NULL); +} + + + +char * +XMLDocument::PushUntil(const char * t, const char * s0 , const char * s1) +{ + pos = 0; + while (!feof(f)) + { + if ( (s0 != NULL && Match(s0, false)) || + (s1 != NULL && Match(s1, false)) + ) + { + buffer[pos] = 0; + return buffer; + } + else + Push(t, 1); + } + + buffer[pos] = 0; + return (pos > 0 ? buffer : NULL); +} + + + +char * +XMLDocument::PushName(const char * t) +{ + pos = 0; + for (int i=0;; i++) + { + char c= fgetc(f); + ungetc(c, f); // Peek + if (feof(f)) throw "Unexpected end of file (3)"; + + if ( ('a' <= c && c <= 'z') || + ('A' <= c && c <= 'Z') || + c == '_' || + c == ':' || + (i != 0 && c == '-') || + (i != 0 && c == '.') || + (i != 0 && '0' <= c && c <= '9') + ) + Push(t, 1); + else + { + buffer[pos] = 0; + return (pos > 0 ? buffer : NULL); // test needed??? + } + } + return NULL; // internal error throw +} + + + +void +XMLDocument::SetAction(const char * s) +{ + action = s; + action_line = line; +} + + + +XMLNode * +XMLDocument::ParseXMLDeclaration(XMLNode * parent) +{ + SetAction("parsing XML declaration"); + PushUntil("XD", "?>"); + Skip("XD", 2); + SkipWhitespace("WS"); // TEST + return Parse(parent); // Ignore this, return next element +} + + + +XMLNode * +XMLDocument::ParseProcessingInstruction(XMLNode * parent) +{ + SetAction("parsing procesing instruction"); + PushName("N<"); + char * name = create_string(buffer); + + if (pos == 0) throw "Valid character for processing instruction name expected"; + + PushUntil("PI", "?>"); + char * content = create_string(buffer); + + Skip("PI", 2); + + return new XMLProcessingInstruction(name, content, Parse(parent)); +} + + + +XMLNode * +XMLDocument::ParseComment(XMLNode * parent) +{ + SetAction("parsing comment"); + char * text = create_string(PushUntil("CM", "-->")); + Skip("CO", 3); + return new XMLComment(text, Parse(parent)); +} + + + +XMLNode * +XMLDocument::ParseDoctype(XMLNode * parent) // The DOCTYPE will be removed +{ + SetAction("parsing doctype"); + int c = 1; + while (c >0) + { + if (feof(f)) throw "Unexpected end of file (4)"; + PushUntil("DT", "<", ">"); + if (Match("<")) + c++; + else if (Match(">")) + c--; + } + return Parse(parent); +} + + + +XMLNode * +XMLDocument::ParseCDATA(XMLNode * parent) // Return character data with CDATA tag +{ + SetAction("parsing CDATA"); + char * text = create_string(PushUntil("CD", "]]>")); + PushUntil("CD", "]]>"); + Skip("CD", 3); + return new XMLCharacterData(text, true, Parse(parent)); +} + + + +XMLNode * +XMLDocument::ParseCharacterData(XMLNode * parent) +{ + SetAction("parsing character data"); + char * s = create_string(PushUntil("DA", "<")); + if(s) + return new XMLCharacterData(s, false, Parse(parent)); + else + return Parse(parent); // ** experimental ** +} + + + +XMLAttribute * +XMLDocument::ParseAttribute(const char * element_name, bool & empty) +{ + SetAction("parsing attributes"); + SkipWhitespace("WS"); + + if (Match("/")) // empty element + { + SkipWhitespace("WS"); + if (!Match(">")) + throw "'>' expected after '/'"; + empty = true; + return NULL; + } + + if (Match(">")) + { + empty = false; + return NULL; + } + + if (Match("<")) + { + sprintf(errbuf, "Start tag <%s> not terminated", element_name); + throw errbuf; + } + + char * name = create_string(PushName("AT")); + if (name == NULL) throw "Attribute not found"; + + // Check that attribute does not already exist *** + + SkipWhitespace("WS"); + if (!Match("=")) throw "'=' expected"; + SkipWhitespace("WS"); + + const char * q = NULL; + if (Match('"')) + q = "\""; + else if (Match('\'')) + q = "'"; + else + throw "Quoted attribute value expected"; + + PushUntil("AV", "<", q); + if (Match('<')) throw "< not allowed in attribute value"; + Match(q); + + char * value = create_string(buffer); + return new XMLAttribute(name, value, q[0], ParseAttribute(element_name, empty)); +} + + + +XMLNode * +XMLDocument::ParseElement(XMLNode * parent) +{ + SetAction("parsing element"); + int start_line = line; + PushName("N<"); + char * name = create_string(buffer); + + if (pos == 0) throw "Valid character for tag name expected"; + + bool empty = false; + XMLAttribute * attributes = ParseAttribute(name, empty); + + if (empty) return new XMLElement(parent, name, attributes, true, NULL, Parse(parent)); + + XMLElement * e = new XMLElement(parent, name, attributes, false); + XMLNode * content = Parse(e); + e->content = content; + + if (!Match(" expected", name); + throw errbuf; + } + + PushName("N>"); + + if (strcmp(name, buffer)) + { + sprintf(errbuf, "Start tag <%s> at line %d does not match end tag ", name, start_line, buffer); + throw errbuf; + } + + PushUntil("ET", ">"); + Skip("ET", 1); + + e->next = Parse(parent); + return e; +} + + + +XMLNode * +XMLDocument::Parse(XMLNode * parent) +{ + if (feof(f)) + return NULL; + + if (Match("\n\n"); + xml->Print(file, 0); +} + + diff --git a/Source/Kernel/IKAROS_XML.h b/Source/Kernel/IKAROS_XML.h new file mode 100755 index 000000000..200366fbe --- /dev/null +++ b/Source/Kernel/IKAROS_XML.h @@ -0,0 +1,203 @@ +// +// Ikaros_XML.h +// XMLParser +// +// Version 1.0.1 +// +// Copyright (C) 2001-2008 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created 2006-03-05. +// + + +#include +#include + +class XMLElement; + +class XMLNode +{ +public: + XMLNode * parent; + XMLNode * prev; + XMLNode * next; + void * aux; // used for extensions + + XMLNode() : parent(NULL), prev(NULL), next(NULL), aux(NULL) + {}; + virtual ~XMLNode() + { + delete next; + }; + + virtual void Print(FILE * f, int d); + + virtual XMLElement * GetElement(const char * element_name=NULL); + virtual bool IsElement(const char * e=NULL) + { + return false; + } + + virtual void SetPrev(XMLNode * p); // recursively set prev links + virtual XMLNode * Disconnect(); // disconnect from XML tree +}; + + + +class XMLCharacterData : public XMLNode +{ +public: + char * data; + bool cdata; + + XMLCharacterData(char * s, bool cd, XMLNode * n); + virtual ~XMLCharacterData(); + + virtual void Print(FILE * f, int d); +}; + + + +class XMLComment : public XMLNode +{ +public: + char * data; + + XMLComment(char * s, XMLNode * n); + virtual ~XMLComment(); + + virtual void Print(FILE * f, int d); +}; + + + +class XMLAttribute : public XMLNode +{ +public: + char * name; + char * value; + char quote; + + XMLAttribute(char * nm, char * v, int q, XMLNode * n); + virtual ~XMLAttribute(); + + virtual void Print(FILE * f, int d); +}; + + + +class XMLElement : public XMLNode +{ +public: + XMLNode * content; + XMLAttribute * attributes; + + char * name; + bool empty; + + XMLElement(XMLNode * p, char * nm, XMLAttribute * a, bool e); + XMLElement(XMLNode * p, char * nm, XMLAttribute * a, bool e, XMLNode * c, XMLNode * n); + virtual ~XMLElement(); + + virtual void Print(FILE * f, int d); + + virtual bool IsElement(const char * e=NULL) // Is this an element with a particular name or any element (if NULL) + { + return !e || !strcmp(e, name); + } + + virtual void SetPrev(XMLNode * p); + + const char * GetAttribute(const char *); + void SetAttribute(const char * a, const char * v); + + virtual XMLElement * GetElement(const char * element_name=NULL); // NULL indicates any element + virtual XMLElement * GetContentElement(const char * element_name=NULL); + virtual XMLElement * GetNextElement(const char * element_name=NULL); + virtual XMLElement * GetParentElement(); +}; + + + +class XMLProcessingInstruction : public XMLNode +{ +public: + char * name; + char * content; + + XMLProcessingInstruction(char * nm, char * c, XMLNode * n); + virtual ~XMLProcessingInstruction(); + + virtual void Print(FILE * f, int d); + + virtual bool IsElement(const char * e=NULL) + { + return false; + } +}; + + + +const int max_buffer = 64000; + +class XMLDocument +{ +public: + FILE * f; + int line; + int character; + bool debug_mode; + char buffer[max_buffer]; + int pos; + + const char * action; + int action_line; + + char errbuf[1024]; + + XMLElement * xml; + XMLNode * prolog; + + XMLDocument(const char * filename, bool debug = false); + ~XMLDocument(); + + bool Match(const char c, bool skip=true); + bool Match(const char * s, bool skip=true); + + void Skip(const char * t, int n); + void SkipWhitespace(const char *t); + + char * Push(const char * t, int n); + char * PushUntil(const char *t, const char * s0, const char * s1=NULL); + char * PushName(const char *t); + + void SetAction(const char *); + + XMLNode * ParseXMLDeclaration(XMLNode * parent); + XMLNode * ParseProcessingInstruction(XMLNode * parent); + XMLNode * ParseComment(XMLNode * parent); + XMLNode * ParseDoctype(XMLNode * parent); + XMLNode * ParseCDATA(XMLNode * parent); + XMLNode * ParseCharacterData(XMLNode * parent); + XMLAttribute * ParseAttribute(const char * element_name, bool & empty); + XMLNode * ParseElement(XMLNode * parent); + XMLNode * Parse(XMLNode * parent); + + void Print(FILE * f); +}; diff --git a/Source/Kernel/main.cc b/Source/Kernel/main.cc new file mode 100755 index 000000000..1eef805a2 --- /dev/null +++ b/Source/Kernel/main.cc @@ -0,0 +1,334 @@ +// +// main.cc The main code for the IKAROS project +// +// Copyright (C) 2001-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: August 8, 2001 +// +// The main function in IKAROS does two things: +// +// 1. It installs all modules and the kernel +// 2. It calls the kernel to start execution + +#include +#include + +#ifdef WINDOWS +#include +#else +#include +#endif + +#ifdef WINDOWS32 +#include +#undef GetClassName +#else +#include +#endif + +#include + +// Kernel + +#include "IKAROS.h" +#include "WebUI/WebUI.h" + +// +// Modules +// + +#include "Modules/Modules.h" +#include "UserModules/UserModules.h" + + +void PrintInfo(); + +void +PrintInfo() +{ + printf("\n"); + printf("The file to use should be given at the command line:\n"); + printf("\n"); + printf(" IKAROS file.ikc\n"); + printf("\n"); + printf("Use the w-option to also start the WebUI:\n"); + printf("\n"); + printf(" IKAROS -w file.ikc\n"); + printf("\n"); + printf("This examaple will wait for a request from the Web browser at\n"); + printf("the default port (8000).\n"); + printf("\n"); + printf("Usage:\n"); + printf("\n"); + printf("\tIKAROS [-w#][-W#][-p][-t][-T][-b#][-r#][-v][-q][-x][-X][-m][-l][-i][-a][file]\n\n"); + printf("\t-w# WebUI\n"); + printf("\t-W# WebUI: debug mode, list requests\n"); + printf("\t-p profile\n"); + printf("\t-t threaded\n"); + printf("\t-T list thread allocation\n"); + printf("\t-b# run one item in batch\n"); + printf("\t-B batch mode\n"); + printf("\t-r# real time mode; # is time per tick in milliseconds\n"); + printf("\t-s# stop after # ticks\n"); + printf("\t-v verbose mode\n"); + printf("\t-q quiet mode\n"); + printf("\t-x list xml after parsing/combination\n"); + printf("\t-X debug xml parser\n"); + printf("\t-n look for NANs in outputs\n"); + printf("\t-m list modules and connections\n"); + printf("\t-c list installed classes\n"); + printf("\t-l list scheduling\n"); + printf("\t-i list installed functionality sockets, timer etc, type of target system\n"); + printf("\t-a list all; implies -m -l and -T (if -t is set)\n"); + printf("\t-z# seed random number generator\n"); + printf("\t-u# number of ticks to run for each step in the WebUI\n"); + printf("\n"); +} + + +static int +count_elements(const char * s) +{ + if(!s) return 0; + size_t c = 0; + size_t l = strlen(s); + if(l==0) + return 0; + for(size_t i=0; i ' ' && ((s[i+1] <= ' ' )|( s[i+1] == '\0'))) + c++; + return (int)c; +} + + + +int run_batch(Options * options); + +int +run_batch(Options * options) +{ + printf("IKAROS: Running in batch mode.\n"); + + // Set up path to load IKC file + + char * ikc_dir = options->GetFileDirectory(); + char * ikc_file_name = options->GetFileName(); + + if (ikc_file_name[0] == 0) + { + printf( "Empty file name.\n"); + return -1; + } + + char path[PATH_MAX]; + copy_string(path, ikc_dir, PATH_MAX); + append_string(path, ikc_file_name, PATH_MAX); + printf("IKAROS: Reading XML file \"%s\".\n", ikc_file_name); + + if (chdir(ikc_dir) < 0) + { + printf("IKAROS: The directory \"%s\" could not be found.\n", ikc_dir); + return -1; + } + + XMLDocument * xmlDoc = new XMLDocument(ikc_file_name, options->GetOption('X')); + + if (xmlDoc->xml == NULL) + { + printf("IKAROS: Could not read (or find) \"%s\".\n", ikc_file_name); + return -1; + } + + XMLElement * xml = xmlDoc->xml->GetElement("group"); + if (xml == NULL) + { + printf("IKAROS: Did not find element in IKC file \"%s\".\n", ikc_file_name); + return -1; + } + + // Get max batch index + + + printf("IKAROS: BATCH: targets: "); + int batch_count = 0; + bool first = true; + for (XMLElement * xml_node = xml->GetContentElement(); xml_node != NULL; xml_node = xml_node->GetNextElement("batch")) + { + if(xml_node->GetAttribute("target") != NULL) + { + if(first) + first = false; + else + printf(", "); + printf("%s", xml_node->GetAttribute("target")); + } + int c = count_elements(xml_node->GetAttribute("values")); + if(c > batch_count) + batch_count = c; + } + printf("\n"); + printf("IKAROS: BATCH: count: %d\n", batch_count); + + // Change options + + options->ResetOption('B'); + // Loop over each execution + + for(int i=1; i<=batch_count; i++) + { + char n[6]; + snprintf(n, 5, "%d", i); + options->SetOption('b', n); + + printf("\nIKAROS: BATCH: #%d\n", i); + + try + { + Kernel k(options); + + k.ListInfo(); + + InitModules(k); + InitUserModules(k); + + k.Init(); + k.ListClasses(); + k.ListModulesAndConnections(); + k.ListScheduling(); + k.ListThreads(); + k.Run(); + k.PrintTiming(); + k.ListProfiling(); + } + catch(...) + { + printf("IKAROS: BATCH: An error occured\n"); + } + } + + // delete xml tree *** + // delete options tree *** + + return 0; +} + + + +int +main(int argc, char *argv[]) +{ + if (argc == 1) + { + PrintInfo(); + return 0; + } + + Options * options = new Options(argc, argv); + + if (options->GetOption('v')) + options->Print(); + + if (options->GetOption('B')) + { + return run_batch(options); + } + + // Create and Init kernel + + Kernel k(options); + + try + { + k.ListInfo(); + + InitModules(k); + InitUserModules(k); + + k.Init(); + + k.ListClasses(); + k.ListModulesAndConnections(); + k.ListScheduling(); + k.ListThreads(); + + // Select UI + + if (!k.Terminate() && (options->GetOption('w') || options->GetOption('W'))) + { +#ifdef USE_SOCKET + WebUI webUI(&k); + webUI.Run(); +#else + printf("IKAROS was compiled without support for sockets and WebUI\n"); +#endif + } + else + { + k.Run(); + } + + k.PrintTiming(); + k.ListProfiling(); + + delete options; + } + + // Catch Exceptions and Terminate Execution + + catch (std::bad_alloc&) + { + k.Notify(msg_exception, "Could not allocate memory. Program terminates.\n"); + return 1; // MEMORY ERROR + } + /* + catch(XMLError ex) + { + k.Notify(msg_exception, "%s at line %d. Program terminates (%d).\n", ex.string, ex.line, ex.internal_reference); + return 2; // XML ERROR + } + */ + + catch (SerialException se) + { + k.Notify(msg_exception, "Serial Exception: %s (%d). Program terminates.\n", se.string, se.internal_reference); + } +#ifdef USE_SOCKET + catch (SocketException ex) + { + k.Notify(msg_exception, "Socket(%d): %s\n", ex.internal_reference, ex.string); + return 3; // SOCKET ERROR + } +#endif + catch (int i) + { + // k.Init(); + k.Notify(msg_exception, "%d. Program terminates.\n", i); + return i; // OTHER ERROR + } + catch (...) + { +// k.Init(); + k.Notify(msg_exception, "Undefined exception. Program terminates.\n"); + return -1; // UNDEFINED ERROR + } + + return 0; +} + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/AcquisitionExtinction/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/AcquisitionExtinction/input.txt new file mode 100755 index 000000000..16dee29f2 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/AcquisitionExtinction/input.txt @@ -0,0 +1,181 @@ +CS/1 R/1 LOC/1 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 1 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 +0 0 0 +1 0 1 +0 0 0 diff --git a/Source/Modules/BrainModels/Moren2002/Examples/AcquisitionExtinction/network.xml b/Source/Modules/BrainModels/Moren2002/Examples/AcquisitionExtinction/network.xml new file mode 100755 index 000000000..c15e8fedb --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/AcquisitionExtinction/network.xml @@ -0,0 +1,107 @@ + + + + + + + + + + + + + + + + + 0.2 + + + 0.2 + + + + + 4 + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Blocking/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/Blocking/input.txt new file mode 100755 index 000000000..528436e16 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Blocking/input.txt @@ -0,0 +1,150 @@ +CS/2 R/1 LOC/2 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Blocking/network.xml b/Source/Modules/BrainModels/Moren2002/Examples/Blocking/network.xml new file mode 100755 index 000000000..69d89e3e6 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Blocking/network.xml @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/ConditionedInhibition/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/ConditionedInhibition/input.txt new file mode 100755 index 000000000..00e991dd1 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/ConditionedInhibition/input.txt @@ -0,0 +1,335 @@ +CS/3 R/1 LOC/3 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +1 0 0 0 1 0 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +1 1 0 0 1 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 1 1 0 0 1 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 1 0 0 0 1 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 +0 0 0 0 0 0 0 +0 1 0 0 0 1 0 +0 0 0 1 0 0 0 + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/ConditionedInhibition/network.xml b/Source/Modules/BrainModels/Moren2002/Examples/ConditionedInhibition/network.xml new file mode 100755 index 000000000..e60f16e1e --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/ConditionedInhibition/network.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + 0.2 + + + 0.2 + + + + + 4 + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Discrimination/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/Discrimination/input.txt new file mode 100755 index 000000000..ef9170bc4 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Discrimination/input.txt @@ -0,0 +1,374 @@ +CS/3 R/1 LOC/2 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 1 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 0 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 +0 0 0 0 0 0 +1 1 0 0 1 0 +0 0 0 0 0 0 +0 0 0 0 0 0 +0 1 1 0 0 1 +0 0 0 1 0 0 + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Discrimination/network.ikc b/Source/Modules/BrainModels/Moren2002/Examples/Discrimination/network.ikc new file mode 100755 index 000000000..69d89e3e6 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Discrimination/network.ikc @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition/input.txt new file mode 100755 index 000000000..f105ad130 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition/input.txt @@ -0,0 +1,144 @@ +CS/2 R/1 LOC/2 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 1 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +1 0 0 0 1 +0 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition/network.ikc b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition/network.ikc new file mode 100755 index 000000000..8f7d953af --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition/network.ikc @@ -0,0 +1,144 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_connection + sourcemodule = "Cortex" + source = "OUTPUT" + targetmodule = "OFC" + target = "INPUT" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition2/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition2/input.txt new file mode 100755 index 000000000..9fa2fb44c --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition2/input.txt @@ -0,0 +1,114 @@ +CS/3 R/1 LOC/2 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 1 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 1 0 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 +0 0 1 0 0 1 +0 0 0 0 0 0 +1 0 0 0 1 0 diff --git a/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition2/network.ikc b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition2/network.ikc new file mode 100755 index 000000000..27ad19387 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/Disinhibition2/network.ikc @@ -0,0 +1,146 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + <_connection + sourcemodule = "Cortex" + source = "OUTPUT" + targetmodule = "OFC" + target = "INPUT" + /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/NegativePatterning/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/NegativePatterning/input.txt new file mode 100755 index 000000000..e7d665a00 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/NegativePatterning/input.txt @@ -0,0 +1,191 @@ +CS/2 R/1 LOC/2 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 1 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/NegativePatterning/network.xml b/Source/Modules/BrainModels/Moren2002/Examples/NegativePatterning/network.xml new file mode 100755 index 000000000..e60f16e1e --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/NegativePatterning/network.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + 0.2 + + + 0.2 + + + + + 4 + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/PositivePatterning/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/PositivePatterning/input.txt new file mode 100755 index 000000000..3d4f2d07a --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/PositivePatterning/input.txt @@ -0,0 +1,182 @@ +CS/2 R/1 LOC/2 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 1 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 1 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 0 1 +0 0 0 0 0 diff --git a/Source/Modules/BrainModels/Moren2002/Examples/PositivePatterning/network.xml b/Source/Modules/BrainModels/Moren2002/Examples/PositivePatterning/network.xml new file mode 100755 index 000000000..e60f16e1e --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/PositivePatterning/network.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + 0.2 + + + 0.2 + + + + + 4 + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/README b/Source/Modules/BrainModels/Moren2002/Examples/README new file mode 100755 index 000000000..89384c3a8 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/README @@ -0,0 +1,34 @@ +Examples/Emotional Learning +--------------------------- + +These are some representative experiments to be run with the amygdala, +hippocampus and OFC models. As the result of any conditioning experiment +depends on the exact schedule used, and, for these models, also on such things +as the location of each stimulus, there are a number of possible variations of +these. Thus do not take these experiments as gospel, but as some +representative testfiles to run the models on. + +Jan MorŽn + +------------------------------------------------------------------------------------- +To run the examples, start Ikaros with the file test.ikc and specify the +experiment to run using the -b option at start up. The number after -b selects +the experimenat from the list: + +0: AcquisitionExtinction +1: Blocking +2: ConditionedInhibition +3: Discrimination +4: Disinhibition +5: Disinhibition2 +6: Blocking +7: NegativePatterning +8: PositivePatterning +9: SFPD + +For example, use the following to test blocking: + +IKAROS -b1 test.ikc + +There are old xml files in some of the directories that do not work anymore. +They are included for documentational puraposes. \ No newline at end of file diff --git a/Source/Modules/BrainModels/Moren2002/Examples/SFPD/input.txt b/Source/Modules/BrainModels/Moren2002/Examples/SFPD/input.txt new file mode 100755 index 000000000..709f7173f --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/SFPD/input.txt @@ -0,0 +1,109 @@ +CS/2 R/1 LOC/2 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 1 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +1 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +1 0 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 1 0 1 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 +0 0 0 0 0 + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/SFPD/network.xml b/Source/Modules/BrainModels/Moren2002/Examples/SFPD/network.xml new file mode 100755 index 000000000..e60f16e1e --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/SFPD/network.xml @@ -0,0 +1,108 @@ + + + + + + + + + + + + + + + 0.2 + + + 0.2 + + + + + 4 + 4 + + + 2 + + + 2 + + + 2 + + + 2 + + + 2 + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/Examples/test.ikc b/Source/Modules/BrainModels/Moren2002/Examples/test.ikc new file mode 100755 index 000000000..27da868bc --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/Examples/test.ikc @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Amygdala/M02_Amygdala.cc b/Source/Modules/BrainModels/Moren2002/M02_Amygdala/M02_Amygdala.cc new file mode 100755 index 000000000..8f261460d --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Amygdala/M02_Amygdala.cc @@ -0,0 +1,96 @@ +// M02_Amygdala.cc +// +// Copyright (C) 2001-2002 Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 +// USA +// +// +// 2001-12-06 Initial version +// 2002-12-20 Moved to IKAROS 0.7 +// 2009-06-20 Moved to Ikaros 1.2 (CB) +// +// Implements the basic Amygdala model. Also needed is - ideally - an +// Orbitofrontal model and perhaps a Hippocampus and/or Thalamus. + +#include "M02_Amygdala.h" + +using namespace ikaros; + +void M02_Amygdala::Init() +{ + Bind(alpha, "alpha"); + + size = GetInputSize("INPUT"); + + input = GetInputArray("INPUT"); + input_last = create_array(size); + + Rew = GetInputArray("Rew"); + EO = GetInputArray("EO", false); // This input is not required; do not produce error if unconnected + + V = GetOutputArray("V"); + A = GetOutputArray("A"); + E = GetOutputArray("E"); + + set_array(V, 0.0, size); // initial weights + + SumA = 0; + OldSumA = 0; + EOld = 0; +} + + +M02_Amygdala::~M02_Amygdala() +{ + destroy_array(input_last); +} + + +void M02_Amygdala::Tick() +{ + // Update weights + // We use Old SumA to allow Rew to succeed the CS by one timestep + + float ARew = max(0.0, (Rew[0] - OldSumA)); + for(int i=0; i + + + + +The module implements the model of the amygdala cortex described in the PhD thesis by Jan Morén 2002. + + + + + + + + + + + + + + + + + + + + + + + +Jan Moren +jan.moren@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Jan.Moren/ + + + +Morén, J. (2002) Emotional Learning: A Computational Model of the Amygdala. Lund Univeristy Cognitive Studies, 93. + + + +M02_Amygdala.h +M02_Amygdala.cc +M02_Amygdala.ikc + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.cc b/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.cc new file mode 100755 index 000000000..e52fe2461 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.cc @@ -0,0 +1,60 @@ +// +// M02_Cortex.cc +// 2009-06-20 Moved to Ikaros 1.2 +// + + +#include "M02_Cortex.h" + +#include "IKAROS.h" + + + +Module * +M02_Cortex::Create(Parameter * p) +{ + return new M02_Cortex(p); +} + + + +M02_Cortex::M02_Cortex(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT", GetIntValue("outputsize", 4)); + + input = NULL; + output = NULL; +} + + + +void +M02_Cortex::Init() +{ + theNoOfInputs = GetInputSize("INPUT"); + theNoOfOutputs = GetInputSize("OUTPUT"); + + input = GetInputArray("INPUT"); + output = GetInputArray("OUTPUT"); +} + + + +M02_Cortex::~M02_Cortex() +{ +} + + + +void +M02_Cortex::Tick() +{ + // Get input + + copy_array(output, input, theNoOfOutputs); +} + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.h b/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.h new file mode 100755 index 000000000..1bbcbf614 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.h @@ -0,0 +1,49 @@ +// +// M02_Cortex.h +// + + +// +// This module defines the M02_Cortex model descibed in +// Balkenius & Morén, Amygdala, CybSyst etc, 2001 +// +// The model does absolutely nothing!!! +// It is simply a placeholder. +// +// Inputs +// +// INPUT +// +// Outputs +// +// OUTPUT (outputsize = 4) +// +// The size of the output must be equal to the size of the input +// + + +#include "IKAROS.h" + + + +class M02_Cortex: public Module +{ +public: + + M02_Cortex(Parameter * p); + virtual ~M02_Cortex(); + + static Module * Create(Parameter * p); + + void Init(); + void Tick(); + + int theNoOfInputs; + int theNoOfOutputs; + + float * input; + float * output; +}; + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.ikc b/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.ikc new file mode 100755 index 000000000..0d140e1d3 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Cortex/M02_Cortex.ikc @@ -0,0 +1,44 @@ + + + + + +The module implements the cortex model described in the PhD thesis by Jan Morén 2002. +This model does absolutely nothing and is just a placeholder. + + + + + + + + + + + + + +Jan Moren +jan.moren@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Jan.Moren/ + + + +M02_Cortex.h +M02_Cortex.cc +M02_Cortex.ikc + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.cc b/Source/Modules/BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.cc new file mode 100755 index 000000000..dc5c67877 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.cc @@ -0,0 +1,245 @@ +// +// M02_Hippocampus.cc +// +// Copyright (C) 2002, 2003 Christian Balkenius, Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// 2009-06-20 Moved to Ikaros 1.2 + +#include "M02_Hippocampus.h" + +using namespace ikaros; + + + +// Neural network primitives + +static int +categorize_or_store_euclidean(float * a, float ** m, int size_a, int & size_r, int max_r, float threshold, bool * new_category=NULL, float * match=NULL) +{ + float best_match = 0; + int best_index = 0; + + if(size_r > 0) + { + // Find closest prototype + + best_match = dist(a, m[0], size_a); + best_index = 0; + + float t=0; + for(int i=1; i threshold && size_r < max_r) || size_r == 0) + { + copy_array(m[size_r], a, size_a); // FIXME: Is this correct? + best_index = size_r; + best_match = 0; + size_r++; + if(new_category != NULL) + *new_category = true; + } + + if(match != NULL) + *match = best_match; + + return best_index; +} + + + +static bool +match_expectations(float * e, float * a, int size) +{ + for(int i=0; i a[i]) + return true; + return false; +} + + + +// Matrix operations + +static void +matrix_product(float * r, float * a, float ** m, int size_a, int size_r) // FIXME: use Ikaros_Math functions instead +{ + if(size_a < 1 || size_r < 1) + return; + + for(int j=0; j input => novelty + + // RESET: Reset Context + + if(theNovelty) + { +// printf("NOVELTY\n"); // TODO: remove + reset[0] = 1; + + reset_array(context, theUsedContexts); + theCurrentContext = -1; + + reset_array(bind, theUsedBind); + bind[best_bind] = 1; + + if(theBindTrig) // Create new context + { +// printf("NEW CONTEXT\n"); // TODO: remove + if(theUsedContexts == theNoOfContexts-1) + { + Notify(msg_fatal_error, "ERROR: M02_Hippocampus: Not enough context nodes. Increase and run again."); + } + else + { + theCurrentContext = theUsedContexts; + copy_array(CXW[theCurrentContext], bind, theUsedBind); + theUsedContexts++; + } + } + } + else + { + for(int j=0; j Obj +}; + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.ikc b/Source/Modules/BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.ikc new file mode 100755 index 000000000..b3d09427a --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.ikc @@ -0,0 +1,99 @@ + + + + + +The module implements the model of context processing described in the PhD thesis by Jan Morén 2002. +The model was originally published by Balkenius and Morén in 2000. + + + + + + + + + + + + + + + + + + + + + + + + + +Christian Balkenius +christian.balkenius@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Christian.Balkenius/ + + + +Jan Moren +jan.moren@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Jan.Moren/ + + + +Morén, J. (2002) Emotional Learning: A Computational Model of the Amygdala. Lund Univeristy Cognitive Studies, 93. + + + +Balkenius, C. and Morén, J. (2000) A Computational Model of Context Processing. In Jean-Arcady Meyer, Alain Berthoz, +Dario Floreano, Herbert L. Roitblat, Stewart W. Wilson, (Eds) From Animals to Animats 6: Proceedings of the 6th +International Conference on the Simulation of Adaptive Behaviour, Cambridge, MA. The MIT Press. + + + +M02_Hippocampus.h +M02_Hippocampus.cc +M02_Hippocampus.ikc + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_OFC/M02_OFC.cc b/Source/Modules/BrainModels/Moren2002/M02_OFC/M02_OFC.cc new file mode 100755 index 000000000..e3fb63e3c --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_OFC/M02_OFC.cc @@ -0,0 +1,136 @@ +// M02_OFC.cc +// +// Copyright (C) 2001, 2003 Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// Jan Morén, 2001-12-26 +// +// 2002-12-23 Moved to the new simulator +// 2009-06-20 Moved to Ikaros 1.2 (CB) +// +// Implements the basic orbitofrontal model. +// Used together with the amygdala model (M02_Amygdala). + +#include "M02_OFC.h" + +using namespace ikaros; + +void M02_OFC::SetSizes() +{ + Module::SetSizes(); + + int CONi = GetInputSize("CON"); + int CSi = GetInputSize("INPUT"); + + if(CONi != unknown_size && CSi != unknown_size) + { + if(CONi==0) + SetOutputSize("W", CSi); + else + SetOutputSize("W", CSi * CONi); + } +} + + +void M02_OFC::Init() +{ + Bind(beta, "beta"); + + CON_size = GetInputSize("CON"); + input_size = GetInputSize("INPUT"); + A_size = GetInputSize("A"); + + input = GetInputArray("INPUT"); + CON = GetInputArray("CON", false); + Rew = GetInputArray("Rew"); + A = GetInputArray("A"); + W = GetOutputArray("W"); + EO = GetOutputArray("EO"); + + if(CON_size==0) + { + CON_size = 1; + CON = create_array(1); + CON[0] = 1; + } + + T_size = input_size*CON_size; + + T = create_array(T_size); + T_last = create_array(T_size); + O = create_array(T_size); +} + + +M02_OFC::~M02_OFC() +{ + destroy_array(T); + destroy_array(T_last); + destroy_array(O); +} + + +void M02_OFC::Tick() +{ + // We need to combine the CS and CON inputs. We do this by populating an + // array of size CS*CON with, well, CS*CON. Actually the outer product of CS and CON + // (Morén, 2002, page 123) + + for(int i=0; i + + + + +The module implements the model of the orbitofrontal cortex described in the PhD thesis by Jan Morén 2002. + + + + + + + + + + + + + + + + + + + + + + + +Jan Moren +jan.moren@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Jan.Moren/ + + + +Morén, J. (2002) Emotional Learning: A Computational Model of the Amygdala. Lund Univeristy Cognitive Studies, 93. + + + +M02_OFC.h +M02_OFC.cc +M02_OFC.ikc + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.cc b/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.cc new file mode 100755 index 000000000..1de1ace9b --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.cc @@ -0,0 +1,44 @@ +// +// M02_SensoryCortex.cc This file is a part of the IKAROS project +// This module implemets a sensory cortical surface as a multi-peak SOM +// +// Copyright (C) 2001-2002 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2001-10-22 +// 2009-06-20 Moved to Ikaros 1.2 (CB) +// + +#include "M02_SensoryCortex.h" + + +void +M02_SensoryCortex::Init() +{ + size = GetInputSize("INPUT"); + input = GetInputArray("INPUT"); + output = GetOutputArray("OUTPUT"); +} + + + +void +M02_SensoryCortex::Tick() +{ + copy_array(output, input, size); +} + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.h b/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.h new file mode 100755 index 000000000..f21965c4d --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.h @@ -0,0 +1,45 @@ +// +// M02_SensoryCortex.cc This file is a part of the IKAROS project +// Cortex model that does abolutely nothing +// +// Copyright (C) 2001-2002 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2001-10-22 +// + +#include "IKAROS.h" + + + +class M02_SensoryCortex: public Module +{ +public: + + M02_SensoryCortex(Parameter * p) : Module(p) {} + virtual ~M02_SensoryCortex() {} + + static Module * Create(Parameter * p) {return new M02_SensoryCortex(p);} + + void Init(); + void Tick(); + + int size; + float * input; + float * output; +}; + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.ikc b/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.ikc new file mode 100755 index 000000000..d17a15973 --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.ikc @@ -0,0 +1,45 @@ + + + + + +The module implements the cortex model described in the PhD thesis by Jan Morén 2002. + + + + + + + + + + + + + + +Jan Moren +jan.moren@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Jan.Moren/ + + + +M02_SensoryCortex.h +M02_SensoryCortex.cc +M02_SensoryCortex.ikc + + + + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.cc b/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.cc new file mode 100755 index 000000000..adb38818e --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.cc @@ -0,0 +1,49 @@ +// +// M02_Thalamus.cc This file is a part of the IKAROS project +// A module implementing a simplistic model of the Thalamus +// +// Copyright (C) 2002 Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2002-01-05 +// +// 2002-12-25 Converted for new simulator +// 2009-06-22 Moved to Ikaros 1.2 (CB) +// +// A fake Thalamus module. All it does is add a new output of the maximum over +// all inputs. Do not take this as a serious model of thalamic function! + +#include "M02_Thalamus.h" + +using namespace ikaros; + +void M02_Thalamus::Init() +{ + size = GetInputSize("INPUT"); + input = GetInputArray("INPUT"); + Th = GetOutputArray("TH"); + output = GetOutputArray("OUTPUT"); + +} + + +void M02_Thalamus::Tick() +{ + copy_array(output, input, size); + Th[0] = max(input, size); +} + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.h b/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.h new file mode 100755 index 000000000..86e2f517c --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.h @@ -0,0 +1,67 @@ +// +// M02_Thalamus.h This file is a part of the IKAROS project +// A module implemeting a simplistic model of the M02_Thalamus +// +// Copyright (C) 2002 Jan Morén +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2002-01-05 +// +// 2002-12-25 Converted to new simulator +// +// A fake thalamus module. All it does is add a new output of the maximum over +// all inputs. Do not take this as a serious model of thalamic function! + +/******************************************************************** + +Simulation definition file: + + + + +In: + + CS - Vector of stimuli + +Out: + + CSout - Vector of stimuli - identical to CS + + TH - Scalar maximum ovar all CS + +*******************************************************************/ + +#include "IKAROS.h" + +class M02_Thalamus: public Module +{ +public: + M02_Thalamus(Parameter * p) : Module(p) {} + virtual ~M02_Thalamus() {} + + static Module * Create(Parameter * p) {return new M02_Thalamus(p);} + + void Init(); + void Tick(); + + int size; + + float * input; // The main input vector ("CS") + float * Th; // Thalamic output (scalar) ("TH") + float * output; // Output to Amygdala ("CSout" , "CSout" parameter) +}; + + diff --git a/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.ikc b/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.ikc new file mode 100755 index 000000000..344dbd9ea --- /dev/null +++ b/Source/Modules/BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.ikc @@ -0,0 +1,54 @@ + + + + + +The module implements the thalamus model described in the PhD thesis by Jan Morén 2002. + + + + + + + + + + + + + + + +Jan Moren +jan.moren@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Jan.Moren/ + + + +Morén, J. (2002) Emotional Learning: A Computational Model of the Amygdala. Lund Univeristy Cognitive Studies, 93. + + + +M02_Amygdala.h +M02_Amygdala.cc +M02_Amygdala.ikc + + + + + diff --git a/Source/Modules/CodingModules/CoarseCoder/CoarseCoder.cc b/Source/Modules/CodingModules/CoarseCoder/CoarseCoder.cc new file mode 100755 index 000000000..229d05658 --- /dev/null +++ b/Source/Modules/CodingModules/CoarseCoder/CoarseCoder.cc @@ -0,0 +1,99 @@ +// +// CoarseCoder.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "CoarseCoder.h" + +using namespace ikaros; + +void +CoarseCoder::Init() +{ + type = GetIntValueFromList("type"); + output_size = GetIntValue("output_size"); + radius = GetIntValue("radius"); + min = GetFloatValue("min"); + max = GetFloatValue("max"); + + if(GetBoolValue("normalize", false)) + value = 1.0/sqr(2*radius+1); + else + value = 1.0; + + input = GetInputArray("INPUT"); + if(GetInputSize("INPUT") != 2) + { + Notify(msg_fatal_error, "%s (CoarseCoder) input must have size 2 (not %d)\n", GetName(), GetInputSize("INPUT")); + return; + } + + output = GetOutputMatrix("OUTPUT"); +} + + + +void +CoarseCoder::MakeTile() +{ + float r = float(radius); + float w = 1+2*r; + float s = float(output_size); + float scale = s-w; + float x = r+scale*(input[0] - min)/(max-min); + float y = r+scale*(input[1] - min)/(max-min); + + reset_matrix(output, output_size, output_size); + + for (int j=int(y-r+0.5); j<=int(y+r+0.5); j++) + for (int i=int(x-r+0.5); i<=int(x+r+0.5); i++) + output[j][i] = value; +} + + + +void +CoarseCoder::MakeGaussian() +{ + float r = float(radius); + float w = 1+2*r; + float s = float(output_size); + float scale = s-w; + float x = r+scale*(input[0] - min)/(max-min); + float y = r+scale*(input[1] - min)/(max-min); + + for (int j=0; j + + + + + Module that generates a tile or gaussian code for a two-dimensional real-valued input. + + + + + + + + + + + + + + + + + + + + 2007 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + CoarseCoder.h + CoarseCoder.cc + CoarseCoder.ikc + + + + diff --git a/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoded_GridWorld2_test.ikc b/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoded_GridWorld2_test.ikc new file mode 100755 index 000000000..5090e01e6 --- /dev/null +++ b/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoded_GridWorld2_test.ikc @@ -0,0 +1,114 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoded_GridWorld_test.ikc b/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoded_GridWorld_test.ikc new file mode 100755 index 000000000..b1beec4df --- /dev/null +++ b/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoded_GridWorld_test.ikc @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoder_test.ikc b/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoder_test.ikc new file mode 100755 index 000000000..0e6a9dc83 --- /dev/null +++ b/Source/Modules/CodingModules/CoarseCoder/Examples/CoarseCoder_test.ikc @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/CodingModules/IntervalCoder/Examples/IntervalCoder_test.ikc b/Source/Modules/CodingModules/IntervalCoder/Examples/IntervalCoder_test.ikc new file mode 100755 index 000000000..cd4c013b1 --- /dev/null +++ b/Source/Modules/CodingModules/IntervalCoder/Examples/IntervalCoder_test.ikc @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/CodingModules/IntervalCoder/IntervalCoder.cc b/Source/Modules/CodingModules/IntervalCoder/IntervalCoder.cc new file mode 100755 index 000000000..2fc2f81c2 --- /dev/null +++ b/Source/Modules/CodingModules/IntervalCoder/IntervalCoder.cc @@ -0,0 +1,63 @@ +// +// IntervalCoder.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "IntervalCoder.h" + + +void +IntervalCoder::Init() +{ + input = GetInputArray("INPUT"); + output = GetOutputArray("OUTPUT"); + + output_size = GetOutputSize("OUTPUT"); + + radius = GetIntValue("radius", 1); + min = GetFloatValue("min", 0.0); + max = GetFloatValue("max", 1.0); + +} + + + +void +IntervalCoder::Tick() +{ + reset_array(output, output_size); + + float N = float(output_size) - 2 * float(radius); + float I = (max-min) / float(N-1); +// float c0 = min - float(radius) * I; + + for (int i=0; i + + + + + Module that generates a simple interval code for a real-valued input. + + + + + + + + + + + + + + + + + + 2003 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + IntervalCoder.h + IntervalCoder.cc + IntervalCoder.ikc + + + + diff --git a/Source/Modules/CodingModules/IntervalDecoder/Examples/IntervalDecoder_test.ikc b/Source/Modules/CodingModules/IntervalDecoder/Examples/IntervalDecoder_test.ikc new file mode 100755 index 000000000..973bf6f62 --- /dev/null +++ b/Source/Modules/CodingModules/IntervalDecoder/Examples/IntervalDecoder_test.ikc @@ -0,0 +1,91 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/CodingModules/IntervalDecoder/IntervalDecoder.cc b/Source/Modules/CodingModules/IntervalDecoder/IntervalDecoder.cc new file mode 100755 index 000000000..b98a7480d --- /dev/null +++ b/Source/Modules/CodingModules/IntervalDecoder/IntervalDecoder.cc @@ -0,0 +1,54 @@ +// +// IntervalDecoder.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "IntervalDecoder.h" + + +void +IntervalDecoder::Init() +{ + radius = GetIntValue("radius", 1); + min = GetFloatValue("min", 0.0); + max = GetFloatValue("max", 1.0); + + input = GetInputArray("INPUT"); + input_size = GetInputSize("INPUT"); + output = GetOutputArray("OUTPUT"); +} + + + +void +IntervalDecoder::Tick() +{ + float N = float(input_size) - 2 * float(radius); + float I = (max-min) / float(N-1); + float c0 = min - float(radius) * I; + + float v = c0; + for (int i=0; i + + + + + Module used to decode an interval coded vector. + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + IntervalDecoder.h + IntervalDecoder.cc + IntervalDecoder.ikc + + + diff --git a/Source/Modules/ControlModules/KalmanFilter/Examples/KalmanFilter_test.ikc b/Source/Modules/ControlModules/KalmanFilter/Examples/KalmanFilter_test.ikc new file mode 100755 index 000000000..d67a9bba9 --- /dev/null +++ b/Source/Modules/ControlModules/KalmanFilter/Examples/KalmanFilter_test.ikc @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.cc b/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.cc new file mode 100755 index 000000000..5a0821775 --- /dev/null +++ b/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.cc @@ -0,0 +1,172 @@ +// +// KalmanFilter.cc This file is a part of the IKAROS project +// The module implements a standard Kalman filter +// +// Copyright (C) 2009 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: 2009-05-27 +// +// + + +#include "KalmanFilter.h" + +using namespace ikaros; + + + +void +KalmanFilter::Init() +{ + Bind(process_noise, "process_noise"); + Bind(observation_noise, "observation_noise"); + + u_size = GetInputSize("INPUT"); + z_size = GetInputSize("OBSERVATION"); + x_size = GetOutputSize("STATE"); + + u = GetInputArray("INPUT"); + z = GetInputArray("OBSERVATION"); + x = GetOutputArray("STATE"); + y = GetOutputArray("INNOVATION"); + + A = GetMatrix("A", x_size, x_size); + B = GetMatrix("B", u_size, x_size); + H = GetMatrix("H", x_size, z_size); + + A_T = transpose(create_matrix(x_size, x_size), A, x_size, x_size); + B_T = transpose(create_matrix(x_size, u_size), B, x_size, u_size); + H_T = transpose(create_matrix(z_size, x_size), H, z_size, x_size); + + P = eye(create_matrix(x_size, x_size), x_size); + Q = multiply(eye(create_matrix(x_size, x_size), x_size), process_noise, x_size, x_size); // Process noise + R = multiply(eye(create_matrix(z_size, z_size), z_size), observation_noise, z_size, z_size); // Observation (measurement) noise + +// K = create_matrix(z_size, x_size); + K = GetOutputMatrix("KALMAN_GAIN"); +// int ksx = GetOutputSizeX("KALMAN_GAIN"); +// int ksy = GetOutputSizeY("KALMAN_GAIN"); + + I = eye(create_matrix(x_size, x_size), x_size); +} + + + +KalmanFilter::~KalmanFilter() +{ + destroy_matrix(A); + destroy_matrix(B); + destroy_matrix(H); + + destroy_matrix(A_T); + destroy_matrix(B_T); + destroy_matrix(H_T); + + destroy_matrix(P); + destroy_matrix(Q); + destroy_matrix(R); + + destroy_matrix(K); + destroy_matrix(I); +} + + + +void +KalmanFilter::Tick() +{ + // Recalculate variances for interactive demo + + multiply(eye(Q, x_size), process_noise, x_size, x_size); + multiply(eye(R, z_size), observation_noise, z_size, z_size); + + // Allocate temporary matrices + + float * x_p = create_array(x_size); + float ** P_p = create_matrix(x_size, x_size); + float ** tmp_zz = create_matrix(z_size, z_size); + float ** tmp_xz = create_matrix(x_size, z_size); + float ** tmp_zx = create_matrix(z_size, x_size); + float ** tmp_xx = create_matrix(x_size, x_size); + float ** tmp_xx2 = create_matrix(x_size, x_size); + float * tmp_z = create_array(z_size); + float ** S = create_matrix(z_size, z_size); + + float * Ax = create_array(x_size); + float * Bu = create_array(x_size); + + // Prediction: x_p = A*x + B*u + + multiply(Ax, A, x, x_size, x_size); + multiply(Bu, B, u, u_size, x_size); + add(x_p, Ax, Bu, x_size); + +// print_array(" x", x, x_size, x_size); +// print_array("x_p", x_p, x_size, x_size); + + // Prediction: P_p = A*P*T(A) + Q + + multiply(P_p, A, P, x_size, x_size, x_size); + multiply(tmp_xx, P_p, A_T, x_size, x_size, x_size); + add(P_p, tmp_xx, Q, x_size, x_size); + + // Measurement residual: y = z - H * x_p (innovation) + + multiply(tmp_z, H, x_p, x_size, z_size); + subtract(y, z, tmp_z, z_size); +// print_array(" y", y, z_size); + + // Residual covariance: S = H * P_p * H_T + R + + multiply(tmp_xz, H, P_p, x_size, z_size, x_size); + multiply(tmp_zz, tmp_xz, H_T, z_size, z_size, x_size); + add(S, tmp_zz, R, z_size, z_size); + + // Optimal Kalman gain: K = P_p * H_T * Inv(S) + + multiply(K, P_p, H_T, z_size, x_size, x_size); + bool r = inv(tmp_zz, S, z_size); + if(!r) + { + Notify(msg_warning, "KalmanFilter: Matrix S is singular.\n"); + return; + } + + multiply(tmp_zx, K, tmp_zz, z_size, x_size, z_size); + copy_matrix(K, tmp_zx, z_size, x_size); +// print_matrix(" K", K, z_size, x_size); + + // Posteriori update: x = x_p + K * y + + multiply(x, K, y, z_size, x_size); + add(x, x_p, x_size); + + // Posteriori update: P = (I - K * H) * P_p + + multiply(tmp_xx, K, H, x_size, x_size, z_size); + subtract(tmp_xx2, I, tmp_xx, x_size, x_size); + multiply(P, tmp_xx2, P_p, x_size, x_size, x_size); +// print_matrix(" P", P, x_size, x_size); + + // Clean up + + // FIXME: Clean upp the temporary matrices, or better still make them permanent +} + + diff --git a/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.h b/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.h new file mode 100755 index 000000000..93fcb9f01 --- /dev/null +++ b/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.h @@ -0,0 +1,78 @@ +// +// KalmanFilter.h This file is a part of the IKAROS project +// The module implements a standard Kalman filter +// +// Copyright (C) 2009 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: 2009-05-27 +// +// Inspired by the very clear implementation of the Kalman filter +// by Naba Kumar at http://libnxt.sourceforge.net and the +// explanation on Wikipedia +// + +#ifndef _KalmanFilter_ +#define _KalmanFilter_ + +#include "IKAROS.h" + +class KalmanFilter: public Module + { + public: + KalmanFilter(Parameter * p) : Module(p) {} + virtual ~KalmanFilter(); + + static Module * Create(Parameter * p) { return new KalmanFilter(p); } + + void Init(); + void Tick(); + + float process_noise; + float observation_noise; + + int u_size; + int x_size; + int z_size; + + float * u; // input + float * x; // state + float * z; // observation (measurement) + float * y; // innovation + + float * x_last; + float * x_in; + + float ** A; // state gain + float ** B; // input gain + float ** H; // measurement gain + + float ** A_T; // transposed matrices + float ** B_T; + float ** H_T; + + float ** P; // measurement gain + float ** Q; // state transition uncertainity covariance + float ** R; // obervation uncertainity covariance + + float ** K; // Kalman gain + + float ** I; // identity matrix +}; + +#endif diff --git a/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.ikc b/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.ikc new file mode 100755 index 000000000..7b1017f1e --- /dev/null +++ b/Source/Modules/ControlModules/KalmanFilter/KalmanFilter.ikc @@ -0,0 +1,130 @@ + + + + + +The module implements a standard Kalman filter. The process is described by the equation x(t+1) = Ax(t)+Bu(t), +where x is the state of the process and u is the control input. The observation (or measurement) is described by +Hz(t). The a priori process variance is set by the parameter process_noise and the measurement variance by +observation_noise. + + + +It should be possible to specify the full covariance matrices for the process and measurements (R and Q). + + + +The matrices A, B and H should also be able to use inputs instead of parameters. + + + +Observation and state sizes should be inferred from the matrix parameters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +Christian Balkenius +christian.balkenius@lucs.lu.se +Lund Univeristy Cognitive Science +http://www.lucs.lu.se/Christian.Balkenius/ + + + +KalmanFilter.h +KalmanFilter.cc +KalmanFilter.ikc + + + + + diff --git a/Source/Modules/ControlModules/PIDController/Examples/PIDController_test.ikc b/Source/Modules/ControlModules/PIDController/Examples/PIDController_test.ikc new file mode 100755 index 000000000..22fd75ba9 --- /dev/null +++ b/Source/Modules/ControlModules/PIDController/Examples/PIDController_test.ikc @@ -0,0 +1,35 @@ + + + + + + Example experiment file for PIDController. + This file only tests that the PIDController is functional. + It is not a good example of how to use the module. + + + + + + + + + + + + + + + + diff --git a/Source/Modules/ControlModules/PIDController/Examples/input.dat b/Source/Modules/ControlModules/PIDController/Examples/input.dat new file mode 100755 index 000000000..987329814 --- /dev/null +++ b/Source/Modules/ControlModules/PIDController/Examples/input.dat @@ -0,0 +1,16 @@ +# +# input.dat +# +# Example data for to test PIDController +# +# The data consists of two columns X and S +# with one value in each. +# + +X/1 S/1 +1 3 +2 3 +3 3 +4 3 +5 3 +6 3 diff --git a/Source/Modules/ControlModules/PIDController/PIDController.cc b/Source/Modules/ControlModules/PIDController/PIDController.cc new file mode 100755 index 000000000..6a0e96b5c --- /dev/null +++ b/Source/Modules/ControlModules/PIDController/PIDController.cc @@ -0,0 +1,106 @@ +// +// PIDController.cc This file is a part of the IKAROS project +// +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// + +#include "PIDController.h" + +using namespace ikaros; + +FILE * f = NULL; + + +PIDController::~PIDController() +{ + destroy_array(input_last); + + if(f) fclose(f); +} + + + +void PIDController::Init() +{ + Bind(Kb, "Kb"); + Bind(Kp, "Kp"); + Bind(Ki, "Ki"); + Bind(Kd, "Kd"); + + Bind(Fs, "Fs"); + Bind(Fm, "Fm"); + Bind(Fp, "Fp"); + Bind(Fi, "Fi"); + Bind(Fd, "Fd"); + Bind(Fc, "Fc"); + + Bind(Cmin, "Cmin"); + Bind(Cmax, "Cmax"); + + size = GetInputSize("INPUT"); + + input = GetInputArray("INPUT"); + set_point = GetInputArray("SETPOINT"); + output = GetOutputArray("OUTPUT"); + delta = GetOutputArray("DELTA"); + + filtered_set_point = GetOutputArray("FILTERED_SETPOINT"); + filtered_input = GetOutputArray("FILTERED_INPUT"); + filtered_error_p = GetOutputArray("FILTERED_ERROR_P"); + filtered_error_i = GetOutputArray("FILTERED_ERROR_I"); + filtered_error_d = GetOutputArray("FILTERED_ERROR_D"); + + input_last = create_array(size); + integral = GetOutputArray("INTEGRAL"); +} + + + +void PIDController::Tick() +{ + for(int i=0; i Cmax) + { + co = Cmax; + integral[i] -= filtered_error_i[i]; + } + else if(co < Cmin) + { + co = Cmin; + integral[i] -= filtered_error_i[i]; + } + + output[i] = (1-Fc) * co + (Fc) * output[i]; + } + + copy_array(input_last, filtered_input, size); +} + + + diff --git a/Source/Modules/ControlModules/PIDController/PIDController.h b/Source/Modules/ControlModules/PIDController/PIDController.h new file mode 100755 index 000000000..f6e36c62d --- /dev/null +++ b/Source/Modules/ControlModules/PIDController/PIDController.h @@ -0,0 +1,76 @@ +// +// PIDController.h This file is a part of the IKAROS project +// +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef PIDCONTROLLER +#define PIDCONTROLLER + +#include "IKAROS.h" + +class PIDController: public Module +{ +public: + // Control constants + + float Kb; // Bias (CO bias) + float Kp; // Proportional Gain + float Ki; // Intergral Gain + float Kd; // Differential Gain + + // Signal filters + + float Fs; // Set point filter + float Fm; // Measurement filter (PB filter) + float Fp; // Error filter for Proportional Gain + float Fi; // Error filter for Intergral Gain + float Fd; // Error filter for Differential Gain + float Fc; // Control filter (CO filter) + + // Min/Max Output + + float Cmin; + float Cmax; + + int size; // Size of the inputs + + float * input; // Current state of the system + float * input_last; // Last state of the system + float * set_point; // Desired set point + + + float * filtered_set_point; + float * filtered_input; + float * filtered_error_p; + float * filtered_error_i; + float * filtered_error_d; + + float * output; // Control output + float * delta; // Current state error + float * integral; // The integrated error + + static Module * Create(Parameter * p) { return new PIDController(p); } + + PIDController(Parameter * p) : Module(p) {} + virtual ~PIDController(); + + void Init(); + void Tick(); +}; + +#endif + diff --git a/Source/Modules/ControlModules/PIDController/PIDController.ikc b/Source/Modules/ControlModules/PIDController/PIDController.ikc new file mode 100755 index 000000000..90f5c13a6 --- /dev/null +++ b/Source/Modules/ControlModules/PIDController/PIDController.ikc @@ -0,0 +1,69 @@ + + + + + + Module that applies PID control independently to each of its inputs. + + All inputs and the control output can be filtered using the exponentially moving average. The filter constant + is set by the parameters Fs, Fm and Fc. Also the error used for propertional, integral and derivative + control can be filtered by setting the constants Fp, Fi and Fd to a value below 1. + + The integrator will not integerate the error when the control output has reached its minimum or maximum. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + PIDController.h + PIDController.cc + PIDController.ikc + + + + diff --git a/Source/Modules/EnvironmentModules/GridWorld/Examples/GridWorld_test.ikc b/Source/Modules/EnvironmentModules/GridWorld/Examples/GridWorld_test.ikc new file mode 100755 index 000000000..e24935b59 --- /dev/null +++ b/Source/Modules/EnvironmentModules/GridWorld/Examples/GridWorld_test.ikc @@ -0,0 +1,81 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/EnvironmentModules/GridWorld/GridWorld.cc b/Source/Modules/EnvironmentModules/GridWorld/GridWorld.cc new file mode 100755 index 000000000..29cdca26a --- /dev/null +++ b/Source/Modules/EnvironmentModules/GridWorld/GridWorld.cc @@ -0,0 +1,287 @@ +// +// GridWorld.cc This file is a part of the IKAROS project +// Implements a simple grid world with obstacles and rewards +// +// Copyright (C) 2003-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2003-07-14 +// +// surrounding: variable size + rotation, direction in image + +#include "GridWorld.h" + +#include "ctype.h" + + +using namespace ikaros; + +Module * GridWorld::Create(Parameter * p) +{ + return new GridWorld(p); +} + + + +GridWorld::GridWorld(Parameter * p): + Module(p) +{ + AddInput("OBSTACLES"); + AddInput("VALUES"); + + AddInput("MOVE"); + + AddOutput("REWARD", 1); + AddOutput("COLLISION", 1); + AddOutput("COORDINATE", 2); + AddOutput("LOCATION"); + AddOutput("LOCAL_OBSTACLES", 3, 3); + AddOutput("LOCAL_VALUES", 3, 3); + + AddOutput("IMAGE"); + + x_start = GetIntValue("x_start", 1); + y_start = GetIntValue("y_start", 1); + + mode = GetIntValueFromList("mode"); + normalize_coordinate = GetBoolValue("normalize_coordinate"); +} + + + +void +GridWorld::SetSizes() +{ + int sizex = GetInputSizeX("OBSTACLES"); + int sizey = GetInputSizeY("OBSTACLES"); + + if(sizex == unknown_size || sizey == unknown_size) + return; + + SetOutputSize("LOCATION", sizex, sizey); + SetOutputSize("IMAGE", sizex, sizey); +} + + + +void +GridWorld::Draw(int _x, int _y) +{ + copy_matrix(image, obstacles, size_x, size_y); + + for (int j=0; j 0) + image[j][i] = 3; + + image[_y][_x] = 2.0; +} + + + +void +GridWorld::Init() +{ + move = GetInputArray("MOVE"); + + location = GetOutputMatrix("LOCATION"); + coordinate = GetOutputArray("COORDINATE"); + + local_obstacles = GetOutputMatrix("LOCAL_OBSTACLES"); + local_values = GetOutputMatrix("LOCAL_VALUES"); + + obstacles = GetInputMatrix("OBSTACLES"); + values = GetInputMatrix("VALUES"); + + reward = GetOutputArray("REWARD"); + collision = GetOutputArray("COLLISION"); + image = GetOutputMatrix("IMAGE"); + + size_x = GetInputSizeX("OBSTACLES"); + size_y = GetInputSizeY("OBSTACLES"); + + // Check inputs here + + if((size_x != GetInputSizeX("VALUES")) || (size_y != GetInputSizeY("VALUES"))) + { + Notify(msg_fatal_error, "Size of VALUES input of module %s (%s) does not match OBSTACLES input\n", GetName(), GetClassName()); + return; + } + + + // CHECK INPUT SIZE 3 or 4 !!!!! + + x_start = max(min(x_start, size_x-2), 1); + y_start = max(min(y_start, size_y-2), 1); + + x = x_start; + y = y_start; + + Draw(x_start, y_start); +} + + + +GridWorld::~GridWorld() +{ +} + + + +static int dx[4] = { 0, 1, 0, -1 }; +static int dy[4] = { -1, 0, 1, 0 }; + +void +GridWorld::Tick() +{ + if (move == NULL || zero(move, (mode < 2 ? 4 : 3))) + { + reward[0] = 0; + Draw(x, y); + return; + } + + int xr = 0; + int yr = 0; + int mv = 0; + + switch (mode) + { + case 0: // sum + { + float m[4] = {move[0]-move[2], move[1]-move[3], move[2]-move[0], move[3]-move[1]}; + mv = arg_max(m, 4); + xr = dx[mv]; + yr = dy[mv]; + } break; + + case 1: // max + { + mv = arg_max(move, 4); + xr = dx[mv]; + yr = dy[mv]; + } break; + + case 2: // relative sum + { + float m[3] = {move[0]-move[1], move[1]-move[0], move[3]}; + mv = arg_max(m, 3); + if (mv == 2) + { + xr = dx[dir]; + yr = dy[dir]; + } + else if (mv == 1) + dir = (dir + 1) % 4; + else if (mv == 1) + dir = (dir - 1 + 4) % 4; + } break; + + case 3: // relative max + { + mv = arg_max(move, 3); + if (mv == 2) + { + xr = dx[dir]; + yr = dy[dir]; + } + else if (mv == 1) + dir = (dir + 1) % 4; + else if (mv == 1) + dir = (dir - 1 + 4) % 4; + } break; + + default: + ; + } + + // Agent can not occupy the outer border of the grid + + if (x+xr > 0 && x+xr < size_x-1 && y+yr > 0 && y+yr < size_y-1 && obstacles[y+yr][x+xr] != 1) + { + x += xr; + y += yr; + *collision = 1; + } + else + *collision = 0; + + Draw(x, y); + + reward[0] = values[y][x]; + + if (reward != NULL && reward[0] > 0) + { +// reward[0] = 0.0; + x = x_start; + y = y_start; +// reward[0] = values[y][x]; + if(normalize_coordinate) + { + coordinate[0] = 1/(2*float(size_x)) + float(x)/float(size_x); + coordinate[1] = 1/(2*float(size_y)) + float(y)/float(size_y); + } + else + { + coordinate[0] = x; + coordinate[1] = y; + } + + // The rest should be used in ONE place + + reset_matrix(location, size_x, size_y); + location[y][x] = 1; + Draw(x, y); + + // Set surrounding + + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + local_obstacles[j][i] = obstacles[y+j-1][x+i-1]; + + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + local_values[j][i] = values[y+j-1][x+i-1]; + + return; + } + + if(normalize_coordinate) + { + coordinate[0] = 1/(2*float(size_x)) + float(x)/float(size_x); + coordinate[1] = 1/(2*float(size_y)) + float(y)/float(size_y); + } + else + { + coordinate[0] = x; + coordinate[1] = y; + } + + reset_matrix(location, size_x, size_y); + location[y][x] = 1.0; + + // Set surrounding + + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + local_obstacles[j][i] = obstacles[y+j-1][x+i-1]; + + for (int i=0; i<3; i++) + for (int j=0; j<3; j++) + local_values[j][i] = values[y+j-1][x+i-1]; +} + + diff --git a/Source/Modules/EnvironmentModules/GridWorld/GridWorld.h b/Source/Modules/EnvironmentModules/GridWorld/GridWorld.h new file mode 100755 index 000000000..c5a97465c --- /dev/null +++ b/Source/Modules/EnvironmentModules/GridWorld/GridWorld.h @@ -0,0 +1,71 @@ +// +// GridWorld.h This file is a part of the IKAROS project +// Implements a simple grid world with obstacles and rewards +// +// Copyright (C) 2003-2007 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2003-07-14 +// Revised: 2007-07-18 + +#ifndef GridWorld_ +#define GridWorld_ + + +#include "IKAROS.h" +#include "ctype.h" + +class GridWorld: public Module +{ +public: + float * move; + float ** location; + float * coordinate; + float ** obstacles; + float ** values; + float ** local_obstacles; + float ** local_values; + float * reward; + float * collision; + float ** image; + + int x_start; + int y_start; + + int mode; + bool normalize_coordinate; + + int x; + int y; + int dir; + + int size_x; + int size_y; + + GridWorld(Parameter * p); + virtual ~GridWorld(); + + static Module * Create(Parameter * p); + + void Draw(int x, int y); + + void SetSizes(); + void Init(); + void Tick(); + +}; + +#endif diff --git a/Source/Modules/EnvironmentModules/GridWorld/GridWorld.ikc b/Source/Modules/EnvironmentModules/GridWorld/GridWorld.ikc new file mode 100755 index 000000000..fa3401af2 --- /dev/null +++ b/Source/Modules/EnvironmentModules/GridWorld/GridWorld.ikc @@ -0,0 +1,78 @@ + + + + + +

+ Module that implements a simple grid world with obstacles and rewards/reinforcement. + Movements are given either as absolute or relative directions in the MOVE input. +

+

+ In absolute mode set by move = "max", the maximum direction in the MOVE array sets the + direction of movement. The four components in the array correspond to north (up), east (right), + south (down) and west (left). In absolute mode with summation, set by move = "sum", the movement + is the result of adding all directions in the MOVE input before finding the maximum direction. +

+

+ In relative mode, set by move = "relative", the array MOVE is interpreted as having + three components: move-ahead, turn-left, turn-right. With mode = "relative_sum", the components + turn-left and turn-right are subtracted before the maximum is found. +

+

+ No action is performed if MOVE is the zero vector. +

+

+ The agent is automatically moved to the initial location when a reward location is reached. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + It should be possible to turn off the automatic movement of the agent from goal to start locations. + + + 2003 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + GridWorld.h + GridWorld.cc + GridWorld.ikc + + +
diff --git a/Source/Modules/EnvironmentModules/MazeGenerator/Examples/MazeGenerator_and_QL_test.ikc b/Source/Modules/EnvironmentModules/MazeGenerator/Examples/MazeGenerator_and_QL_test.ikc new file mode 100755 index 000000000..0d574ab00 --- /dev/null +++ b/Source/Modules/EnvironmentModules/MazeGenerator/Examples/MazeGenerator_and_QL_test.ikc @@ -0,0 +1,90 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + <_object class="BarGraph" module="GW" source="REWARD" x="1" y="1" /> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/EnvironmentModules/MazeGenerator/Examples/MazeGenerator_test.ikc b/Source/Modules/EnvironmentModules/MazeGenerator/Examples/MazeGenerator_test.ikc new file mode 100755 index 000000000..65674a4a7 --- /dev/null +++ b/Source/Modules/EnvironmentModules/MazeGenerator/Examples/MazeGenerator_test.ikc @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + diff --git a/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.cc b/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.cc new file mode 100755 index 000000000..6796085d4 --- /dev/null +++ b/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.cc @@ -0,0 +1,176 @@ +// +// MazeGenerator.cc This file is a part of the IKAROS project +// Implements a simple maze generator +// +// Copyright (C) 2009 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +#include "MazeGenerator.h" + +using namespace ikaros; + + +void +MazeGenerator::SetSizes() +{ + size = GetIntValue("size"); + + SetOutputSize("OUTPUT", 2*size+1, 2*size+1); + SetOutputSize("GOAL", 2*size+1, 2*size+1); +} + + + +void +MazeGenerator::GeneratePerfectMaze() +{ + // Fill in walls + + for(int j=0; j0 && output[yy][xx-1] == 1 && output[yy][xx+1] == 1 && output[yy-1][xx] == 1 && output[yy+1][xx] == 1 ) + { + cell[0] = true; + cells++; + } + + yy = 2*y+1; + xx = 2*(x+1)+1; + if(x0 && output[yy][xx-1] == 1 && output[yy][xx+1] == 1 && output[yy-1][xx] == 1 && output[yy+1][xx] == 1 ) + { + cell[2] = true; + cells++; + } + + yy = 2*(y+1)+1; + xx = 2*x+1; + if(y 0) + { + int r = random(4); // for random output, select directional for longer corridors? + while(!cell[r]) + r = (r+1) % 4; + + stack[sp++] = current_cell; + + switch(r) + { + case 0: + yy = 2*y+1; + xx = 2*x+1-1; + output[yy][xx] = 0; + current_cell = y*size+(x-1); + break; + + case 1: + yy = 2*y+1; + xx = 2*x+1+1; + output[yy][xx] = 0; + current_cell = y*size+(x+1); + break; + + case 2: + yy = 2*y+1-1; + xx = 2*x+1; + output[yy][xx] = 0; + current_cell = (y-1)*size+x; + break; + + case 3: + yy = 2*y+1+1; + xx = 2*x+1; + output[yy][xx] = 0; + current_cell = (y+1)*size+x; + break; + } + visited_cells++; + } + + else // pop + { + current_cell = stack[--sp]; + } + } +} + + + +void +MazeGenerator::Init() +{ + + output = GetOutputMatrix("OUTPUT"); + sizex = GetOutputSizeX("OUTPUT"); + sizey = GetOutputSizeY("OUTPUT"); + + regenerate = GetIntValue("regenerate"); + tick = 0; + + if(regenerate == 0) + GeneratePerfectMaze(); +} + + + +void +MazeGenerator::Tick() +{ + if(regenerate != 0 && tick++ % regenerate == 0) + GeneratePerfectMaze(); +} + diff --git a/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.h b/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.h new file mode 100755 index 000000000..ac1d38fe1 --- /dev/null +++ b/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.h @@ -0,0 +1,54 @@ +// +// MazeGenerator.h This file is a part of the IKAROS project +// Implements a simple maze generator +// +// Copyright (C) 2009 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef MazeGenerator_ +#define MazeGenerator_ + + +#include "IKAROS.h" + +class MazeGenerator: public Module +{ +public: + int size; + + int sizex; + int sizey; + int regenerate; + int tick; + + float ** output; + + static Module * Create(Parameter * p) { return new MazeGenerator(p); } + + void GeneratePerfectMaze(); + + MazeGenerator(Parameter * p) : Module(p) {} + virtual ~MazeGenerator() {}; + + void SetSizes(); + void Init(); + void Tick(); + +}; + +#endif + diff --git a/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.ikc b/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.ikc new file mode 100755 index 000000000..2bb4ee046 --- /dev/null +++ b/Source/Modules/EnvironmentModules/MazeGenerator/MazeGenerator.ikc @@ -0,0 +1,46 @@ + + + + + +

+ Module that implements a depth-first method that generates a perfect maze. A partfect maze is + one with exactly one path between any two locations in the maze. The maze is randomly generated. + use -z# at the command line with different numbers for # to get different mazes each time. +

+
+ + + + + + + + + + + + + + 2009 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + MazeGenerator.h + MazeGenerator.cc + MazeGenerator.ikc + + +
+ diff --git a/Source/Modules/EnvironmentModules/PlanarArm/Examples/PlanarArm_test.ikc b/Source/Modules/EnvironmentModules/PlanarArm/Examples/PlanarArm_test.ikc new file mode 100755 index 000000000..c5e48c0fb --- /dev/null +++ b/Source/Modules/EnvironmentModules/PlanarArm/Examples/PlanarArm_test.ikc @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.cc b/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.cc new file mode 100755 index 000000000..b39ca2d07 --- /dev/null +++ b/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.cc @@ -0,0 +1,204 @@ +// +// PlanarArm.cc This file is a part of the IKAROS project +// Implements a simple arm and a target object +// +// Copyright (C) 2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "PlanarArm.h" + +using namespace ikaros; + +void +PlanarArm::UpdateArm() +{ + // Check bounds of angles + + angles[0] = clip(angles[0], -pi/1.5, pi/1.5); + angles[1] = clip(angles[1], 0, pi); + angles[2] = clip(angles[2], 0, pi); + + // Set joints + + joints[0][0] = 0.5; + joints[0][1] = 0.0; + + joints[1][0] = joints[0][0] + segment_length[0] * sin(angles[0]); + joints[1][1] = joints[0][1] + segment_length[0] * cos(angles[0]); + + joints[2][0] = joints[1][0] + segment_length[1] * sin(angles[1]+angles[0]); + joints[2][1] = joints[1][1] + segment_length[1] * cos(angles[1]+angles[0]); + + joints[3][0] = joints[2][0] + segment_length[2] * sin(angles[2]+angles[1]+angles[0]); + joints[3][1] = joints[2][1] + segment_length[2] * cos(angles[2]+angles[1]+angles[0]); + + hand_position[0] = joints[3][0]; + hand_position[1] = joints[3][1]; +} + + + +void +PlanarArm::MoveArm() +{ + subtract(movement, desired_angles, angles, 3); + + // amax + + float m = abs(movement[0]); + if (abs(movement[1]) > m) + m =abs(movement[1]); + if (abs(movement[2]) > m) + m =abs(movement[2]); + + // correct for maximum speed + + if (m > speed) + multiply(movement, speed/m, 3); + +// printf("%f %f %f\n", movement[0], movement[1], movement[2]); + + float a0 = angles[0]; + float a1 = angles[1]; + float a2 = angles[2]; + + add(angles, movement, 3); + UpdateArm(); + + // Reject positions outside the 0.01-0.99 frame + + if (hand_position[0] < 0.01f || hand_position[0]>0.99f || hand_position[1] < 0.01f || hand_position[1]>0.99f) + { + angles[0] = a0; + angles[1] = a1; + angles[2] = a2; + UpdateArm(); + } +} + + + +void +PlanarArm::Init() +{ + target_behavior = GetIntValueFromList("target_behavior"); + target_speed = GetFloatValue("target_speed"); + target_size = GetFloatValue("target_size"); + target_range = GetFloatValue("target_range"); + target_noise = GetFloatValue("target_noise"); + + speed = GetFloatValue("speed"); + + grasp_limit = GetFloatValue("grasp_limit"); + + target = GetOutputArray("TARGET"); + joints = GetOutputMatrix("JOINTS"); + hand_position = GetOutputArray("HAND_POSITION"); + angles = GetOutputArray("ANGLES"); + desired_angles = GetInputArray("DESIRED_ANGLES", false); // check size = 3 if connected + movement = create_array(3); + + distance = GetOutputArray("DISTANCE"); + contact = GetOutputArray("CONTACT"); + + segment_length = create_array(3); + + segment_length[0] = 0.35; + segment_length[1] = 0.25; + segment_length[2] = 0.20; + + set_array(angles, 0.4, 3); + + UpdateArm(); +} + + + +void +PlanarArm::Tick() +{ + // Arm simulation + + if (desired_angles) + MoveArm(); + + // Detect grasp posibility + + *distance = dist(hand_position, target, 2); + if (*distance < target_size) + *contact = 1; + else + *contact = 0; + + // Target simulation + + switch (target_behavior) + { + case 0: // random + { + if (time == 0 || *distance < grasp_limit || time % 100 == 0) + { + target[0] = random(0.1, 0.9); + target[1] = random(0.1, 0.9); + } + break; + } + case 1: // linear (sin speed) + { + target[0] = 0.5+target_range*sin(target_speed*float(time)); + target[1] = 0.5; + break; + } + case 2: // circle + { + target[0] = 0.5+target_range*sin(target_speed*float(time)); + target[1] = 0.5+target_range*cos(target_speed*float(time)); + break; + } + + case 3: // lisajous + { + target[0] = 0.5+target_range*sin(target_speed*float(time)); + target[1] = 0.5+target_range*cos(0.3*target_speed*float(time)); + break; + } + case 4: // square + { + float x = sin(target_speed*float(time)); + float y = cos(target_speed*float(time)); + float L = abs(x)+abs(y); + target[0] = 0.5+target_range*(L != 0 ? x/L : 0); + target[1] = 0.5+target_range*(L != 0 ? y/L : 0); + break; + } + default: + + break; + } + +// printf("%f %f\t", target[0], target[1]); // Actual + + target[0] += gaussian_noise(0, target_noise); + target[1] += gaussian_noise(0, target_noise); + + if (*distance < grasp_limit) + time = int(random(0, 100)); + + time++; +} + + diff --git a/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.h b/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.h new file mode 100755 index 000000000..a6eefb807 --- /dev/null +++ b/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.h @@ -0,0 +1,73 @@ +// +// PlanarArm.h This file is a part of the IKAROS project +// Implements a simple arm and a target object +// +// Copyright (C) 2007 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef PlanarArm_ +#define PlanarArm_ + +#include "IKAROS.h" + +class PlanarArm: public Module +{ +public: + // Arm variables + + float * desired_angles; // input: desired angles + float * angles; // output: current angles of the arm + float * movement; // internal: actual movement (< speed) + + float * segment_length; // parameter: arm lengths + float ** joints; // output: position of the joints + float * hand_position; // position of the last + float * hit; // output: 0/1 contact with the target + + float speed; // maximum angular velocity per tick + + // Target variables + + float * target; // output: location of the target + int target_behavior; // random, circular, linear, etc + float target_speed; + float target_range; // distance from center + float target_noise; // stdev of gaussian noise + float target_size; // radius of the target + int time; + + // Distance + + float * distance; // output: distance from hand to target + float * contact; // output: 0/1 + float grasp_limit; // max distance from hand to target for a grasp (which moves the target to a random location) + + PlanarArm(Parameter * p) : Module(p) {} + virtual ~PlanarArm() {} + + static Module * Create(Parameter * p) { return new PlanarArm(p); } + + void MoveArm(); + void UpdateArm(); + + void Init(); + void Tick(); + +}; + +#endif + diff --git a/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.ikc b/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.ikc new file mode 100755 index 000000000..a94d56a61 --- /dev/null +++ b/Source/Modules/EnvironmentModules/PlanarArm/PlanarArm.ikc @@ -0,0 +1,58 @@ + + + + + +

+ Module that implements a simple arm simulation. +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + Not yet fully implemented + + + 2007 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + PlanarArm.h + PlanarArm.cc + PlanarArm.ikc + + +
+ diff --git a/Source/Modules/Examples/DelayOne/DelayOne.cc b/Source/Modules/Examples/DelayOne/DelayOne.cc new file mode 100755 index 000000000..e9110a70b --- /dev/null +++ b/Source/Modules/Examples/DelayOne/DelayOne.cc @@ -0,0 +1,139 @@ +// +// DelayOne.cc This file is a part of the IKAROS project +// Pointless example module delaying its input one tick. +// +// Copyright (C) 2002 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2002-01-27 +// +// This module demonstrates how the output size can depend on the input size +// using the SetSizes function + + +#include "DelayOne.h" + + +// This is a function used to create and return an object +// of class DelayOne +// This function is identical for all modules + +Module * DelayOne::Create(Parameter * p) +{ + return new DelayOne(p); +} + + +// This is the creator function +// It should include code to add inputs and outputs to a module + +DelayOne::DelayOne(Parameter * p): + Module(p) +{ + // Add and intput named "INPUT" + + AddInput("INPUT"); + + // Add an output to the module names "OUTPUT" + // The size of the output size not set here + // The parameter 'unknown_size' can be left out since it is the default + // It is included here for clarity + + AddOutput("OUTPUT", unknown_size); + + // Set pointers to NULL if something goes wrong during initilization + // This indicates that no memory has been allocated for these + // arrays yet + + input = NULL; + output = NULL; +} + + + +// SetSizes is called during initialization of a network to +// let modules set output sizes based on the sizes of their inputs + +void +DelayOne::SetSizes() +{ + // Get the size of the input named "INTPUT" + + int s = GetInputSize("INPUT"); + + // Check that the size of the input is set and set the + // size of the output named "OUTPUT" accordingly + + if (s != unknown_size) + SetOutputSize("OUTPUT", s); +} + + +// The function Init is called at start-up when the size of all intputs +// and outputs have been calculated. +// You should allocate any additional memory here. +// This is also a useful place to get the pointers to intput and +// output arrays as well as their sizes. + +void +DelayOne::Init() +{ + // Get the sizes of inputs and outputs + + theNoOfInputs = GetInputSize("INPUT"); + theNoOfOutputs = GetOutputSize("OUTPUT"); + + // Do some error checking + + if (theNoOfOutputs == unknown_size) // This should never happen since the kernel should already have terminated the program + { + Notify(msg_fatal_error, "DelayOne: OutputSize could not be resolved\n"); + return; + } + + if (theNoOfInputs != theNoOfOutputs) // This should never happen since DelayOne::SetSizes() should make sure this condition is met + { + Notify(msg_fatal_error, "DelayOne: Both inputs and outputs need to be of the same size\n"); + return; + } + + // Get pointers to the input and output arrays + // so we do not have to do that at each iteration later + + input = GetInputArray("INPUT"); + output = GetOutputArray("OUTPUT"); +} + +// This is the destructor function for the module +// Any additional memory allocated in Init should +// be deallocated here + +DelayOne::~DelayOne() +{ +} + + +// Tick is the module function that is called repeatedly during +// execution. It transforms its input to the new input +// In this simple example module it copies the input to the +// output. This will delay the signal by one time step. + +void DelayOne::Tick() +{ + for (int i=0; i + + + + + Module that sums its two inputs element by element, + which can be one or two dimensional. + Both inputs must have the same size. + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + WhiteBalance.h + WhiteBalance.cc + WhiteBalance.ikc + + + diff --git a/Source/Modules/Examples/Sum/Examples/Sum_test.ikc b/Source/Modules/Examples/Sum/Examples/Sum_test.ikc new file mode 100755 index 000000000..ae4f19335 --- /dev/null +++ b/Source/Modules/Examples/Sum/Examples/Sum_test.ikc @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/Source/Modules/Examples/Sum/Examples/inputfile.txt b/Source/Modules/Examples/Sum/Examples/inputfile.txt new file mode 100755 index 000000000..26dfbb351 --- /dev/null +++ b/Source/Modules/Examples/Sum/Examples/inputfile.txt @@ -0,0 +1,8 @@ +A/2 B/2 +1 1 1 1 +2 1 1 2 +3 1 1 3 +4 1 1 4 +5 5 5 5 +0 0 0 0 +0 0 0 0 diff --git a/Source/Modules/Examples/Sum/Examples/outputfile.txt b/Source/Modules/Examples/Sum/Examples/outputfile.txt new file mode 100755 index 000000000..e69de29bb diff --git a/Source/Modules/Examples/Sum/Sum.cc b/Source/Modules/Examples/Sum/Sum.cc new file mode 100755 index 000000000..36e817e15 --- /dev/null +++ b/Source/Modules/Examples/Sum/Sum.cc @@ -0,0 +1,125 @@ +// +// Sum.cc This file is a part of the IKAROS project +// Old example for version 1.1 and earlier. +// +// Copyright (C) 2001-2002 Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2001-12-01 +// +// 2003-01-14 Updated for the new simulator + +#include "Sum.h" + +Module * Sum::Create(Parameter * p) +{ + return new Sum(p); +} + + +Sum::Sum(Parameter * p): Module(p) +{ + + // AddInput here declares two inputs for the module. These are the same + // names used in the experiment configuration file. + + AddInput("INPUT1"); + AddInput("INPUT2"); + + // Here we declare an output and tell the simulator that its size will be + // figured out later. The parameter is not strictly necessary as it is the + // default value, but it is a good idea to include it for clarity. + + AddOutput("OUTPUT", unknown_size); + +} + +// SetSizes is called during initialization of a network to +// let modules set output sizes based on the sizes of their inputs +// +// It is called repeatedly until all sizes for all modules are fixed or until +// Ikaros discovers it is not possible to set a consistent set of data sizes. + +void Sum::SetSizes() +{ + // find out the sizes of the inputs. + + int in1 = GetInputSize("INPUT1"); + int in2 = GetInputSize("INPUT2"); + + // now, we require that the input vectors are the same size. So we first + // check that the sizes are both set, and the compare them to see if + // they're equal. If not, we abort with an error message. + + if (in1 != unknown_size && in2 != unknown_size){ + if (in1!=in2) + { + Notify(msg_fatal_error, "Sum: the input sizes must be equal: INPUT1 = %d\t INPUT2 = %d\n", in1, in2); + return; + } + + // Set the size of the output vector to be equal to the size of the + // input vectors. + + SetOutputSize("OUTPUT", in1); + } +} + + +void Sum::Init() +{ + input1 = NULL; + input2 = NULL; + output = NULL; + + theNoOfInputs1 = GetInputSize("INPUT1"); + theNoOfInputs2 = GetInputSize("INPUT2"); + theNoOfOutputs = GetOutputSize("OUTPUT"); + + // Here we could add any number of consistency checks and do any memory + // allocations and other initializations that wer need to do. + + + + // Set the variables that will be associated with the inputs and outputs + // during the simulation. Each time the Tick method is entered, the input1 + // and input2 will point to the input vectors, and output will point to + // the output vector. + + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); +} + + +Sum::~Sum() +{ +} + + +void Sum::Tick() +{ + int i; + + // Sum in action. input1 and input2 are pointers to the current input + // vectors and output points to the output vector that will be sent + // along to whatever modules it is connected to. + + for (i=0; i + + + + + Module that sums its two inputs element by element. + Both inputs must have the same size. + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Sum.h + Sum.cc + Sum.ikc + + + diff --git a/Source/Modules/IOModules/FileInput/InputFile/Examples/input.dat b/Source/Modules/IOModules/FileInput/InputFile/Examples/input.dat new file mode 100755 index 000000000..8ae1d615e --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputFile/Examples/input.dat @@ -0,0 +1,19 @@ +# +# input.dat +# +# Example data for InputModule +# +# The data consists of two columns X and Y +# with two values in each. +# +# The module InputFile will create two outputs +# called X and Y that will output the values +# on each row. +# + +X/2 Y/2 +1 2 3 4 +2 3 5 7 +3 7 3 4 +9 7 6 2 + diff --git a/Source/Modules/IOModules/FileInput/InputFile/Examples/inputfile_test.ikc b/Source/Modules/IOModules/FileInput/InputFile/Examples/inputfile_test.ikc new file mode 100755 index 000000000..8ea5d129d --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputFile/Examples/inputfile_test.ikc @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileInput/InputFile/InputFile.cc b/Source/Modules/IOModules/FileInput/InputFile/InputFile.cc new file mode 100755 index 000000000..fc33e7ed6 --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputFile/InputFile.cc @@ -0,0 +1,246 @@ +// +// InputFile.cc This file is a part of the IKAROS project +// A module for reading from files with data in column form +// +// Copyright (C) 2001-2002 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Revision History +// +// 2002-01-15 Support for # comments and blank lines added +// 2002-01-17 Support for UNIX, Mac and DOS end of line tokens added + +//#define DEBUG_INPUTFILE + +#include "InputFile.h" + +static void +skip_comment_lines(FILE * file) +{ + char c = fgetc(file); + + while (c=='#' || c==' ' || c=='\t' || c=='\n' || c=='\r') + { + if (c=='#') + { + fscanf(file, "%*[^\n\r]"); + fscanf(file, " \r"); + fscanf(file, " \n"); + } + else if (c==' ' || c=='\t') + { + fscanf(file, " \r"); + fscanf(file, " \n"); + } + else if (c=='\n') + { + fscanf(file, " \n"); + } + else if (c=='\r') + { + fscanf(file, " \r"); + fscanf(file, " \n"); + } + c = fgetc(file); + } + ungetc(c, file); +} + + +/* +static char +fpeekc(FILE * f) +{ + char c = fgetc(f); + ungetc(c, f); + return c; +} +*/ + + +InputFile::InputFile(Parameter * p): + Module(p) +{ + // Scan input file and add output connections + + /* char * */ + + filename = GetValue("filename"); + if (filename == NULL) + { + Notify(msg_fatal_error, "No input file parameter supplied.\n"); + return; + } + + iteration = 1; + iterations = GetIntValue("iterations", 1); + extend = GetIntValue("extend", 0); + cur_extension = 0; + extending = false; + print_iteration = GetBoolValue("print_iteration"); + + file = fopen(filename, "rb"); + if (file == NULL) + { + Notify(msg_fatal_error, "Could not open input file \"%s\" \n", filename); + return; + } + + no_of_columns = 0; + char col_label[64]; + int col_size; + + // Count number of columns in input file + + skip_comment_lines(file); + fscanf(file, "%*[^A-Za-z\n\r]"); // Skip until letter or end of line + + while (fscanf(file, "%[^/\n\r]/%d", col_label, &col_size) == 2) + { + no_of_columns++; + fscanf(file, "%*[^A-Za-z\n\r]"); // Skip until letter or end of line +#ifdef DEBUG_INPUTFILE + printf(" Counting column \"%s\" with width %d in file \"%s\".\n", col_label, col_size, filename); +#endif + } + + column_name = new char * [no_of_columns]; + column_size = new int [no_of_columns]; + column_data = new float * [no_of_columns]; + + for (int i=0; i= extend-1) + Notify(msg_end_of_file); + + else if (cur_extension == 0) + { + for (int col=0; col < no_of_columns; col++) + for (int i=0; i + + + + +

+ Module used for reading numerical input data from a text file. The data is represented in the file as a number of columns given names in a header. Each set of columns will be available as an output vector from the module with the same name as the columns. +

+

+ The following example shows how the header describes the number of columns in each output vector and its name: +

+
+  X/2 Y/3
+  10   2.0    12     5     8
+   2    31   5.4    10     1
+   :
+   :
+
+

+ The first output will get the name "X" and consists of two values while the second output will be called "Y" and contain three elements. Each row in the file corresponds to the output from an InputFile module at each time step. +

+

+ Comments can be added in the data file after a hash sign (#) as in the following example: +

+
+ # This is a comment; this line will be ignored in the input
+   X/2 Y/3
+  10   2.0    12     5     8	# This is also a comment
+   2    31   5.4    10     1	# and this
+   :
+   :
+
+

+ Blank lines in the file are skipped. When the whole file has been read, the module send an end-of-file signal to the IKAROS kernel that will stop the execution. This is useful in off-line simulations. +

+

+ InputFile can read files using any of the three popular line terminators: CR, LF, or CR+LF. +

+
+ + + + + + + + + + + + + + + + It is not possible to loop the data file indefinitely. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + 2001 + + + InputFile.h + InputFile.cc + InputFile.ikc + + +
diff --git a/Source/Modules/IOModules/FileInput/InputQTMovie/Examples/InputQTMovie_fun.ikc b/Source/Modules/IOModules/FileInput/InputQTMovie/Examples/InputQTMovie_fun.ikc new file mode 100755 index 000000000..cc576e2e3 --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputQTMovie/Examples/InputQTMovie_fun.ikc @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileInput/InputQTMovie/Examples/InputQTMovie_test.ikc b/Source/Modules/IOModules/FileInput/InputQTMovie/Examples/InputQTMovie_test.ikc new file mode 100755 index 000000000..3561b1fdf --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputQTMovie/Examples/InputQTMovie_test.ikc @@ -0,0 +1,25 @@ + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.M b/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.M new file mode 100755 index 000000000..772c2965d --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.M @@ -0,0 +1,197 @@ +// +// InputQTMovie.M This file is a part of the IKAROS project +// A module for reading from a QuickTime movie +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// This module is written in Objective-C++ to allow easy interface with QTKit +// + +#include "InputQTMovie.h" + +#ifdef USE_QUICKTIME + + +#import +#import +#import + + + +class InputQTMovieData +{ +public: + NSAutoreleasePool * pool; + QTMovie * movie; +}; + + + +InputQTMovie::InputQTMovie(Parameter * p): +Module(p) +{ + + data = new InputQTMovieData(); + + data->pool = [[NSAutoreleasePool alloc] init]; + [QTMovie enterQTKitOnThread]; + + filename = GetValue("filename"); + loop = GetBoolValue("loop", false); + + size_x = GetIntValue("size_x"); + size_y = GetIntValue("size_y"); + + if (!filename) + { + Notify(msg_fatal_error, "No filename for InputQTMovie.\n"); + return; + } + + data->movie = nil; + + NSString * fileName = [NSString stringWithCString:filename encoding: NSUTF8StringEncoding]; + NSURL * url = [NSURL fileURLWithPath: fileName]; + if([QTMovie canInitWithURL: url]) + { + data->movie = [QTMovie movieWithURL:url error:nil]; + + NSSize size = [[data->movie attributeForKey:QTMovieNaturalSizeAttribute] sizeValue]; + native_size_x = int(size.width); + native_size_y = int(size.height); + + if(size_x == 0 || size_y == 0) + { + size_x = native_size_x; + size_y = native_size_y; + } + + AddOutput("INTENSITY", size_x, size_y); + AddOutput("RED", size_x, size_y); + AddOutput("GREEN", size_x, size_y); + AddOutput("BLUE", size_x, size_y); + + AddOutput("RESTART", 1); + + [data->movie gotoBeginning]; + } + + else + { + Notify(msg_fatal_error, "Could not find movie file \"%s\".\n", filename); + } +} + + + +InputQTMovie::~InputQTMovie() +{ + [data->movie release]; +// [data->pool drain]; + + delete data; + [QTMovie exitQTKitOnThread]; +} + + + +void +InputQTMovie::Init() +{ + intensity = GetOutputArray("INTENSITY"); + red = GetOutputArray("RED"); + green = GetOutputArray("GREEN"); + blue = GetOutputArray("BLUE"); + + restart = GetOutputArray("RESTART"); + restart[0] = -1; // indicates first tick +} + + + +void +InputQTMovie::Tick() +{ + const float c13 = 1.0/3.0; + const float c1255 = 1.0/255.0; + + restart[0] = (restart[0] == -1 ? 1 : 0); + + NSImage * image = [data->movie currentFrameImage]; + + if(image == nil || [data->movie duration].timeValue == [data->movie currentTime].timeValue) + { + if(loop) + { + [data->movie gotoBeginning]; + image = [data->movie currentFrameImage]; + restart[0] = 1; + } + else + { + Notify(msg_end_of_file, "End of movie"); + return; + } + } + + if(size_x != native_size_x || size_y != native_size_y) + { + NSImage * scaledImage = [[NSImage alloc] initWithSize:NSMakeSize(float(size_x), float(size_y))]; + + [scaledImage lockFocus]; + + [image drawInRect: NSMakeRect(0, 0, float(size_x), float(size_y)) + fromRect: NSZeroRect + operation: NSCompositeSourceOver + fraction: 1.0]; + + [scaledImage unlockFocus]; + image = scaledImage; + } + + NSData * tiffData = [image TIFFRepresentation]; + NSBitmapImageRep * bitmap = [NSBitmapImageRep imageRepWithData:tiffData]; + unsigned char * rawData = [bitmap bitmapData]; +/* + NSLog(@"bytes per row %d", [bitmap bytesPerRow]); + NSLog(@"bytes per plane %d", [bitmap bytesPerPlane]); + NSLog(@"samples per pixel %d", [bitmap samplesPerPixel]); + NSLog(@"number of planes %d", [bitmap numberOfPlanes]); +*/ + // Copy to IKAROS output arrays + + int w = size_x; + int h = size_y; + long rb = [bitmap bytesPerRow]; + long ix = 0; + + for (int y=0; ymovie stepForward]; +} + +#endif \ No newline at end of file diff --git a/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.h b/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.h new file mode 100755 index 000000000..e77fb355c --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.h @@ -0,0 +1,73 @@ +// +// InputQTMovie.h This file is a part of the IKAROS project +// A module for reading images from a QuickTime movie +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// 2009-07-01 Restart trig added (CB) +// 2011-08-18 Finally updated for QTKit (CB) + + +#ifndef INPUTQTMOVIE +#define INPUTQTMOVIE + +#include "IKAROS.h" + +#ifdef USE_QUICKTIME + +class InputQTMovieData; + +class InputQTMovie: public Module { +public: + InputQTMovieData * data; + + const char * filename; + bool loop; + + int size_x; + int size_y; + + int native_size_x; + int native_size_y; + + float * intensity; + float * red; + float * green; + float * blue; + + float * restart; + + static Module * Create(Parameter * p) {return new InputQTMovie(p); } + + InputQTMovie(Parameter * p); + virtual ~InputQTMovie(); + + void Init(); + void Tick(); +}; + +#endif + +#ifndef USE_QUICKTIME +class InputQTMovie { +public: + static Module * Create(Parameter * p) { return NULL; } +}; +#endif + + +#endif diff --git a/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.ikc b/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.ikc new file mode 100755 index 000000000..4902c44a2 --- /dev/null +++ b/Source/Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.ikc @@ -0,0 +1,47 @@ + + + + + + Module that reads a movie using QuickTime. The movie can be optionally scaled by setting the parameters size_x and size_y. + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + 2003 + + + InputQTMovie.h + InputQTMovie.cc + InputQTMovie.ikc + + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputFile/OutputFile.cc b/Source/Modules/IOModules/FileOutput/OutputFile/OutputFile.cc new file mode 100755 index 000000000..99c967d55 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputFile/OutputFile.cc @@ -0,0 +1,171 @@ +// +// OutputFile.cc This file is a part of the IKAROS project +// A module for writing to files in column form +// +// Copyright (C) 2001-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "OutputFile.h" + +#include + +using namespace ikaros; + +OutputFile::OutputFile(Parameter * p): + Module(p) +{ + const char * file_name = GetValue("filename"); + if (file_name == NULL) + { + Notify(msg_fatal_error, "No output file parameter supplied\n"); + return; + } + + file = fopen(file_name, "wb"); + if (file == NULL) + { + Notify(msg_fatal_error, "Could not open output file \"%s\" \n", file_name); + return; + } + + time = 0; + no_of_columns = 0; + + no_of_decimals = GetIntValue("decimals", 4); + + // Count columns *** parnent_group->appended_ekements + + XMLNode * par = xml->parent; + for (XMLElement * c = ((XMLElement *)(par))->GetContentElement("column"); c != NULL; c = c->GetNextElement("column")) + no_of_columns++; + + // Allocate memory + + column_name = new char * [no_of_columns]; + column_size = new int [no_of_columns]; + column_decimals = new int [no_of_columns]; + column_data = new float * [no_of_columns]; + + for (int i=0; iGetContentElement("column"); c != NULL; c = c->GetNextElement("column")) + { +// printf("Column: %s\n", c->GetAttribute("name")); + + const char * col_name = c->GetAttribute("name"); + if (col_name == NULL) + { + Notify(msg_warning, "Column name missing in module \"%s\". Ignored.\n", GetName()); + break; + } + column_name[col] = create_string(col_name); // Allocate memory for the column name + AddInput(col_name); + + column_decimals[col] = string_to_int(c->GetAttribute("decimals"), no_of_decimals); + + col++; + } +} + + + +void +OutputFile::Init() +{ + for (int i=0; i + + + + +

+ Module used for writing numerical data to a text file. The data is represented in the + file as a number of columns given names in a header. The first column is called "T" + and contains the time (in ticks) when the row was written. All other columns in the + output file are defined in the XML file. +

+

+ Example XML definitions +

+
+  <module
+    class = "OutputFile"
+    name = "OUT"
+    filename = "data.txt"
+  >
+    <column name = "X" />  
+    <column name = "Y" />  
+  </module>
+
+

+ The following example shows how the header describes the number of' + columns in each output column and its name. The file could have been + produced by the above module definition if the input vector to "X" had one + value and the input to "Y" had two values. +

+
+  T/1  X/1       Y/2
+  0     2.0000   12.0000     5.0102
+  1    31.0000    5.4000    10.4321
+   :
+   :
+
+

+ As default there are four decimals in each column. This can be changed with the decimals attribute: +

+
+  <module
+    class = "OutputFile"
+    name = "OUT"
+    filename = "data.txt"
+    decimals = "0"
+  >
+    <column name = "X" />  
+    <column name = "Y" decimals = "2" />  
+  </module>
+
+

+ Here, the attribute decimals in the module tag sets the default decimals to none for all columns. This is changed locally for column Y where 2 decimals are used. The example above will now become: +

+
+  T/1  X/1  Y/2
+  0     2   12.00     5.01
+  1    31    5.40    10.43
+   :
+   :
+
+
+ + + + + + + + + + + + + + + + + + + It should be possible to supress the timing column "T". + + + 2002 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + OutputFile.h + OutputFile.cc + OutputFile.ikc + + +
diff --git a/Source/Modules/IOModules/FileOutput/OutputJPEG/Examples/OutputJPEG_RGB_test.ikc b/Source/Modules/IOModules/FileOutput/OutputJPEG/Examples/OutputJPEG_RGB_test.ikc new file mode 100755 index 000000000..7a2517498 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputJPEG/Examples/OutputJPEG_RGB_test.ikc @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputJPEG/Examples/OutputJPEG_test.ikc b/Source/Modules/IOModules/FileOutput/OutputJPEG/Examples/OutputJPEG_test.ikc new file mode 100755 index 000000000..644aa23bb --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputJPEG/Examples/OutputJPEG_test.ikc @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.cc b/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.cc new file mode 100755 index 000000000..7d91bfe1e --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.cc @@ -0,0 +1,296 @@ +// +// OutputJPEG.cc This file is a part of the IKAROS project +// A module for writing JPEG images to files +// +// Copyright (C) 2005 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "OutputJPEG.h" +#include + +//#include +#include + +extern "C" +{ +#include "jpeglib.h" +} + + + +Module * +OutputJPEG::Create(Parameter * p) +{ + return new OutputJPEG(p); +} + + + +OutputJPEG::OutputJPEG(Parameter * p): + Module(p) +{ + scale = GetFloatValue("scale", 1.0); + file_name = GetValue("filename"); + supress = GetIntValue("supress", 1); + offset = GetIntValue("offset", 0); + + quality = GetIntValue("quality", 100); + + if (file_name == NULL) + { + Notify(msg_fatal_error, "No filename(s) supplied.\n"); + return; + } + + cur_image = 0; + + AddInput("WRITE"); + + AddInput("INTENSITY"); + + AddInput("RED"); + AddInput("GREEN"); + AddInput("BLUE"); +} + + + +OutputJPEG::~OutputJPEG() +{} + + + +void +OutputJPEG::Init() +{ + if(InputConnected("INTENSITY")) + writesig = GetInputArray("INTENSITY"); + + if(InputConnected("INTENSITY")) + { + input_intensity = GetInputMatrix("INTENSITY"); + size_x = GetInputSizeX("INTENSITY"); + size_y = GetInputSizeY("INTENSITY"); + } + + else + { + input_red = GetInputMatrix("RED"); + input_green = GetInputMatrix("GREEN"); + input_blue = GetInputMatrix("BLUE"); + size_x = GetInputSizeX("RED"); + size_y = GetInputSizeY("RED"); + + // Check connection consistency + } +} + + + +void +OutputJPEG::WriteGrayJPEG(FILE * fileref, float ** image) +{ + // Calculate max and min of image + + float maximum = image[0][0]; + float minimum = image[0][0]; + + for (int j=0; j maximum) + maximum = image[j][i]; + else if (image[j][i] < minimum) + minimum = image[j][i]; + + if (minimum < 0 || maximum > 1) + { + Notify(msg_warning, "WARNING: OutputJPEG - Gray levels not within range [0..1]. Will be scaled."); + } + else + { + minimum = 0.0; + maximum = 1.0; + } + + JSAMPLE * image_buffer = new JSAMPLE [size_x]; + + struct jpeg_compress_struct cinfo; + struct jpeg_error_mgr jerr; + + JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */ + //int row_stride; /* physical row width in image buffer */ + + cinfo.err = jpeg_std_error(&jerr); + + jpeg_create_compress(&cinfo); // Replace with ikaros error handler later + + jpeg_stdio_dest(&cinfo, fileref); + + // Set compression parameters + + cinfo.image_width = size_x; /* image width and height, in pixels */ + cinfo.image_height = size_y; + cinfo.input_components = 1; /* # of color components per pixel */ + cinfo.in_color_space = JCS_GRAYSCALE; + + jpeg_set_defaults(&cinfo); + jpeg_set_quality(&cinfo, quality, true); + + // Do the compression + + jpeg_start_compress(&cinfo, true); + + //row_stride = size_x * 1; /* JSAMPLEs per row in image_buffer */ + int j=0; + + while (cinfo.next_scanline < cinfo.image_height) + { + // Convert row to image buffer (assume max == 1 for now) + if (maximum-minimum != 0) + for (int i=0; i 1.0 ? 1.0 : r[j][i])); + float gg = (g[j][i] < 0.0 ? 0.0 : (g[j][i] > 1.0 ? 1.0 : g[j][i])); + float bb = (b[j][i] < 0.0 ? 0.0 : (b[j][i] > 1.0 ? 1.0 : b[j][i])); + + clipping |= (rr != r[j][i]) || (gg != g[j][i]) || (bb != b[j][i]); + + image_buffer[x++] = int(255.0*rr); + image_buffer[x++] = int(255.0*gg); + image_buffer[x++] = int(255.0*bb); + } + + // Write to compressor + row_pointer[0] = image_buffer; // & image_buffer[cinfo.next_scanline * row_stride]; + (void) jpeg_write_scanlines(&cinfo, row_pointer, 1); + j++; + } + jpeg_finish_compress(&cinfo); + jpeg_destroy_compress(&cinfo); + + delete [] image_buffer; + + if (clipping) + Notify(msg_warning, "OutputJPEG - some color values were not in the required range 0..1. These values werre clipped."); +} + + + +void +OutputJPEG::Tick() +{ + char fn[256]; + sprintf(fn, file_name, offset + cur_image); + + // If we are using a gating signal from outside, we're looking for it here + + if ((writesig != NULL) && (!(writesig[0] > 0.0))) { + + Notify(msg_verbose, " Write signal suppression: \"%s\" (%dx%d)\n", fn, size_x, size_y); + cur_image++; + return; + } + + + if (supress > cur_image) + { + Notify(msg_verbose, "Supressing write of \"%s\" (%dx%d)\n", fn, size_x, size_y); + cur_image++; + return; + } + + file = fopen(fn, "wb"); + + Notify(msg_verbose, "Writing \"%s\" (%dx%d)\n", fn, size_x, size_y); + + if (file == NULL) + { + Notify(msg_fatal_error, "Could not open image file \"%s\" \n", fn); + return; + } + + if (input_intensity != NULL) + WriteGrayJPEG(file, input_intensity); + else if (input_red != NULL) + WriteRGBJPEG(file, input_red, input_green, input_blue); + + fclose(file); + + cur_image++; +} + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.h b/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.h new file mode 100755 index 000000000..5342ee91c --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.h @@ -0,0 +1,67 @@ +// +// OutputJPEG.h This file is a part of the IKAROS project +// A module for writing JPEG images to files +// +// Copyright (C) 2005 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef OUTPUTJPEG +#define OUTPUTJPEG + +#include "IKAROS.h" + + +class OutputJPEG: public Module +{ +public: + int cur_image; + const char * file_name; + + float scale; + int quality; + + int supress; + int offset; + + int size_x; + int size_y; + + + float * writesig; // If you want to write selectively + float ** input_intensity; // Connect this one + + float ** input_red; // Or all of these + float ** input_green; + float ** input_blue; + + OutputJPEG(Parameter * p); + virtual ~OutputJPEG(); + + static Module * Create(Parameter * p); + + void Init(); + void Tick(); + + void WriteGrayJPEG(FILE * filename, float ** image); + void WriteRGBJPEG(FILE * filename, float ** r, float ** g, float ** b); + +private: + FILE * file; +}; + +#endif + diff --git a/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.ikc b/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.ikc new file mode 100755 index 000000000..26dfb9379 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.ikc @@ -0,0 +1,58 @@ + + + + + + Module used for writing an image (or sequences of images) to file(s). + The files are saved in JPEG format. For a gray scale image, connect only + the INTENSITY input. For a color image, connect all of RED, GREEN and + BLUE input (but not INTENSITY). It is assumed that the values lies in the range 0..1. + This can be adjusted with the scale factor which is multiplied with each intensity value. + + + + + + + + + + + + + + + + + + + + + + If %d is not in the filename each new file will overwrite the + previous. On Unix systems this is actually useful. + + + 2005 + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + OutputJPEG.h + OutputJPEG.cc + OutputJPEG.ikc + + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputPNG/Examples/OutputPNG_gray_test.ikc b/Source/Modules/IOModules/FileOutput/OutputPNG/Examples/OutputPNG_gray_test.ikc new file mode 100755 index 000000000..99140da45 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputPNG/Examples/OutputPNG_gray_test.ikc @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputPNG/Examples/OutputPNG_rgb_test.ikc b/Source/Modules/IOModules/FileOutput/OutputPNG/Examples/OutputPNG_rgb_test.ikc new file mode 100755 index 000000000..48b29192e --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputPNG/Examples/OutputPNG_rgb_test.ikc @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.cc b/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.cc new file mode 100755 index 000000000..33546f668 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.cc @@ -0,0 +1,369 @@ +// +// OutputPNG.cc This file is a part of the IKAROS project +// A module for writing PNG images to files +// +// Copyright (C) 2007 Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "OutputPNG.h" +#include + +#ifdef USE_LIBPNG + + +extern "C" { +#include "png.h" +} + +#include +#include + + + Module * +OutputPNG::Create(Parameter * p) +{ + return new OutputPNG(p); +} + + + +OutputPNG::OutputPNG(Parameter * p): + Module(p) +{ + file_name = GetValue("filename"); + supress = GetIntValue("supress", 1); + offset = GetIntValue("offset", 0); + + + if(file_name == NULL) + { + Notify(msg_fatal_error, "No filename(s) supplied.\n"); + return; + } + + cur_image = 0; + + AddInput("WRITE"); + + AddInput("INTENSITY"); + + AddInput("RED"); + AddInput("GREEN"); + AddInput("BLUE"); +} + + + +OutputPNG::~OutputPNG() +{ +} + + + +void +OutputPNG::Init() +{ + if(InputConnected("WRITE")) + writesig = GetInputArray("WRITE"); + + if(InputConnected("INTENSITY")) + { + input_intensity = GetInputMatrix("INTENSITY"); + size_x = GetInputSizeX("INTENSITY"); + size_y = GetInputSizeY("INTENSITY"); + } + + else + { + input_red = GetInputMatrix("RED"); + input_green = GetInputMatrix("GREEN"); + input_blue = GetInputMatrix("BLUE"); + size_x = GetInputSizeX("RED"); + size_y = GetInputSizeY("RED"); + + // Check connection consistency + } +} + + + +void +OutputPNG::WriteGrayPNG(FILE * fileprt, float ** image) +{ + // Calculate max and min of image + + float maximum = image[0][0]; + float minimum = image[0][0]; + + for(int j=0; j maximum) + maximum = image[j][i]; + else if(image[j][i] < minimum) + minimum = image[j][i]; + + if(minimum < 0 || maximum > 1) + { + Notify(msg_warning, "WARNING: OutputPNG - Gray levels not within range [0..1]. Will be scaled."); + } + else + { + minimum = 0.0; + maximum = 1.0; + } + + // Beginning of the PNG-specific parts. Note how all other parts of this + // module are almost identical to the corresponding JPEG writer. This is by + // design. + + png_structp png_ptr = png_create_write_struct + (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (!png_ptr){ + Notify (msg_fatal_error, "Could not allocate PNG write struct\n"); + return; + } + + png_infop info_ptr = png_create_info_struct(png_ptr); + if (!info_ptr) + { + png_destroy_write_struct(&png_ptr, + (png_infopp)NULL); + Notify (msg_fatal_error, "Could not allocate PNG info struct\n"); + return; + } + + // Default error handling + + if (setjmp(png_jmpbuf(png_ptr))) + { + png_destroy_write_struct(&png_ptr, &info_ptr); + fclose(fileprt); + Notify (msg_fatal_error, "Abnormal abort on PNG write\n"); + return; + } + + + png_init_io(png_ptr, fileprt); + + // Here we wstart setting the actual image parameters. Up until now + // it's been identical code for all PNG writing variations. + + png_set_IHDR(png_ptr, info_ptr, + size_x, size_y, // Size of image, in pixels + 8, // Bit depth of one channel + PNG_COLOR_TYPE_GRAY, // color type + PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_DEFAULT, + PNG_FILTER_TYPE_DEFAULT); + + // There's _lots_ of additional info and parameters that could be set, + // like gamma, colorspace and rendering intent, ICC device profile, + // comments and so on. We don't need any of it, but be aware that such + // things are possible if needed. + + + // As an example, write a default gamma value + // png_set_gAMA(png_ptr, info_ptr, 1.8); // Wild guess + + + // This writes all data coming before the image itself. It is possible + // to add more data after the image if needed. + + png_write_info(png_ptr, info_ptr); + + png_byte *image_buffer = new png_byte [size_x*size_y]; + png_byte **row_pointer = new png_byte * [size_y]; // pointer to rows + + int row_stride = size_x * 1; // Make it easier to cut and paste + + int rpos = 0; + for (int j=0; j 1.0 ? 1.0 : r[j][i])); + float gg = (g[j][i] < 0.0 ? 0.0 : (g[j][i] > 1.0 ? 1.0 : g[j][i])); + float bb = (b[j][i] < 0.0 ? 0.0 : (b[j][i] > 1.0 ? 1.0 : b[j][i])); + + clipping |= (rr != r[j][i]) || (gg != g[j][i]) || (bb != b[j][i]); + + image_buffer[ppos++] = int(255.0*rr); + image_buffer[ppos++] = int(255.0*gg); + image_buffer[ppos] = int(255.0*bb); + } + } + + png_write_image(png_ptr, row_pointer); + png_write_end(png_ptr, info_ptr); + png_destroy_write_struct(&png_ptr, &info_ptr); + + delete image_buffer; + delete row_pointer; + + if(clipping) + Notify(msg_warning, "OutputPNG - some color values were not in the required range 0..1. These values werre clipped."); +} + + + +void +OutputPNG::Tick() +{ + char fn[256]; + sprintf(fn, file_name, offset + cur_image); + + // If we are using a gating signal from outside, we're looking for it here + if ((writesig != NULL) && (!writesig[0] > 0.0)) { + + Notify(msg_verbose, " Write signal suppression: \"%s\" (%dx%d)\n", fn, size_x, size_y); + cur_image++; + return; + } + + + if(supress > cur_image) + { + Notify(msg_verbose, "Supressing write of \"%s\" (%dx%d)\n", fn, size_x, size_y); + cur_image++; + return; + } + + file = fopen(fn, "wb"); + + Notify(msg_verbose, "Writing \"%s\" (%dx%d)\n", fn, size_x, size_y); + + if(file == NULL) + { + Notify(msg_fatal_error, "Could not open image file \"%s\" \n", fn); + return; + } + + if(input_intensity != NULL) + WriteGrayPNG(file, input_intensity); + else if(input_red != NULL) + WriteRGBPNG(file, input_red, input_green, input_blue); + + fclose(file); + + cur_image++; +} + +#endif + diff --git a/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.h b/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.h new file mode 100755 index 000000000..1ebbe9b18 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.h @@ -0,0 +1,81 @@ +// +// OutputPNG.h This file is a part of the IKAROS project +// A module for writing PNG images to files +// +// Copyright (C) 2007 Jan Moren +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef OUTPUTPNG +#define OUTPUTPNG + +#include "IKAROS.h" + +#ifdef USE_LIBPNG + +class OutputPNG: public Module { + public: + int cur_image; + const char * file_name; + +// float scale; +// int quality; + + int supress; + int offset; + + int size_x; + int size_y; + + + float * writesig; // Writing or not + float ** input_intensity; // Connect this one + + float ** input_red; // Or all of these + float ** input_green; + float ** input_blue; + + OutputPNG(Parameter * p); + virtual ~OutputPNG(); + + static Module * Create(Parameter * p); + + void Init(); + void Tick(); + + void WriteGrayPNG(FILE * file, float ** image); + void WriteRGBPNG(FILE * file, float ** r, float ** g, float ** b); + + private: + FILE* file; +}; +#endif + +#ifndef USE_LIBPNG + +class OutputPNG { + public: + static Module * Create(Parameter * p) + { + printf("This version of IKAROS does not support PNG files.\n"); + return NULL; + } +}; + +#endif + +#endif + diff --git a/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.ikc b/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.ikc new file mode 100755 index 000000000..6ec342ffc --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputPNG/OutputPNG.ikc @@ -0,0 +1,68 @@ + + + + + + Module used for writing an image (or sequences of images) to file(s). + The files are saved in PNG format. For a gray scale image, connect + only the INTENSITY input. For a color image, connect all of RED, + GREEN and BLUE input (but not INTENSITY). To selectively output only + certain images, connect the WRITE input. + + The PNG format is, unlike JPEG, lossless but takes up + more space. If writing speed and small size is + important, please use Jpeg. If precise fidelity is + important, PNG is a good choice. + + + + + + + + + + + + + + + + + + + + + We aren't using all of PNG:s strenghts - no 16 bit output, no + indexed color for smaller files and no way to create an alpha + channel. + + + + If %d is not in the filename each new file will overwrite the + previous. This is a feature, since you can create + a named pipe and in that way stream images to another application. + + + 2007 + + Jan Moren + jan.moren@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/People/Jan.Moren + + + + OutputPNG.h + OutputPNG.cc + OutputPNG.ikc + + + diff --git a/Source/Modules/IOModules/FileOutput/OutputRawImage/OutputRawImage.cc b/Source/Modules/IOModules/FileOutput/OutputRawImage/OutputRawImage.cc new file mode 100755 index 000000000..eb1b8b5d7 --- /dev/null +++ b/Source/Modules/IOModules/FileOutput/OutputRawImage/OutputRawImage.cc @@ -0,0 +1,105 @@ +// +// OutputRawImage.cc This file is a part of the IKAROS project +// A module for writing raw image data to files +// +// Copyright (C) 2001-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "OutputRawImage.h" + + +using namespace ikaros; + + +Module * +OutputRawImage::Create(Parameter * p) +{ + return new OutputRawImage(p); +} + + + +OutputRawImage::OutputRawImage(Parameter * p): + Module(p) +{ + scale = GetFloatValue("scale"); + file_name = GetValue("filename"); + supress = GetIntValue("supress"); + offset = GetIntValue("offset"); + + if (file_name == NULL) + { + Notify(msg_fatal_error, "No filename(s) supplied.\n"); + return; + } + + cur_image = 0; + + AddInput("INPUT"); +} + + + +OutputRawImage::~OutputRawImage() +{ +} + + + +void +OutputRawImage::Init() +{ + image = GetInputArray("INPUT"); + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); +} + + + +void +OutputRawImage::Tick() +{ + char fn[256]; + sprintf(fn, file_name, offset + cur_image); + + if (supress > cur_image) + { + Notify(msg_verbose, "Supressing write of \"%s\" (%dx%d)\n", fn, size_x, size_y); + cur_image++; + return; + } + + file = fopen(fn, "wb"); + + Notify(msg_verbose, "Writing \"%s\" (%dx%d)\n", fn, size_x, size_y); + + if (file == NULL) + { + Notify(msg_fatal_error, "Could not open image file \"%s\" \n", fn); + return; + } + + for (int i=0; i + + + + + Module used for writing an image (or sequences of images) to file(s). + The files are saved in RAW format with one byte per pixel. Since Ikaros uses floats between 0 and 1 to represent images the input is first multiplied with 255. This can be changed using the scale parameter. + The size of the file is not saved in the file. + + + + + + + + + + + + + + + + + If %d is not in the filename each new file will overwrite the previous. + Maybe this is a feature. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + OutputRawImage.h + OutputRawImage.cc + OutputRawImage.ikc + + + diff --git a/Source/Modules/IOModules/Video/InputVideoQT/Examples/InputVideoQT_test.ikc b/Source/Modules/IOModules/Video/InputVideoQT/Examples/InputVideoQT_test.ikc new file mode 100755 index 000000000..629bcde6c --- /dev/null +++ b/Source/Modules/IOModules/Video/InputVideoQT/Examples/InputVideoQT_test.ikc @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/Video/InputVideoQT/Examples/InputVideoQT_two_camera_test.ikc b/Source/Modules/IOModules/Video/InputVideoQT/Examples/InputVideoQT_two_camera_test.ikc new file mode 100755 index 000000000..0131adf0a --- /dev/null +++ b/Source/Modules/IOModules/Video/InputVideoQT/Examples/InputVideoQT_two_camera_test.ikc @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/Video/InputVideoQT/InputVideoQT.M b/Source/Modules/IOModules/Video/InputVideoQT/InputVideoQT.M new file mode 100755 index 000000000..0930a89f9 --- /dev/null +++ b/Source/Modules/IOModules/Video/InputVideoQT/InputVideoQT.M @@ -0,0 +1,224 @@ +// +// InputVideoQT.cc This file is a part of the IKAROS project +// A module to grab image data from a QuickTime compatible camera +// +// Copyright (C) 2002-2012 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// TODO: +// +// scale image from camera +// remove dependence on TIFF represenattion to get rid of the stupid mutex-solution +// allow camera to be unconnected and reconnected during operation +// + + +#include "InputVideoQT.h" + +#ifdef USE_QUICKTIME + + +#import +#import +#import + +#import "QTGrab.h" + +// Since TIFFRepresentation is not thread-safe +// we use the following object as a lock +// This work as long as no other modules use the +// same strategy. + +static NSObject * lock = [NSObject new]; + + + +InputVideoQT::InputVideoQT(Parameter * p): + Module(p) +{ + size_x = GetIntValue("size_x"); + size_y = GetIntValue("size_y"); + flip = GetBoolValue("flip"); + mode = GetIntValueFromList("mode"); + device_id = create_string(GetValue("device_id")); + list_devices = GetBoolValue("list_devices"); + + if(list_devices) + { + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + NSArray * devices = [QTGrab videoDevices]; + Notify(msg_print, "\n"); + Notify(msg_print, "Video devices (name, model, device_id):\n"); + Notify(msg_print, "\n"); + for(QTCaptureDevice * d in devices) + { + Notify(msg_print, "\"%s\", \"%s\", \"%s\"\n", [[d localizedDisplayName] UTF8String], [[d modelUniqueID] UTF8String], [[d uniqueID] UTF8String]); + } + Notify(msg_print, "\n"); + [pool release]; + } + + grabber = [[QTGrab alloc] init]; // Instance of this QTGrab class + + + QTCaptureDevice * device = nil; + if(!equal_strings(device_id, "")) + { + device = [QTCaptureDevice deviceWithUniqueID: [NSString stringWithFormat:@"%s", device_id]]; + if(!device) + device = [QTCaptureDevice deviceWithUniqueID: [NSString stringWithFormat:@" %s", device_id]]; // Work around possible bug where device names starts with a space + } + else + { + device = [QTGrab defaultVideoDevice]; + device_id = create_string([[device uniqueID] cStringUsingEncoding: NSUTF8StringEncoding]); + Notify(msg_print, "InputVideoQT.device_id = \"%s\"\n", device_id); + } + + if(!device) + { + Notify(msg_warning, "InputVideoQT: video device not found\n"); + grabber = nil; + } + + else if(device && ![(QTGrab *)grabber startSession: device withMode: mode andRequestedWidth:size_x andHeight:size_y]) + { + [(QTGrab *)grabber release]; + grabber = nil; + Notify(msg_warning, "InputVideoQT: video grabber could not be created\n"); + } + + if(grabber) + { + size_x = [(QTGrab *)grabber width]; + size_y = [(QTGrab *)grabber height]; + } + + AddOutput("INTENSITY", size_x, size_y); + AddOutput("RED", size_x, size_y); + AddOutput("GREEN", size_x, size_y); + AddOutput("BLUE", size_x, size_y); +} + + + +InputVideoQT::~InputVideoQT() +{ + Notify(msg_verbose, "Closing Grabber\n"); + + [(QTGrab *)grabber stopSession]; + [(QTGrab *)grabber release]; +} + + + +void +InputVideoQT::Init() +{ + intensity = GetOutputArray("INTENSITY"); + red = GetOutputArray("RED"); + green = GetOutputArray("GREEN"); + blue = GetOutputArray("BLUE"); + +} + + + +void +InputVideoQT::Tick() +{ + // We need to create an autorelease pool every tick since each may be run in a new thread every time + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + const float c13 = 1.0/3.0; + const float c1255 = 1.0/255.0; + + if(!grabber) + { + [pool release]; + return; + } + + CVImageBufferRef buffer = [(QTGrab *)grabber grabCVBuffer]; + if(!buffer) + { + [pool release]; + return; + } + + CFTypeID bufferType = CFGetTypeID(buffer); + if (bufferType != CVPixelBufferGetTypeID()) + { + [pool release]; + printf("ERROR WRONG VIDEO FORMAT\n"); + return; + } + +// TODO: Should check color space here +// CGColorSpaceRef colorSpace = CVImageBufferGetColorSpace(buffer); +// NSLog(@"%@", colorSpace); + + size_t w = CVPixelBufferGetWidth(buffer); + size_t h = CVPixelBufferGetHeight(buffer); + size_t rb = CVPixelBufferGetBytesPerRow(buffer); + size_t ix = 0; + + CVPixelBufferLockBaseAddress(buffer, 0); + unsigned char * rawData = (unsigned char *)CVPixelBufferGetBaseAddress(buffer); + + // Correct conversion to grayscale + // 0.2126 R + 0.7152 G + 0.0722 B + // y = (r*77)+(g*151)+(b*28); + + if(!flip) + { + for (long y=0; y + + + + + Module used for grabbing images from a video source using QuickTime such + as iSight or a DV camera with FireWire. The module only works with OS X. + + If sizes are are set the module requests that the image be scaled to that size. + + The module operates in asynchronous mode, which means that the image + retreived is the previous one. Ikaros continues to run while the next image is + transferred from the camera and the module gets it at the next tick. This can + appear confusing when Ikaros is single steped from the viewer. + + The mode parameter is used to determine whether to use preview mode or not. + The lag may be lower in preview but the image quiality can become lower. + See the QTKit documentation for details. + + By setting the device_id parameter. The module will receive input from that particular + device. If the device_id is not set, the module will connect to the default device. The device id + has the form " 0xa27000413a443-video" (note that it starts with a space). + The space may be a bug in OX X and it is recommended that the space is not included in the string + since Ikaros will add it if it cannot open the device with the supplied name. + + The device_id for the found default device is printed when Ikaros is starting up. It can also + be found in the System Information application by looking up the GUID for the device and adding "-video" + to it. + + + + + + + + + + + + + + + + + + + + + + + + + + It should be possible to run the module also in synchronous mode, where the + module would wait for each new frame before continuing. + + + + The code uses a temporary solution to work around that TIFFRepresentation is not thread safe. + This is actually a bug in Cocoa. + + + 2004 + 2011 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + InputVideoQT.h + InputVideoQT.cc + InputVideoQT.ikc + + + + diff --git a/Source/Modules/IOModules/Video/InputVideoQT/QTGrab.h b/Source/Modules/IOModules/Video/InputVideoQT/QTGrab.h new file mode 100755 index 000000000..6e38322a3 --- /dev/null +++ b/Source/Modules/IOModules/Video/InputVideoQT/QTGrab.h @@ -0,0 +1,70 @@ +// +// QTGrab.h This file is a part of the IKAROS project +// Frame grabber using QTKit +// +// Copyright (C) 2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// Based on code by Robert Harder on 9/10/09. +// http://iharder.sourceforge.net/current/macosx/imagesnap/ + + +#import +#import + +#include "QTGrab.h" + + +@interface QTGrab : NSThread +{ +@public + NSAutoreleasePool* pool; + + QTCaptureSession *session; + QTCaptureDeviceInput *deviceInput; + QTCaptureDecompressedVideoOutput *decompressedVideoOutput; + CVImageBufferRef imageBuffer; + + int requestedMode; + NSSize requestedSize; + QTCaptureDevice * requestedDevice; + + int status; // 0 = error, 1 = ok +} + + ++(NSArray *)videoDevices; ++(QTCaptureDevice *)defaultVideoDevice; ++(QTCaptureDevice *)deviceNamed:(NSString *)name; + ++(NSImage *)singleSnapshotFrom:(QTCaptureDevice *)device; + +-(id)init; +-(void)dealloc; + +-(BOOL)startSession:(QTCaptureDevice *)device withMode:(int)mode andRequestedWidth:(int)w andHeight:(int)h; +-(void)stopSession; + +-(int)width; +-(int)height; + +-(NSImage *)grab; +-(CVImageBufferRef)grabCVBuffer; + +-(void)main; + +@end diff --git a/Source/Modules/IOModules/Video/InputVideoQT/QTGrab.m b/Source/Modules/IOModules/Video/InputVideoQT/QTGrab.m new file mode 100755 index 000000000..12d7e8748 --- /dev/null +++ b/Source/Modules/IOModules/Video/InputVideoQT/QTGrab.m @@ -0,0 +1,331 @@ +// +// QTGrab.m This file is a part of the IKAROS project +// Frame grabber using QTKit +// +// Copyright (C) 2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// +// Based on code by Robert Harder on 9/10/09. +// http://iharder.sourceforge.net/current/macosx/imagesnap/ + + +#import "QTGrab.h" +#include + +@interface QTGrab() + + +- (void)captureOutput:(QTCaptureOutput *)captureOutput + didOutputVideoFrame:(CVImageBufferRef)videoFrame + withSampleBuffer:(QTSampleBuffer *)sampleBuffer + fromConnection:(QTCaptureConnection *)connection; + +@end + + +@implementation QTGrab + +- (id)init +{ + self = [super init]; + session = nil; + deviceInput = nil; + decompressedVideoOutput = nil; + imageBuffer = nil; + requestedMode = 0; + requestedDevice = nil; + requestedSize = NSMakeSize(0,0); + status = 0; + return self; +} + + + +- (void)dealloc +{ + [session release]; + [deviceInput release]; + [decompressedVideoOutput release]; + CVBufferRelease(imageBuffer); + [super dealloc]; +} + + + +// Returns an array of video devices attached to this computer. ++ (NSArray *)videoDevices +{ + NSMutableArray *results = [NSMutableArray arrayWithCapacity:3]; + [results addObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeVideo]]; + [results addObjectsFromArray:[QTCaptureDevice inputDevicesWithMediaType:QTMediaTypeMuxed]]; + return results; +} + + + +// Returns the default video device or nil if none found. ++ (QTCaptureDevice *)defaultVideoDevice +{ + QTCaptureDevice *device = nil; + + device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeVideo]; + if( device == nil ){ + device = [QTCaptureDevice defaultInputDeviceWithMediaType:QTMediaTypeMuxed]; + } + return device; +} + + + +// Returns the named capture device or nil if not found. ++(QTCaptureDevice *)deviceNamed:(NSString *)name +{ + QTCaptureDevice *result = nil; + + NSArray *devices = [QTGrab videoDevices]; + for(QTCaptureDevice *device in devices) + { + if ([name isEqualToString:[device description]]) + { + result = device; + } + } + + return result; +} + + + ++(NSImage *)singleSnapshotFrom:(QTCaptureDevice *)device +{ + NSImage *image = nil; + QTGrab *snap = [[QTGrab alloc] init]; + if([snap startSession:device withMode:0 andRequestedWidth:0 andHeight:0]) + { + image = [snap grab]; + [snap stopSession]; + } + [snap release]; + + return image; +} + + + +-(NSImage *)grab +{ + NSDate * startGrabTime = [NSDate date]; + CVImageBufferRef frame = nil; + while(frame == nil && [startGrabTime timeIntervalSinceNow] > -1.0) // Time out after 1 second + { + @synchronized(self) + { + frame = imageBuffer; + CVBufferRetain(frame); + } + + if(frame == nil) + { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; + } + } + + NSCIImageRep *imageRep = [NSCIImageRep imageRepWithCIImage:[CIImage imageWithCVImageBuffer:frame]]; + NSImage *image = [[[NSImage alloc] initWithSize:[imageRep size]] autorelease]; + [image addRepresentation:imageRep]; + CVBufferRelease(frame); + + return image; +} + + + +-(CVImageBufferRef)grabCVBuffer +{ + NSDate * startGrabTime = [NSDate date]; + CVImageBufferRef frame = nil; + while(frame == nil && [startGrabTime timeIntervalSinceNow] > -1.0) // Time out after 1 second + { + @synchronized(self) + { + frame = imageBuffer; + CVBufferRetain(frame); + } + + if(frame == nil) + { + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; + } + } + + return frame; +} + + + + +-(void)stopSession +{ + while(session != nil) + { + [session stopRunning]; + if( [session isRunning] ){ + [[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow: 0.1]]; + } + else + { + [session release]; + [deviceInput release]; + [decompressedVideoOutput release]; + + session = nil; + deviceInput = nil; + decompressedVideoOutput = nil; + } + } +} + + + +-(BOOL)startSession:(QTCaptureDevice *)device withMode:(int)mode andRequestedWidth:(int)w andHeight:(int)h +{ + if(device == nil) + return NO; + + requestedMode = mode; + requestedDevice = device; + requestedSize = NSMakeSize((float)(w), (float)(h)); + + [self start]; // Start independent capture thread + + for(int i=0; i<500; i++) // Give the start up max 5 second + { + CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, YES); + if(status == 1) + break; + usleep((useconds_t)(1000*10)); + } + + return (status == 1 ? YES : NO); +} + + + +-(int)width +{ + return [[[decompressedVideoOutput pixelBufferAttributes] objectForKey:(id)kCVPixelBufferWidthKey] intValue]; +} + + + +-(int)height +{ + return [[[decompressedVideoOutput pixelBufferAttributes] objectForKey:(id)kCVPixelBufferHeightKey] intValue]; +} + + + +- (void)captureOutput:(QTCaptureOutput *)captureOutput + didOutputVideoFrame:(CVImageBufferRef)videoFrame + withSampleBuffer:(QTSampleBuffer *)sampleBuffer + fromConnection:(QTCaptureConnection *)connection +{ + if (videoFrame == nil) + return; + + CVImageBufferRef imageBufferToRelease; + CVBufferRetain(videoFrame); + + @synchronized(self) + { + imageBufferToRelease = imageBuffer; + imageBuffer = videoFrame; + } + + CVBufferRelease(imageBufferToRelease); +} + + + +-(void)main +{ + pool = [[NSAutoreleasePool alloc] init]; + + NSError *error = nil; + + session = [[QTCaptureSession alloc] init]; + if( ![requestedDevice open:&error] ) + { + [session release]; + session = nil; + return; //fail + } + + deviceInput = [[QTCaptureDeviceInput alloc] initWithDevice:requestedDevice]; + if (![session addInput:deviceInput error:&error]) + { + [session release]; + [deviceInput release]; + session = nil; + deviceInput = nil; + return; //fail + } + + if(requestedMode == 0) + decompressedVideoOutput = [[QTCaptureDecompressedVideoOutput alloc] init]; + else + decompressedVideoOutput = (QTCaptureDecompressedVideoOutput *)[[QTCaptureVideoPreviewOutput alloc] init]; + [decompressedVideoOutput setDelegate:self]; + + // Request image parameters + [decompressedVideoOutput setPixelBufferAttributes: + [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithDouble: requestedSize.width], (id)kCVPixelBufferWidthKey, + [NSNumber numberWithDouble: requestedSize.height], (id)kCVPixelBufferHeightKey, + [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32ARGB], (id)kCVPixelBufferPixelFormatTypeKey, + nil]]; + + if(![session addOutput:decompressedVideoOutput error:&error]) + { + [session release]; + [deviceInput release]; + [decompressedVideoOutput release]; + session = nil; + deviceInput = nil; + decompressedVideoOutput = nil; + return; // fail + } + + @synchronized(self) + { + if(imageBuffer != nil) + { + CVBufferRelease(imageBuffer); + imageBuffer = nil; + } + } + + [session startRunning]; + + status = 1; +} + + + +@end + + diff --git a/Source/Modules/IOModules/Video/NetworkCamera/Examples/NetworkCamera_test.ikc b/Source/Modules/IOModules/Video/NetworkCamera/Examples/NetworkCamera_test.ikc new file mode 100755 index 000000000..2c52017ec --- /dev/null +++ b/Source/Modules/IOModules/Video/NetworkCamera/Examples/NetworkCamera_test.ikc @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.cc b/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.cc new file mode 100755 index 000000000..6b7d37881 --- /dev/null +++ b/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.cc @@ -0,0 +1,236 @@ +// +// NetworkCamera.cc This file is a part of the IKAROS project +// A module to grab images from a network camera +// +// Copyright (C) 2002-2010 Christian Balkenius, Birger Johansson +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +#include "NetworkCamera.h" + +#ifdef USE_LIBJPEG +#ifdef USE_SOCKET + +#define MAX_STR_LEN 512 + + + +extern "C" { +#include "jpeglib.h" +} + +#include + +using namespace ikaros; + +void +NetworkCamera::SkipBoundary(char * bound) +{ + int p = 0; + //int rc; + char c; + + while (bound[p] != 0) + { + //rc = + socket->ReadData(&c, 1); + if (boundary[p] == c) + p++; + } + + socket->ReadData(&c, 1); // Skip line break + socket->ReadData(&c, 1); // Skip line break +} + + + +void +NetworkCamera::ReadLine(char * line) +{ + int p = 0; + int rc; + char c; + do + { + rc = socket->ReadData(&c, 1); + if (rc == 1 && c != '\n' && c!= '\r') + line[p++] = c; + else + line[p] = 0; + } + while (c != 13); + socket->ReadData(&c, 1); // Skip line break +} + + + +bool +NetworkCamera::ReadBlock() +{ + // Check for new image data on the socket + + if (!socket->Poll()) + return false; + + // Read Header + + char line[256]; + char attribute[256]; + int length = 0; + do + { + ReadLine(line); + int cnt = sscanf(line, "%[^:]", attribute); + + if (cnt == 1 && !strcmp(attribute, "Content-Length")) + { + sscanf(line, "%[^:]:%d", attribute, &length); + } + + else if (cnt == 1 && !strcmp(attribute, "Delta-time")) + { + int delta_time; + cnt = sscanf(line, "%[^:]:%d", attribute, &delta_time); + if (cnt > 0) + timestamp += delta_time; + } + } + while (strlen(line) > 0); + + // Read Image Data (fill buffer) + + if(length > buffer_size) + { + buffer_size = length; + buffer = (char *)realloc(buffer, buffer_size*sizeof(char)); + if(!buffer) + Notify(msg_fatal_error, "NetworkCamera: memory allocation failed\n"); + } + + socket->ReadData(buffer, length, true); + SkipBoundary(boundary); + + return true; +} + + + +void +NetworkCamera::ReadHeader() // This part is specific for the AXIS camera and should be more general +{ + char header[1024]; + + int rc = socket->ReadData(header, 100); // we just happen to know that the header size == 100 + header[100] = 0; + + // Read boundary marker + + int b = 0; + char c; + do + { + rc = socket->ReadData(&c, 1); + if (rc == 0) + { + Notify(msg_warning, "NetworkCamera::ReadHeader: Error reading boundary marker\n"); + return; + } + if (c != '\r' && c != '\n') + boundary[b++] = c; + } while (c != '\n'); + boundary[b] = 0; + + // The boundary marker in the package from the camera should probably not contain + // the leading "--" but since it does we just keep them in the string + // This may have to be changed for other cameras + + SkipBoundary(boundary); +} + + + +NetworkCamera::NetworkCamera(Parameter * p): + Module(p) +{ + timestamp = 0; + + buffer_size = INITIAL_BUFFER_SIZE; + buffer = (char *)malloc(INITIAL_BUFFER_SIZE*sizeof(char)); + + size_x = GetIntValue("size_x", 352); // 704x480, 176x144, 352x240 + size_y = GetIntValue("size_y", 240); + + if (size_x*size_y < 1) + { + Notify(msg_fatal_error, "Image size not supplied.\n"); + return; + } + + host_ip = GetValue("host_ip"); + host_port = GetIntValue("host_port", 80); + image_request = GetValue("image_request"); // Not used + fps = GetIntValue("fps", 10); + compression = GetIntValue("compression", 50); + + AddOutput("INTENSITY", size_x, size_y); + AddOutput("RED", size_x, size_y); + AddOutput("GREEN", size_x, size_y); + AddOutput("BLUE", size_x, size_y); + + // Create socket + + socket = new Socket(); + + // Set up connection and tell camera to stream data + + char msg[1024]; + + sprintf(msg, "GET /axis-cgi/mjpg/video.cgi?deltatime=1&showlength=1&resolution=%dx%d&req_fps=%d&compression=%d HTTP/1.1\r\n\r\n", size_x, size_y, fps, compression); + + if (!socket->SendRequest(host_ip, host_port, msg)) + { + Notify(msg_fatal_error, "Could not connect to network camera at %s:%d.\n", host_ip, host_port); + return; + } + + ReadHeader(); +} + + + +void +NetworkCamera::Init() +{ + intensity = GetOutputMatrix("INTENSITY"); + red = GetOutputMatrix("RED"); + green = GetOutputMatrix("GREEN"); + blue = GetOutputMatrix("BLUE"); +} + + + +void +NetworkCamera::Tick() +{ + while (ReadBlock()) ; // Read all available blocks + jpeg_decode(red, green, blue, intensity, size_x, size_y, buffer, buffer_size); +} + +#endif +#endif + diff --git a/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.h b/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.h new file mode 100755 index 000000000..a20ef0e2c --- /dev/null +++ b/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.h @@ -0,0 +1,80 @@ +// +// NetworkCamera.h This file is a part of the IKAROS project +// A module to grab images from a network camera +// +// Copyright (C) 2002-2008 Christian Balkenius, Birger Johansson +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef NETWORKCAMERA +#define NETWORKCAMERA + +#include "IKAROS.h" + +#if defined USE_SOCKET && defined USE_LIBJPEG + +#define INITIAL_BUFFER_SIZE 65536 + +class NetworkCamera: public Module { +public: + int size_x; // Size of the image to grab + int size_y; + + float ** intensity; + float ** red; + float ** green; + float ** blue; + + const char * host_ip; + int host_port; + Socket * socket; + const char * image_request; + + int fps; + int compression; + + long timestamp; + + char boundary[128]; + + long int buffer_size; + char * buffer; + + static Module * Create(Parameter * p) {return new NetworkCamera(p);}; + + NetworkCamera(Parameter * p); + virtual ~NetworkCamera() {}; + + void ReadLine(char * line); + void SkipBoundary(char * bound); + void ReadHeader(); + bool ReadBlock(); + + void Init(); + void Tick(); +}; + +#else + +class NetworkCamera { +public: + static Module * Create(char * name, Parameter * p) { return NULL; } +}; + + +#endif +#endif + diff --git a/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.ikc b/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.ikc new file mode 100755 index 000000000..4e6a2ceac --- /dev/null +++ b/Source/Modules/IOModules/Video/NetworkCamera/NetworkCamera.ikc @@ -0,0 +1,58 @@ + + + + + + Module used for grabbing images from a network camera. The module has + been tested with the the Axis 2130 pan-til-zoom camera and probably works + also with other Axis cameras. It requests a MJPEG stream. + + + + + + + + + + + + + + + + + + + + + + + + + The image sizes should be calculated automatically from the first image. + + + + The module currently ignores the image_request parameter and works only with AXIS cameras. + + + 2003 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + NetworkCamera.h + NetworkCamera.cc + NetworkCamera.ikc + + + diff --git a/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.data b/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.data new file mode 100755 index 000000000..0da05a392 --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.data @@ -0,0 +1,13 @@ +DT/7 OT/7 + +# when weighed, class is (close to) 1, else around 0 +0.1 0.1 0.1 0.2 0.2 0.5 0.5 1 1 1 0 0 0 0 + +# class is between 1.0 and 2.0 +0.5 0.5 0.2 0.2 0.2 0.5 0.5 1 1 2 2 2 0 0 + +# always becomes class 0 since there is such an instance with distance=0.0 +0.5 0.2 0.2 0.1 0.2 0.5 0.0 5 1 1 2 2 0 0 + +# when weighed, class is (close to) 6 +0.5 0.5 0.5 0.5 0.5 0.05 0.0001 5 1 1 1 1 0 6 diff --git a/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.ikc b/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.ikc new file mode 100755 index 000000000..2b67ebb53 --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.ikc @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.output b/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.output new file mode 100755 index 000000000..ac67df8f9 --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/Examples/5neighbors_categorical.output @@ -0,0 +1,5 @@ +T/1 OUTCLASS/1 +0 0 +1 1 +2 0 +3 2 diff --git a/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.cc b/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.cc new file mode 100755 index 000000000..04bc0664d --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.cc @@ -0,0 +1,287 @@ +// +// KNN_Pick.cc This file is a part of the IKAROS project +// This module provides a few simple ways to pick a class based on K neighbors. +// +// Copyright (C) 2007 Alexander Kolodziej +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: July 2007 +// +// + +#include "KNN_Pick.h" +//#include + +#define EMPTY -1 + + +Module * +KNN_Pick::Create(Parameter * p) +{ + return new KNN_Pick(p); +} + + +KNN_Pick::KNN_Pick(Parameter * p): Module(p) +{ + AddInput("OUTPUT_TABLE"); + AddInput("DISTANCE_TABLE"); + + AddOutput("CLASS_OUTPUT", 1); + + CheckParameters(); +} + + +void +KNN_Pick::SetSizes() +{ + int tmp; + + k = GetInputSize("OUTPUT_TABLE"); + if (k == unknown_size) + return; + + tmp = GetInputSize("DISTANCE_TABLE"); + + if (tmp != k) + Notify(msg_fatal_error, "KNN_Pick - Sizes for DISTANCE_TABLE (size=%i) and OUTPUT_TABLE (size=%i) do not match!\n", tmp, k); +} + + +void +KNN_Pick::Init() +{ + output_table = GetInputArray("OUTPUT_TABLE"); + distance_table = GetInputArray("DISTANCE_TABLE"); + + class_output = GetOutputArray("CLASS_OUTPUT"); + + categories = create_array(k); +} + + +KNN_Pick::~KNN_Pick() +{ + destroy_array(categories); +} + + +/** calculate the class_output depending on what is chosen in the IKC file. + if an element with zero distance is found, the class of that element + is chosen (the first zero distance element is chosen if there would be + more than one). **/ +void +KNN_Pick::Tick() +{ + //printf("\n NEW TICK \n"); + //PrintTable("input table", input_table, 1, k); + //PrintTable("output_table", &output_table, 1, k); + //PrintTable("distance_table", &distance_table, 1, k); + + #ifdef CHECK_FOR_NEGATIVE_DISTANCE + CheckForNegativeDistance(); + #endif + + if (distance_table[GetClosestIndex()] == 0) + class_output[0] = output_table[GetClosestIndex()]; + else{ + if (categorical) + class_output[0] = CountAmount(); + else + class_output[0] = CalculateMean(); + } + + //printf("\nchose class: %.1f\n\n", class_output[0]); +} + + +/** distances shouldnt be allowed to be negative, so it might be a good + idea to check for that. this function CAN be skipped by not having + CHECK_FOR_NEGATIVE_DISTANCES defined in the header file. **/ +void +KNN_Pick::CheckForNegativeDistance() +{ + int i; + + for (i = 0; i < k; i++) + if (distance_table[i] < 0) + Notify(msg_fatal_error, "KNN_Pick - ERROR: No negative distances allowed!\n"); +} + + +/** this function returns a factor with which we can weigh our elements + depending on their distance. returns 1 if elements are not supposed to be + weighed. feel free to edit if you want some other weighing. **/ +inline float +KNN_Pick::GetWeightFactor(float distance) +{ + if (weighed) + //return weight_divisor / distance; // beware of dividing by zero! + return weight_divisor / ikaros::log(1.0001 + distance); + else + return 1.0; +} + + +/** return the class of the category with the most elements, or if there + are two or more categories with an equal amount of elements, return + the class of the one which has the closes element. + the amount can be weighed. + NOTE: assuming categorical classes. qualitative classes not allowed. + this should be checked in CheckParameters() though. **/ +float +KNN_Pick::CountAmount() +{ + int i, j, m; + float this_category; + float this_size; + float biggest_size; + int this_closest; + int biggest_closest = 0; + int c = 0; + + // categories is an array where the categories that have been + // found are entered, so they are not counted more than once + set_array(categories, EMPTY, k); + biggest_size = 0; + + //printf("count amount\n"); + for (i = 0; i < k; i++){ + this_category = output_table[i]; + + //printf("looking at output_table[%i]=%f\n", i, output_table[i]); + + // look for this category in categories + for (j = 0; j < k; j++) + // break if we find it or run out of entries + if ((categories[j] == this_category) || (categories[j] == EMPTY)) + break; + + // if this category already is calculated, continue + if (categories[j] == this_category) + continue; + + // else we have (categories[j] == EMPTY) and hence we have found + // a new category. the for loop above always breaks before j == k + + //printf("new category: %.1f \t", this_category); + c++; + + // index i is the first (and hence closest) we have found of this category + categories[j] = this_category; + this_size = 1 * GetWeightFactor(distance_table[i]); + this_closest = i; + + // since this category wasnt found earlier, we can start looping from the + // next element + for (m = i+1; m < k; m++) + if (output_table[m] == this_category){ + this_size += 1 * GetWeightFactor(distance_table[m]); + if (distance_table[m] < distance_table[this_closest]) + this_closest = m; + } + + //printf("size: %.2f\n", this_size); + + // see if this category is bigger than the last biggest was + // if so, make this the biggest + if (this_size > biggest_size){ + //printf("new biggest cat: %.1f\n", output_table[this_closest]); + biggest_size = this_size; + biggest_closest = this_closest; + } + + // if its the same size as the previous biggest + // make the one with the closest element the biggest + else if (this_size == biggest_size) + if (distance_table[this_closest] < distance_table[biggest_closest]){ + //printf("new biggest/closest cat: %.1f\n", output_table[this_closest]); + biggest_size = this_size; + biggest_closest = this_closest; + } + + } + //printf("found %i categories\n", c); + return output_table[biggest_closest]; +} + + +/** calculate mean of classes (this function is not used when classes are categorical). + the amount of instances might be weighed. **/ +float +KNN_Pick::CalculateMean() +{ + float tot = 0, instances = 0; + int i; + + for (i = 0; i < k; i++){ + tot += output_table[i] * GetWeightFactor(distance_table[i]); + instances += 1 * GetWeightFactor(distance_table[i]); + } + //printf("tot=%f instances=%f", tot, instances); + return tot / instances; +} + + +/** return index to the (first) closest element. **/ +int +KNN_Pick::GetClosestIndex() +{ + int i, closest_index; + + closest_index = 0; + + for (i = 1; i < k; i++) + if (distance_table[i] < distance_table[closest_index]) + closest_index = i; + + return closest_index; +} + + +/** prints some matrix with fancy headers. yeah, debugging... **/ +void +KNN_Pick::PrintTable(char *title, float **array, int amount, int elements) +{ + int i, j; + + if (title == NULL) + printf("--- NULL --- rows: %i --- columns: %i ---\n", amount, elements); + else + printf("--- %s --- rows: %i --- columns: %i ---\n", title, amount, elements); + + for (i = 0; i < amount; i++) + for (j = 0; j < elements; j++){ + if (j < elements - 1) + printf("%.2f ", array[i][j]); + else + printf("%.2f\n", array[i][j]); + } + +} + + +void +KNN_Pick::CheckParameters() +{ + categorical = GetBoolValue("categorical", true); + weighed = GetBoolValue("weighed", false); + weight_divisor = GetFloatValue("weight_divisor", 1.0); +} + diff --git a/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.h b/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.h new file mode 100755 index 000000000..cc94d4022 --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.h @@ -0,0 +1,75 @@ +// +// KNN_Pick.h This file is a part of the IKAROS project +// This module provides a few simple ways to pick a class based on K neighbors. +// +// Copyright (C) 2007 Alexander Kolodziej +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: July 2007 +// +// + +#ifndef KNN_Pick_H +#define KNN_Pick_H + +// if this is defined, a fatal error occurs when distances <0 are found +#define CHECK_FOR_NEGATIVE_DISTANCE +#include "IKAROS.h" + + +class KNN_Pick: public Module +{ +public: + + KNN_Pick(Parameter * p); + virtual ~KNN_Pick(); + + static Module * Create(Parameter * p); + + void SetSizes(); + void Init(); + void Tick(); + + void PrintTable(char *title, float **array, int amount, int elements); + void CheckParameters(void); + + // used when outputs are categorical. class will be the class of + // the elements we found the most of. might be weighed. + float CountAmount(void); + // used when outputs are qualitative (non-categorical). class is + // the mean of the neighbors. might be weighed. + float CalculateMean(void); + // returns a multiplier with which to manipulate the amount of + // instances we found. returns 1 if weighed=false + inline float GetWeightFactor(float distance); + void CheckForNegativeDistance(void); + int GetClosestIndex(void); + + float *output_table; + float *distance_table; + float *class_output; + + int k; + float *categories; + + bool categorical; + bool weighed; + float weight_divisor; +}; + +#endif diff --git a/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.ikc b/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.ikc new file mode 100755 index 000000000..d3263e00c --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/KNN_Pick.ikc @@ -0,0 +1,76 @@ + + + + + + + + This module chooses a class based on some input elements (neighbors). + It can deal with categorical classes (then the amount of instances of the + classes decides), and with qualitative classes (then the mean is calculated). + The amount of instances and the mean can be weighed. If this is the case, then + instances will be counted more (or less) times, depending on their distance. + This module can be connected to the KNN module (KNN.OUTPUT_TABLE to KNN_PICK.OUTPUT_TABLE + and KNN.DISTANCE_TABLE to KNN_PICK.DISTANCE_TABLE. Note: KNN.INPUT_TABLE is not + used by this module. This module is too simple to look at individual elements + coordinates.). + + + + + + + + + + + + + + + + + + + + + + + + + Alexander Kolodziej + alexander.kolodziej@gmail.com + LUCS + + + + KNN_Pick.h + KNN_Pick.cc + KNN_Pick.ikc + + + diff --git a/Source/Modules/LearningModules/KNN_Pick/README.txt b/Source/Modules/LearningModules/KNN_Pick/README.txt new file mode 100755 index 000000000..f2c747e4d --- /dev/null +++ b/Source/Modules/LearningModules/KNN_Pick/README.txt @@ -0,0 +1,5 @@ +* '5neighbors_categorical.ikc' + +Runs a session with 4 ticks with 5 neighbors in each tick. +Outputs the chosen class to '5neighbors_categorical.output'. +The data file is commented. diff --git a/Source/Modules/LearningModules/LinearAssociator/Examples/LinearAssociator_test.ikc b/Source/Modules/LearningModules/LinearAssociator/Examples/LinearAssociator_test.ikc new file mode 100755 index 000000000..eb67240c5 --- /dev/null +++ b/Source/Modules/LearningModules/LinearAssociator/Examples/LinearAssociator_test.ikc @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/LearningModules/LinearAssociator/Examples/input.dat b/Source/Modules/LearningModules/LinearAssociator/Examples/input.dat new file mode 100755 index 000000000..f90392461 --- /dev/null +++ b/Source/Modules/LearningModules/LinearAssociator/Examples/input.dat @@ -0,0 +1,34 @@ +# +# input.dat +# +# Example data for LinearAssociator +# +# The data consists of two columns X and Y +# with two values in each. +# +# The values in Y are the sum and differences +# of the two values in X +# + +X/2 Y/2 + +0 0 0 0 +0 1 1 -1 +0 2 2 -2 +0 3 3 -3 + +1 0 1 1 +1 1 2 0 +1 2 3 -1 +1 3 4 -2 + +2 0 2 2 +2 1 3 1 +2 2 4 0 +2 3 5 -1 + +3 0 3 3 +3 1 4 2 +3 2 5 1 +3 3 6 0 + diff --git a/Source/Modules/LearningModules/LinearAssociator/LinearAssociator.cc b/Source/Modules/LearningModules/LinearAssociator/LinearAssociator.cc new file mode 100755 index 000000000..82776b7ff --- /dev/null +++ b/Source/Modules/LearningModules/LinearAssociator/LinearAssociator.cc @@ -0,0 +1,132 @@ +// +// LinearAssociator.cc This file is a part of the IKAROS project +// +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "LinearAssociator.h" + +using namespace ikaros; + + +LinearAssociator::~LinearAssociator() +{ + destroy_array(delta); + destroy_matrix(m); +} + + +void +LinearAssociator::Init() +{ + alpha = GetFloatValue("alpha", 0.1); + beta = GetFloatValue("beta", 0.1); + + // Test that INPUT and T-INPUT have the same sizes + + if(GetInputSize("INPUT") != GetInputSize("T-INPUT")) + { + Notify(msg_fatal_error, "INPUT and T-INPUT must have the same sizes. (%d != %d)", GetInputSize("INPUT"), GetInputSize("T-INPUT")); + return; + } + + input_size = GetInputSize("INPUT"); + output_size = GetOutputSize("OUTPUT"); + + input = GetInputArray("INPUT"); + t_input = GetInputArray("T-INPUT"); + output = GetOutputArray("OUTPUT"); + t_output = GetInputArray("T-OUTPUT"); + + memory_max = GetIntValue("memory_max", 1); + memory_used = 0; + memory_training = GetIntValue("memory_training", 1); + memory_t_input = create_matrix(input_size, memory_max); + memory_t_output = create_matrix(output_size, memory_max); + + error = GetOutputArray("ERROR"); + confidence = GetOutputArray("CONFIDENCE"); + learning_rate = GetInputArray("LEARNING", false); + + delta = create_array(output_size); + momentum = create_array(output_size); + + m = create_matrix(input_size, output_size); +} + + + +void +LinearAssociator::Train(float * x, float * y) +{ + multiply(output, m, x, input_size, output_size); + subtract(delta, y, output, output_size); + + add(momentum, beta, momentum, (1.0f-beta), delta, output_size); + + // Learn [ add_outer(alpha, delta, t_input) ] + + for(int j=0; j0 && memory_used>0) + { + for(int mem=0; mem + + + + + Module that learns a linear mapping from INPUT to OUTPUT based on training samples + in T-INPUT and T-OUTPUT. + + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + LinearAssociator.h + LinearAssociator.cc + LinearAssociator.ikc + + + + diff --git a/Source/Modules/LearningModules/QLearning/Examples/QLearning_test.ikc b/Source/Modules/LearningModules/QLearning/Examples/QLearning_test.ikc new file mode 100755 index 000000000..e61d840e4 --- /dev/null +++ b/Source/Modules/LearningModules/QLearning/Examples/QLearning_test.ikc @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + <_object class="BarGraph" module="GW" source="REWARD" x="1" y="1" /> + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/LearningModules/QLearning/QLearning.cc b/Source/Modules/LearningModules/QLearning/QLearning.cc new file mode 100755 index 000000000..49766209d --- /dev/null +++ b/Source/Modules/LearningModules/QLearning/QLearning.cc @@ -0,0 +1,132 @@ +// +// QLearning.cc This file is a part of the IKAROS project +// Implementation of Q-learning +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2003-08-02 +// + +#include "QLearning.h" + + +using namespace ikaros; + +void +QLearning::Init() +{ + horizon = GetIntValueFromList("horizon"); + alpha = GetFloatValue("alpha"); + gamma = GetFloatValue("gamma"); + epsilon = GetFloatValue("epsilon"); + initial = GetFloatValue("initial"); + + state = GetInputMatrix("STATE"); + size_x = GetInputSizeX("STATE"); + size_y = GetInputSizeY("STATE"); + + reinforcement = GetInputArray("REINFORCEMENT"); + action = GetOutputArray("ACTION"); + + Q[0] = set_matrix(create_matrix(size_x, size_y), initial, size_x, size_y); + Q[1] = set_matrix(create_matrix(size_x, size_y), initial, size_x, size_y); + Q[2] = set_matrix(create_matrix(size_x, size_y), initial, size_x, size_y); + Q[3] = set_matrix(create_matrix(size_x, size_y), initial, size_x, size_y); + + value = GetOutputMatrix("VALUE"); + + last_action = -1; + + // Fill in initial values + + for(int j=0; j 0) + V = *reinforcement; + } + + Q[last_action][last_y][last_x] += alpha * (gamma * V - Q[last_action][last_y][last_x]); + } + + // Produce new action + + int a = int(random(0.0, 4.0)); + if(random(0.0, 1.0) > epsilon) + { + float action_strength[4]; + for(int i = 0; i < 4; i++) + action_strength[i] = Q[i][y][x]; + if(non_zero(action_strength, 4)) + a = arg_max(action_strength, 4); + } + + reset_array(action, 4); + action[a] = 1; + + // Update value output (assuming we start with 0 in Q-table) + + value[last_y][last_x] = 0; + for(int i = 0; i < 4; i++) + value[last_y][last_x] = max(Q[i][last_y][last_x], value[last_y][last_x]); + + // Remember action and state + + last_action = a; + last_x = x; + last_y = y; +} + + diff --git a/Source/Modules/LearningModules/QLearning/QLearning.h b/Source/Modules/LearningModules/QLearning/QLearning.h new file mode 100755 index 000000000..8ad52064e --- /dev/null +++ b/Source/Modules/LearningModules/QLearning/QLearning.h @@ -0,0 +1,65 @@ +// +// QLearning.h This file is a part of the IKAROS project +// Simple implementation of Q-learning +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2003-08-02 +// + +#ifndef QLEARNING +#define QLEARNING + +#include "IKAROS.h" + +class QLearning: public Module +{ +public: + float ** state; + float * action; + float * reinforcement; + float ** Q[4]; + float ** value; + + int size_x; + int size_y; + + int last_action; + int last_x; + int last_y; + + int horizon; // 0 = infinite, 1 = finite + float alpha; + float gamma; + float epsilon; + float initial; + + QLearning(Parameter * p) : Module(p) {} + virtual ~QLearning(); + + static Module * Create(Parameter * p) { return new QLearning(p); } + + void Init(); + + void RunQ(float R); + + void Tick(); + +}; + +#endif + diff --git a/Source/Modules/LearningModules/QLearning/QLearning.ikc b/Source/Modules/LearningModules/QLearning/QLearning.ikc new file mode 100755 index 000000000..d7c822c47 --- /dev/null +++ b/Source/Modules/LearningModules/QLearning/QLearning.ikc @@ -0,0 +1,50 @@ + + + + + + Basic Q-learning. + + + + + + + + + + + + + + + + + + + + + + It should be possible to turn off the automatic movement of the agent from goal to start locations. + + + 2003 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + QLearning.h + QLearning.cc + QLearning.ikc + + + + diff --git a/Source/Modules/Modules.h b/Source/Modules/Modules.h new file mode 100755 index 000000000..026119af2 --- /dev/null +++ b/Source/Modules/Modules.h @@ -0,0 +1,299 @@ +// +// Modules.h This file is a part of the IKAROS project +// This file includes the h-files of all standard modules +// +// Copyright (C) 2006-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// +// This section includes all modules that are to be compiled with IKAROS +// When new standard modules are added to the system, they must be included here +// +// User modules should not be included here but in UserModules.h +// + +// IO Modules + + +#include "Modules/IOModules/FileInput/InputFile/InputFile.h" +#include "Modules/IOModules/FileOutput/OutputFile/OutputFile.h" +#include "Modules/IOModules/FileInput/InputRawImage/InputRawImage.h" +#include "Modules/IOModules/FileInput/InputJPEG/InputJPEG.h" +#include "Modules/IOModules/FileInput/InputPNG/InputPNG.h" +#include "Modules/IOModules/FileInput/InputQTMovie/InputQTMovie.h" +#include "Modules/IOModules/FileInput/InputQTAudio/InputQTAudio.h" + +#include "Modules/IOModules/FileOutput/OutputRawImage/OutputRawImage.h" +#include "Modules/IOModules/FileOutput/OutputJPEG/OutputJPEG.h" +#include "Modules/IOModules/FileOutput/OutputPNG/OutputPNG.h" +#include "Modules/IOModules/FileOutput/OutputQTAudioVisual/OutputQTAudioVisual.h" + +#include "Modules/IOModules/Video/InputVideoQT/InputVideoQT.h" +#include "Modules/IOModules/Video/NetworkCamera/NetworkCamera.h" + +// UtilityModules + +#include "Modules/UtilityModules/Add/Add.h" +#include "Modules/UtilityModules/Arbiter/Arbiter.h" +#include "Modules/UtilityModules/Average/Average.h" +#include "Modules/UtilityModules/Constant/Constant.h" +#include "Modules/UtilityModules/Counter/Counter.h" +#include "Modules/UtilityModules/Delay/Delay.h" +#include "Modules/UtilityModules/Distance/Distance.h" +#include "Modules/UtilityModules/Divide/Divide.h" +#include "Modules/UtilityModules/FunctionGenerator/FunctionGenerator.h" +#include "Modules/UtilityModules/Gate/Gate.h" +#include "Modules/UtilityModules/Integrator/Integrator.h" +#include "Modules/UtilityModules/MatrixMultiply/MatrixMultiply.h" +#include "Modules/UtilityModules/Max/Max.h" +#include "Modules/UtilityModules/Min/Min.h" +#include "Modules/UtilityModules/ArgMax/ArgMax.h" +#include "Modules/UtilityModules/Multiply/Multiply.h" +#include "Modules/UtilityModules/Normalize/Normalize.h" +#include "Modules/UtilityModules/Noise/Noise.h" +#include "Modules/UtilityModules/OuterProduct/OuterProduct.h" +#include "Modules/UtilityModules/Polynomial/Polynomial.h" +#include "Modules/UtilityModules/Randomizer/Randomizer.h" +#include "Modules/UtilityModules/Abs/Abs.h" +#include "Modules/UtilityModules/Scale/Scale.h" +#include "Modules/UtilityModules/SelectMax/SelectMax.h" +#include "Modules/UtilityModules/Shift/Shift.h" +#include "Modules/UtilityModules/Softmax/Softmax.h" +#include "Modules/UtilityModules/Subtract/Subtract.h" +#include "Modules/UtilityModules/Sweep/Sweep.h" +#include "Modules/UtilityModules/Threshold/Threshold.h" + +// CodingModules + +#include "Modules/CodingModules/IntervalCoder/IntervalCoder.h" +#include "Modules/CodingModules/IntervalDecoder/IntervalDecoder.h" +#include "Modules/CodingModules/CoarseCoder/CoarseCoder.h" + +// VisionModules + +#include "Modules/VisionModules/ImageConvolution/ImageConvolution.h" +#include "Modules/VisionModules/ColorTransform/ColorTransform.h" +#include "Modules/VisionModules/ColorMatch/ColorMatch.h" +#include "Modules/VisionModules/WhiteBalance/WhiteBalance.h" +#include "Modules/VisionModules/SaliencyMap/SaliencyMap.h" +#include "Modules/VisionModules/AttentionFocus/AttentionFocus.h" + +#include "Modules/VisionModules/ImageOperators/GaborFilter/GaborFilter.h" + +#include "Modules/VisionModules/ImageOperators/EdgeDetectors/RobertsEdgeDetector/RobertsEdgeDetector.h" +#include "Modules/VisionModules/ImageOperators/EdgeDetectors/PrewittEdgeDetector/PrewittEdgeDetector.h" +#include "Modules/VisionModules/ImageOperators/EdgeDetectors/SobelEdgeDetector/SobelEdgeDetector.h" +#include "Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.h" +#include "Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/CannyEdgeDetector.h" +#include "Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.h" + +#include "Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/HarrisDetector.h" + +#include "Modules/VisionModules/ImageOperators/ChangeDetector/ChangeDetector.h" + +#include "Modules/VisionModules/Scaling/Upsample/Upsample.h" +#include "Modules/VisionModules/Scaling/Downsample/Downsample.h" + +#include "Modules/VisionModules/ImageOperators/MorphologicalOperators/Erode/Erode.h" +#include "Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.h" + +#include "Modules/VisionModules/ColorClassifier/ColorClassifier.h" +#include "Modules/VisionModules/SpatialClustering/SpatialClustering.h" + + +// Examples + +#include "Modules/Examples/DelayOne/DelayOne.h" +#include "Modules/Examples/Sum/Sum.h" + +// Environment Modules + +#include "Modules/EnvironmentModules/GridWorld/GridWorld.h" +#include "Modules/EnvironmentModules/PlanarArm/PlanarArm.h" +#include "Modules/EnvironmentModules/MazeGenerator/MazeGenerator.h" + +// Learning Modules + +#include "Modules/LearningModules/LinearAssociator/LinearAssociator.h" +#include "Modules/LearningModules/QLearning/QLearning.h" +#include "Modules/LearningModules/KNN/KNN.h" +#include "Modules/LearningModules/KNN_Pick/KNN_Pick.h" + +// Learning Modules + +#include "Modules/ControlModules/PIDController/PIDController.h" +#include "Modules/ControlModules/KalmanFilter/KalmanFilter.h" + +// ANN Modules + +#include "Modules/ANN/Perceptron/Perceptron.h" + +// Robot Modules + +#include "Modules/RobotModules/Epuck/Epuck.h" +#include "Modules/RobotModules/SSC32/SSC32.h" +#include "Modules/RobotModules/Dynamixel/Dynamixel.h" + +// Brain Models + +#include "BrainModels/Moren2002/M02_Amygdala/M02_Amygdala.h" +#include "BrainModels/Moren2002/M02_Cortex/M02_Cortex.h" +#include "BrainModels/Moren2002/M02_Hippocampus/M02_Hippocampus.h" +#include "BrainModels/Moren2002/M02_OFC/M02_OFC.h" +#include "BrainModels/Moren2002/M02_SensoryCortex/M02_SensoryCortex.h" +#include "BrainModels/Moren2002/M02_Thalamus/M02_Thalamus.h" + +void InitModules(Kernel & k); + +void +InitModules(Kernel & k) +{ + // Install module classes in the kernel + // All modules that are to be used must be installed here or in the file UserModules.h + + // IOModules + + k.AddClass("InputFile", &InputFile::Create, "Source/Modules/IOModules/FileInput/InputFile/"); + k.AddClass("OutputFile", &OutputFile::Create, "Source/Modules/IOModules/FileOutput/OutputFile/"); + k.AddClass("InputRawImage", &InputRawImage::Create, "Source/Modules/IOModules/FileInput/InputRawImage/"); + k.AddClass("InputJPEG", &InputJPEG::Create, "Source/Modules/IOModules/FileInput/InputJPEG/"); + k.AddClass("InputPNG", &InputPNG::Create, "Source/Modules/IOModules/FileInput/InputPNG/"); + k.AddClass("InputQTMovie", &InputQTMovie::Create, "Source/Modules/IOModules/FileInput/InputQTMovie/"); + k.AddClass("InputQTAudio", &InputQTAudio::Create, "Source/Modules/IOModules/FileInput/InputQTAudio/"); + k.AddClass("OutputRawImage", &OutputRawImage::Create, "Source/Modules/IOModules/FileOutput/OutputRawImage/"); + k.AddClass("OutputJPEG", &OutputJPEG::Create, "Source/Modules/IOModules/FileOutput/OutputJPEG/"); + k.AddClass("OutputPNG", &OutputPNG::Create, "Source/Modules/IOModules/FileOutput/OutputPNG/"); + k.AddClass("OutputQTAudioVisual", &OutputQTAudioVisual::Create, "Source/Modules/IOModules/FileOutput/OutputQTAudioVisual/"); + k.AddClass("InputVideoQT", &InputVideoQT::Create, "Source/Modules/IOModules/Video/InputVideoQT/"); + k.AddClass("NetworkCamera", &NetworkCamera::Create, "Source/Modules/IOModules/Video/NetworkCamera/"); + + // Utlity Modules + + k.AddClass("Arbiter", &Arbiter::Create, "Source/Modules/UtilityModules/Arbiter/"); + k.AddClass("Constant", &Constant::Create, "Source/Modules/UtilityModules/Constant/"); + k.AddClass("Sweep", &Sweep::Create, "Source/Modules/UtilityModules/Sweep/"); + k.AddClass("Randomizer", &Randomizer::Create, "Source/Modules/UtilityModules/Randomizer/"); + + k.AddClass("Abs", &Abs::Create, "Source/Modules/UtilityModules/Abs/"); + k.AddClass("Add", &Add::Create, "Source/Modules/UtilityModules/Add/"); + k.AddClass("Subtract", &Subtract::Create, "Source/Modules/UtilityModules/Subtract/"); + k.AddClass("Multiply", &Multiply::Create, "Source/Modules/UtilityModules/Multiply/"); + k.AddClass("Divide", &Divide::Create, "Source/Modules/UtilityModules/Divide/"); + k.AddClass("Scale", &Scale::Create, "Source/Modules/UtilityModules/Scale/"); + k.AddClass("Normalize", &Normalize::Create, "Source/Modules/UtilityModules/Normalize/"); + k.AddClass("Noise", &Noise::Create, "Source/Modules/UtilityModules/Noise/"); + + k.AddClass("OuterProduct", &OuterProduct::Create, "Source/Modules/UtilityModules/OuterProduct/"); + k.AddClass("MatrixMultiply", &MatrixMultiply::Create, "Source/Modules/UtilityModules/MatrixMultiply/"); + + k.AddClass("Max", &Max::Create, "Source/Modules/UtilityModules/Max/"); + k.AddClass("Min", &Min::Create, "Source/Modules/UtilityModules/Min/"); + k.AddClass("ArgMax", &ArgMax::Create, "Source/Modules/UtilityModules/ArgMax/"); + + k.AddClass("Delay", &Delay::Create, "Source/Modules/UtilityModules/Delay/"); + k.AddClass("Threshold", &Threshold::Create, "Source/Modules/UtilityModules/Threshold/"); + k.AddClass("Gate", &Gate::Create, "Source/Modules/UtilityModules/Gate/"); + k.AddClass("Integrator", &Integrator::Create, "Source/Modules/UtilityModules/Integrator/"); + k.AddClass("Average", &Average::Create, "Source/Modules/UtilityModules/Average/"); + k.AddClass("Softmax", &Softmax::Create, "Source/Modules/UtilityModules/Softmax/"); + k.AddClass("SelectMax", &SelectMax::Create, "Source/Modules/UtilityModules/SelectMax/"); + k.AddClass("Shift", &Shift::Create, "Source/Modules/UtilityModules/Shift/"); + k.AddClass("FunctionGenerator", &FunctionGenerator::Create, "Source/Modules/UtilityModules/FunctionGenerator/"); + k.AddClass("Polynomial", &Polynomial::Create, "Source/Modules/UtilityModules/Polynomial/"); + k.AddClass("Distance", &Distance::Create, "Source/Modules/UtilityModules/Distance/"); + + k.AddClass("Counter", &Counter::Create, "Source/Modules/UtilityModules/Counter/"); + + // Coding Modules + + k.AddClass("IntervalCoder", &IntervalCoder::Create, "Source/Modules/CodingModules/IntervalCoder/"); + k.AddClass("IntervalDecoder", &IntervalDecoder::Create, "Source/Modules/CodingModules/IntervalDecoder/"); + k.AddClass("CoarseCoder", &CoarseCoder::Create, "Source/Modules/CodingModules/CoarseCoder/"); + + + // Vision Modules + + k.AddClass("ImageConvolution", &ImageConvolution::Create, "Source/Modules/VisionModules/ImageConvolution/"); + k.AddClass("ColorTransform", &ColorTransform::Create, "Source/Modules/VisionModules/ColorTransform/"); + k.AddClass("ColorMatch", &ColorMatch::Create, "Source/Modules/VisionModules/ColorMatch/"); + k.AddClass("WhiteBalance", &WhiteBalance::Create, "Source/Modules/VisionModules/WhiteBalance/"); + k.AddClass("SaliencyMap", &SaliencyMap::Create, "Source/Modules/VisionModules/SaliencyMap/"); + k.AddClass("AttentionFocus", &AttentionFocus::Create, "Source/Modules/VisionModules/AttentionFocus/"); + + k.AddClass("GaborFilter", &GaborFilter::Create, "Source/Modules/VisionModules/ImageOperators/GaborFilter/"); + + k.AddClass("RobertsEdgeDetector", &RobertsEdgeDetector::Create, "Source/Modules/VisionModules/ImageOperators/EdgeDetectors/RobertsEdgeDetector/"); + k.AddClass("PrewittEdgeDetector", &PrewittEdgeDetector::Create, "Source/Modules/VisionModules/ImageOperators/EdgeDetectors/PrewittEdgeDetector/"); + k.AddClass("SobelEdgeDetector", &SobelEdgeDetector::Create, "Source/Modules/VisionModules/ImageOperators/EdgeDetectors/SobelEdgeDetector/"); + k.AddClass("GaussianEdgeDetector", &GaussianEdgeDetector::Create, "Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/"); + k.AddClass("CannyEdgeDetector", &CannyEdgeDetector::Create, "Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/"); + + k.AddClass("HysteresisThresholding", &HysteresisThresholding::Create, "Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/"); + + k.AddClass("HarrisDetector", &HarrisDetector::Create, "Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/"); + + k.AddClass("ChangeDetector", &ChangeDetector::Create, "Source/Modules/VisionModules/ImageOperators/ChangeDetector/"); + + k.AddClass("Erode", &Erode::Create, "Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Erode/"); + k.AddClass("Dilate", &Dilate::Create, "Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/"); + + k.AddClass("Upsample", &Upsample::Create, "Source/Modules/VisionModules/Scaling/Upsample/"); + k.AddClass("Downsample", &Downsample::Create , "Source/Modules/VisionModules/Scaling/Downsample/"); + + k.AddClass("ColorClassifier", &ColorClassifier::Create , "Source/Modules/VisionModules/ColorClassifier/"); + k.AddClass("SpatialClustering", &SpatialClustering::Create , "Source/Modules/VisionModules/SpatialClustering/"); + + // Examples + + k.AddClass("DelayOne", &DelayOne::Create , "Source/Modules/Examples/DelayOne/"); + k.AddClass("Sum", &Sum::Create, "Source/Modules/Examples/Sum/"); + + // Environment Modules + + k.AddClass("GridWorld", &GridWorld::Create, "Source/Modules/EnvironmentModules/GridWorld/"); + k.AddClass("PlanarArm", &PlanarArm::Create, "Source/Modules/EnvironmentModules/PlanarArm/"); + k.AddClass("MazeGenerator", &MazeGenerator::Create, "Source/Modules/EnvironmentModules/MazeGenerator/"); + + // Learning Modules + + k.AddClass("LinearAssociator", &LinearAssociator::Create, "Source/Modules/LearningModules/LinearAssociator/"); + k.AddClass("QLearning", &QLearning::Create, "Source/Modules/LearningModules/QLearning/"); + + // ANN Modules + + k.AddClass("Perceptron", &Perceptron::Create, "Source/Modules/ANN/Perceptron/"); + + // Control Modules + + k.AddClass("PIDController", &PIDController::Create, "Source/Modules/ControlModules/PIDController/"); + k.AddClass("KalmanFilter", &KalmanFilter::Create, "Source/Modules/ControlModules/KalmanFilter/"); + + // Robot Modules + + k.AddClass("Epuck", &Epuck::Create, "Source/Modules/RobotModules/Epuck/"); + k.AddClass("SSC32", &SSC32::Create, "Source/Modules/RobotModules/SSC32/"); + k.AddClass("Dynamixel", &Dynamixel::Create, "Source/Modules/RobotModules/Dynamixel/"); + + // Brain Models + + k.AddClass("M02_Amygdala", &M02_Amygdala::Create, "Source/Modules/BrainModels/Moren2002/M02_Amygdala/"); + k.AddClass("M02_Cortex", &M02_Cortex::Create, "Source/Modules/BrainModels/Moren2002/M02_Cortex/"); + k.AddClass("M02_Hippocampus", &M02_Hippocampus::Create, "Source/Modules/BrainModels/Moren2002/M02_Hippocampus/"); + k.AddClass("M02_OFC", &M02_OFC::Create, "Source/Modules/BrainModels/Moren2002/M02_OFC/"); + k.AddClass("M02_SensoryCortex", &M02_SensoryCortex::Create, "Source/Modules/BrainModels/Moren2002/M02_SensoryCortex/"); + k.AddClass("M02_Thalamus", &M02_Thalamus::Create, "Source/Modules/BrainModels/Moren2002/M02_Thalamus/"); +} diff --git a/Source/Modules/RobotModules/Dynamixel/Dynamixel.cc b/Source/Modules/RobotModules/Dynamixel/Dynamixel.cc new file mode 100755 index 000000000..be58f01b9 --- /dev/null +++ b/Source/Modules/RobotModules/Dynamixel/Dynamixel.cc @@ -0,0 +1,470 @@ +// +// Dynamixel.cc This file is a part of the IKAROS project +// +// Copyright (C) 2010-2011 Christian Balkenius +// +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// + +#include "Dynamixel.h" +#include "DynamixelComm.h" + +using namespace ikaros; + + +class Servo +{ +public: + int ID; + int servo_model; + const char * servo_model_string; + int position_max; + int speed_max; + int torque_max; + float angle_max; + float nominal_speed; // RPM + bool continuous_mode; + + Servo(DynamixelComm *com, int id) + { + unsigned char inbuf[256]; + + ID = id; + + // Get data from servo + + com->ReadMemoryBlock(ID, inbuf, 0, 50); + + // Get servo type and data from servo + + servo_model = inbuf[0]+256*inbuf[1]; + continuous_mode = (inbuf[6] == 0 && inbuf[7] == 0 && inbuf[8] == 0 && inbuf[9] == 0); +// float voltage = float(inbuf[0x2A])/10.0; // will be used to calculate nominal speed + + switch (servo_model) + { + case 12: + servo_model_string = "AX-12"; + position_max = 0x3ff; + speed_max = 0x3ff; + torque_max = 0x3ff; + angle_max = 300; // degrees + nominal_speed = 51; // RPM @ 10V // TODO: calculate based on voltage (0.269/60 deg @ 7V, 0.196/60 deg @ 10V); or 114 @ 0x3ff ??? + break; + + case 24: + servo_model_string = "RX-24F"; + position_max = 0x3ff; + speed_max = 0x3ff; // .111rpm per step + torque_max = 0x3ff; + angle_max = 300; // degrees + nominal_speed = 51; // RPM @ 10V // TODO: calculate based on voltage (0.269/60 deg @ 7V, 0.196/60 deg @ 10V) or 114 @ 0x3ff ??? + break; + + case 28: + servo_model_string = "RX-28"; + position_max = 0x3ff; + speed_max = 0x3ff; + torque_max = 0x3ff; + angle_max = 300; // degrees + nominal_speed = 59.9; // RPM @ 12V // TODO: calculate based on voltage (0.269/60 deg @ 7V, 0.196/60 deg @ 10V) or 114 @ 0x3ff ??? + break; + + case 29: + servo_model_string = "MX-28"; + position_max = 0xfff; // 0.088 deg per step + speed_max = 0x3ff; + torque_max = 0x3ff; + angle_max = 300; // degrees + nominal_speed = 54; // RPM @ ??V // TODO: calculate based on voltage (0.269/60 deg @ 7V, 0.196/60 deg @ 10V) or 114 @ 0x3ff ??? + break; + + case 64: + servo_model_string = "EX-64"; + position_max = 0x3ff; + speed_max = 0x3ff; + torque_max = 0x3ff; + angle_max = 300; // degrees + nominal_speed = 53.2; // RPM @ 15V // TODO: calculate based on voltage (69.9 @ 18.5V) + break; + + case 107: + servo_model_string = "EX-106"; + position_max = 0xfff; + speed_max = 0x3ff; + torque_max = 0x3ff; + angle_max = 280.6; // degrees + nominal_speed = 54.9; // RPM @ 14.8V // TODO: calculate based on voltage (63.69 @ 18V) + break; + + default: + servo_model_string = "Unknown"; + position_max = 0x3ff; + torque_max = 0x3ff; + angle_max = 300; // degrees + nominal_speed = 114; // RPM + break; + } + } + + ~Servo() + { + } + + float ConvertToAngle(int position, int angle_unit); + int ConvertToPosition(float angle, int angle_unit); +}; + + + +float +Servo::ConvertToAngle(int position, int angle_unit) +{ + float angle = angle_max * float(position)/float(position_max); + switch(angle_unit) + { + case 0: + default: return angle; + case 1: return 2.0*pi*angle/360.0; + case 2: return angle/360.0; + case 3: return angle/angle_max; + } + + return 0; +} + + + +int +Servo::ConvertToPosition(float angle, int angle_unit) +{ + switch(angle_unit) + { + case 0: + default: break; // angle = angle; + case 1: angle = 360*angle/(2*pi); break; + case 2: angle = 360*angle; + case 3: angle = angle_max*angle; + } + + angle = clip(angle, 0, angle_max)/angle_max; + return int(float(position_max)*angle); +} + + + +Dynamixel::Dynamixel(Parameter * p): + Module(p) +{ + Bind(position_speed, "position_speed"); + + device = GetValue("device"); + + if(!device) + { + Notify(msg_warning, "Dynamixel serial device name is not set."); + size = 0; + return; + } + + com = new DynamixelComm(device, 1000000); // FIXME: should be a parameter + if(!com) + { + Notify(msg_warning, "Dynamixel serial device \"%s\" could not be opened.", device); + return; + } + + use_feedback = GetBoolValue("feedback"); + + start_up_delay = GetIntValue("start_up_delay"); + + index_mode = GetIntValueFromList("index_mode"); + angle_unit = GetIntValueFromList("angle_unit"); + int max_servo_id = GetIntValue("max_servo_id"); + int servo_id_list_size = 0; + int * servo_id_list = GetIntArray("servo_id", servo_id_list_size); + + servo = new Servo * [256]; // maximum number of servos + for(int i=0; i<256; i++) + servo[i] = NULL; + + // Alt 1: create a list of servos with the IDs read from servo_id + + if(servo_id_list_size > 0 && index_mode == 0) + { + for(int i=0; iPing(servo_id_list[i])) + { + servo[servo_id_list[i]] = new Servo(com, servo_id_list[i]); + } + else + { + servo[servo_id_list[i]] = NULL; + Notify(msg_warning, "Dynamixel servo with ID = %d could not be found\n", servo_id_list[i]); + } + if(servo_id_list[i] > size) + size = servo_id_list[i]+1; + } + } + + else if(servo_id_list_size > 0 && index_mode == 1) + { + for(int i=0; iPing(servo_id_list[i])) + { + servo[i] = new Servo(com, servo_id_list[i]); + } + else + { + servo[i] = NULL; + Notify(msg_warning, "Dynamixel servo with ID = %d could not be found\n", servo_id_list[i]); + } + } + size = servo_id_list_size; + } + + // Alt 2: scan for servos + + else if(index_mode == 0) + { + size = 0; + for(int i=1; iPing(i)) + { + servo[i] = new Servo(com, i); + size = i+1; + } + else + servo[i] = NULL; + } + } + else + { + size = 0; + for(int i=1; iPing(i)) + { + servo[size] = new Servo(com, i); + size += 1; + } + } + } + + // Adjust size if set as a parameter + + int psize = GetIntValue("size"); + if(psize > 256) + psize = 256; + if(psize != 0) + size = psize; + + // Count servos + + servos = 0; + for(int i=0; iID; + } +} + + + +void +Dynamixel::Print() +{ + printf("Size: %d\n", size); + printf("Servos: %d\n\n", servos); + printf("ix ID Model Mode MaxPos MaxSpeed MaxAngle NomSpeed \n"); + printf("------------------------------------------------------------\n"); + for(int i=0; iID); + printf("%-10s", servo[i]->servo_model_string); + printf("%-6s", (servo[i]->continuous_mode ? "wheel" : "servo" )); + + printf(" %4d ", servo[i]->position_max); + printf(" %4d ", servo[i]->speed_max); + printf(" %6.1f ", servo[i]->angle_max); + printf(" %5.2f ", servo[i]->nominal_speed); + printf("\n"); + } + printf("\n"); +} + +/* +int position_max; +int speed_max; +int torque_max; +float angle_max; +float nominal_speed; // RPM +bool continuous_mode; +*/ + +void +Dynamixel::SetSizes() +{ + SetOutputSize("OUTPUT", size); + SetOutputSize("LOAD", size); + SetOutputSize("VOLTAGE", size); + SetOutputSize("TEMPERATURE", size); +} + + + +void +Dynamixel::Init() +{ + input = GetInputArray("INPUT"); + speed = GetInputArray("SPEED", false); + torque = GetInputArray("TORQUE", false); + + output = GetOutputArray("OUTPUT"); + + load = GetOutputArray("LOAD"); + voltage = GetOutputArray("VOLTAGE"); + temperature = GetOutputArray("TEMPERATURE"); + + // Get the initial position values + + for(int i=0; iConvertToAngle(com->GetPosition(servo[i]->ID), angle_unit); + else + output[i] = 0; + + timebase = (float)GetTickLength(); + + Print(); +} + + + +Dynamixel::~Dynamixel() +{ + // Turn off torque for all servos + + com->SetTorque(254, 0); // TODO: Rampa ner torque!!! + + delete servo_id; + delete positions; + delete speeds; + delete torques; +} + + + +void +Dynamixel::Tick() +{ + // check that the device exists and is open + + if(!device) + return; + + if(!com) + return; + + // do not move if the input contains only zeros + + if(norm(input, size) == 0) + return; + + // send position commands (for servos in position mode) + + for(int i=0; icontinuous_mode && speed) + { + positions[servo_index[i]] = 0; // Do different servis have different direction bit? + speeds[servo_index[i]] = int((servo[i]->speed_max-1)*clip(abs(input[i]), 0, 1)) | (input[i] < 0 ? 0x400 : 0x000); + torques[i] = 0; + } + else // servo mode + { + positions[servo_index[i]] = servo[i]->ConvertToPosition(input[i], angle_unit); + speeds[servo_index[i]] = int(1+position_speed*float(servo[i]->speed_max-1)); // avoid speed of 0 which would turn off speed control + if(torque) + torques[i] = servo[i]->torque_max*clip(torque[i], 0, 1); + else + torques[i] = 0; + } + } + + if(timebase != 0) // Calculate speeds based on distance to target if we are running in real-time mode + for(int i=0; ispeed_max / (360*timebase*servo[i]->nominal_speed); + float speed_extra = 0.1; + int s = int(speed_p*abs(output[i]-input[i])) + speed_extra; + if(s > servo[i]->speed_max-1) + s = servo[i]->speed_max-1; + speeds[servo_index[i]] = 1+s; + } + + if(GetTick() >= start_up_delay) // Do not send commands the first few ticks + { + if(torque) + com->SyncMoveWithIdSpeedAndTorque(servo_id, positions, speeds, torques, servos); + else + com->SyncMoveWithIdAndSpeed(servo_id, positions, speeds, servos); + } + + if(use_feedback) + { + unsigned char inbuf[256]; // temp buffer + for(int i=0; iReadAllData(servo[i]->ID, inbuf); // The whole block is fetched but only a few of the values are used in ikaros. + + output[i] = servo[i]->ConvertToAngle(inbuf[36]+256*inbuf[37], angle_unit); //Extract the Position + load[i] = float((inbuf[41] & 1024) == 0 ? -1: 1)*float((inbuf[40]+256*inbuf[41]) & 1023)/1023.0; //Extract the Load + voltage[i] = 0.1*float(inbuf[42]); //Extract the Voltage + temperature[i] = float(inbuf[43]); //Extract the Temperature in degrees Celcius + } + } + + else + { + copy_array(output, input, size); + } +} + + diff --git a/Source/Modules/RobotModules/Dynamixel/Dynamixel.h b/Source/Modules/RobotModules/Dynamixel/Dynamixel.h new file mode 100755 index 000000000..0c5d4a91e --- /dev/null +++ b/Source/Modules/RobotModules/Dynamixel/Dynamixel.h @@ -0,0 +1,94 @@ +// +// Dynamixel.h This file is a part of the IKAROS project +// +// Copyright (C) 2010-2011 Christian Balkenius +// +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef Dynamixel_ +#define Dynamixel_ + +#include "IKAROS.h" +#include "DynamixelComm.h" + +class Servo; + +class Dynamixel: public Module +{ +public: + static Module * Create(Parameter * p) { return new Dynamixel(p); } + + Dynamixel(Parameter * p); + virtual ~Dynamixel(); + + void SetSizes(); + + void Print(); + + void Init(); + void Tick(); + +private: + int size; + int servos; + + int index_mode; + int angle_unit; + float position_speed; // global speed in fraction of max + + float timebase; + bool use_feedback; + + int start_up_delay; + bool list_servos; + + // Continusou rotation parameters + + float gain_alpha; + float gain_initial; + float deadband_initial; + + // Inputs and outputs + + float * input; + float * speed; + float * torque; + + float * output; + float * load; + float * voltage; + float * temperature; + + // Array of servo data + + Servo ** servo; + + // Arrays used to send commands to servos // FIXME: USE separat list for continous servos + + int * servo_index; + int * servo_id; + int * positions; + int * speeds; + int * torques; + + + const char * device; + DynamixelComm * com; +}; + +#endif + diff --git a/Source/Modules/RobotModules/Dynamixel/Dynamixel.ikc b/Source/Modules/RobotModules/Dynamixel/Dynamixel.ikc new file mode 100755 index 000000000..2a49b0395 --- /dev/null +++ b/Source/Modules/RobotModules/Dynamixel/Dynamixel.ikc @@ -0,0 +1,96 @@ + + + + + +

+ Driver for the Dynamixel servos from ROBOTIS. The module can control servos both in position and continuous (wheel) mode. The IDs of the modules can be set with the parameter 'servo_id'. If this parameter is not set, the module will instead scan the bus for servos. +

+

+ When the index_mode indirect is set, the input and output arrays ranges from 0 to N, where N is the number of connected servos. If the module scanned for the IDs, they will be in numerical order, otherwise they will be in the order listen in the pramater servo_id. +

+

+ When the index_mode is set to direct, the input and output arrays ranges from 0 to the ID of the servos with highest ID. In this mode, some of the elements in the input and output arrays may not be used and will always be set to 0. +

+

+ If the parameter size is set, it will override the other calculations of the size of the arrays and either truncate or extend the array to the requested size. +

+

+ It is usually necessary to install the drivers for the FTDI USB serial driver before using the + USB2Dynamixel with Ikaros. This driver is available from the FTDI site. When the driver is + installed a device called something like "cu.usbserial-A7005Lxn" will show up under the /dev directory. +

+

+ If the servo is set up to run in continuous mode, the module uses the input SPEED to set the speed directly + between min (0) and max (1). No speed control is performed by this module. +

+

+ If the TORQUE input is connected, the torque for each servo can be set individually between min (0) and max (1). +

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The module should ping the servos to see how many there are and set the output accordingly to + allow automatic reconfiguration of the controller. + + + + The module should read additional data such as temperature and force from the servos. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Dynamixel.h + Dynamixel.cc + Dynamixel.ikc + DynamixelComm.h + DynamixelComm.cc + + +
+ diff --git a/Source/Modules/RobotModules/Dynamixel/DynamixelComm.cc b/Source/Modules/RobotModules/Dynamixel/DynamixelComm.cc new file mode 100755 index 000000000..a41913717 --- /dev/null +++ b/Source/Modules/RobotModules/Dynamixel/DynamixelComm.cc @@ -0,0 +1,319 @@ +// +// DynamixelComm.cc Class to communicate with USB2Dynamixel +// +// Copyright (C) 2010-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// +// Created: April 4, 2010 +// + + + +#include "DynamixelComm.h" + + +DynamixelComm::DynamixelComm(const char * serial_device, unsigned long baud_rate): + Serial(serial_device, baud_rate) +{ + max_failed_reads = 1; +} + + + +DynamixelComm::~DynamixelComm() +{ +} + + + +unsigned char +DynamixelComm::CalculateChecksum(unsigned char * b) +{ + unsigned char checksum = 0; + for(int i=0; i<(b[3]+1); i++) + checksum += b[i+2]; + checksum = ~checksum; + return checksum; +} + + + +void +DynamixelComm::Send(unsigned char * b) +{ + b[b[3]+3] = CalculateChecksum(b); + + SendBytes((char *)b, b[3]+4); +} + + + +int +DynamixelComm::Receive(unsigned char * b) +{ + int c = ReceiveBytes((char *)b, 4); + if(c < 4) + { +// printf("receive error (data size = %d)\n", c); + return 0; + } + c += ReceiveBytes((char *)&b[4], b[3]); + + unsigned char checksum = CalculateChecksum(b); + if(checksum != b[b[3]+3]) + { + printf("receive error (data size = %d) incorrect checksum\n", c); + return -1; + } + + return c; +} + + + +bool +DynamixelComm::ReadMemoryBlock(int id, unsigned char * buffer, int fromAddress, int toAddress) +{ + unsigned char outbuf[256] = {0XFF, 0XFF, id, 4, INST_READ, fromAddress, toAddress, 0X00}; + unsigned char inbuf[256]; + + Send(outbuf); + int n = Receive(inbuf); + + if(n==0) + return false; + + // TODO: exit if checksum incorrect + + // TODO: check ID @ inbuf[2] + // TODO: check ERROR @ inbuf[4], should be 0 + + // copy data to buffer + + // print all values from servo + //printDynamixelData(inbuf,0,50); + + + for(int i=0; i<50; i++) + buffer[i] = inbuf[i+5]; + + return true; +} + + + +bool +DynamixelComm::ReadAllData(int id, unsigned char * buffer) +{ + unsigned char outbuf[256] = {0XFF, 0XFF, id, 4, INST_READ, 0, 50, 0X00}; + unsigned char inbuf[256]; + + Send(outbuf); + int n = Receive(inbuf); + + if(n==0) + return false; + + // TODO: exit if checksum incorrect + + // TODO: check ID @ inbuf[2] + // TODO: check ERROR @ inbuf[4], should be 0 + + // copy data to buffer + + for(int i=0; i<50; i++) + buffer[i] = inbuf[i+5]; + + return true; +} + + + +int +DynamixelComm::Move(int id, int pos, int speed) +{ + unsigned char outbuf[256] = {0XFF, 0XFF, id, 7, INST_WRITE, P_GOAL_POSITION_L, pos % 256, pos / 256, speed % 256, speed / 256, 0X00}; // move to position with speed + unsigned char inbuf[256]; + + Send(outbuf); + Receive(inbuf); + + return 1; +} + + + +int +DynamixelComm::SetSpeed(int id, int speed) +{ + unsigned char outbuf[256] = {0XFF, 0XFF, id, 5, INST_WRITE, P_GOAL_SPEED_L, speed % 256, speed / 256, 0X00}; // write two bytes for present position + unsigned char inbuf[256]; + + Send(outbuf); + Receive(inbuf); + + return 1; +} + + + +int +DynamixelComm::SetPosition(int id, int pos) +{ + unsigned char outbuf[256] = {0XFF, 0XFF, id, 5, INST_WRITE, P_GOAL_POSITION_L, pos % 256, pos / 256, 0X00}; // write two bytes for present position + unsigned char inbuf[256]; + + Send(outbuf); + Receive(inbuf); + + return 1; +} + + + +int +DynamixelComm::SetTorque(int id, int value) +{ + unsigned char outbuf[256] = {0XFF, 0XFF, id, 4, INST_WRITE, P_TORQUE_ENABLE, value, 0X00}; // write two bytes for present position + unsigned char inbuf[256]; + + Send(outbuf); + + if(id != 254) + Receive(inbuf); + + return 1; +} + + + +void +DynamixelComm::SyncMoveWithSpeed(int * pos, int * speed, int n) +{ + unsigned char outbuf[256] = + {0XFF, 0XFF, 0XFE, + (4+1)*n+4, // (datalength+1)*N+4 + 0X83, // sync_write + 0X1E, // address + 0x04 // length + }; + + for(int i=0; i + + + + + This example scans the bus of a single Dynamixel servo that can be controlled through the WebUI. + The device name will have to be changed to fit your USB2Dynamixel. The name can be found by looking + in the /dev directory for something similar to the device name in the example below. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/RobotModules/SSC32/Examples/SSC32_test.ikc b/Source/Modules/RobotModules/SSC32/Examples/SSC32_test.ikc new file mode 100755 index 000000000..db6735c8a --- /dev/null +++ b/Source/Modules/RobotModules/SSC32/Examples/SSC32_test.ikc @@ -0,0 +1,85 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/RobotModules/SSC32/Examples/data.txt b/Source/Modules/RobotModules/SSC32/Examples/data.txt new file mode 100755 index 000000000..c4f6cf53c --- /dev/null +++ b/Source/Modules/RobotModules/SSC32/Examples/data.txt @@ -0,0 +1,12 @@ +# Movement data +OUTPUT/5 + +0.5 0.5 0.5 0.5 0.5 + +0.5 0.5 0.7 0.5 0.5 + +0 0 0 0.5 0.5 + +1.0 1.0 1.0 0.5 0.5 + +1.0 1.0 1.0 1.0 0.0 \ No newline at end of file diff --git a/Source/Modules/RobotModules/SSC32/SSC32.cc b/Source/Modules/RobotModules/SSC32/SSC32.cc new file mode 100755 index 000000000..b295cb20d --- /dev/null +++ b/Source/Modules/RobotModules/SSC32/SSC32.cc @@ -0,0 +1,181 @@ +// +// SSC32.cc This file is a part of the IKAROS project +// Driver for the SSC-32 servo controller from Lynxmotion +// +// Copyright (C) 20072010 Christian Balkenius, Magnus Johnsson +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: 2007-08-27 +// + + +#include "SSC32.h" + +using namespace ikaros; + +Module * SSC32::Create(Parameter * p) +{ + return new SSC32(p); +} + + + +SSC32::SSC32(Parameter * p): + Module(p) +{ + no_of_servos = GetIntValue("no_of_servos", unknown_size); // Default to automatic size setting + + AddInput("INPUT"); + AddOutput("OUTPUT", no_of_servos); + + max_speed = GetIntValue("maxspeed", 100); + timebase = GetIntValue("timebase", 1000); + min_position = GetArray("min", 32); + max_position = GetArray("max", 32); + home = GetArray("home", 32); + device = GetValue("device"); + + if(!device) + { + Notify(msg_fatal_error, "Device not given - will not be able to communicate with SSC-32.\n"); + return; + } +} + + + +void +SSC32::SetSizes() +{ + if(GetOutputSize("OUTPUT") != unknown_size) + return; + + SetOutputSize("OUTPUT", GetInputSize("INPUT")); +} + + + +void +SSC32::SendPositions(float * pos, int t) +{ + bool debug = false; + if(debug) printf("Sending [%d]: ", size); + for(int i=0; i max_position[i]) + v = max_position[i]; + else if(v < min_position[i]) + v = min_position[i]; + if(debug) printf("%5d", int(v)); + fprintf(ssc, "#%d P%d S%d", i, int(v), max_speed); + } + + if(t > 0) + fprintf(ssc, "T%d\r", t); + else + fprintf(ssc, "\r"); + + if(debug) printf(" T%d\r", t); + fflush(ssc); + + if(debug) printf("\n"); + if(debug) fflush(NULL); +} + + + +void +SSC32::ReceivePositions() +{ + unsigned char positions[32]; + + // Send request + + for(int i=0; i + + + + + Driver for the SSC-32 RC servo controller by Lynxmotion. + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + SSC32.h + SSC32.cc + SSC32.ikc + + + + diff --git a/Source/Modules/UtilityModules/Abs/Abs.cc b/Source/Modules/UtilityModules/Abs/Abs.cc new file mode 100755 index 000000000..fdb793066 --- /dev/null +++ b/Source/Modules/UtilityModules/Abs/Abs.cc @@ -0,0 +1,44 @@ +// +// Abs.cc This file is a part of the IKAROS project +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Abs.h" + +using namespace ikaros; + +void +Abs::Init() +{ + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +Abs::Tick() +{ + abs(output, input, size_x, size_y); +} + + diff --git a/Source/Modules/UtilityModules/Abs/Abs.h b/Source/Modules/UtilityModules/Abs/Abs.h new file mode 100755 index 000000000..de578be97 --- /dev/null +++ b/Source/Modules/UtilityModules/Abs/Abs.h @@ -0,0 +1,47 @@ +// +// Abs.h This file is a part of the IKAROS project +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef Abs_ +#define Abs_ + +#include "IKAROS.h" + + +class Abs: public Module +{ +public: + + Abs(Parameter * p) : Module(p) {} + virtual ~Abs() {} + + static Module * Create(Parameter * p) { return new Abs(p); } + + void Init(); + void Tick(); + + int size_x; + int size_y; + + float ** input; + float ** output; +}; + + +#endif diff --git a/Source/Modules/UtilityModules/Abs/Abs.ikc b/Source/Modules/UtilityModules/Abs/Abs.ikc new file mode 100755 index 000000000..dd9475942 --- /dev/null +++ b/Source/Modules/UtilityModules/Abs/Abs.ikc @@ -0,0 +1,46 @@ + + + + + + Module used to rectify its input. The output is calculated as, + output(t) = | input(t) | + The module calculates the absolute value of each input component. + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Abs.h + Abs.cc + Abs.ikc + + + diff --git a/Source/Modules/UtilityModules/Abs/Examples/Abs_test.ikc b/Source/Modules/UtilityModules/Abs/Examples/Abs_test.ikc new file mode 100755 index 000000000..b9a0f792a --- /dev/null +++ b/Source/Modules/UtilityModules/Abs/Examples/Abs_test.ikc @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Add/Add.cc b/Source/Modules/UtilityModules/Add/Add.cc new file mode 100755 index 000000000..47efdcfec --- /dev/null +++ b/Source/Modules/UtilityModules/Add/Add.cc @@ -0,0 +1,46 @@ +// +// Add.cc This file is a part of the IKAROS project +// Implements a modules that adds its two inputs +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// Updated: 2008-12-29 with new IKC default functions + + +#include "Add.h" + +using namespace ikaros; + +void +Add::Init() +{ + input1 = GetInputArray("INPUT1"); // The input and outputs are treated as arrays internally + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Add::Tick() +{ + add(output, input1, input2, size); +} + + diff --git a/Source/Modules/UtilityModules/Add/Add.h b/Source/Modules/UtilityModules/Add/Add.h new file mode 100755 index 000000000..20142f56e --- /dev/null +++ b/Source/Modules/UtilityModules/Add/Add.h @@ -0,0 +1,46 @@ +// +// Add.h This file is a part of the IKAROS project +// Implements a modules that adds its two inputs +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef ADD +#define ADD + +#include "IKAROS.h" + +class Add: public Module +{ +public: + static Module * Create(Parameter * p) { return new Add(p); } + + float * input1; + float * input2; + float * output; + int size; + + Add(Parameter * p) : Module(p) {}; + virtual ~Add() {}; + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Add/Add.ikc b/Source/Modules/UtilityModules/Add/Add.ikc new file mode 100755 index 000000000..2a2d498d9 --- /dev/null +++ b/Source/Modules/UtilityModules/Add/Add.ikc @@ -0,0 +1,49 @@ + + + + + + Module that sums its two inputs element by element, + which can be one or two dimensional. + Both inputs must have the same size. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Add.h + Add.cc + Add.ikc + + + + diff --git a/Source/Modules/UtilityModules/Add/Examples/Add_test.ikc b/Source/Modules/UtilityModules/Add/Examples/Add_test.ikc new file mode 100755 index 000000000..9da86205d --- /dev/null +++ b/Source/Modules/UtilityModules/Add/Examples/Add_test.ikc @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Arbiter/Arbiter.cc b/Source/Modules/UtilityModules/Arbiter/Arbiter.cc new file mode 100755 index 000000000..7987e606f --- /dev/null +++ b/Source/Modules/UtilityModules/Arbiter/Arbiter.cc @@ -0,0 +1,58 @@ +// +// Arbiter.cc This file is a part of the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "Arbiter.h" + +using namespace ikaros; + + +void +Arbiter::Init() +{ + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + value1 = GetInputArray("VALUE1", false); + value2 = GetInputArray("VALUE2", false); + output = GetOutputArray("OUTPUT"); + value = GetOutputArray("VALUE"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Arbiter::Tick() +{ + float v1 = (value1 ? value1[0] : norm(input1, size)); + float v2 = (value2 ? value2[0] : norm(input2, size)); + + if (v1 >= v2) + { + copy_array(output, input1, size); + value[0] = v1; + } + else + { + copy_array(output, input2, size); + value[0] = v2; + } +} + + diff --git a/Source/Modules/UtilityModules/Arbiter/Arbiter.h b/Source/Modules/UtilityModules/Arbiter/Arbiter.h new file mode 100755 index 000000000..400b32fe5 --- /dev/null +++ b/Source/Modules/UtilityModules/Arbiter/Arbiter.h @@ -0,0 +1,50 @@ +// +// Arbiter.h This file is a part of the IKAROS project +// +// Copyright (C) 2006 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// input: 2 x (vector weight) +// output: (vector with max weight (output) and the max veight (value)) +// allows cascading + +#ifndef ARBITER +#define ARBITER + +#include "IKAROS.h" + +class Arbiter: public Module +{ +public: + static Module * Create(Parameter * p) { return new Arbiter(p); } + + float * input1; + float * input2; + float * value1; + float * value2; + float * output; + float * value; + int size; + + Arbiter(Parameter * p) : Module(p) {}; + virtual ~Arbiter() {}; + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Arbiter/Arbiter.ikc b/Source/Modules/UtilityModules/Arbiter/Arbiter.ikc new file mode 100755 index 000000000..a1b116326 --- /dev/null +++ b/Source/Modules/UtilityModules/Arbiter/Arbiter.ikc @@ -0,0 +1,61 @@ + + + + + + Module that selects between its two inputs based on the values in the value inputs. + The output is a copy of the input with the highest corresponding value input. + The inputs can be one or two dimensional. Both inputs must have the same size. + When the values are equal, INPUT1 is selected. If the value inputs are not connected, + the euclidean norm of the corresponding input is used instead. + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Arbiter.h + Arbiter.cc + Arbiter.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Arbiter/Examples/Arbiter_test.ikc b/Source/Modules/UtilityModules/Arbiter/Examples/Arbiter_test.ikc new file mode 100755 index 000000000..c1ba72735 --- /dev/null +++ b/Source/Modules/UtilityModules/Arbiter/Examples/Arbiter_test.ikc @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/ArgMax/ArgMax.cc b/Source/Modules/UtilityModules/ArgMax/ArgMax.cc new file mode 100755 index 000000000..36161e2a8 --- /dev/null +++ b/Source/Modules/UtilityModules/ArgMax/ArgMax.cc @@ -0,0 +1,50 @@ +// +// ArgMax.cc This file is a part of the IKAROS project +// A module that finds the maximum element of an array or matrix +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "ArgMax.h" + +using namespace ikaros; + +void +ArgMax::Init() +{ + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputArray("OUTPUT"); +} + + + +void +ArgMax::Tick() +{ + int x = 0; + int y = 0; + arg_max(x, y, input, size_x, size_y); + + output[0] = float(x); + output[1] = float(y); +} + + diff --git a/Source/Modules/UtilityModules/ArgMax/ArgMax.h b/Source/Modules/UtilityModules/ArgMax/ArgMax.h new file mode 100755 index 000000000..5c4a18244 --- /dev/null +++ b/Source/Modules/UtilityModules/ArgMax/ArgMax.h @@ -0,0 +1,50 @@ +// +// ArgMax.h This file is a part of the IKAROS project +// A module that sets finds the position of the maximum element in a matrix +// +// Copyright (C) 2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef ArgMax_ +#define ArgMax_ + +#include "IKAROS.h" + + + +class ArgMax: public Module +{ +public: + + ArgMax(Parameter * p) : Module(p) {} + virtual ~ArgMax() {} + + static Module * Create(Parameter * p) { return new ArgMax(p); } + + void Init(); + void Tick(); + + int size_x; + int size_y; + + float ** input; + float * output; +}; + + +#endif + diff --git a/Source/Modules/UtilityModules/ArgMax/ArgMax.ikc b/Source/Modules/UtilityModules/ArgMax/ArgMax.ikc new file mode 100755 index 000000000..b4c2c02dd --- /dev/null +++ b/Source/Modules/UtilityModules/ArgMax/ArgMax.ikc @@ -0,0 +1,45 @@ + + + + + + A module that finds the maximum element of an array or matrix. + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + ArgMax.h + ArgMax.cc + ArgMax.ikc + + + + diff --git a/Source/Modules/UtilityModules/ArgMax/Examples/ArgMax_test.ikc b/Source/Modules/UtilityModules/ArgMax/Examples/ArgMax_test.ikc new file mode 100755 index 000000000..b55ba390d --- /dev/null +++ b/Source/Modules/UtilityModules/ArgMax/Examples/ArgMax_test.ikc @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Average/Average.cc b/Source/Modules/UtilityModules/Average/Average.cc new file mode 100755 index 000000000..3ab33ca33 --- /dev/null +++ b/Source/Modules/UtilityModules/Average/Average.cc @@ -0,0 +1,54 @@ +// +// Average.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Average.h" + +using namespace ikaros; + +void +Average::Init() +{ + size = GetInputSize("INPUT"); + input = GetInputArray("INPUT"); + sum = create_array(size); + output = GetOutputArray("OUTPUT"); + tick_count = 0; +} + + + +Average::~Average() +{ + destroy_array(sum); +} + + + +void +Average::Tick() +{ + tick_count++; + add(sum, input, size); + multiply(output, sum, 1.0/float(tick_count), size); +} + + diff --git a/Source/Modules/UtilityModules/Average/Average.h b/Source/Modules/UtilityModules/Average/Average.h new file mode 100755 index 000000000..b6d6ccec0 --- /dev/null +++ b/Source/Modules/UtilityModules/Average/Average.h @@ -0,0 +1,47 @@ +// +// Average.h This file is a part of the IKAROS project +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef AVERAGE +#define AVERAGE + +#include "IKAROS.h" + + +class Average: public Module +{ +public: + static Module * Create(Parameter * p) { return new Average(p); } + + int size; + float * input; + float * sum; + float * output; + long tick_count; + + Average(Parameter * p) : Module(p) {} + virtual ~Average(); + + void Init(); + void Tick(); + +}; + + +#endif diff --git a/Source/Modules/UtilityModules/Average/Average.ikc b/Source/Modules/UtilityModules/Average/Average.ikc new file mode 100755 index 000000000..7bb83ab36 --- /dev/null +++ b/Source/Modules/UtilityModules/Average/Average.ikc @@ -0,0 +1,49 @@ + + + + + + Module used to calculate the average of its input over time. + + + + + + + + + + + + + + + + + If run for very long numerical problems are likely to occur when + the number of ticks or the sum of all inputs becomes too large. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Average.h + Average.cc + Average.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Average/Examples/Average_test.ikc b/Source/Modules/UtilityModules/Average/Examples/Average_test.ikc new file mode 100755 index 000000000..9af6dcd58 --- /dev/null +++ b/Source/Modules/UtilityModules/Average/Examples/Average_test.ikc @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Constant/Constant.cc b/Source/Modules/UtilityModules/Constant/Constant.cc new file mode 100755 index 000000000..6b2f41934 --- /dev/null +++ b/Source/Modules/UtilityModules/Constant/Constant.cc @@ -0,0 +1,46 @@ +// +// Constant.cc This file is a part of the IKAROS project +// Implements a modules that outputs a constant array +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + + +#include "Constant.h" + + +void +Constant::Init() +{ + output = GetOutputArray("OUTPUT"); + outputsize = GetOutputSize("OUTPUT"); // Use one-dimensional representation internally + + Bind(data, outputsize, "data"); +} + + + +void +Constant::Tick() +{ + copy_array(output, data, outputsize); // Copy every iteration if parameter changed through the binding +} + + diff --git a/Source/Modules/UtilityModules/Constant/Constant.h b/Source/Modules/UtilityModules/Constant/Constant.h new file mode 100755 index 000000000..547685461 --- /dev/null +++ b/Source/Modules/UtilityModules/Constant/Constant.h @@ -0,0 +1,45 @@ +// +// Constant.h This file is a part of the IKAROS project +// Implements a modules that outputs a constant array +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef CONSTANT +#define CONSTANT + +#include "IKAROS.h" + +class Constant: public Module +{ +public: + static Module * Create(Parameter * p) { return new Constant(p); } + + float * data; + float * output; + int outputsize; + + Constant(Parameter * p) : Module(p) {} + virtual ~Constant() {} + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Constant/Constant.ikc b/Source/Modules/UtilityModules/Constant/Constant.ikc new file mode 100755 index 000000000..5d30f7a9e --- /dev/null +++ b/Source/Modules/UtilityModules/Constant/Constant.ikc @@ -0,0 +1,57 @@ + + + + + + Module that outputs a constant array or matrix each time step. + It can be one or two dimensional depending on whether outputsize_x and + outputsize_y or only outputsize is used in the ikc definition. + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Constant.h + Constant.cc + Constant.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Constant/Examples/Constant_test.ikc b/Source/Modules/UtilityModules/Constant/Examples/Constant_test.ikc new file mode 100755 index 000000000..d0f013c77 --- /dev/null +++ b/Source/Modules/UtilityModules/Constant/Examples/Constant_test.ikc @@ -0,0 +1,35 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Counter/Counter.cc b/Source/Modules/UtilityModules/Counter/Counter.cc new file mode 100755 index 000000000..66da946b7 --- /dev/null +++ b/Source/Modules/UtilityModules/Counter/Counter.cc @@ -0,0 +1,83 @@ +// +// Counter.cc This file is a part of the IKAROS project +// A module that counts how many time its input is above a threshold +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Counter.h" + +void +Counter::Init() +{ + mode = GetIntValueFromList("mode"); + threshold = GetFloatValue("threshold"); + + reset_interval = GetIntValue("reset_interval"); + print_interval = GetIntValue("print_interval"); + count_interval = GetIntValue("count_interval"); + + interval_counter = 0; + integrator = 0; + + size = GetInputSize("INPUT"); + input = GetInputArray("INPUT"); + count = GetOutputArray("COUNT"); + percent = GetOutputArray("PERCENT"); + + tick_counter = 0; + counter = 0; +} + + + +void +Counter::Tick() +{ + for (int i=0; i threshold) + counter++; + + count[0] = float(counter); + percent[0] = float(counter)/float(sample_counter); + + if (tick_counter % print_interval == 0) + Notify(msg_print, "COUNTER: %7ld %7ld %7.2f%%\n", tick_counter, counter, 100*percent[0]); + + if (sample_counter >= reset_interval) + { + sample_counter = 0; + counter = 0; + } + + interval_counter = 0; + integrator = 0; +} + + diff --git a/Source/Modules/UtilityModules/Counter/Counter.h b/Source/Modules/UtilityModules/Counter/Counter.h new file mode 100755 index 000000000..18da35b88 --- /dev/null +++ b/Source/Modules/UtilityModules/Counter/Counter.h @@ -0,0 +1,60 @@ +// +// Counter.h This file is a part of the IKAROS project +// A module that counts how many time its input is above a threshold +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef COUNTER +#define COUNTER + +#include "IKAROS.h" + + +class Counter: public Module +{ +public: + static Module * Create(Parameter * p) { return new Counter(p); } + + Counter(Parameter * p) : Module(p) {} + virtual ~Counter() {} + + void Init(); + void Tick(); + + int mode; // count each (0), count any (1) + float threshold; + int reset_interval; + int print_interval; + int count_interval; + int interval_counter; + + int size; + + long int counter; + long int sample_counter; + long int tick_counter; + + float integrator; + + float * input; + float * count; + float * percent; +}; + + +#endif diff --git a/Source/Modules/UtilityModules/Counter/Counter.ikc b/Source/Modules/UtilityModules/Counter/Counter.ikc new file mode 100755 index 000000000..0eb5b8427 --- /dev/null +++ b/Source/Modules/UtilityModules/Counter/Counter.ikc @@ -0,0 +1,75 @@ + + + + + + Module used to calculate statistics from signals in a simulation. + It counts how many times its input is above a threshold. It also + outputs the percent of the ticks the input has been above the threshold. + + In "component" mode, each input component is counted individually. + In "any" mode, any component above the threshold is counted. In "component" + mode, the outputs have the same size as the input, while in "any" mode, + the output has size 1. + + The counter can be set up to periodically reset the counter and/or print the count. + It is also possible to specify how often the counter checks its input. + + NOTE: Only "any" mode has been implemented. + + + + + + + + + + + + + + + + + + + Only runs in "any" mode at the moment. + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Counter.h + Counter.cc + Counter.ikc + + + + diff --git a/Source/Modules/UtilityModules/Counter/Examples/Counter_test.ikc b/Source/Modules/UtilityModules/Counter/Examples/Counter_test.ikc new file mode 100755 index 000000000..f4b99e01f --- /dev/null +++ b/Source/Modules/UtilityModules/Counter/Examples/Counter_test.ikc @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Delay/Delay.cc b/Source/Modules/UtilityModules/Delay/Delay.cc new file mode 100755 index 000000000..1dc00182b --- /dev/null +++ b/Source/Modules/UtilityModules/Delay/Delay.cc @@ -0,0 +1,83 @@ +// Delay.cc This file is a part of the IKAROS project +// A generic Delay module, used to properly sync inputs from different sources +// This module is not necessary now that connections can have delays +// +// Copyright (C) 2002 Jan Moren +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2002-11-14 +// +// 2003-01-30 Minor changes Christian Balkenius +// 2007-02-01 Minor changes Christian Balkenius + +#include "Delay.h" + +#include + +void Delay::CopyArray(float *from, float *to) +{ + for (int i=0; i + + + + + Module used to delay its input a number of ticks. The delay is + set by the attribute delay. This module is mainly included for + compatibility with earlier versions of Ikaros. Starting with + version 0.7.8 the delay attribute (e.g. delay = "2") can be used + directly in the connection declarations in the ikc files. + + + + + + + + + + + + + + + Jan Morén + jan.moren@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/People/Jan.Moren/ + + + + Delay.h + Delay.cc + Delay.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Differentiator/Differentiator.ikc b/Source/Modules/UtilityModules/Differentiator/Differentiator.ikc new file mode 100755 index 000000000..63bcf343e --- /dev/null +++ b/Source/Modules/UtilityModules/Differentiator/Differentiator.ikc @@ -0,0 +1,42 @@ + + + + + + Module used to differentiate its input over time. + The output is calculated as, + output(t) = input(t) - input(t-1) + The module retains the size of the input even if it is a matrix. + The module can thus be used to differentiate images. + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Differentiator.h + Differentiator.cc + Differentiator.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Distance/Distance.cc b/Source/Modules/UtilityModules/Distance/Distance.cc new file mode 100755 index 000000000..5fcaa1e07 --- /dev/null +++ b/Source/Modules/UtilityModules/Distance/Distance.cc @@ -0,0 +1,59 @@ +// +// Distance.cc This file is a part of the IKAROS project +// Implements a modules that calculates the distance between its two inputs +// +// Copyright (C) 2005 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2005-04-13 +// + + +#include "Distance.h" + +using namespace ikaros; + +void +Distance::Init() +{ + type = GetIntValueFromList("type"); + + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + + int size1 = GetInputSize("INPUT1"); + int size2 = GetInputSize("INPUT2"); + + if (size1 != size2) + Notify(msg_warning, "Module \"%s\" (Distance): The input sizes should normally be equal: INPUT1 = %d, INPUT2 = %d\n", GetName(), size1, size2); + + size = (size1 < size2 ? size1 : size2); +} + + + +void +Distance::Tick() +{ + if(type == 0) + output[0] = dist(input1, input2, size); + + else if(type==1) + output[0] = dist1(input1, input2, size); +} + + diff --git a/Source/Modules/UtilityModules/Distance/Distance.h b/Source/Modules/UtilityModules/Distance/Distance.h new file mode 100755 index 000000000..1ff982815 --- /dev/null +++ b/Source/Modules/UtilityModules/Distance/Distance.h @@ -0,0 +1,47 @@ +// +// Distance.h This file is a part of the IKAROS project +// Implements a modules that calculates the euclidean distance between its two inputs +// +// Copyright (C) 2005 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2005-04-13 +// + +#ifndef DISTANCE +#define DISTANCE + +#include "IKAROS.h" + +class Distance: public Module +{ +public: + static Module * Create(Parameter * p) {return new Distance(p); } + + int type; + float * input1; + float * input2; + float * output; + int size; + + Distance(Parameter * p) : Module(p) {} + virtual ~Distance() {} + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Distance/Distance.ikc b/Source/Modules/UtilityModules/Distance/Distance.ikc new file mode 100755 index 000000000..e7ef7502e --- /dev/null +++ b/Source/Modules/UtilityModules/Distance/Distance.ikc @@ -0,0 +1,49 @@ + + + + + + Module that calculates the distance + between its two input vectors or matrices using the euclidean or citiblock norm. + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Distance.h + Distance.cc + Distance.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Distance/Examples/Distance_test.ikc b/Source/Modules/UtilityModules/Distance/Examples/Distance_test.ikc new file mode 100755 index 000000000..38d4d552f --- /dev/null +++ b/Source/Modules/UtilityModules/Distance/Examples/Distance_test.ikc @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Divide/Divide.cc b/Source/Modules/UtilityModules/Divide/Divide.cc new file mode 100755 index 000000000..3ccf9f3b4 --- /dev/null +++ b/Source/Modules/UtilityModules/Divide/Divide.cc @@ -0,0 +1,66 @@ +// +// Divide.cc This file is a part of the IKAROS project +// Implements a modules that divides its first input with the second +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#include "Divide.h" + +using namespace ikaros; + +void +Divide::Init() +{ + // The test of equal input size must be done here and not in SetSize + // to allow an ouput to be connected to an input of the same module + + int size1x = GetInputSizeX("INPUT1"); + int size1y = GetInputSizeY("INPUT1"); + + int size2x = GetInputSizeX("INPUT2"); + int size2y = GetInputSizeY("INPUT2"); + + if (size1x != size2x || size1y != size2y) + { + Notify(msg_fatal_error, "Module \"%s\" (Divide): The input sizes must be equal: INPUT1 = [%d, %d] INPUT2 = [%d, %d]\n", GetName(), size1x, size1y, size2x, size2y); + return; + } + + // The input and outputs are treated as arrays internally + + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Divide::Tick() +{ + for (int i=0; i< size; i++) + if (input2[i] != 0) + output[i] = input1[i] / input2[i]; + else + output[i] = 0; +} + + diff --git a/Source/Modules/UtilityModules/Divide/Divide.h b/Source/Modules/UtilityModules/Divide/Divide.h new file mode 100755 index 000000000..ba24be47a --- /dev/null +++ b/Source/Modules/UtilityModules/Divide/Divide.h @@ -0,0 +1,46 @@ +// +// Divide.h This file is a part of the IKAROS project +// Implements a modules that divides its first input with the second +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef DIVIDE +#define DIVIDE + +#include "IKAROS.h" + +class Divide: public Module +{ +public: + static Module * Create(Parameter * p) {return new Divide(p); } + + float * input1; + float * input2; + float * output; + int size; + + Divide(Parameter * p) : Module(p) {} + virtual ~Divide() {} + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Divide/Divide.ikc b/Source/Modules/UtilityModules/Divide/Divide.ikc new file mode 100755 index 000000000..b0cf69800 --- /dev/null +++ b/Source/Modules/UtilityModules/Divide/Divide.ikc @@ -0,0 +1,48 @@ + + + + + + Module that divides its two inputs component by component. + Both inputs must have the same size. The division is safe + when input2 = 0. In this case the result will be set to 0. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Divide.h + Divide.cc + Divide.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Divide/Examples/Divide_test.ikc b/Source/Modules/UtilityModules/Divide/Examples/Divide_test.ikc new file mode 100755 index 000000000..5cf250770 --- /dev/null +++ b/Source/Modules/UtilityModules/Divide/Examples/Divide_test.ikc @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/FunctionGenerator/Examples/FunctionGenerator_test.ikc b/Source/Modules/UtilityModules/FunctionGenerator/Examples/FunctionGenerator_test.ikc new file mode 100755 index 000000000..cbfa7601f --- /dev/null +++ b/Source/Modules/UtilityModules/FunctionGenerator/Examples/FunctionGenerator_test.ikc @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/FunctionGenerator/FunctionGenerator.cc b/Source/Modules/UtilityModules/FunctionGenerator/FunctionGenerator.cc new file mode 100755 index 000000000..cdbf802ab --- /dev/null +++ b/Source/Modules/UtilityModules/FunctionGenerator/FunctionGenerator.cc @@ -0,0 +1,128 @@ +// +// FunctionGenerator.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2005 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2005-02-15 +// + + + +#include "FunctionGenerator.h" + +using namespace ikaros; + +void +FunctionGenerator::Init() +{ + Bind(type, "type"); + + Bind(offset, "offset"); + Bind(amplitude, "amplitude"); + Bind(frequency, "frequency"); + Bind(shift, "shift"); + Bind(duty, "duty"); + + Bind(basetime, "basetime"); + Bind(tickduty, "tickduty"); + + output = GetOutputArray("OUTPUT"); + + t = 0; +} + + + +// Functions + +static float +triangle(float t) +{ + float v = 2*(t/(2*pi)-trunc(t/(2*pi))); + if (v<1.0) + return v; + else + return 2-v; +} + + + +static float +ramp(float t) +{ + float v = t/(2*pi)-trunc(t/(2*pi)); + return v; +} + + + +static float +square(float t, float d) +{ + float v = t/(2*pi)-trunc(t/(2*pi)); + if (v + + + + + Module that produces a function of time as its output. + ramp: get an inverse ramp by setting offset=1 and amplitude=-1. + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + FunctionGenerator.h + FunctionGenerator.cc + FunctionGenerator.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Gate/Examples/Gate_test.ikc b/Source/Modules/UtilityModules/Gate/Examples/Gate_test.ikc new file mode 100755 index 000000000..8cd46b627 --- /dev/null +++ b/Source/Modules/UtilityModules/Gate/Examples/Gate_test.ikc @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Gate/Gate.cc b/Source/Modules/UtilityModules/Gate/Gate.cc new file mode 100755 index 000000000..46bb38f8c --- /dev/null +++ b/Source/Modules/UtilityModules/Gate/Gate.cc @@ -0,0 +1,58 @@ +// +// Gate.cc This file is a part of the IKAROS project +// A module can be used to disconnect modules using a flag +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Gate.h" + +void +Gate::Init() +{ + is_open = GetBoolValue("open", 1); + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +Gate::Tick() +{ + switch (int(is_open)) + { + case true: // OPEN + for (int i=0; i + + + + + Module that lets its input through to the output when the attribute + "open" is set to "true", otherwise it sets all its outputs to 0. + + + + + + + + + + + + + Should have an input that opens and closes the gate. + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Gate.h + Gate.cc + Gate.ikc + + + diff --git a/Source/Modules/UtilityModules/Integrator/Examples/Integrator_test.ikc b/Source/Modules/UtilityModules/Integrator/Examples/Integrator_test.ikc new file mode 100755 index 000000000..1f6773b1c --- /dev/null +++ b/Source/Modules/UtilityModules/Integrator/Examples/Integrator_test.ikc @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Integrator/Integrator.cc b/Source/Modules/UtilityModules/Integrator/Integrator.cc new file mode 100755 index 000000000..408b9cc1a --- /dev/null +++ b/Source/Modules/UtilityModules/Integrator/Integrator.cc @@ -0,0 +1,60 @@ +// +// Integrator.cc This file is a part of the IKAROS project +// A module that integrates its input over time +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Integrator.h" + +void +Integrator::Init() +{ + alpha = GetFloatValue("alpha"); + beta = GetFloatValue("beta"); + + minimum = GetFloatValue("min"); + maximum = GetFloatValue("max"); + + usemin = GetValue("min") != NULL; + usemax = GetValue("max") != NULL; + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +Integrator::Tick() +{ + for (int i=0; i maximum) + output[j][i] = maximum; + } +} + + diff --git a/Source/Modules/UtilityModules/Integrator/Integrator.h b/Source/Modules/UtilityModules/Integrator/Integrator.h new file mode 100755 index 000000000..f5ac14f57 --- /dev/null +++ b/Source/Modules/UtilityModules/Integrator/Integrator.h @@ -0,0 +1,56 @@ +// +// Integrator.h This file is a part of the IKAROS project +// A module that integrates its input over time +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef INTEGRATOR +#define INTEGRATOR + +#include "IKAROS.h" + + +class Integrator: public Module +{ +public: + static Module * Create(Parameter * p) { return new Integrator(p); } + + Integrator(Parameter * p) : Module(p) {} + virtual ~Integrator() {} + + void Init(); + void Tick(); + + int size_x; + int size_y; + + float alpha; + float beta; + + float minimum; + float maximum; + + bool usemax; + bool usemin; + + float ** input; + float ** output; +}; + + +#endif diff --git a/Source/Modules/UtilityModules/Integrator/Integrator.ikc b/Source/Modules/UtilityModules/Integrator/Integrator.ikc new file mode 100755 index 000000000..5ef02440d --- /dev/null +++ b/Source/Modules/UtilityModules/Integrator/Integrator.ikc @@ -0,0 +1,59 @@ + + + + + + Module used to integrate its input over time. + The output is calculated as, + output(t) = alpha * output(t) + beta * input(t). + Depending on the constants alpha and beta, + the module can be used as leaky integrator or an accumulator. + If they are set in the XML-file the constants minimum and + maximum set the allowed range of the output. It will be clipped + if it is outside the range. + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Integrator.h + Integrator.cc + Integrator.ikc + + + + diff --git a/Source/Modules/UtilityModules/MatrixMultiply/Examples/MatrixMultiply_test.ikc b/Source/Modules/UtilityModules/MatrixMultiply/Examples/MatrixMultiply_test.ikc new file mode 100755 index 000000000..2e25325be --- /dev/null +++ b/Source/Modules/UtilityModules/MatrixMultiply/Examples/MatrixMultiply_test.ikc @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.cc b/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.cc new file mode 100755 index 000000000..fb718892f --- /dev/null +++ b/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.cc @@ -0,0 +1,71 @@ +// +// MatrixMultiply.cc This file is a part of the IKAROS project +// Implements a modules that calculates the matrix product of two inputs +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "MatrixMultiply.h" + +using namespace ikaros; + +void +MatrixMultiply::Init() +{ + input1 = GetInputMatrix("INPUT1"); + input2 = GetInputMatrix("INPUT2"); + output = GetOutputMatrix("OUTPUT"); + + size1_x = GetInputSizeX("INPUT1"); + size1_y = GetInputSizeY("INPUT1"); + size2_x = GetInputSizeX("INPUT2"); + size2_y = GetInputSizeY("INPUT2"); +} + + + +void MatrixMultiply::SetSizes() +{ + int sz1_x = GetInputSizeX("INPUT1"); + int sz1_y = GetInputSizeY("INPUT1"); + int sz2_x = GetInputSizeX("INPUT2"); + int sz2_y = GetInputSizeY("INPUT2"); + + if (sz1_x == unknown_size || sz1_y == unknown_size || sz2_x == unknown_size || sz2_y == unknown_size) + return; + + if (sz1_x != sz2_y) + { + Notify(msg_fatal_error, "MatrixMultiply: The sizes of the inputs are not compatible: INPUT1 = [%d, %d] INPUT2 = [%d, %d]\n", sz1_x, sz1_y, sz2_x, sz2_y); + return; + } + + SetOutputSize("OUTPUT", sz2_x, sz1_y); +} + + + +void +MatrixMultiply::Tick() +{ + multiply(output, input1, input2, size2_x, size1_y, size1_x); +} + + diff --git a/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.h b/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.h new file mode 100755 index 000000000..89a4f09f3 --- /dev/null +++ b/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.h @@ -0,0 +1,50 @@ +// +// MatrixMultiply.h This file is a part of the IKAROS project +// Implements a modules that calculates the matrix product of two inputs +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-11-15 +// + +#ifndef MATRIXMULTIPLY +#define MATRIXMULTIPLY + +#include "IKAROS.h" + +class MatrixMultiply: public Module +{ +public: + float ** input1; + float ** input2; + float ** output; + int size1_x; + int size1_y; + int size2_x; + int size2_y; + + MatrixMultiply(Parameter * p) : Module(p) {} + virtual ~MatrixMultiply() {} + + static Module * Create(Parameter * p) { return new MatrixMultiply(p); } + + void SetSizes(); + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.ikc b/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.ikc new file mode 100755 index 000000000..7fb592626 --- /dev/null +++ b/Source/Modules/UtilityModules/MatrixMultiply/MatrixMultiply.ikc @@ -0,0 +1,40 @@ + + + + + + Module that calculates the matrix product of its two inputs. + The matrix product is a matrix of size row1 x col2, where + row1 x col1 is the size of the first input and row2 x col2 is + the size of the second input. The usual rules for matrix + multiplications applies, i. e., col1 = row2 (Note that column = x and row = y). + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + MatrixMultiply.h + MatrixMultiply.cc + MatrixMultiply.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Max/Examples/Max_test.ikc b/Source/Modules/UtilityModules/Max/Examples/Max_test.ikc new file mode 100755 index 000000000..4818450ac --- /dev/null +++ b/Source/Modules/UtilityModules/Max/Examples/Max_test.ikc @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Max/Max.cc b/Source/Modules/UtilityModules/Max/Max.cc new file mode 100755 index 000000000..d9023b423 --- /dev/null +++ b/Source/Modules/UtilityModules/Max/Max.cc @@ -0,0 +1,63 @@ +// +// Max.cc This file is a part of the IKAROS project +// Module that Maxs its inputs (and keeps its topology if possible) +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "Max.h" + +using namespace ikaros; + +void +Max::Init() +{ + // The test of equal input size must be done here and not in SetSize + // to allow an ouput to be connected to an input of the same module + + int size1x = GetInputSizeX("INPUT1"); + int size1y = GetInputSizeY("INPUT1"); + + int size2x = GetInputSizeX("INPUT2"); + int size2y = GetInputSizeY("INPUT2"); + + if (size1x != size2x || size1y != size2y) + { + Notify(msg_fatal_error, "Module \"%s\" (Max): The input sizes must be equal: INPUT1 = [%d, %d] INPUT2 = [%d, %d]\n", GetName(), size1x, size1y, size2x, size2y); + return; + } + + // The input and outputs are treated as arrays internally + + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Max::Tick() +{ + max(output, input1, input2, size); +} + + diff --git a/Source/Modules/UtilityModules/Max/Max.h b/Source/Modules/UtilityModules/Max/Max.h new file mode 100755 index 000000000..99cd6cdbc --- /dev/null +++ b/Source/Modules/UtilityModules/Max/Max.h @@ -0,0 +1,46 @@ +// +// Max.h This file is a part of the IKAROS project +// Implements a modules that calcuates the max of each element of its two inputs +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef MAXCLASS +#define MAXCLASS + +#include "IKAROS.h" + +class Max: public Module +{ +public: + float * input1; + float * input2; + float * output; + int size; + + Max(Parameter * p) : Module(p) {} + virtual ~Max() {} + + static Module * Create(Parameter * p) { return new Max(p); } + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Max/Max.ikc b/Source/Modules/UtilityModules/Max/Max.ikc new file mode 100755 index 000000000..b4c912679 --- /dev/null +++ b/Source/Modules/UtilityModules/Max/Max.ikc @@ -0,0 +1,48 @@ + + + + + + Module that calculates the maximum of each elementy of + its two inputs, which can be one or two dimensional. + Both inputs must have the same size. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Max.h + Max.cc + Max.ikc + + + diff --git a/Source/Modules/UtilityModules/Min/Examples/Min_test.ikc b/Source/Modules/UtilityModules/Min/Examples/Min_test.ikc new file mode 100755 index 000000000..15c7ec3d2 --- /dev/null +++ b/Source/Modules/UtilityModules/Min/Examples/Min_test.ikc @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Min/Min.cc b/Source/Modules/UtilityModules/Min/Min.cc new file mode 100755 index 000000000..54173b0c1 --- /dev/null +++ b/Source/Modules/UtilityModules/Min/Min.cc @@ -0,0 +1,62 @@ +// +// Min.cc This file is a part of the IKAROS project +// Module that minimum each element of its two inputs +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "Min.h" + +using namespace ikaros; + +void +Min::Init() +{ + // The test of equal input size must be done here and not in SetSize + // to allow an ouput to be connected to an input of the same module + + int size1x = GetInputSizeX("INPUT1"); + int size1y = GetInputSizeY("INPUT1"); + + int size2x = GetInputSizeX("INPUT2"); + int size2y = GetInputSizeY("INPUT2"); + + if (size1x != size2x || size1y != size2y) + { + Notify(msg_fatal_error, "Module \"%s\" (Min): The input sizes must be equal: INPUT1 = [%d, %d] INPUT2 = [%d, %d]\n", GetName(), size1x, size1y, size2x, size2y); + return; + } + + // The input and outputs are treated as arrays internally + + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + +void +Min::Tick() +{ + min(output, input1, input2, size); +} + + diff --git a/Source/Modules/UtilityModules/Min/Min.h b/Source/Modules/UtilityModules/Min/Min.h new file mode 100755 index 000000000..aad9581ac --- /dev/null +++ b/Source/Modules/UtilityModules/Min/Min.h @@ -0,0 +1,46 @@ +// +// Min.h This file is a part of the IKAROS project +// Module that minimum each element of its two inputs +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef MINCLASS +#define MINCLASS + +#include "IKAROS.h" + +class Min: public Module +{ +public: + float * input1; + float * input2; + float * output; + int size; + + Min(Parameter * p) : Module(p) {} + virtual ~Min() {} + + static Module * Create(Parameter * p){ return new Min(p); } + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Min/Min.ikc b/Source/Modules/UtilityModules/Min/Min.ikc new file mode 100755 index 000000000..30a39ab45 --- /dev/null +++ b/Source/Modules/UtilityModules/Min/Min.ikc @@ -0,0 +1,48 @@ + + + + + + Module that calculates the minimum of each elementy of + its two inputs, which can be one or two dimensional. + Both inputs must have the same size. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Min.h + Min.cc + Min.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Multiply/Examples/Multiply_test.ikc b/Source/Modules/UtilityModules/Multiply/Examples/Multiply_test.ikc new file mode 100755 index 000000000..38f93e5bf --- /dev/null +++ b/Source/Modules/UtilityModules/Multiply/Examples/Multiply_test.ikc @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Multiply/Multiply.cc b/Source/Modules/UtilityModules/Multiply/Multiply.cc new file mode 100755 index 000000000..03394be93 --- /dev/null +++ b/Source/Modules/UtilityModules/Multiply/Multiply.cc @@ -0,0 +1,64 @@ +// +// Multiply.cc This file is a part of the IKAROS project +// Implements a modules that multiplies its two inputs element by element +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "Multiply.h" + +using namespace ikaros; + + +void +Multiply::Init() +{ + // The test of equal input size must be done here and not in SetSize + // to allow an ouput to be connected to an input of the same module + + int size1x = GetInputSizeX("INPUT1"); + int size1y = GetInputSizeY("INPUT1"); + + int size2x = GetInputSizeX("INPUT2"); + int size2y = GetInputSizeY("INPUT2"); + + if (size1x != size2x || size1y != size2y) + { + Notify(msg_fatal_error, "Module \"%s\" (Multiply): The input sizes must be equal: INPUT1 = [%d, %d] INPUT2 = [%d, %d]\n", GetName(), size1x, size1y, size2x, size2y); + return; + } + + // The input and outputs are treated as arrays internally + + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Multiply::Tick() +{ + multiply(output, input1, input2, size); +} + + diff --git a/Source/Modules/UtilityModules/Multiply/Multiply.h b/Source/Modules/UtilityModules/Multiply/Multiply.h new file mode 100755 index 000000000..0930b0ac3 --- /dev/null +++ b/Source/Modules/UtilityModules/Multiply/Multiply.h @@ -0,0 +1,46 @@ +// +// Multiply.h This file is a part of the IKAROS project +// Implements a modules that multiplies its two inputs element by element +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef MULTIPLY +#define MULTIPLY + +#include "IKAROS.h" + +class Multiply: public Module +{ +public: + float * input1; + float * input2; + float * output; + int size; + + Multiply(Parameter * p) : Module(p) {} + virtual ~Multiply() {} + + static Module * Create(Parameter * p) { return new Multiply(p); } + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Multiply/Multiply.ikc b/Source/Modules/UtilityModules/Multiply/Multiply.ikc new file mode 100755 index 000000000..ce6064c6a --- /dev/null +++ b/Source/Modules/UtilityModules/Multiply/Multiply.ikc @@ -0,0 +1,47 @@ + + + + + + Module that multiplies its two inputs component + by component. Both inputs must have the same size. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Multiply.h + Multiply.cc + Multiply.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Noise/Examples/Noise_test.ikc b/Source/Modules/UtilityModules/Noise/Examples/Noise_test.ikc new file mode 100755 index 000000000..d2d85d1ef --- /dev/null +++ b/Source/Modules/UtilityModules/Noise/Examples/Noise_test.ikc @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Noise/Noise.cc b/Source/Modules/UtilityModules/Noise/Noise.cc new file mode 100755 index 000000000..1addef97d --- /dev/null +++ b/Source/Modules/UtilityModules/Noise/Noise.cc @@ -0,0 +1,50 @@ +// +// Noise.cc This file is a part of the IKAROS project +// A module applies a threshold to its input +// +// Copyright (C) 2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Noise.h" + +using namespace ikaros; + +void +Noise::Init() +{ + mean = GetFloatValue("mean", 0.0); + sigma = GetFloatValue("sigma", 1.0); + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +Noise::Tick() +{ + for (int i=0; i + + + + + Module used to add gaussian noise to a signal. + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Noise.h + Noise.cc + Noise.ikc + + + diff --git a/Source/Modules/UtilityModules/Normalize/Examples/Normalize_test.ikc b/Source/Modules/UtilityModules/Normalize/Examples/Normalize_test.ikc new file mode 100755 index 000000000..c120556e4 --- /dev/null +++ b/Source/Modules/UtilityModules/Normalize/Examples/Normalize_test.ikc @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Normalize/Normalize.cc b/Source/Modules/UtilityModules/Normalize/Normalize.cc new file mode 100755 index 000000000..c2a0d16a0 --- /dev/null +++ b/Source/Modules/UtilityModules/Normalize/Normalize.cc @@ -0,0 +1,75 @@ +// +// Normalize.cc This file is a part of the IKAROS project +// Module that normalizes its inputs to the range 0-1 +// +// Copyright (C) 2005 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "Normalize.h" + +using namespace ikaros; + +void +Normalize::Init() +{ + type = GetIntValueFromList("type"); + + input = GetInputArray("INPUT"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Normalize::Tick() +{ + if(type == 0) + { + float minimum; + float maximum; + + minmax(minimum, maximum, input, size); + + if (minimum != maximum) + for (int i=0; i< size; i++) + output[i] = (input[i] - minimum) / (maximum - minimum); + } + + else if(type == 1) + { + copy_array(output, input, size); + normalize(output, size); + } + + else if(type == 2) + { + copy_array(output, input, size); + normalize1(output, size); + } + + else if(type == 3) + { + copy_array(output, input, size); + normalize_max(output, size); + } +} + + diff --git a/Source/Modules/UtilityModules/Normalize/Normalize.h b/Source/Modules/UtilityModules/Normalize/Normalize.h new file mode 100755 index 000000000..f097ba5e1 --- /dev/null +++ b/Source/Modules/UtilityModules/Normalize/Normalize.h @@ -0,0 +1,48 @@ +// +// Normalize.h This file is a part of the IKAROS project +// A modules that Normalizes its input to the range 0-1 +// +// Copyright (C) 2005 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef NORMALIZE +#define NORMALIZE + +#include "IKAROS.h" + +class Normalize: public Module +{ +public: + float * input; + float * output; + int size; + + int type; + + Normalize(Parameter * p) : Module(p) {} + virtual ~Normalize() {} + + static Module * Create(Parameter * p) { return new Normalize(p); } + + void Init(); + void Tick(); +}; + +#endif + diff --git a/Source/Modules/UtilityModules/Normalize/Normalize.ikc b/Source/Modules/UtilityModules/Normalize/Normalize.ikc new file mode 100755 index 000000000..9011ff507 --- /dev/null +++ b/Source/Modules/UtilityModules/Normalize/Normalize.ikc @@ -0,0 +1,48 @@ + + + + + + Module that normalizes its input in various ways. With type 'range' it maps its input onto the interval [0..1] such that the minimal element becomes o and the maximal 1. + With type 'euclidean' the input vector is divided by the eulidean norm and with 'cityblock' the input vector is divided by the cityblock norm of the input. Finally for + the type 'max', each element is divided by the maximal element making it 1. The output will be 0 when the input vector consists of only zeros. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Normalize.h + Normalize.cc + Normalize.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/OuterProduct/Examples/OuterProduct_test.ikc b/Source/Modules/UtilityModules/OuterProduct/Examples/OuterProduct_test.ikc new file mode 100755 index 000000000..ec2341452 --- /dev/null +++ b/Source/Modules/UtilityModules/OuterProduct/Examples/OuterProduct_test.ikc @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/OuterProduct/OuterProduct.cc b/Source/Modules/UtilityModules/OuterProduct/OuterProduct.cc new file mode 100755 index 000000000..b12d657d4 --- /dev/null +++ b/Source/Modules/UtilityModules/OuterProduct/OuterProduct.cc @@ -0,0 +1,60 @@ +// +// OuterProduct.cc This file is a part of the IKAROS project +// Implements a modules that calculates the outer product of two inputs +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "OuterProduct.h" + +using namespace ikaros; + +void +OuterProduct::Init() +{ + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputMatrix("OUTPUT"); + size1 = GetOutputSizeX("OUTPUT"); + size2 = GetOutputSizeY("OUTPUT"); +} + + + +void OuterProduct::SetSizes() +{ + int sz1 = GetInputSize("INPUT1"); + int sz2 = GetInputSize("INPUT2"); + + if (sz1 == unknown_size || sz2 == unknown_size) + return; + + SetOutputSize("OUTPUT", sz1, sz2); +} + + + +void +OuterProduct::Tick() +{ + outer(output, input1, input2, size1, size2); +} + + diff --git a/Source/Modules/UtilityModules/OuterProduct/OuterProduct.h b/Source/Modules/UtilityModules/OuterProduct/OuterProduct.h new file mode 100755 index 000000000..98dd916fc --- /dev/null +++ b/Source/Modules/UtilityModules/OuterProduct/OuterProduct.h @@ -0,0 +1,48 @@ +// +// OuterProduct.h This file is a part of the IKAROS project +// Implements a modules that calculates the outer product of two inputs +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef OUTERPRODUCT +#define OUTERPRODUCT + +#include "IKAROS.h" + +class OuterProduct: public Module +{ +public: + float * input1; + float * input2; + float ** output; + int size1; + int size2; + + OuterProduct(Parameter * p) : Module(p) {} + virtual ~OuterProduct() {} + + static Module * Create(Parameter * p) { return new OuterProduct(p); } + + void SetSizes(); + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/OuterProduct/OuterProduct.ikc b/Source/Modules/UtilityModules/OuterProduct/OuterProduct.ikc new file mode 100755 index 000000000..9541126af --- /dev/null +++ b/Source/Modules/UtilityModules/OuterProduct/OuterProduct.ikc @@ -0,0 +1,58 @@ + + + + + + Module that calculates the outer product of its two input vectors. + The outer product is a matrix of size s1*s2, where s1 is the size + of the first input and s2 is the size of the second input. Each + element in the output matrix is the product of one element i + each of the inputs: + + output[j][i] = input1[j]*input2[i]. + + If the inputs will be flattened before the elements are multiplied + if they are not one-dimensional . The output is thus always a + two-dimensional matrix regardless of the dimensions of the inputs. + + The outer product is also somtimes called the tensor product. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + OuterProduct.h + OuterProduct.cc + OuterProduct.ikc + + + diff --git a/Source/Modules/UtilityModules/Polynomial/Examples/Polynomial_test.ikc b/Source/Modules/UtilityModules/Polynomial/Examples/Polynomial_test.ikc new file mode 100755 index 000000000..32a1f1da4 --- /dev/null +++ b/Source/Modules/UtilityModules/Polynomial/Examples/Polynomial_test.ikc @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Polynomial/Polynomial.cc b/Source/Modules/UtilityModules/Polynomial/Polynomial.cc new file mode 100755 index 000000000..058071be4 --- /dev/null +++ b/Source/Modules/UtilityModules/Polynomial/Polynomial.cc @@ -0,0 +1,63 @@ +// +// Polynomial.cc This file is a part of the IKAROS project +// Implements a modules that calcuates a polynomal function of its input +// +// Copyright (C) 2005 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2005-04-12 +// + + +#include "Polynomial.h" + +#include "ctype.h" + + +void +Polynomial::Init() +{ + // Initialize as one or two dimensional + + order = GetIntValue("order", 1); + c = GetArray("coefficients", order); + + input = GetInputArray("INPUT"); + output = GetOutputArray("OUTPUT"); + outputsize = GetInputSize("INPUT"); // Use one-dimensional representation internally +} + + + +void +Polynomial::Tick() +{ + if (input == NULL) + return; + + for (int i=0; i + + + + +

+ Module that calculates a polynomial function of ints input. + The order of the polynomial is set by the attribute order and + the coefficients are set by coefficients. This example will calculate the function: +

+

+ The example will calculate the function: + y = x-2x2+3x3+2x5 + for each input element. +

+
+ + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Polynomial.h + Polynomial.cc + Polynomial.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Randomizer/Examples/Randomizer_test.ikc b/Source/Modules/UtilityModules/Randomizer/Examples/Randomizer_test.ikc new file mode 100755 index 000000000..f31f6a6ae --- /dev/null +++ b/Source/Modules/UtilityModules/Randomizer/Examples/Randomizer_test.ikc @@ -0,0 +1,26 @@ + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Randomizer/Randomizer.cc b/Source/Modules/UtilityModules/Randomizer/Randomizer.cc new file mode 100755 index 000000000..93fe30635 --- /dev/null +++ b/Source/Modules/UtilityModules/Randomizer/Randomizer.cc @@ -0,0 +1,47 @@ +// +// Randomizer.cc This file is a part of the IKAROS project +// Implements a a modules that outputs a random array +// +// Copyright (C) 2003-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2003-07-14 +// + + +#include "Randomizer.h" + +using namespace ikaros; + +void +Randomizer::Init() +{ + Bind(maximum, "max"); + Bind(minimum, "min"); + + output = GetOutputArray("OUTPUT"); + outputsize = GetOutputSize("OUTPUT"); // Use one-dimensional internally +} + + + +void +Randomizer::Tick() +{ + random(output, minimum, maximum, outputsize); +} + + diff --git a/Source/Modules/UtilityModules/Randomizer/Randomizer.h b/Source/Modules/UtilityModules/Randomizer/Randomizer.h new file mode 100755 index 000000000..9a3312244 --- /dev/null +++ b/Source/Modules/UtilityModules/Randomizer/Randomizer.h @@ -0,0 +1,49 @@ +// +// Randomizer.h This file is a part of the IKAROS project +// Implements a modules that outputs a random array +// +// Copyright (C) 2003 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2003-07-14 +// + +#ifndef RADNOMIZER +#define RADNOMIZER + +#include "IKAROS.h" + +class Randomizer: public Module +{ +public: + float * output; + int outputsize; + + float minimum; + float maximum; + + Randomizer(Parameter * p) : Module(p) {} + virtual ~Randomizer() {} + + static Module * Create(Parameter * p) { return new Randomizer(p); } + + void Init(); + void Tick(); + +}; + + +#endif diff --git a/Source/Modules/UtilityModules/Randomizer/Randomizer.ikc b/Source/Modules/UtilityModules/Randomizer/Randomizer.ikc new file mode 100755 index 000000000..e98a8a605 --- /dev/null +++ b/Source/Modules/UtilityModules/Randomizer/Randomizer.ikc @@ -0,0 +1,60 @@ + + + + + + + + Module that outputs a random array each time step. + Can be one or two dimensional depending on whether + outputsize_x and outputsize_y or only outputsize is used + in the xml definition. + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Randomizer.h + Randomizer.cc + Randomizer.ikc + + + + + + diff --git a/Source/Modules/UtilityModules/Scale/Examples/Scale_test.ikc b/Source/Modules/UtilityModules/Scale/Examples/Scale_test.ikc new file mode 100755 index 000000000..ada651016 --- /dev/null +++ b/Source/Modules/UtilityModules/Scale/Examples/Scale_test.ikc @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Scale/Scale.cc b/Source/Modules/UtilityModules/Scale/Scale.cc new file mode 100755 index 000000000..1573818b8 --- /dev/null +++ b/Source/Modules/UtilityModules/Scale/Scale.cc @@ -0,0 +1,49 @@ +// +// Scale.cc This file is a part of the IKAROS project +// Module that multiplies its inputs (and keeps its topology if possible) +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "Scale.h" + +using namespace ikaros; + +void +Scale::Init() +{ +// factor = GetFloatValue("factor", 1.0); + + Bind(factor, "factor"); + + input = GetInputArray("INPUT"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Scale::Tick() +{ + multiply(output, input, factor, size); +} + + diff --git a/Source/Modules/UtilityModules/Scale/Scale.h b/Source/Modules/UtilityModules/Scale/Scale.h new file mode 100755 index 000000000..b736285f1 --- /dev/null +++ b/Source/Modules/UtilityModules/Scale/Scale.h @@ -0,0 +1,47 @@ +// +// Scale.h This file is a part of the IKAROS project +// Implements a modules that scales its input with a constant factor +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef SCALE +#define SCALE + +#include "IKAROS.h" + +class Scale: public Module +{ +public: + float * input; + float factor; + float * output; + int size; + + Scale(Parameter * p) : Module(p) {} + virtual ~Scale() {} + + static Module * Create(Parameter * p) { return new Scale(p); } + + void Init(); + void Tick(); +}; + +#endif + diff --git a/Source/Modules/UtilityModules/Scale/Scale.ikc b/Source/Modules/UtilityModules/Scale/Scale.ikc new file mode 100755 index 000000000..2555e5752 --- /dev/null +++ b/Source/Modules/UtilityModules/Scale/Scale.ikc @@ -0,0 +1,47 @@ + + + + + + Module that multiplies its input by a constant + factor. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Scale.h + Scale.cc + Scale.ikc + + + diff --git a/Source/Modules/UtilityModules/SelectMax/Examples/SelectMax_test.ikc b/Source/Modules/UtilityModules/SelectMax/Examples/SelectMax_test.ikc new file mode 100755 index 000000000..40e1c026d --- /dev/null +++ b/Source/Modules/UtilityModules/SelectMax/Examples/SelectMax_test.ikc @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/SelectMax/SelectMax.cc b/Source/Modules/UtilityModules/SelectMax/SelectMax.cc new file mode 100755 index 000000000..899491726 --- /dev/null +++ b/Source/Modules/UtilityModules/SelectMax/SelectMax.cc @@ -0,0 +1,50 @@ +// +// SelectMax.cc This file is a part of the IKAROS project +// A module that sets the maximum element of its input to 1 +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "SelectMax.h" + +using namespace ikaros; + +void +SelectMax::Init() +{ + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +SelectMax::Tick() +{ + int x = 0; + int y = 0; + arg_max(x, y, input, size_x, size_y); + + reset_matrix(output, size_x, size_y); + output[y][x] = 1; +} + + diff --git a/Source/Modules/UtilityModules/SelectMax/SelectMax.h b/Source/Modules/UtilityModules/SelectMax/SelectMax.h new file mode 100755 index 000000000..0e6e720f3 --- /dev/null +++ b/Source/Modules/UtilityModules/SelectMax/SelectMax.h @@ -0,0 +1,49 @@ +// +// SelectMax.h This file is a part of the IKAROS project +// A module that sets the maximum element of its input to 1 +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef SELECTMAX +#define SELECTMAX + +#include "IKAROS.h" + + + +class SelectMax: public Module +{ +public: + + SelectMax(Parameter * p) : Module(p) {} + virtual ~SelectMax() {} + + static Module * Create(Parameter * p) { return new SelectMax(p); } + + void Init(); + void Tick(); + + int size_x; + int size_y; + + float ** input; + float ** output; +}; + + +#endif diff --git a/Source/Modules/UtilityModules/SelectMax/SelectMax.ikc b/Source/Modules/UtilityModules/SelectMax/SelectMax.ikc new file mode 100755 index 000000000..75fc36004 --- /dev/null +++ b/Source/Modules/UtilityModules/SelectMax/SelectMax.ikc @@ -0,0 +1,46 @@ + + + + + + A module sets the output element corresponding to its + maximum input element to 1. The rest of the output is 0. + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + SelectMax.h + SelectMax.cc + SelectMax.ikc + + + + diff --git a/Source/Modules/UtilityModules/Shift/Examples/Shift_test.ikc b/Source/Modules/UtilityModules/Shift/Examples/Shift_test.ikc new file mode 100755 index 000000000..9cd998dad --- /dev/null +++ b/Source/Modules/UtilityModules/Shift/Examples/Shift_test.ikc @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Shift/Shift.cc b/Source/Modules/UtilityModules/Shift/Shift.cc new file mode 100755 index 000000000..e501b7106 --- /dev/null +++ b/Source/Modules/UtilityModules/Shift/Shift.cc @@ -0,0 +1,64 @@ +// +// Shift.cc This file is a part of the IKAROS project +// A module that shifts a matrix +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Shift.h" + +using namespace ikaros; + + +void +Shift::Init() +{ + offset_x = GetFloatValue("offset_x", 0); + offset_y = GetFloatValue("offset_y", 0); + direction = GetFloatValue("direction", 1); + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); + shift = GetInputArray("SHIFT"); + + if (shift == NULL) + { + Notify(msg_fatal_error, "Shift: SHIFT input not connected\n"); + } +} + + + +void +Shift::Tick() +{ + int dx = int(offset_x + direction * shift[0]); + int dy = int(offset_y + direction * shift[1]); + + for (int i=0; i + + + + + Module that shifts the elements of a matrix the + distance in the x and y direction indicated by the input SHIFT. + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Shift.h + Shift.cc + Shift.ikc + + + + diff --git a/Source/Modules/UtilityModules/Softmax/Examples/Softmax_test.ikc b/Source/Modules/UtilityModules/Softmax/Examples/Softmax_test.ikc new file mode 100755 index 000000000..43b81a01c --- /dev/null +++ b/Source/Modules/UtilityModules/Softmax/Examples/Softmax_test.ikc @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Softmax/Softmax.cc b/Source/Modules/UtilityModules/Softmax/Softmax.cc new file mode 100755 index 000000000..409ed1b19 --- /dev/null +++ b/Source/Modules/UtilityModules/Softmax/Softmax.cc @@ -0,0 +1,78 @@ +// +// Softmax.cc This file is a part of the IKAROS project +// A module applies a softmax function to its input +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Softmax.h" + + +using namespace ikaros; + +void +Softmax::Init() +{ + type = GetIntValueFromList("type"); + exponent = GetFloatValue("exponent", 2.0); + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +Softmax::Tick() +{ + if(type == 0) // p0lynomial + { + for (int i=0; i + + + + + Module used to calculate the softmax over its input. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Softmax.h + Softmax.cc + Softmax.ikc + + + diff --git a/Source/Modules/UtilityModules/Subtract/Examples/Subtract_test.ikc b/Source/Modules/UtilityModules/Subtract/Examples/Subtract_test.ikc new file mode 100755 index 000000000..0304fb9c9 --- /dev/null +++ b/Source/Modules/UtilityModules/Subtract/Examples/Subtract_test.ikc @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Subtract/Subtract.cc b/Source/Modules/UtilityModules/Subtract/Subtract.cc new file mode 100755 index 000000000..c6c296d19 --- /dev/null +++ b/Source/Modules/UtilityModules/Subtract/Subtract.cc @@ -0,0 +1,46 @@ +// +// Subtract.cc This file is a part of the IKAROS project +// Implements a modules that subtracts its two inputs +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + + +#include "Subtract.h" + +using namespace ikaros; + +void +Subtract::Init() +{ + input1 = GetInputArray("INPUT1"); + input2 = GetInputArray("INPUT2"); + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); +} + + + +void +Subtract::Tick() +{ + subtract(output, input1, input2, size); +} + + diff --git a/Source/Modules/UtilityModules/Subtract/Subtract.h b/Source/Modules/UtilityModules/Subtract/Subtract.h new file mode 100755 index 000000000..53fbda51e --- /dev/null +++ b/Source/Modules/UtilityModules/Subtract/Subtract.h @@ -0,0 +1,46 @@ +// +// Subtract.h This file is a part of the IKAROS project +// Implements a modules that subtracts its two inputs +// +// Copyright (C) 2004 Christian Balkenius +/// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-22 +// + +#ifndef SUBTRACT +#define SUBTRACT + +#include "IKAROS.h" + +class Subtract: public Module +{ +public: + static Module * Create(Parameter * p) { return new Subtract(p); } + + float * input1; + float * input2; + float * output; + int size; + + Subtract(Parameter * p) : Module(p) {}; + virtual ~Subtract() {}; + + void Init(); + void Tick(); +}; + +#endif diff --git a/Source/Modules/UtilityModules/Subtract/Subtract.ikc b/Source/Modules/UtilityModules/Subtract/Subtract.ikc new file mode 100755 index 000000000..d38e7ae7e --- /dev/null +++ b/Source/Modules/UtilityModules/Subtract/Subtract.ikc @@ -0,0 +1,47 @@ + + + + + + Module that subtracts the second input from the first input, element by element. + Both inputs must have the same size. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Subtract.h + Subtract.cc + Subtract.ikc + + + diff --git a/Source/Modules/UtilityModules/Sweep/Examples/Sweep_test.ikc b/Source/Modules/UtilityModules/Sweep/Examples/Sweep_test.ikc new file mode 100755 index 000000000..35638efe0 --- /dev/null +++ b/Source/Modules/UtilityModules/Sweep/Examples/Sweep_test.ikc @@ -0,0 +1,18 @@ + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Sweep/Sweep.cc b/Source/Modules/UtilityModules/Sweep/Sweep.cc new file mode 100755 index 000000000..0ecca4511 --- /dev/null +++ b/Source/Modules/UtilityModules/Sweep/Sweep.cc @@ -0,0 +1,59 @@ +// +// Sweep.cc This file is a part of the IKAROS project +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Created: 2004-03-24 +// + + +#include "Sweep.h" + + +void +Sweep::Init() +{ + minimum = GetFloatValue("min", 0); + maximum = GetFloatValue("max", 1); + step = GetFloatValue("step", 0.1); + + output = GetOutputArray("OUTPUT"); + size = GetOutputSize("OUTPUT"); + + for (int i=0; i maximum) + value = minimum; + + for (int i=0; i + + + + + Module that sweeps the output from min to max in steps set by step. + Restarts when min (or max) is reached. Can be one or two dimensional + depending on whether outputsize_x and outputsize_y or only outputsize + is used. When the output contains more than one + elements, they all have the same value. + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Sweep.h + Sweep.cc + Sweep.ikc + + + \ No newline at end of file diff --git a/Source/Modules/UtilityModules/Threshold/Examples/Threshold_test.ikc b/Source/Modules/UtilityModules/Threshold/Examples/Threshold_test.ikc new file mode 100755 index 000000000..697f14538 --- /dev/null +++ b/Source/Modules/UtilityModules/Threshold/Examples/Threshold_test.ikc @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/UtilityModules/Threshold/Threshold.cc b/Source/Modules/UtilityModules/Threshold/Threshold.cc new file mode 100755 index 000000000..5df8ce61f --- /dev/null +++ b/Source/Modules/UtilityModules/Threshold/Threshold.cc @@ -0,0 +1,62 @@ +// +// Threshold.cc This file is a part of the IKAROS project +// A module applies a threshold to its input +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "Threshold.h" + +void +Threshold::Init() +{ + type = GetIntValueFromList("type"); + threshold = GetFloatValue("threshold"); + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +void +Threshold::Tick() +{ + switch (type) + { + case 0: // Binary + for (int i=0; i threshold ? 1.0 : 0.0); + break; + + case 1: // Linear + for (int i=0; i threshold ? input[j][i] - threshold : 0.0); + break; + + default: + break; + } +} + + diff --git a/Source/Modules/UtilityModules/Threshold/Threshold.h b/Source/Modules/UtilityModules/Threshold/Threshold.h new file mode 100755 index 000000000..cdc9c439c --- /dev/null +++ b/Source/Modules/UtilityModules/Threshold/Threshold.h @@ -0,0 +1,50 @@ +// +// Threshold.h This file is a part of the IKAROS project +// A module applies a threshold to its input +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef THRESHOLD +#define THRESHOLD + +#include "IKAROS.h" + +class Threshold: public Module +{ +public: + + Threshold(Parameter * p) : Module(p) {} + virtual ~Threshold() {} + + static Module * Create(Parameter * p) { return new Threshold(p); } + + void Init(); + void Tick(); + + int size_x; + int size_y; + + int type; + float threshold; + + float ** input; + float ** output; +}; + + +#endif diff --git a/Source/Modules/UtilityModules/Threshold/Threshold.ikc b/Source/Modules/UtilityModules/Threshold/Threshold.ikc new file mode 100755 index 000000000..dee3b3454 --- /dev/null +++ b/Source/Modules/UtilityModules/Threshold/Threshold.ikc @@ -0,0 +1,52 @@ + + + + + + Module used to apply a threshold to each element of its input. + When the input is below the threshold, the output is 0. When the + input is above the threshold, the output is 1 in binary mode, and + input - threshold in linear mode. + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Threshold.h + Threshold.cc + Threshold.ikc + + + diff --git a/Source/Modules/VisionModules/AttentionFocus/AttentionFocus.cc b/Source/Modules/VisionModules/AttentionFocus/AttentionFocus.cc new file mode 100755 index 000000000..1b00ceeaa --- /dev/null +++ b/Source/Modules/VisionModules/AttentionFocus/AttentionFocus.cc @@ -0,0 +1,129 @@ +// +// AttentionFocus.cc This file is a part of the IKAROS project +// Module that extracts a focus of attention from an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "AttentionFocus.h" + +using namespace ikaros; + +Module * +AttentionFocus::Create(Parameter * p) +{ + return new AttentionFocus(p); +} + + + +AttentionFocus::AttentionFocus(Parameter * p): + Module(p) +{ + output_radius = GetIntValue("output_radius", 15); + scale = GetBoolValue("scale", true); + mask = GetBoolValue("mask", false); + + AddInput("FOCUS"); + AddInput("INPUT"); + AddOutput("OUTPUT", output_radius*2+1, output_radius*2+1); + + input = NULL; + output = NULL; + focus = NULL; +} + + + +void +AttentionFocus::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + if (GetInputSize("FOCUS") != 2) + Notify(msg_warning, "Input \"FOCUS\" of module \"%s\" should be of size 2 x 1.\n", GetName()); + + focus = GetInputArray("FOCUS"); + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +AttentionFocus::~AttentionFocus() +{ +// delete [] input; +} + + + +void +AttentionFocus::Tick() +{ + int center_x; + int center_y; + + if (!scale) + { + center_x = int(focus[0]); + center_y = int(focus[1]); + } + else + { + center_x = int(inputsize_x*focus[0]); + center_y = int(inputsize_y*focus[1]); + } + + if(!mask) + { + for (int i=0; i + + + + + Module that extracts a region of an image around the + coordinates given in the FOCUS input. + + + + + + + + + + + + + + + + 2003 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + AttentionFocus.h + AttentionFocus.cc + AttentionFocus.ikc + + + diff --git a/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.cc b/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.cc new file mode 100755 index 000000000..b823db95b --- /dev/null +++ b/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.cc @@ -0,0 +1,280 @@ +// +// ColorClassifier.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2005-2008 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +#include "ColorClassifier.h" + +using namespace ikaros; + +#define HMAX 256 + +void +ColorClassifier::Init() +{ + compensation = GetBoolValue("compensation", false); + diagnostics = GetBoolValue("diagnostics", false); + + color = 2*pi*GetFloatValue("color", 225.0)/360.0; + width = cos(2*pi*GetFloatValue("width", 20)/360.0); + + saturation_min = GetFloatValue("saturation_min", 0.05); + saturation_max = GetFloatValue("saturation_max", 0.50); + + cr = sin(color); + cg = cos(color); + + r = GetInputMatrix("R"); + g = GetInputMatrix("G"); + I = GetInputMatrix("I"); + + size_x = GetInputSizeX("R"); + size_y = GetInputSizeY("R"); + + output = GetOutputMatrix("OUTPUT"); + + r_prim = create_matrix(size_x, size_y); + g_prim = create_matrix(size_x, size_y); + + Dm = create_matrix(size_x, size_y); + + colorspace_store_r = create_matrix(HMAX, HMAX); + colorspace_store_g = create_matrix(HMAX, HMAX); + colorspace_store_b = create_matrix(HMAX, HMAX); + + colorspace_r = GetOutputMatrix("COLORSPACE_R", false); + colorspace_g = GetOutputMatrix("COLORSPACE_G", false); + colorspace_b = GetOutputMatrix("COLORSPACE_B", false); + + InitColorSpace(); +} + + + +ColorClassifier::~ColorClassifier() +{ + destroy_matrix(r_prim); + destroy_matrix(g_prim); + destroy_matrix(Dm); +} + + + +// float L2 = s(*Xp++)+s(*Yp++); +// if(saturation_min2 < L2 && L2 < saturation_max2 && *Dp > 0 && (s(*Dp) > width2 * L2) ) + +void +ColorClassifier::InitColorSpace() +{ + float white_red = 1.0/3.0; + float white_green = 1.0/3.0; + + for(float _r=0; _r < 255; _r+=2) + for(float _g=0; _g < 255; _g+=2) + for(float _b=0; _b < 255; _b+=2) + { + float X = _r/(_r+_g+_b) - white_red; + float Y = _g/(_r+_g+_b) - white_green; + float L = sqrt(X*X+Y*Y); + + int hx = int(HMAX*(1.0/3.0+X)); + int hy = int(HMAX*(1.0/3.0+Y)); + + X /= L; + Y /= L; + + if(hx < HMAX-1 && hy < HMAX-1 && hx >= 0 && hy >= 0) + { + if(saturation_min < L && L < saturation_max && cr * X + cg * Y > width) + { + colorspace_store_r[hx][hy] = _r/255.0; + colorspace_store_g[hx][hy] = _g/255.0; + colorspace_store_b[hx][hy] = _b/255.0; + + colorspace_store_r[hx+1][hy] = _r/255.0; + colorspace_store_g[hx+1][hy] = _g/255.0; + colorspace_store_b[hx+1][hy] = _b/255.0; + + colorspace_store_r[hx][hy+1] = _r/255.0; + colorspace_store_g[hx][hy+1] = _g/255.0; + colorspace_store_b[hx][hy+1] = _b/255.0; + + colorspace_store_r[hx+1][hy+1] = _r/255.0; + colorspace_store_g[hx+1][hy+1] = _g/255.0; + colorspace_store_b[hx+1][hy+1] = _b/255.0; + } + else + { + colorspace_store_r[hx][hy] = _r/512.0; + colorspace_store_g[hx][hy] = _g/512.0; + colorspace_store_b[hx][hy] = _b/512.0; + + colorspace_store_r[hx+1][hy] = _r/512.0; + colorspace_store_g[hx+1][hy] = _g/512.0; + colorspace_store_b[hx+1][hy] = _b/512.0; + + colorspace_store_r[hx][hy+1] = _r/512.0; + colorspace_store_g[hx][hy+1] = _g/512.0; + colorspace_store_b[hx][hy+1] = _b/512.0; + + colorspace_store_r[hx+1][hy+1] = _r/512.0; + colorspace_store_g[hx+1][hy+1] = _g/512.0; + colorspace_store_b[hx+1][hy+1] = _b/512.0; + } + } + } + + for(int i=0; i= 0 && hy >= 0) + { + colorspace_r[hx][hy] = 0.25; + colorspace_g[hx][hy] = 0.25; + colorspace_b[hx][hy] = 0.25; + } + + float L2 = s(*Xp++)+s(*Yp++); + if(saturation_min2 < L2 && L2 < saturation_max2 && *Dp > 0 && (s(*Dp) > width2 * L2) ) + { + if(hx < HMAX && hy < HMAX && hx >= 0 && hy >= 0) + { + colorspace_r[hx][hy] = 0; + colorspace_g[hx][hy] = 0; + colorspace_b[hx][hy] = 0; + } + + output[j][i] = 1.0; + } + Dp++; + } +} + + + +void +ColorClassifier::Tick_Fast() +{ + reset_matrix(output, size_x, size_y); + + // Pass 0: Calculate White Point + + float white_red = 1.0f/3.0f; + float white_green = 1.0f/3.0f; + + if(compensation) + { + white_red = mean(r, size_x, size_y); + white_green = mean(g, size_x, size_y); + } + + // Pass 1: Find Target Color + + subtract(r_prim, r, white_red, size_x, size_y); + subtract(g_prim, g, white_green, size_x, size_y); + add(Dm, cr, r_prim, cg, g_prim, size_x, size_y); + + float saturation_min2 = sqr(saturation_min); + float saturation_max2 = sqr(saturation_max); + float width2 = sqr(width); + + float * Xp = r_prim[0]; + float * Yp = g_prim[0]; + float * Dp = Dm[0]; + + for(int j=0; j 0 && (s(*Dp) > width2 * L2) ) + output[j][i] = 1.0; + Dp++; + } +} + + + +void +ColorClassifier::Tick() +{ + if(!diagnostics) + Tick_Fast(); + else + Tick_Slow(); +} + diff --git a/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.h b/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.h new file mode 100755 index 000000000..3cc36fa50 --- /dev/null +++ b/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.h @@ -0,0 +1,75 @@ +// +// ColorClassifier.h This file is a part of the IKAROS project +// +// +// Copyright (C) 2005-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef COLORCLASSIFIER +#define COLORCLASSIFIER + +#include "IKAROS.h" + +class ColorClassifier: public Module +{ +public: + ColorClassifier(Parameter * p) : Module(p) {} + virtual ~ColorClassifier(); + + static Module * Create(Parameter * p) { return new ColorClassifier(p); } + + void InitColorSpace(); + void Init(); + + void Tick_Slow(); + void Tick_Fast(); + void Tick(); + + float ** r; + float ** g; + float ** I; + float ** r_prim; + float ** g_prim; + + float ** Dm; + + float ** output; + + float ** colorspace_store_r; + float ** colorspace_store_g; + float ** colorspace_store_b; + + float ** colorspace_r; + float ** colorspace_g; + float ** colorspace_b; + + int size_x; + int size_y; + + float color; + float width; + float saturation_min; + float saturation_max; + + float cr; + float cg; + + bool compensation; + bool diagnostics; +}; + +#endif diff --git a/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.ikc b/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.ikc new file mode 100755 index 000000000..df30bd5a3 --- /dev/null +++ b/Source/Modules/VisionModules/ColorClassifier/ColorClassifier.ikc @@ -0,0 +1,57 @@ + + + + + + Module used to classify one or several objects of a particular color in a scene. + The input is a color image in rgI format which can be obained from the ColorTransform module. + The output is a table of target coordinates. + + + + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + ColorClassifier.h + ColorClassifier.cc + ColorClassifier.ikc + + + + diff --git a/Source/Modules/VisionModules/ColorClassifier/Examples/ColorClassifier_test.ikc b/Source/Modules/VisionModules/ColorClassifier/Examples/ColorClassifier_test.ikc new file mode 100755 index 000000000..ed746e21b --- /dev/null +++ b/Source/Modules/VisionModules/ColorClassifier/Examples/ColorClassifier_test.ikc @@ -0,0 +1,75 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ColorMatch/ColorMatch.cc b/Source/Modules/VisionModules/ColorMatch/ColorMatch.cc new file mode 100755 index 000000000..7754911fa --- /dev/null +++ b/Source/Modules/VisionModules/ColorMatch/ColorMatch.cc @@ -0,0 +1,110 @@ +// +// ColorMatch.cc This file is a part of the IKAROS project +// +// Copyright (C) 2004 Christian Balkenius, Anders J Johansson +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "ColorMatch.h" + +using namespace ikaros; + +void +ColorMatch::Init() +{ + alpha = GetFloatValue("alpha", 0.01); + sigma = GetFloatValue("sigma", 25.0); + gain = GetFloatValue("gain", 1.0); + + target0 = GetFloatValue("target0", 0.0); + target1 = GetFloatValue("target1", 0.0); + target2 = GetFloatValue("target2", 0.0); + + threshold = GetFloatValue("threshold", 0.0); + + size_x = GetInputSizeX("INPUT0"); + size_y = GetInputSizeY("INPUT0"); + + input0 = GetInputMatrix("INPUT0"); + input1 = GetInputMatrix("INPUT1"); + input2 = GetInputMatrix("INPUT2"); + + if(InputConnected("TARGETINPUT0")) + { + target_input0 = GetInputMatrix("TARGETINPUT0"); + target_input1 = GetInputMatrix("TARGETINPUT1"); + target_input2 = GetInputMatrix("TARGETINPUT2"); + } + + if(InputConnected("REINFORCEMENT")) + reinforcement = GetInputArray("REINFORCEMENT"); + + if(InputConnected("FOCUS")) + focus = GetInputArray("FOCUS"); + + output = GetOutputMatrix("OUTPUT"); +} + + + +#define sqr(x) (x)*(x) + +void +ColorMatch::Tick() +{ + // Normalize Target + + float s = target0+target1+target2; + + if (s != 0) + { + target0 /= s; + target1 /= s; + target2 /= s; + } + + // Calculate Color Map + + for (int i=0; i threshold) + { + float d = sqrt(sqr(input0[j][i]/cs - target0) + sqr(input1[j][i]/cs - target1) + sqr(input2[j][i]/cs - target2)); + output[j][i] = gain*exp(-sigma*d); + } + else + { + output[j][i] = 0.0; + } + } + + + // Retune Target + + if (reinforcement != NULL && focus != NULL && alpha != 0) + { + float d = alpha * reinforcement[0]; + target0 = (1.0-d)*target0 + d*target_input0[int(focus[1])][int(focus[0])]; + target1 = (1.0-d)*target1 + d*target_input1[int(focus[1])][int(focus[0])]; + target2 = (1.0-d)*target2 + d*target_input2[int(focus[1])][int(focus[0])]; + } +} + + + diff --git a/Source/Modules/VisionModules/ColorMatch/ColorMatch.h b/Source/Modules/VisionModules/ColorMatch/ColorMatch.h new file mode 100755 index 000000000..b19f63bbb --- /dev/null +++ b/Source/Modules/VisionModules/ColorMatch/ColorMatch.h @@ -0,0 +1,69 @@ +// +// ColorMatch.h This file is a part of the IKAROS project +// A module to detect a color in an image +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef COLORMATCH +#define COLORMATCH + +#include "IKAROS.h" + + + +class ColorMatch: public Module +{ +public: + + ColorMatch(Parameter * p) : Module(p) {} + virtual ~ColorMatch() {} + + static Module * Create(Parameter * p) { return new ColorMatch(p); } + + void Init(); + void Tick(); + + int size_x; + int size_y; + + float ** input0; + float ** input1; + float ** input2; + + float ** target_input0; + float ** target_input1; + float ** target_input2; + + float * focus; // 2 x 1 + float * reinforcement; + + float ** output; + + float alpha; + float sigma; + float gain; + + float target0; + float target1; + float target2; + + float threshold; +}; + + +#endif diff --git a/Source/Modules/VisionModules/ColorMatch/ColorMatch.ikc b/Source/Modules/VisionModules/ColorMatch/ColorMatch.ikc new file mode 100755 index 000000000..e6e55d3b4 --- /dev/null +++ b/Source/Modules/VisionModules/ColorMatch/ColorMatch.ikc @@ -0,0 +1,55 @@ + + + + + + Module used match colors in an image to a prototype color. + The module can also learn the color based on its reinforcement + input and a target input image. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + ColorMatch.h + ColorMatch.cc + ColorMatch.ikc + + + diff --git a/Source/Modules/VisionModules/ColorMatch/Examples/ColorMatch_test.ikc b/Source/Modules/VisionModules/ColorMatch/Examples/ColorMatch_test.ikc new file mode 100755 index 000000000..b886acde0 --- /dev/null +++ b/Source/Modules/VisionModules/ColorMatch/Examples/ColorMatch_test.ikc @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ColorTransform/ColorTransform.cc b/Source/Modules/VisionModules/ColorTransform/ColorTransform.cc new file mode 100755 index 000000000..be2d347b2 --- /dev/null +++ b/Source/Modules/VisionModules/ColorTransform/ColorTransform.cc @@ -0,0 +1,256 @@ +// +// ColorTransform.cc This file is a part of the IKAROS project +// A module to convert color coordinates +// +// Copyright (C) 2003 Christian Balkenius, Anders J Johansson +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Partially based on code by Mark Ruzon from C code by Yossi Rubner, 23 September 1997. +// Updated for MATLAB 5 28 January 1998. Moved to IKAROS February 2003. + + +#include "ColorTransform.h" + +using namespace ikaros; + + +// Transformation types + +#define RGB2LAB 0 +#define RGB2XYZ 1 +#define LAB2RGB 2 +#define XYZ2RGB 3 +#define RGB2rgI 4 + + + +static inline +float +limit(float x, float a, float b) +{ + return(x < a ? a : (x > b ? b : x)); +} + + + +//inline +static void +transform_rgb2xyz(float red, float green, float blue, float & X, float & Y, float & Z) +{ + X = 0.412453*red + 0.357581*green + 0.180423*blue; + Y = 0.212670*red + 0.715160*green + 0.072169*blue; + Z = 0.019334*red + 0.119193*green + 0.950227*blue; +} + + + +//inline +static void +transform_xyz2rgb(float X, float Y, float Z, float & red, float & green, float & blue) +{ + red = 3.240479*X - 1.537150*Y - 0.498535*Z; + green = -0.969256*X + 1.875992*Y + 0.041556*Z; + blue = 0.055648*X - 0.204043*Y + 1.057311*Z; +} + + + +const float T = 0.008856; + + + +static float +f(float t) +{ + if (t > T) + return ikaros::pow((t), 1.0/3.0); + else + return 7.787*(t) + 16.0/116.0; +} + + + +// transform_rgb2lab transforms from RGB into CIE Lab. +// Based on ITU-R Recommendation BT.709 using the D65 white point reference. + +inline +static void +transform_rgb2lab(float red, float green, float blue, float & L, float & a, float & b) +{ + float X, Y, Z; + + X = 0.412453*red + 0.357581*green + 0.180423*blue; + Y = 0.212670*red + 0.715160*green + 0.072169*blue; + Z = 0.019334*red + 0.119193*green + 0.950227*blue; + + X /= 0.950456; + Y /= 1.000000; + Z /= 1.088754; + + if (Y > T) + L = 116.0*ikaros::pow(Y, 1.0/3.0)-16.0; + else + L = 903.3*Y; + + if (L < 0) + L = 0; + + a = 500.0*( f(X) - f(Y) ); + b = 200.0*( f(Y) - f(Z) ); +} + + + +inline +static void +transform_lab2rgb(float L, float a, float b, float & red, float & green, float & blue, float scale = 1.0) +{ + float T1 = 0.008856; + float T2 = 0.206893; + + // Compute Y + + float fY = ikaros::pow(((L + 16) / 116), 3.0); + bool YT = fY > T1; + + if (!YT) + fY = L / 903.3; + + float Y = fY; + + if (YT) + fY = ikaros::pow(fY, 1.0/3.0); + else + fY = (7.787 * fY + 16/116); + + // Compute X + + float fX = a / 500 + fY; + bool XT = fX > T2; + float X; + + if (XT) + X = ikaros::pow(fX, 3.0); + else + X =(fX - 16/116) / 7.787; + + // Compute Z + + float fZ = fY - b / 200; + bool ZT = fZ > T2; + + float Z; + if (ZT) + Z = ikaros::pow(fZ, 3.0); + else + Z = (fZ - 16/116) / 7.787; + + X *= 0.950456; + Y *= 1.000000; + Z *= 1.088754; + + red = 3.240479*X - 1.537150*Y - 0.498535*Z; + green = -0.969256*X + 1.875992*Y + 0.041556*Z; + blue = 0.055648*X - 0.204043*Y + 1.057311*Z; + + red = scale * limit(red, 0.0, 1.0); + green = scale * limit(green, 0.0, 1.0); + blue = scale * limit(blue, 0.0, 1.0); +} + + + +void +ColorTransform::Init() +{ + transform = GetIntValueFromList("transform"); + scale = GetFloatValue("scale"); + + Notify(msg_verbose, "transform = %d\n", transform); + + size_x = GetInputSizeX("INPUT0"); + size_y = GetInputSizeY("INPUT0"); + + int size_x1 = GetInputSizeX("INPUT1"); + int size_y1 = GetInputSizeY("INPUT1"); + + int size_x2 = GetInputSizeX("INPUT2"); + int size_y2 = GetInputSizeY("INPUT2"); + + if(size_x != size_x1 || size_x1 != size_x2 || size_y != size_y1 || size_y1 != size_y2) + { + Notify(msg_fatal_error, "ColorTransform: the sizes of the inputs to \"%s\"are not equal.", GetName()); + } + + input0 = GetInputMatrix("INPUT0"); + input1 = GetInputMatrix("INPUT1"); + input2 = GetInputMatrix("INPUT2"); + + output0 = GetOutputMatrix("OUTPUT0"); + output1 = GetOutputMatrix("OUTPUT1"); + output2 = GetOutputMatrix("OUTPUT2"); +} + + + +void +ColorTransform::Tick() +{ + switch (transform) + { + case RGB2LAB: + for (int j=0; j + + + + + Module used for transformation of color coordinates. + The RGB to CIE L*a*b* transformation is based on ITU-R Recommendation + BT.709 using the D65 white point reference. + The RGB to rgI transform maps black points on gray. + + + + + + + + + + + + + + + + + + + + 2003 + + + Commission Internationale de l'Eclairage (CIE) (1978). Official recommendation on color spaces, + color difference and metric color terms, Supplement No. 2 for CIE-Publication No. 15, Colorimetry + (E-1.3.1), 1971. + + + + The "XYZ->RGB" and "Lab->RGB" transformations have not been tested. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + ColorTransform.h + ColorTransform.cc + ColorTransform.ikc + + + diff --git a/Source/Modules/VisionModules/ColorTransform/Examples/ColorTransform_test.ikc b/Source/Modules/VisionModules/ColorTransform/Examples/ColorTransform_test.ikc new file mode 100755 index 000000000..ab9cf48e3 --- /dev/null +++ b/Source/Modules/VisionModules/ColorTransform/Examples/ColorTransform_test.ikc @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageConvolution/Examples/Convolution_cam.ikc b/Source/Modules/VisionModules/ImageConvolution/Examples/Convolution_cam.ikc new file mode 100755 index 000000000..5eebb1aad --- /dev/null +++ b/Source/Modules/VisionModules/ImageConvolution/Examples/Convolution_cam.ikc @@ -0,0 +1,54 @@ + + + + + + + + + + 1 0 -1 + 2 0 -2 + 1 0 -1 + + + + + + 1 2 1 + 0 0 0 + -1 -2 -1 + + + + + + -1 2 -1 + -1 2 -1 + -1 2 -1 + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageConvolution/Examples/Convolution_test.ikc b/Source/Modules/VisionModules/ImageConvolution/Examples/Convolution_test.ikc new file mode 100755 index 000000000..2e4da06e8 --- /dev/null +++ b/Source/Modules/VisionModules/ImageConvolution/Examples/Convolution_test.ikc @@ -0,0 +1,74 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageConvolution/ImageConvolution.cc b/Source/Modules/VisionModules/ImageConvolution/ImageConvolution.cc new file mode 100755 index 000000000..52bd5d9d5 --- /dev/null +++ b/Source/Modules/VisionModules/ImageConvolution/ImageConvolution.cc @@ -0,0 +1,126 @@ +// +// ImageConvolution.cc This file is a part of the IKAROS project +// A module to filter image with a kernel +// +// Copyright (C) 2002-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "ImageConvolution.h" +#include "ctype.h" + +using namespace ikaros; + + +Module * +ImageConvolution::Create(Parameter * p) +{ + return new ImageConvolution(p); +} + + + +ImageConvolution::ImageConvolution(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; + filter = NULL; + + scale = 1.0; + bias = 0.0; + + init_ok = false; + + // Init filter kernel from xml file + + rectify = GetBoolValue("rectify"); + scale = GetFloatValue("scale"); + bias = GetFloatValue("bias"); + filtersize_x = GetIntValue("size_x"); + filtersize_y = GetIntValue("size_y"); + filter = GetMatrix("kernel", filtersize_x, filtersize_y); + + for (int j=0; j + + + + + Module used for basic image filtering with user-defined filter kernels. + + + + + + + + + + + + + + + + + + + 2002 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + ImageConvolution.h + ImageConvolution.cc + ImageConvolution.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/ChangeDetector/ChangeDetector.cc b/Source/Modules/VisionModules/ImageOperators/ChangeDetector/ChangeDetector.cc new file mode 100755 index 000000000..3938b6617 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/ChangeDetector/ChangeDetector.cc @@ -0,0 +1,94 @@ +// +// ChangeDetector.cc This file is a part of the IKAROS project +// A module to find changes in an image +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "ChangeDetector.h" + +using namespace ikaros; + +Module * +ChangeDetector::Create(Parameter * p) +{ + return new ChangeDetector(p); +} + + + +ChangeDetector::ChangeDetector(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + last_input = NULL; + input = NULL; + output = NULL; + + border = GetIntValue("border", 0); +} + + + +void +ChangeDetector::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx-2*border, sy-2*border); +} + + + +void +ChangeDetector::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + last_input = create_matrix(inputsize_x, inputsize_y); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +ChangeDetector::~ChangeDetector() +{ +} + + + +void +ChangeDetector::Tick() +{ + for (int j =0; j + + + + + Module that compares two successive input images and outputs the absolute value of their + difference. In addition, it is possible to throw away a border around the image to make + the output compatible with that of other image operators. + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + ChangeDetector.h + ChangeDetector.cc + ChangeDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/ChangeDetector/Examples/ChangeDetector_test.ikc b/Source/Modules/VisionModules/ImageOperators/ChangeDetector/Examples/ChangeDetector_test.ikc new file mode 100755 index 000000000..4a23e26a5 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/ChangeDetector/Examples/ChangeDetector_test.ikc @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/Examples/HarrisDetector_test.ikc b/Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/Examples/HarrisDetector_test.ikc new file mode 100755 index 000000000..391d5a242 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/Examples/HarrisDetector_test.ikc @@ -0,0 +1,38 @@ + + + + + + <_module class = "InputJPEG" name = "IN" filename = "../../../../../../../Examples/Media/cannes.jpg" iterations = "20" /> + + + + + + + + + + + + + <_object class="Image" module="IN" source="INTENSITY" x="0" y="0" h="2" w="2" /> + + + + diff --git a/Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/HarrisDetector.cc b/Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/HarrisDetector.cc new file mode 100755 index 000000000..81250d1de --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/CurvatureDetectors/HarrisDetector/HarrisDetector.cc @@ -0,0 +1,139 @@ +// +// HarrisDetector.cc This file is a part of the IKAROS project +// A module to estimate curvature in an image +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "HarrisDetector.h" +#include "ctype.h" + +using namespace ikaros; + +#define limit(x, x0, x1) ((x) < (x0) ? (x0) : ((x) > (x1) ? (x1) : (x))) + + + +Module * +HarrisDetector::Create(Parameter * p) +{ + return new HarrisDetector(p); +} + + + +HarrisDetector::HarrisDetector(Parameter * p): + Module(p) +{ + dx = NULL; + dy = NULL; + output = NULL; + + // Add inputs and outputs + + AddInput("DX"); + AddInput("DY"); + + AddOutput("OUTPUT"); +} + + + +void +HarrisDetector::SetSizes() +{ + int sx = GetInputSizeX("DX"); + int sy = GetInputSizeY("DX"); + if (sx != unknown_size && sy != unknown_size) + { + SetOutputSize("OUTPUT", sx, sy); + } +} + + + +void +HarrisDetector::Init() +{ + size_x = GetInputSizeX("DX"); + size_y = GetInputSizeY("DX"); + + dx = GetInputMatrix("DX"); + dy = GetInputMatrix("DY"); + + output = GetOutputMatrix("OUTPUT"); + + dx2 = create_matrix(size_x, size_y); + dy2 = create_matrix(size_x, size_y); + dxy = create_matrix(size_x, size_y); + dxs = create_matrix(size_x, size_y); + dys = create_matrix(size_x, size_y); + dxys = create_matrix(size_x, size_y); +} + + + +HarrisDetector::~HarrisDetector() +{ + destroy_matrix(dx2); + destroy_matrix(dy2); + destroy_matrix(dxy); + destroy_matrix(dxs); + destroy_matrix(dys); + destroy_matrix(dxys); +} + + + +void +HarrisDetector::Tick() +{ + for (int j =0; j + + + + + Module for curvature (corner) detection. Operates on + two gradient images (DX and DY) rather than the original image + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + 2004 + + + HarrisDetector.h + HarrisDetector.cc + HarrisDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/CannyEdgeDetector.cc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/CannyEdgeDetector.cc new file mode 100755 index 000000000..5c8d00cdc --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/CannyEdgeDetector.cc @@ -0,0 +1,224 @@ +// +// CannyEdgeDetector.cc This file is a part of the IKAROS project +// A module to find edges in an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "CannyEdgeDetector.h" + +using namespace ikaros; + + + +Module * +CannyEdgeDetector::Create(Parameter * p) +{ + return new CannyEdgeDetector(p); +} + + + +CannyEdgeDetector::CannyEdgeDetector(Parameter * p): + Module(p) +{ + scale = GetFloatValue("scale", 1.0); + filterradius = int(2*scale+0.5); + filtersize = 1+2*filterradius; + + AddInput("INPUT"); + + AddOutput("EDGES"); // Edge magnitude + AddOutput("MAXIMA"); // Orientation estimation + AddOutput("OUTPUT"); // Final edges + AddOutput("dx"); // Gradient estimation and categorization + AddOutput("dy"); + AddOutput("dGx", filtersize, filtersize); // The filters used + AddOutput("dGy", filtersize, filtersize); + + input = NULL; + edges = NULL; + maxima = NULL; + output = NULL; + dx = NULL; + dy = NULL; + dGx = NULL; + dGy = NULL; + + T0 = GetFloatValue("T0", 100); + T1 = GetFloatValue("T1", 200); + T2 = GetFloatValue("T2", 800); +} + + + +void +CannyEdgeDetector::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + { + SetOutputSize("EDGES", sx-2*filterradius, sy-2*filterradius); // CHECK LATER!!! *** + SetOutputSize("MAXIMA", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("OUTPUT", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("dx", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("dy", sx-2*filterradius, sy-2*filterradius); + } +} + + + +void +CannyEdgeDetector::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + + edges = GetOutputMatrix("EDGES"); + maxima = GetOutputMatrix("MAXIMA"); + output = GetOutputMatrix("OUTPUT"); + + dGx = GetOutputMatrix("dGx"); + dGy = GetOutputMatrix("dGy"); + + dx = GetOutputMatrix("dx"); + dy = GetOutputMatrix("dy"); + + // Initialize Gaussian Filters + + float Gsize = 1.0/scale; + + for (int j=0; j T0) + { + t = dx[j][i] / edges[j][i]; + dx[j][i] = (t > 0.3827 ? 1.0 : (t < -0.3827 ? -1 : 0)); + t = dy[j][i] / edges[j][i]; + dy[j][i] = (t > 0.3827 ? 1.0 : (t < -0.3827 ? -1 : 0)); + } + else + { + edges[j][i] = 0; + dx[j][i] = 0; + dy[j][i] = 0; + } + + // Nonmaximum supression (rotate gradient vector by exchanging coordinates and signs) + + copy_matrix(maxima, edges, outputsize_x, outputsize_y); + for (int j=1; j T2) // && (int(dx[j][i]) != 0 || int(dy[j][i]) != 0) + { + output[j][i] = 1; + + // Extend edge in gradient direction + + int jj = j + int(dx[j][i]); + int ii = i - int(dy[j][i]); + + while (0 + + + + + Module that applies the Canny edge detector to an image. This edge detector works in five steps: + 1. Gradient Estimation using a Gaussian edge detector. + 2. Orientation Classification. + 3. Nonmaximum Supression. + 4. Hysteresis Thresholding. + This is not exactly the algorithm as described by Canny (the edge filter is different and edges are only found at a single scale) but it is reasonably similar. + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + CannyEdgeDetector.h + CannyEdgeDetector.cc + CannyEdgeDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/Examples/CannyEdgeDetector_test.ikc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/Examples/CannyEdgeDetector_test.ikc new file mode 100755 index 000000000..54383a370 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/CannyEdgeDetector/Examples/CannyEdgeDetector_test.ikc @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/Examples/GaussianEdgeDetector_test.ikc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/Examples/GaussianEdgeDetector_test.ikc new file mode 100755 index 000000000..77e5d7852 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/Examples/GaussianEdgeDetector_test.ikc @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.cc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.cc new file mode 100755 index 000000000..0b3a1f48e --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.cc @@ -0,0 +1,191 @@ +// +// GaussianEdgeDetector.cc This file is a part of the IKAROS project +// A module to find edges in an image including their orientation +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +#include "GaussianEdgeDetector.h" + +using namespace ikaros; + + + +Module * +GaussianEdgeDetector::Create(Parameter * p) +{ + return new GaussianEdgeDetector(p); +} + + + +GaussianEdgeDetector::GaussianEdgeDetector(Parameter * p): + Module(p) +{ + scale = GetFloatValue("scale", 1.0); + filterradius = int(2*scale+0.5); + filtersize = 1+2*filterradius; + + AddInput("INPUT"); + + AddOutput("OUTPUT"); // Edge intensity + AddOutput("MAXIMA"); // Edge maxima + AddOutput("NODES"); // Edge nodes + AddOutput("ORIENTATION"); // Orientation estimation + AddOutput("dx"); // The filters used + AddOutput("dy"); + AddOutput("dGx", filtersize, filtersize); // The filters used + AddOutput("dGy", filtersize, filtersize); + + input = NULL; + output = NULL; + maxima = NULL; + orientation = NULL; + dx = NULL; + dy = NULL; + dGx = NULL; + dGy = NULL; +} + + + +void +GaussianEdgeDetector::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + { + SetOutputSize("OUTPUT", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("MAXIMA", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("NODES", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("ORIENTATION", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("dx", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("dy", sx-2*filterradius, sy-2*filterradius); + } +} + + + +void +GaussianEdgeDetector::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); + maxima = GetOutputMatrix("MAXIMA"); + nodes = GetOutputMatrix("NODES"); + orientation = GetOutputMatrix("ORIENTATION"); + + dGx = GetOutputMatrix("dGx"); + dGy = GetOutputMatrix("dGy"); + + dx = GetOutputMatrix("dx"); + dy = GetOutputMatrix("dy"); + + // Initialize Gaussian Filters + + float Gsize = 1.0/scale; + + for (int j=0; j 0.3827 ? 1.0 : (d_x < -0.3827 ? -1 : 0)); + d_y = (d_y > 0.3827 ? 1.0 : (d_y < -0.3827 ? -1 : 0)); + + if (output[j][i] < output[j+int(d_y)][i+int(d_x)] || output[j][i] < output[j-int(d_y)][i-int(d_x)]) + maxima[j][i] = 0.0; + } +} + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.h b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.h new file mode 100755 index 000000000..ba5612e9b --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.h @@ -0,0 +1,46 @@ +// +// GaussianEdgeDetector.h This file is a part of the IKAROS project +// A module to find edges in an image + +#ifndef GAUSSIANEDGEDETECTOR +#define GAUSSIANEDGEDETECTOR + +#include "IKAROS.h" + +class GaussianEdgeDetector: public Module +{ +public: + + GaussianEdgeDetector(Parameter * p); + virtual ~GaussianEdgeDetector(); + + static Module * Create(Parameter * p); + + void SetSizes(); + void Init(); + void Tick(); + + int inputsize_x; + int inputsize_y; + + int outputsize_x; + int outputsize_y; + + float scale; + int filtersize; + int filterradius; + + float ** input; + + float ** dGx; // Derivate gaussian filters + float ** dGy; + float ** dx; + float ** dy; + float ** orientation; + float ** output; + float ** maxima; + float ** nodes; +}; + + +#endif diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.ikc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.ikc new file mode 100755 index 000000000..31ac32023 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/GaussianEdgeDetector/GaussianEdgeDetector.ikc @@ -0,0 +1,43 @@ + + + + + + Module that applies a Gaussian edge filter to an image. + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + GaussianEdgeDetector.h + GaussianEdgeDetector.cc + GaussianEdgeDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.cc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.cc new file mode 100755 index 000000000..f4f328d72 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.cc @@ -0,0 +1,101 @@ +// +// HysteresisThresholding.cc This file is a part of the IKAROS project +// A module to threshold edges in an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + +#include "HysteresisThresholding.h" + + + +Module * +HysteresisThresholding::Create(Parameter * p) +{ + return new HysteresisThresholding(p); +} + + + +HysteresisThresholding::HysteresisThresholding(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; + + T1 = GetFloatValue("T1", 0.3); + T2 = GetFloatValue("T2", 0.6); + + iterations = GetIntValue("iterations", 1); + range = GetIntValue("range", 1); +} + + + +void +HysteresisThresholding::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx, sy); +} + + + +void +HysteresisThresholding::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +HysteresisThresholding::~HysteresisThresholding() +{ +} + + + +void +HysteresisThresholding::Tick() +{ + reset_matrix(output, outputsize_x, outputsize_y); + + for (int n=0; n T2 || output[j][i] > 0) // edge in input or after hysteresis + for (int jj=-range; jj<=range; jj++) + for (int ii=-range; ii<=range; ii++) + if (input[j+jj][i+ii] > T1) + output[j+jj][i+ii] = 1; +} + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.h b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.h new file mode 100755 index 000000000..5e8c033f7 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.h @@ -0,0 +1,39 @@ +// +// HysteresisThresholding.h This file is a part of the IKAROS project +// A module to threshold edges in an image + +#ifndef HYSTERESISTHRESHOLDING +#define HYSTERESISTHRESHOLDING + +#include "IKAROS.h" + +class HysteresisThresholding: public Module +{ +public: + + HysteresisThresholding(Parameter * p); + virtual ~HysteresisThresholding(); + + static Module * Create(Parameter * p); + + void SetSizes(); + void Init(); + void Tick(); + + int inputsize_x; + int inputsize_y; + + int outputsize_x; + int outputsize_y; + + float ** input; + float ** output; + + int iterations; + int range; + float T1; + float T2; +}; + + +#endif diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.ikc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.ikc new file mode 100755 index 000000000..f650b1888 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/HysteresisThresholding/HysteresisThresholding.ikc @@ -0,0 +1,55 @@ + + + + + + This module implements iterative hysteresis thresholding of image. There are two threshold + constants T1 and T2 that determines how to extract edge elements from an edge image. If an + edge has higher intensity than T2 it is included in the output image. If an edge has higher + intensity than T2 it will also be included in the output image, but only if there is an + adjacent edge element that is already included. The parameter range determines how close + the adjacent edge > T2 must be. The algorithm is applied iteratively to the image the number + of times specified by the parameter iterations. This will iteratively fill out edges below T1. + The maximum lenght of an extracted edge element that it is initially below T2 and above T1 is + thus range*iterations. Each found edge element is represented by the value 1.0 in the output. + + + + + + + + + + + + + + + + + + This implementation is very slow and does not give very good results. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + HysteresisThresholding.h + HysteresisThresholding.cc + HysteresisThresholding.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/PrewittEdgeDetector/PrewittEdgeDetector.cc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/PrewittEdgeDetector/PrewittEdgeDetector.cc new file mode 100755 index 000000000..2f863ddfb --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/PrewittEdgeDetector/PrewittEdgeDetector.cc @@ -0,0 +1,93 @@ +// +// PrewittEdgeDetector.cc This file is a part of the IKAROS project +// A module to find edges in an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "PrewittEdgeDetector.h" + +using namespace ikaros; + + +Module * +PrewittEdgeDetector::Create(Parameter * p) +{ + return new PrewittEdgeDetector(p); +} + + + +PrewittEdgeDetector::PrewittEdgeDetector(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; +} + + + +void +PrewittEdgeDetector::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx-2, sy-2); +} + + + +void +PrewittEdgeDetector::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +PrewittEdgeDetector::~PrewittEdgeDetector() +{ +} + + + +void +PrewittEdgeDetector::Tick() +{ + float ** in = input; // alias + for (int j =1; j + + + + + Module that applies the Prewitt edge filter to an image. + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + PrewittEdgeDetector.h + PrewittEdgeDetector.cc + PrewittEdgeDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/RobertsEdgeDetector/RobertsEdgeDetector.cc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/RobertsEdgeDetector/RobertsEdgeDetector.cc new file mode 100755 index 000000000..80410d976 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/RobertsEdgeDetector/RobertsEdgeDetector.cc @@ -0,0 +1,91 @@ +// +// RobertsEdgeDetector.cc This file is a part of the IKAROS project +// A module to find edges in an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "RobertsEdgeDetector.h" + +using namespace ikaros; + +Module * +RobertsEdgeDetector::Create(Parameter * p) +{ + return new RobertsEdgeDetector(p); +} + + + +RobertsEdgeDetector::RobertsEdgeDetector(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; +} + + + +void +RobertsEdgeDetector::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx-1, sy-1); +} + + + +void +RobertsEdgeDetector::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +RobertsEdgeDetector::~RobertsEdgeDetector() +{ +} + + + +void +RobertsEdgeDetector::Tick() +{ + for (int j =0; j + + + + + Module that applies the Roberts edge filter to an image. + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + RobertsEdgeDetector.h + RobertsEdgeDetector.cc + RobertsEdgeDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/SobelEdgeDetector/SobelEdgeDetector.cc b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/SobelEdgeDetector/SobelEdgeDetector.cc new file mode 100755 index 000000000..ad6f21efc --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/EdgeDetectors/SobelEdgeDetector/SobelEdgeDetector.cc @@ -0,0 +1,204 @@ +// +// SobelEdgeDetector.cc This file is a part of the IKAROS project +// A module to find edges in an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "SobelEdgeDetector.h" + + +using namespace ikaros; + + +Module * +SobelEdgeDetector::Create(Parameter * p) +{ + return new SobelEdgeDetector(p); +} + + + +SobelEdgeDetector::SobelEdgeDetector(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + type = GetIntValueFromList("type"); + + input = NULL; + output = NULL; + + dx_temp = NULL; + dy_temp = NULL; +} + + + +void +SobelEdgeDetector::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx-2, sy-2); +} + + + +void +SobelEdgeDetector::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); + + if (type == 0 || type == 1) + { + dx_temp = create_matrix(outputsize_x, outputsize_y); + dy_temp = create_matrix(outputsize_x, outputsize_y); + } + + dx_kernel = create_matrix(3, 3); + dy_kernel = create_matrix(3, 3); + + dx_kernel[0][0] = 1; + dx_kernel[1][0] = 2; + dx_kernel[2][0] = 1; + + dx_kernel[0][2] = -1; + dx_kernel[1][2] = -2; + dx_kernel[2][2] = -1; + + dy_kernel[0][0] = 1; + dy_kernel[0][1] = 2; + dy_kernel[0][2] = 1; + + dy_kernel[2][0] = -1; + dy_kernel[2][1] = -2; + dy_kernel[2][2] = -1; +} + + + +SobelEdgeDetector::~SobelEdgeDetector() +{ + if (dx_temp) destroy_matrix(dx_temp); + if (dy_temp) destroy_matrix(dy_temp); + destroy_matrix(dx_kernel); + destroy_matrix(dy_kernel); +} + + + +void +SobelEdgeDetector::CalculateSqrt() +{ + convolve(dx_temp, input, dx_kernel, outputsize_x, outputsize_y, 3, 3); + convolve(dy_temp, input, dy_kernel, outputsize_x, outputsize_y, 3, 3); + hypot(output, dx_temp, dy_temp, outputsize_x, outputsize_y); + +} + + + +void +SobelEdgeDetector::CalculateAbs() +{ + /* + float ** in = input; // alias + for(int j =1; j + + + + + Module that applies the Sobel edge filter to an image. + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + SobelEdgeDetector.h + SobelEdgeDetector.cc + SobelEdgeDetector.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/GaborFilter/Examples/GaborFilter_test.ikc b/Source/Modules/VisionModules/ImageOperators/GaborFilter/Examples/GaborFilter_test.ikc new file mode 100755 index 000000000..77d3a21a2 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/GaborFilter/Examples/GaborFilter_test.ikc @@ -0,0 +1,80 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/ImageOperators/GaborFilter/GaborFilter.cc b/Source/Modules/VisionModules/ImageOperators/GaborFilter/GaborFilter.cc new file mode 100755 index 000000000..980374efe --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/GaborFilter/GaborFilter.cc @@ -0,0 +1,144 @@ +// +// GaborFilter.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +#include "GaborFilter.h" + +using namespace ikaros; + + + +Module * +GaborFilter::Create(Parameter * p) +{ + return new GaborFilter(p); +} + + + +GaborFilter::GaborFilter(Parameter * p): + Module(p) +{ + scale = GetFloatValue("scale", 1.0); + filterradius = int(2*scale+0.5); + filtersize = 1+2*filterradius; + + gamma = GetFloatValue("gamma", 0.5); // aspect ratio + lambda = GetFloatValue("lambda", 4); // wavelength + theta = GetFloatValue("theta", 0); // orientation + phi = GetFloatValue("phi", 1.57); // phase offset + sigma = GetFloatValue("sigma", 1); // width + + + AddInput("INPUT"); + AddOutput("OUTPUT"); // Filter intensity + AddOutput("FILTER", filtersize, filtersize); // The filter used + AddOutput("GAUSSIAN", filtersize, filtersize); + AddOutput("GRATING", filtersize, filtersize); + + input = NULL; + output = NULL; + filter = NULL; + gaussian = NULL; + grating = NULL; +} + + + +void +GaborFilter::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + { + SetOutputSize("OUTPUT", sx-2*filterradius, sy-2*filterradius); + SetOutputSize("filter", sx-2*filterradius, sy-2*filterradius); + } +} + + + +void +GaborFilter::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); + filter = GetOutputMatrix("FILTER"); + gaussian = GetOutputMatrix("GAUSSIAN"); + grating = GetOutputMatrix("GRATING"); + + // Initialize Gabor Filter + + for (int j=0; j + + + + + Module that constructs a Gabor filter and applies it to an image. + + + + + + + + + + + + + + + + + + + + + + + The current implementation is incredibly slow. + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + GaborFilter.h + GaborFilter.cc + GaborFilter.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.cc b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.cc new file mode 100755 index 000000000..5f4ddc001 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.cc @@ -0,0 +1,97 @@ +// +// Dilate.cc This file is a part of the IKAROS project +// A module to apply the Dilate operator +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +//#define DEBUG + +#include "Dilate.h" + +using namespace ikaros; + +Module * +Dilate::Create(Parameter * p) +{ + return new Dilate(p); +} + + + +Dilate::Dilate(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; +} + + + +void +Dilate::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx-2, sy-2); +} + + + +void +Dilate::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +Dilate::~Dilate() +{ +} + + + +void +Dilate::Tick() +{ + float ** in = input; // alias + for (int j =1; j t) + t = in[j+jj][i+ii]; + output[j-1][i-1] = t; + } +} + + + diff --git a/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.h b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.h new file mode 100755 index 000000000..eee87812f --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.h @@ -0,0 +1,34 @@ +// +// Dilate.h This file is a part of the IKAROS project +// A module to find edges in an image + +#ifndef DILATE +#define DILATE + +#include "IKAROS.h" + +class Dilate: public Module +{ +public: + + Dilate(Parameter * p); + virtual ~Dilate(); + + static Module * Create(Parameter * p); + + void SetSizes(); + void Init(); + void Tick(); + + int inputsize_x; + int inputsize_y; + + int outputsize_x; + int outputsize_y; + + float ** input; + float ** output; +}; + + +#endif diff --git a/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.ikc b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.ikc new file mode 100755 index 000000000..5f825fbd9 --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Dilate/Dilate.ikc @@ -0,0 +1,35 @@ + + + + + + Module that applies the 3x3 dilate operator to an image (here generalized as + the max of the pixels in the area). + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Dilate.h + Dilate.cc + Dilate.ikc + + + diff --git a/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Erode/Erode.cc b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Erode/Erode.cc new file mode 100755 index 000000000..410261f7f --- /dev/null +++ b/Source/Modules/VisionModules/ImageOperators/MorphologicalOperators/Erode/Erode.cc @@ -0,0 +1,95 @@ +// +// Erode.cc This file is a part of the IKAROS project +// A module that erodes an image +// +// Copyright (C) 2004 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "Erode.h" + +using namespace ikaros; + +Module * +Erode::Create(Parameter * p) +{ + return new Erode(p); +} + + + +Erode::Erode(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; +} + + + +void +Erode::SetSizes() +{ + int sx = GetInputSizeX("INPUT"); + int sy = GetInputSizeY("INPUT"); + if (sx != unknown_size && sy != unknown_size) + SetOutputSize("OUTPUT", sx-2, sy-2); +} + + + +void +Erode::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +Erode::~Erode() +{ +} + + + +void +Erode::Tick() +{ + float ** in = input; // alias + for (int j =1; j + + + + + Module that applies the 3x3 erode operator to an image (here generalized as + the max of the pixels in the area). + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Erode.h + Erode.cc + Erode.ikc + + + diff --git a/Source/Modules/VisionModules/SaliencyMap/Examples/SaliencyMap_test.ikc b/Source/Modules/VisionModules/SaliencyMap/Examples/SaliencyMap_test.ikc new file mode 100755 index 000000000..8250f210b --- /dev/null +++ b/Source/Modules/VisionModules/SaliencyMap/Examples/SaliencyMap_test.ikc @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.cc b/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.cc new file mode 100755 index 000000000..712188fd3 --- /dev/null +++ b/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.cc @@ -0,0 +1,261 @@ +// +// SaliencyMap.cc This file is a part of the IKAROS project +// A generic attention map +// +// Copyright (C) 2005-2007 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +// Normalize everything for absolute area +// Coordinates between 0-1 everywhere + +// 2006-01-20 Heavy optimization - now 100 times faster - CBA + + +#include "SaliencyMap.h" + +using namespace ikaros; + +#include "ctype.h" // TODO: remove when GetArrayValue is used + + +Module * +SaliencyMap::Create(Parameter * p) +{ + return new SaliencyMap(p); +} + + + +SaliencyMap::SaliencyMap(Parameter * p): + Module(p) +{ + spatial_bias = NULL; + input = NULL; + focus = NULL; + estimation = NULL; + initial_gain = NULL; + + // Add the requested number of inputs ** function for Module::AddMultipleInputs(name, n) return n + + no_of_inputs = GetIntValue("no_of_inputs", 1); + + for (int i=0; iget()); + + for (int n=0; nget(); + + for (int n=0; nput(input[n][my][mx]); + + estimation_store->put(estimation[0]); + } +} + diff --git a/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.h b/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.h new file mode 100755 index 000000000..79c9c4092 --- /dev/null +++ b/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.h @@ -0,0 +1,78 @@ +// +// SaliencyMap.h This file is a part of the IKAROS project +// A generic attention map +// +// Copyright (C) 2003-2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef SALIENCYMAP +#define SALIENCYMAP + +#include "IKAROS.h" + +class DelayLine; + +class SaliencyMap: public Module +{ +public: + SaliencyMap(Parameter * p); + virtual ~SaliencyMap(); + + static Module * Create(Parameter * p); + + void SetSizes(); + void Init(); + + void Tick(); + + int no_of_inputs; // number of inputs set in xml file + + int input_size_x; // input size + int input_size_y; + + int output_size_x; // input size + int output_size_y; + + float * spatial_bias; + + float *** input; + float ** input_sum; + + float * gain; + float * initial_gain; + + float * beta; + + DelayLine ** input_store; + + float ** salience; + float * focus; // 2 x 1 + float * estimation; + DelayLine * estimation_store; + + float * reinforcement; + + int integration_radius; // smoothing + int type; // max = 0, boltzmann = 1, 2 = exponential + int reinforcement_delay; + + float temperature; + float alpha; +}; + + +#endif diff --git a/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.ikc b/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.ikc new file mode 100755 index 000000000..8f63de895 --- /dev/null +++ b/Source/Modules/VisionModules/SaliencyMap/SaliencyMap.ikc @@ -0,0 +1,47 @@ + + + + + + A minimal saliency map implementation. + + + + + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + SaliencyMap.h + SaliencyMap.cc + SaliencyMap.ikc + + + + diff --git a/Source/Modules/VisionModules/Scaling/Downsample/Downsample.cc b/Source/Modules/VisionModules/Scaling/Downsample/Downsample.cc new file mode 100755 index 000000000..845e62d44 --- /dev/null +++ b/Source/Modules/VisionModules/Scaling/Downsample/Downsample.cc @@ -0,0 +1,98 @@ +// +// Downsample.cc This file is a part of the IKAROS project +// Module that downsamples an image +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "Downsample.h" + + + +Module * +Downsample::Create(Parameter * p) +{ + return new Downsample(p); +} + + + +Downsample::Downsample(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; +} + + + +void +Downsample::SetSizes() +{ + int sizex = GetInputSizeX("INPUT"); + int sizey = GetInputSizeY("INPUT"); + + if (sizex == unknown_size || sizex == unknown_size) + return; + + SetOutputSize("OUTPUT", sizex/2, sizey/2); +} + + + +void +Downsample::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +Downsample::~Downsample() +{ +// delete [] input; +} + + + +void +Downsample::Tick() +{ + int sj = 0; + for (int j=0; j + + + + + Module that downsamples an image to half size. No interpolation is done. + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Downsample.h + Downsample.cc + Downsample.ikc + + + diff --git a/Source/Modules/VisionModules/Scaling/Downsample/Examples/Downsample_test.ikc b/Source/Modules/VisionModules/Scaling/Downsample/Examples/Downsample_test.ikc new file mode 100755 index 000000000..f23a60e04 --- /dev/null +++ b/Source/Modules/VisionModules/Scaling/Downsample/Examples/Downsample_test.ikc @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/Scaling/Upsample/Examples/Upsample_test.ikc b/Source/Modules/VisionModules/Scaling/Upsample/Examples/Upsample_test.ikc new file mode 100755 index 000000000..ff11d41e3 --- /dev/null +++ b/Source/Modules/VisionModules/Scaling/Upsample/Examples/Upsample_test.ikc @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/Scaling/Upsample/Upsample.cc b/Source/Modules/VisionModules/Scaling/Upsample/Upsample.cc new file mode 100755 index 000000000..cc2d63de1 --- /dev/null +++ b/Source/Modules/VisionModules/Scaling/Upsample/Upsample.cc @@ -0,0 +1,102 @@ +// +// Upsample.cc This file is a part of the IKAROS project +// Module that extracts a focus of attention from an image +// +// Copyright (C) 2006 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#include "Upsample.h" + + + +Module * +Upsample::Create(Parameter * p) +{ + return new Upsample(p); +} + + + +Upsample::Upsample(Parameter * p): + Module(p) +{ + AddInput("INPUT"); + AddOutput("OUTPUT"); + + input = NULL; + output = NULL; +} + + + +void +Upsample::SetSizes() +{ + int sizex = GetInputSizeX("INPUT"); + int sizey = GetInputSizeY("INPUT"); + + if (sizex == unknown_size || sizex == unknown_size) + return; + + SetOutputSize("OUTPUT", sizex*2, sizey*2); +} + + + +void +Upsample::Init() +{ + inputsize_x = GetInputSizeX("INPUT"); + inputsize_y = GetInputSizeY("INPUT"); + + outputsize_x = GetOutputSizeX("OUTPUT"); + outputsize_y = GetOutputSizeY("OUTPUT"); + + input = GetInputMatrix("INPUT"); + output = GetOutputMatrix("OUTPUT"); +} + + + +Upsample::~Upsample() +{ +// delete [] input; +} + + + +void +Upsample::Tick() +{ + int sj = 0; + for (int j=0; j + + + + + Module that upsamples an image to double size. No interpolation is done. + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + Upsample.h + Upsample.cc + Upsample.ikc + + + diff --git a/Source/Modules/VisionModules/SpatialClustering/Examples/SpatialClustering_test.ikc b/Source/Modules/VisionModules/SpatialClustering/Examples/SpatialClustering_test.ikc new file mode 100755 index 000000000..d65070c9b --- /dev/null +++ b/Source/Modules/VisionModules/SpatialClustering/Examples/SpatialClustering_test.ikc @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/SpatialClustering/SpatialClustering.cc b/Source/Modules/VisionModules/SpatialClustering/SpatialClustering.cc new file mode 100755 index 000000000..ecd2a8c4e --- /dev/null +++ b/Source/Modules/VisionModules/SpatialClustering/SpatialClustering.cc @@ -0,0 +1,303 @@ +// +// SpatialClustering.cc This file is a part of the Ikaros project +// +// +// Copyright (C) 2005-2008 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + + + +#include "SpatialClustering.h" + +using namespace ikaros; + +void +SpatialClustering::Init() +{ + sorting = GetBoolValue("sorting", false); + no_of_clusters = GetIntValue("no_of_clusters", 1); + + input = GetInputMatrix("INPUT"); + + size_x = GetInputSizeX("INPUT"); + size_y = GetInputSizeY("INPUT"); + output = GetOutputMatrix("OUTPUT"); + confidence = GetOutputArray("CONFIDENCE"); + last_output = create_matrix(2, no_of_clusters); + + active = create_array(no_of_clusters); + + memory_exhausted = false; + + // Get and scale relative values to image size (i. e. pixel) + + threshold = GetFloatValue("threshold", 0.1); + cluster_radius = float(size_x)*GetFloatValue("cluster_radius", 0.1); + max_cluster_area = 2*pi*cluster_radius*cluster_radius; + min_cluster_area = float(size_x)*float(size_y)*GetFloatValue("min_cluster_area", 0.0001); + tracking_distance = float(size_x)*GetFloatValue("tracking_distance", 0.25); + +} + + + +SpatialClustering::~SpatialClustering() +{ + destroy_matrix(last_output); +} + + + +void +SpatialClustering::Cluster::Init() +{ + x_sum = 0; + y_sum = 0; + n = 0; +} + + + +inline float +SpatialClustering::Cluster::Distance(float x, float y) +{ + float cx = x_sum / n; + float cy = y_sum / n; + return hypot(cx-x, cy-y); +} + + + +inline void +SpatialClustering::Cluster::Update(float x, float y) +{ + x_sum += x; + y_sum += y; + + if(n == 0) + { + min_x = x; + max_x = x; + min_y = y; + max_y = y; + } + else + { + if(x > max_x) + max_x = x; + else if(x < min_x) + min_x = x; + + if(y > max_y) + max_y = y; + else if(y < min_y) + min_y = y; + } + + n += 1.0; +} + + + +float SpatialClustering::Cluster::GetX() +{ + return (n>0 ? x_sum / n : 0); +} + + + +float SpatialClustering::Cluster::GetY() +{ + return (n>0 ? y_sum / n : 0); +} + + + +float SpatialClustering::Cluster::GetWeight() +{ + return float(n); +} + + + +float SpatialClustering::Cluster::GetSize() +{ + return (max_x-min_x)*(max_y-min_y); +} + + + +void +SpatialClustering::InitClusters() +{ + cluster_n = 0; +} + + + +inline void +SpatialClustering::AddPoint(float x, float y) +{ + // Find closest cluster + + float min_dist = 1000000; + int min_cluster = 0; + + for(int i=0; i 1.0) + cert = 1.0; + float d = 1000; + float t; + for(int i=0; iGetWeight() < cluster2->GetWeight()) + return -1; + else if(cluster1->GetWeight() > cluster2->GetWeight()) + return 1; + else + return 0; +} + + +// TEST + +float x0=0, x1=0, x2=0, y0=0, y1=0, y2=0; + +// get center method: average / center of rect + +void +SpatialClustering::Tick() +{ + InitClusters(); + + int ccc = 0; + for(int j=0; j threshold) + { + AddPoint(float(i), float(j)); + ccc++; + } + + no_of_found_clusters_last = no_of_found_clusters; + copy_matrix(last_output, output, 2, no_of_clusters); + + reset_array(confidence, no_of_clusters); + + // Sort clusters + + if(sorting) + qsort(cluster, cluster_n, sizeof(Cluster), &compare_cluster); + + // Choose clusters that are large enough + + float t; + for(int c=0; c min_cluster_area) + AddCluster(cluster[c].GetX()/float(size_x), cluster[c].GetY()/float(size_y), t); + } + + for(int i=0; i + + + + + Module used to find clusters in an image. Clusters are made up of pixels of value 1. The maximum number of clusters to be found as well as the minimu area + of the cluster that is filled with 1's can be set. In addition, the module can track clusters between frames to give consistent numbering of the clusters. + The output is a table of target coordinates. + + + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + SpatialClustering.h + SpatialClustering.cc + SpatialClustering.ikc + + + + diff --git a/Source/Modules/VisionModules/WhiteBalance/Examples/WhiteBalance_test.ikc b/Source/Modules/VisionModules/WhiteBalance/Examples/WhiteBalance_test.ikc new file mode 100755 index 000000000..e0052524f --- /dev/null +++ b/Source/Modules/VisionModules/WhiteBalance/Examples/WhiteBalance_test.ikc @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.cc b/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.cc new file mode 100755 index 000000000..76ef033c6 --- /dev/null +++ b/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.cc @@ -0,0 +1,132 @@ +// +// WhiteBalance.cc This file is a part of the IKAROS project +// A module to white balance an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// 2005-01-12 Name changed from VonKries to WhiteBalance +// + +#include "WhiteBalance.h" + +using namespace ikaros; + +void +WhiteBalance::Init() +{ + red_target = GetFloatValue("red_target", 255.0); + green_target = GetFloatValue("green_target", 255.0); + blue_target = GetFloatValue("blue_target", 255.0); + + reference_x0 = GetIntValue("x0", 10); + reference_y0 = GetIntValue("y0", 10); + reference_x1 = GetIntValue("x1", 20); + reference_y1 = GetIntValue("y1", 20); + + log_x0 = GetIntValue("log_x0", 0); + log_y0 = GetIntValue("log_y0", 0); + log_x1 = GetIntValue("log_x1", 0); + log_y1 = GetIntValue("log_y1", 0); + + size_x = GetInputSizeX("INPUT0"); + size_y = GetInputSizeY("INPUT0"); + + input0 = GetInputMatrix("INPUT0"); + input1 = GetInputMatrix("INPUT1"); + input2 = GetInputMatrix("INPUT2"); + + output0 = GetOutputMatrix("OUTPUT0"); + output1 = GetOutputMatrix("OUTPUT1"); + output2 = GetOutputMatrix("OUTPUT2"); +} + + + +void +WhiteBalance::Tick() +{ + float red_ref = 0; + float green_ref = 0; + float blue_ref = 0; + + // Calculate Reference Colour + + for (int i=reference_x0; i\t\t%.2f\t%.2f\t%.2f\n", rr0, gg0, bb0, rr, gg, bb); +} + + + diff --git a/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.h b/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.h new file mode 100755 index 000000000..87dd4ae1c --- /dev/null +++ b/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.h @@ -0,0 +1,66 @@ +// +// WhiteBalance.h This file is a part of the IKAROS project +// A module to white balance an image +// +// Copyright (C) 2003 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// + +#ifndef WHITEBALANCE +#define WHITEBALANCE + +#include "IKAROS.h" + +class WhiteBalance: public Module +{ +public: + + WhiteBalance(Parameter * p) : Module(p) {} + virtual ~WhiteBalance() {} + + static Module * Create(Parameter * p) { return new WhiteBalance(p); } + + void Init(); + void Tick(); + + int size_x; + int size_y; + + float ** input0; + float ** input1; + float ** input2; + + float ** output0; + float ** output1; + float ** output2; + + float red_target; + float green_target; + float blue_target; + + int reference_x0; + int reference_y0; + int reference_x1; + int reference_y1; + + int log_x0; + int log_y0; + int log_x1; + int log_y1; +}; + + +#endif diff --git a/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.ikc b/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.ikc new file mode 100755 index 000000000..aa3a5d012 --- /dev/null +++ b/Source/Modules/VisionModules/WhiteBalance/WhiteBalance.ikc @@ -0,0 +1,78 @@ + + + + + + Module used for white balancing adaptation of a color image. Given a reference image + area and a target color, for example a white part of the input image and the color coordinates + for white, applies von Kries adaptation to the image. This will transform the reference area + the target color and simultaneously change the color coordinates for all other pixels in the + image. The image region for the reference color is given by x0, y0, x1, and y1 and the color + of the reference region is given by red_target, green_target and blue_target. In addition, + the average color of an arbitrary region can be written to the output, This region is set by + the log-parameters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + The reference region can only be set in the XML-file and can not change during execution. + This should be changed in the future with either an adaptive white calcuation or an attention + based method. + + + + von Kries, J. (1902) Chromatic adaptation. In MacAdam, D. L. (Ed.) Sources of color vision, + 109-119, Cambridge, MA: MIT Press. + + + + Balkenius, C., Johansson, A. J, and Balkenius, A. (2003). Color constancy in visual scene + perception. Lund University Cognitive Studies, 98. + + + 2003 + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + WhiteBalance.h + WhiteBalance.cc + WhiteBalance.ikc + + + diff --git a/Source/UserModules/MinimalModule/MinimalModule.cc b/Source/UserModules/MinimalModule/MinimalModule.cc new file mode 100755 index 000000000..84923d71d --- /dev/null +++ b/Source/UserModules/MinimalModule/MinimalModule.cc @@ -0,0 +1,44 @@ +// +// MinimalModule.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2007 +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: +// +// + + +#include "MinimalModule.h" + +using namespace ikaros; + +void +MinimalModule::Init() +{ +} + + + +void +MinimalModule::Tick() +{ +} + + diff --git a/Source/UserModules/MinimalModule/MinimalModule.h b/Source/UserModules/MinimalModule/MinimalModule.h new file mode 100755 index 000000000..1ea6e260d --- /dev/null +++ b/Source/UserModules/MinimalModule/MinimalModule.h @@ -0,0 +1,45 @@ +// +// MinimalModule.h This file is a part of the IKAROS project +// +// +// Copyright (C) 2011 +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: +// +// + +#ifndef MinimalModule_ +#define MinimalModule_ + +#include "IKAROS.h" + +class MinimalModule: public Module +{ +public: + static Module * Create(Parameter * p) { return new MinimalModule(p); } + + MinimalModule(Parameter * p) : Module(p) {} + virtual ~MinimalModule() {} + + void Init(); + void Tick(); +}; + +#endif + diff --git a/Source/UserModules/MinimalModule/MinimalModule.ikc b/Source/UserModules/MinimalModule/MinimalModule.ikc new file mode 100755 index 000000000..c008c194a --- /dev/null +++ b/Source/UserModules/MinimalModule/MinimalModule.ikc @@ -0,0 +1,36 @@ + + + + + + Minimal module that can be used as a start for a new module. + Simply change all occurrences of "MinimalModule" to the name of your new module in + MinimalModule.cc, MinimalModule.h and MinimalModule.ikc (this file), rename the files, and fill + in the new code and documentation. This module is located in the + UserModules directory. + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + MinimalModule.h + MinimalModule.cc + MinimalModule.ikc + + + + diff --git a/Source/UserModules/MyModule/Examples/MyModule_test.ikc b/Source/UserModules/MyModule/Examples/MyModule_test.ikc new file mode 100755 index 000000000..4746eb77e --- /dev/null +++ b/Source/UserModules/MyModule/Examples/MyModule_test.ikc @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + diff --git a/Source/UserModules/MyModule/MyModule.cc b/Source/UserModules/MyModule/MyModule.cc new file mode 100755 index 000000000..9bba3974a --- /dev/null +++ b/Source/UserModules/MyModule/MyModule.cc @@ -0,0 +1,153 @@ +// +// MyModule.cc This file is a part of the IKAROS project +// +// +// Copyright (C) 2011 +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: +// +// This example is intended as a starting point for writing new Ikaros modules +// The example includes most of the calls that you may want to use in a module. +// If you prefer to start with a clean example, use he module MinimalModule instead. +// +// MyModule is a new version of MyModule that uses the IKC file rather than +// function calls during initialization. + +#include "MyModule.h" + +// use the ikaros namespace to access the math library +// this is preferred to using math.h + + +using namespace ikaros; + + +void +MyModule::Init() +{ + // You can get parameters from the IKC file here or in any other + // member functions. Since the method for reading the values + // from the XML structure is not very efficient, it is best to store + // the parameters in member variables as below. + // GetFloatValue gets a parameter as a float with a particular + // name. If the parameter is not found, the default value 7.0 + // is returned instead. + + float_parameter = GetFloatValue("parameter1"); + + // GetIntValue gets parameter2 from the XML structure or + // sets the parameter to the default value 2 if it is not found + + int_parameter = GetIntValue("parameter2"); + + // This is were we get pointers to the inputs and outputs + + // Get a pointer to the input INPUT1 and its size which we set + // to 10 above + // It does not matter whether a matrix of array is connected + // to the inputs. We will teat it an array in this module + // anyway. + + input_array = GetInputArray("INPUT1"); + input_array_size = GetInputSize("INPUT1"); + + // Get pointer to a matrix and treat it as a matrix. If an array is + // connected to this input, the size_y will be 1. + + input_matrix = GetInputMatrix("INPUT2"); + input_matrix_size_x = GetInputSizeX("INPUT2"); + input_matrix_size_y = GetInputSizeY("INPUT2"); + + // Do the same for the outputs + + output_array = GetOutputArray("OUTPUT1"); + output_array_size = GetOutputSize("OUTPUT1"); + + output_matrix = GetOutputMatrix("OUTPUT2"); + output_matrix_size_x = GetOutputSizeX("OUTPUT2"); + output_matrix_size_y = GetOutputSizeY("OUTPUT2"); + + // Allocate some data structures to use internaly + // in the module + + // Create an array with ten elements + // To access the array use internal_array[i]. + + internal_array = create_array(10); + + // Create a matrix with the same size as INPUT2 + // IMPORTANT: For the matrix the sizes are given as X, Y + // which is the OPPOSITE of ROW, COLUMN. + + internal_matrix = create_matrix(input_matrix_size_x, input_matrix_size_y); + + // To acces the matrix use internal_matrix[y][x]. + // + // It is also possible to use the new operator to + // create arrays, but create_array and create_matix + // should be used to make sure that memeory is + // allocated in a way that is suitable for the math + // library and fast copying operations. +} + + + +MyModule::~MyModule() +{ + // Destroy data structures that you allocated in Init. + + destroy_array(internal_array); + destroy_matrix(internal_matrix); + + // Do NOT destroy data structures that you got from the + // kernel with GetInputArray, GetInputMatrix etc. +} + + + +void +MyModule::Tick() +{ + // This is where you implement your algorithm + // to calculate the outputs from the inputs + + // Make a copy of the data on INPUT2 which is now + // in input_matrix to internal_matrix + // Arrays can be copied with copy_array + // To clear an array or matrix use reset_array and reset_matrix + + copy_matrix(internal_matrix, input_matrix, input_matrix_size_x, input_matrix_size_y); + + // Calculate the output by iterating over the elements of the + // output matrix. Note the order of the indices into the matrix. + // + // In most cases it is much faster to put the for-loops with + // the row index (j) in the outer loop, because it will lead + // to more efficient cache use. + + for (int j=0; j +// +// Copyright (C) 2011 +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: +// +// + +#ifndef MyModule_ +#define MyModule_ + +#include "IKAROS.h" + +class MyModule: public Module +{ +public: + static Module * Create(Parameter * p) { return new MyModule(p); } + + MyModule(Parameter * p) : Module(p) {} + virtual ~MyModule(); + + void Init(); + void Tick(); + + // pointers to inputs and outputs + // and integers to represent their sizes + + float * input_array; + int input_array_size; + + float ** input_matrix; + int input_matrix_size_x; + int input_matrix_size_y; + + float * output_array; + int output_array_size; + + float ** output_matrix; + int output_matrix_size_x; + int output_matrix_size_y; + + // internal data storage + + float * internal_array; + float ** internal_matrix; + + // parameter values + + float float_parameter; + int int_parameter; +}; + +#endif diff --git a/Source/UserModules/MyModule/MyModule.ikc b/Source/UserModules/MyModule/MyModule.ikc new file mode 100755 index 000000000..506ebb519 --- /dev/null +++ b/Source/UserModules/MyModule/MyModule.ikc @@ -0,0 +1,47 @@ + + + + + + Module that can be used as a start for a new module. + Simply change all occurrences of "MyModule" to the name of your new module in + MyModule.cc, MyModule.h and MyModule.ikc (this file), rename the files, and fill + in the new code and documentation. This module is located in the + UserModules directory. + + + + + + + + + + + + + + + + + + + Christian Balkenius + christian.balkenius@lucs.lu.se + Lund University Cognitive Science + http://www.lucs.lu.se/Christian.Balkenius + + + + MyModule.h + MyModule.cc + MyModule.ikc + + + + diff --git a/Source/UserModules/UserModules.h b/Source/UserModules/UserModules.h new file mode 100755 index 000000000..bf24bc0a2 --- /dev/null +++ b/Source/UserModules/UserModules.h @@ -0,0 +1,42 @@ +// +// UserModules.h This file is a part of the IKAROS project +// This file includes the h-files of all user modules +// It contains InitUserModules which is called at start-up +// +// Copyright (C) 2003-2011 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created: 2003-04-20 +// +// Include all your modules here + +#include "UserModules/MyModule/MyModule.h" // Change this to the name of your module +#include "UserModules/MinimalModule/MinimalModule.h" // Change this to the name of your module + +void InitUserModules(Kernel & k); + +void +InitUserModules(Kernel & k) +{ +// Add a line for each user module here + + k.AddClass("MyModule", &MyModule::Create, "Source/UserModules/MyModule/"); // Change this to the name and path of your module + k.AddClass("MinimalModule", &MinimalModule::Create, "Source/UserModules/MinimalModule/"); // Change this to the name and path of your module +} + + diff --git a/Source/WebUI/UI/404.html b/Source/WebUI/UI/404.html new file mode 100755 index 000000000..c8b7792d3 --- /dev/null +++ b/Source/WebUI/UI/404.html @@ -0,0 +1,7 @@ + + +404 Not Found + +

Not Found

+The requested URL was not found on this server.

+ diff --git a/Source/WebUI/UI/404.jpg b/Source/WebUI/UI/404.jpg new file mode 100755 index 000000000..ebcdffad2 Binary files /dev/null and b/Source/WebUI/UI/404.jpg differ diff --git a/Source/WebUI/UI/Buttons/pause.png b/Source/WebUI/UI/Buttons/pause.png new file mode 100755 index 000000000..5b707cf37 Binary files /dev/null and b/Source/WebUI/UI/Buttons/pause.png differ diff --git a/Source/WebUI/UI/Buttons/realtime.png b/Source/WebUI/UI/Buttons/realtime.png new file mode 100755 index 000000000..06e907b6f Binary files /dev/null and b/Source/WebUI/UI/Buttons/realtime.png differ diff --git a/Source/WebUI/UI/Buttons/run.png b/Source/WebUI/UI/Buttons/run.png new file mode 100755 index 000000000..e56445cc9 Binary files /dev/null and b/Source/WebUI/UI/Buttons/run.png differ diff --git a/Source/WebUI/UI/Buttons/step.png b/Source/WebUI/UI/Buttons/step.png new file mode 100755 index 000000000..6facd8e12 Binary files /dev/null and b/Source/WebUI/UI/Buttons/step.png differ diff --git a/Source/WebUI/UI/Buttons/stop.png b/Source/WebUI/UI/Buttons/stop.png new file mode 100755 index 000000000..816bb6b7d Binary files /dev/null and b/Source/WebUI/UI/Buttons/stop.png differ diff --git a/Source/WebUI/UI/control.js b/Source/WebUI/UI/control.js new file mode 100755 index 000000000..0fd15f9c5 --- /dev/null +++ b/Source/WebUI/UI/control.js @@ -0,0 +1,708 @@ +var ikc_doc_element = null; +var current_group_path = ""; +var timer = null; +var periodic_task = null; +var current_view = 0; +var view_list = []; + +// STATE + +var realtime = false; +var reconnect_counter = 0; + + +// UTILITIES + +function ignore_data(obj) +{ +} + + + +function get(url, callback, timeout, time) +{ + function getURL_alt(url, callback) + { + function timoutCallback() + { + if(timeout) timeout(); + } + + function callCallback() + { + if (ajaxRequest.readyState == 4) + { + if(ajaxRequest.status == 200) + { + clearTimeout(ajaxTimeout); + if (ajaxCallback) ajaxCallback({content:ajaxRequest.responseText}); + } + //else + // alert("Returned status code " + ajaxRequest.status); + } + } + + var ajaxRequest = null; + var ajaxCallback = callback; + + ajaxRequest = new XMLHttpRequest(); + ajaxRequest.onreadystatechange = callCallback; + ajaxRequest.open("GET", url, true); + ajaxRequest.send(null); + + if(timeout) + ajaxTimeout = setTimeout(function () { timoutCallback(); }, time); + } + + if(window.getURL) + getURL(url, callback); + else if(window.XMLHttpRequest) + getURL_alt(url, callback); + else + alert("Error: This web browser does not have getURL or XMLHttpRequest"); +} + + + +function getXML(url, callback) +{ + function getURL_alt(url, callback) + { + function callCallback() + { + if (ajaxRequest.readyState == 4) + { + if(ajaxRequest.status == 200) + if (ajaxCallback) ajaxCallback(ajaxRequest.responseXML); + } + else + { + } + } + + var ajaxRequest = null; + var ajaxCallback = callback; + + ajaxRequest = new XMLHttpRequest(); + ajaxRequest.onreadystatechange = callCallback; + ajaxRequest.open("GET", url, true); + ajaxRequest.send(null); + } + + if(window.getURL) + getURL(url, callback); + else if(window.XMLHttpRequest) + getURL_alt(url, callback); + else + alert("Error: This web browser does not have getURL or XMLHttpRequest"); +} + + + + + + +// CONTROL AND USER INTERFACE + +function select_button(i) +{ + var c = document.getElementById("controls"); + for(var j=0; j0) + { + triangle = document.createTextNode("▷ "); + tri_span.appendChild(triangle); + + var ul = document.createElement("ul"); + ul.setAttribute("class", "hidden"); + build_group_list(subgroups, ul, ip); + li.appendChild(ul); + } + + list.appendChild(li); + } +} + + + +function build_view_list_with_editor(view) +{ + if(!view) + return; + + view_list = view; + + var vc = document.getElementById("viewdots"); + + if(!vc) + return; + + while(vc.firstChild) + vc.removeChild(vc.firstChild); + + for(i in view_list) + { + var a = document.createElement("a"); + var dot = document.createTextNode("○ "); + a.appendChild(dot); + vc.appendChild(a); + + a.setAttribute("onclick","change_view("+i+")"); + a.setAttribute("title",view_list[i].getAttribute("name")); + } + + // add edit view + + var a = document.createElement("a"); + var dot = document.createTextNode("◽ "); + a.appendChild(dot); + vc.appendChild(a); + a.setAttribute("onclick","change_view("+view_list.length+")"); + a.setAttribute("title","Inspector"); + + // add inspector view + + var a = document.createElement("a"); + var dot = document.createTextNode("ℹ "); + a.appendChild(dot); + a.style.lineHeight="80%"; + vc.appendChild(a); + + a.setAttribute("onclick","change_view("+(view_list.length+1)+")"); + a.setAttribute("title","Editor"); + + change_view(1); +} + + +function build_view_list(view) +{ + if(!view) + return; + + view_list = view; + + var vc = document.getElementById("viewdots"); + + if(!vc) + return; + + while(vc.firstChild) + vc.removeChild(vc.firstChild); + + for(i in view_list) + { + var a = document.createElement("a"); + var dot = document.createTextNode("○ "); + a.appendChild(dot); + vc.appendChild(a); + + a.setAttribute("onclick","change_view("+i+")"); + a.setAttribute("title",view_list[i].getAttribute("name")); + } + + // add inspector view + + var a = document.createElement("a"); + var dot = document.createTextNode("ℹ "); + a.appendChild(dot); + a.style.lineHeight="80%"; + vc.appendChild(a); + + a.setAttribute("onclick","change_view("+(view_list.length)+")"); + a.setAttribute("title","Editor"); + + change_view(1); +} + + + +function change_view_with_editor(index) +{ + current_view = index; + + var vc = document.getElementById("viewdots"); + var alist = getChildrenByTagName(vc, "A"); + for(i in alist) + if(i == alist.length-2) + alist[i].innerHTML = (i == index ? "ℹ " : "ℹ "); + else if(i==alist.length-1) + alist[i].innerHTML = (i == index ? "◾ " : "◽ "); + else + alist[i].innerHTML = (i == index ? "◠" : "○ "); + + var v = document.getElementById("view"); + if(!v) return; + + if(index==alist.length-2) + v.setAttribute("src", "http://"+location.host+current_group_path+"/inspector.html"); //FIXME: change order + else if(index==alist.length-1) + v.setAttribute("src", "http://"+location.host+current_group_path+"/editor.svg"); //FIXME: change order + else + v.setAttribute("src", "http://"+location.host+"/view"+current_group_path+"/view"+current_view+".svg"); + + var vn = document.getElementById("viewname"); + if(vn) + { + if(index==alist.length-2) + vn.innerHTML = "Inspector" + else if(index==alist.length-1) + vn.innerHTML = "Editor" + else + { + var vw = view_list[current_view]; + if(vw) + vn.innerHTML = vw.getAttribute("name"); + else + vn.innerHTML = "View "+index; + } + } +} + + + +function change_view(index) +{ + current_view = index; + + var vc = document.getElementById("viewdots"); + var alist = getChildrenByTagName(vc, "A"); + for(i in alist) + if(i == alist.length-1) + alist[i].innerHTML = (i == index ? "ℹ " : "ℹ "); + else + alist[i].innerHTML = (i == index ? "◠" : "○ "); + + var v = document.getElementById("view"); + if(!v) return; + + if(index==alist.length-1) + v.setAttribute("src", "http://"+location.host+current_group_path+"/inspector.html"); //FIXME: change order + else + v.setAttribute("src", "http://"+location.host+"/view"+current_group_path+"/view"+current_view+".svg"); + + var vn = document.getElementById("viewname"); + if(vn) + { + if(index==alist.length-1) + vn.innerHTML = "Inspector" + else + { + var vw = view_list[current_view]; + if(vw) + vn.innerHTML = vw.getAttribute("name"); + else + vn.innerHTML = "View "+index; + } + } +} + + + +function next_view() +{ + if(current_view < view_list.length+1) + change_view(current_view+1); +} + + + +function prev_view() +{ + if(current_view > 0) + change_view(current_view-1); +} + + + +function update_group_list_and_views() +{ + function handle_data_object(xml) + { + try + { + ikc_doc_element = xml.documentElement; + var title = document.getElementById("title"); + + var name = ikc_doc_element.getAttribute("title"); + if(!name) + name = ikc_doc_element.getAttribute("name"); + if(!name) + name = "Untitled"; + + if(title) title.innerText = name; + + grouplist = document.getElementById("grouplist"); + build_group_list([xml.documentElement], grouplist, "", true); + build_view_list(getChildrenByTagName(xml.documentElement, "view")); + change_view(0); + } + catch(err) + { + alert("Error in update_group_list_and_views: "+err.message); + // RETRY + } + } + + getXML("xml.ikc", handle_data_object); +} + + + +function toggle_inspector() +{ + if(document.getElementById('pane').style.width == "0px") + { + document.getElementById('pane').style.width='300px'; + document.getElementById('split').src="single.png"; + } + else + { + document.getElementById('pane').style.width='0px'; + document.getElementById('split').src="split.png"; + } +} + + + +function toggle(e) // TODO: do something smarter than selecting first view on toggle? +{ + + if(e.target.getAttribute("class") == "group-open") + { + e.target.setAttribute('class', 'group-closed'); + e.target.innerText = "▷ "; + + var ul = e.target.parentElement.parentElement.children.item(1); + if(ul) + ul.setAttribute('class', 'hidden'); + } + + else if(e.target.getAttribute("class") == "group-closed") + { + e.target.setAttribute('class', 'group-open'); + e.target.innerText = "▽ "; + + var ul = e.target.parentElement.parentElement.children.item(1); + if(ul) + ul.setAttribute('class', 'visible'); + } + + else if(e.target.getAttribute("class") == "group-unselected") + { + var s = document.getElementsByClassName("group-selected"); + for(var i=0; iInspector"); + doc.write(""); + doc.write(""); + doc.write("

"); + doc.write("class:
"); + doc.write("name:
"); + doc.write("
"); + doc.write(""); + + + doc.close(); +} + +Background.prototype.mousemove = function(e) +{ + if(!this.drag_object) return; + + var new_x = e.clientX+this.drag_offset_x; + var new_y = e.clientY+this.drag_offset_y; + + // Snap to grid (if not in dynamic mode) + + if(!dynamics) + { + var grid = 25; + new_x = grid*Math.round(new_x/grid)+0.5; + new_y = grid*Math.round(new_y/grid)+0.5; + } + + this.drag_object.set_position(new_x, new_y); +} + +Background.prototype.start_drag = function(obj, evt) +{ + obj.select(); + this.drag_object = obj; + this.drag_offset_x = obj.get_position().x - evt.clientX; + this.drag_offset_y = obj.get_position().y - evt.clientY; +} + +Background.prototype.add_module = function(m) +{ + this.modules.push(m); +} + +Background.prototype.get_module = function(name) +{ + for(var i in this.modules) + { + if(this.modules[i].m.getAttribute('name') == name) + return this.modules[i]; + } + return null; +} + +Background.prototype.get_input_position = function(sm, s) +{ + var m =this.get_module(sm); + if(!m) return null; + return m.get_input_position(s); +} + + +Background.prototype.get_output_position = function(sm, s) +{ + var m = this.get_module(sm); + if(!m) return null; + +// alert("found ("+sm+"."+s+") ="+m.get_output_position(s)); + + return m.get_output_position(s); +} + + +Background.prototype.add_connection = function(c) +{ + this.connections.push(c); +} + +Background.prototype.read_connections = function() +{ + for(var i=this.xml.documentElement.firstChild; i.nextSibling; i=i.nextSibling) + if(i.nodeName == "connection") + { + this.add_connection(new Connection(bg, i)); + } +// var cons = this.xml.getElementsByTagName("connection"); +// for(var i=0; i 0) + rp = "/"+bg.rootpath.join('/'); + + var _this = this; getXML(rp+'/'+this.m.getAttribute("name")+"/modulegraph.svg", function(x) { _this.load_module_svg(x); }); +} + + + +Connection.prototype.set_start = function(m) +{ +// if(!m) alert(null); + if(!m) return; + this.start = {x: m.x, y: m.y}; + this.line.setAttribute('x1', m.x); + this.line.setAttribute('y1', m.y); +} + + + +Connection.prototype.set_end = function(m) +{ +// if(!m) alert(null); + if(!m) return; + this.end = {x: m.x, y: m.y}; + this.line.setAttribute('x2', m.x); + this.line.setAttribute('y2', m.y); +} + + + +function Connection(bg, c) +{ + this.background = bg; + this.c = c; + + this.sourcemodule = c.getAttribute("sourcemodule"); + this.source = c.getAttribute("source"); + this.targetmodule = c.getAttribute("targetmodule"); + this.target = c.getAttribute("target"); + +// window.console.log("CON: "+this.sourcemodule+'.'+this.source+" -> "+this.targetmodule+'.'+this.target); + + // get coordinates + + this.line = document.createElementNS(svgns,"line"); + + this.set_start(bg.get_output_position(this.sourcemodule, this.source)); // ERROR HANDLING *** + this.set_end(bg.get_input_position(this.targetmodule, this.target)); + + var sm = bg.get_module(this.sourcemodule); + if(sm) sm.set_output_connection(this, this.source); + + var tm = bg.get_module(this.targetmodule); + if(tm) tm.set_input_connection(this, this.target); + + this.line.setAttribute('stroke', 'black'); + + document.documentElement.appendChild(this.line); + +// window.console.log("CON: "+this.sourcemodule+'.'+this.source+ "["+this.start.x+","+this.start.y+"]"+" -> "+this.targetmodule+'.'+this.target+ "["+this.end.x+","+this.end.y+"]"); +} + + +/* +function handle_xml(xml) +{ + alert("in handle_xml"); + bg.xml = xml; + var modules = xml.getElementsByTagName("module"); + module_load_count = modules.length; + for(var i=0; i + + + + + + + +Ikaros WebEdit + + + + + diff --git a/Source/WebUI/UI/favicon.ico b/Source/WebUI/UI/favicon.ico new file mode 100755 index 000000000..18e90ffd7 Binary files /dev/null and b/Source/WebUI/UI/favicon.ico differ diff --git a/Source/WebUI/UI/index.html b/Source/WebUI/UI/index.html new file mode 100755 index 000000000..da78fef65 --- /dev/null +++ b/Source/WebUI/UI/index.html @@ -0,0 +1,95 @@ + + + +Ikaros Viewer + + + + + + + + + + + + + +
+ +
+ + + + + + + + + + + + + + + + + + + + +
+ +
0
+ + + + + + + + + + + + +
+
+
    +
+
+
+
+ + +
+
+
+
+ + + + + diff --git a/Source/WebUI/UI/index.ipad.html b/Source/WebUI/UI/index.ipad.html new file mode 100755 index 000000000..d5fddb444 --- /dev/null +++ b/Source/WebUI/UI/index.ipad.html @@ -0,0 +1,360 @@ + + + + + + + + + + + + + + + + +Ikaros Viewer + + + + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
0
+
+
    +
+
+
+
+ + +
+
+
+ + + + + diff --git a/Source/WebUI/UI/inspector.css b/Source/WebUI/UI/inspector.css new file mode 100755 index 000000000..9a5d7a443 --- /dev/null +++ b/Source/WebUI/UI/inspector.css @@ -0,0 +1,83 @@ +body +{ + background-color: #303030; + color: white; + font-family: + sans-serif; + font-size: 0.9em; + padding: 20px +} + +table +{ + background-color: #333; + color: white; + font-family: sans-serif; + font-size: 0.9em; + border: 1px solid gray; + border-collapse: collapse +} + +.io +{ + background-color: #555; + font-size: 1em; + margin: 0px; + border: 1px solid gray; + width: 400px +} + +td +{ + font-size: 0.9em; + padding: 2px; + vertical-align: top; + padding: 5px +} + +.io td +{ + border: 1px solid gray +} + +a +{ + color: white; + text-decoration: none +} + +a:hover +{ + color: white; + text-decoration: underline +} + + +span.classname:hover +{ + text-decoration: none; + cursor: pointer; +} + +div.paramname:hover +{ + text-decoration: none; + cursor: pointer; +} + +div.ioname:hover +{ + text-decoration: none; + cursor: pointer; +} + + +.visible +{ + display: block; +} + +.hidden +{ + display: none; +} \ No newline at end of file diff --git a/Source/WebUI/UI/inspector.js b/Source/WebUI/UI/inspector.js new file mode 100755 index 000000000..cc64f9b8f --- /dev/null +++ b/Source/WebUI/UI/inspector.js @@ -0,0 +1,20 @@ +function toggle_parameter_info(e) +{ + var t = e.parentElement.children.item(1); + var c = t.getAttribute("class"); + if(c == "hidden") + t.setAttribute("class","visible"); + else + t.setAttribute("class","hidden"); +} + + +function toggle_class_info(e) +{ + var t = e.parentElement.children.item(2); + var c = t.getAttribute("class"); + if(c == "hidden") + t.setAttribute("class","visible"); + else + t.setAttribute("class","hidden"); +} \ No newline at end of file diff --git a/Source/WebUI/UI/link.png b/Source/WebUI/UI/link.png new file mode 100755 index 000000000..06344f225 Binary files /dev/null and b/Source/WebUI/UI/link.png differ diff --git a/Source/WebUI/UI/log.html b/Source/WebUI/UI/log.html new file mode 100755 index 000000000..048949e3f --- /dev/null +++ b/Source/WebUI/UI/log.html @@ -0,0 +1,92 @@ + + + +Ikaros Log + + + + + +
+ + + +
+ +
+
+ + + \ No newline at end of file diff --git a/Source/WebUI/UI/single.png b/Source/WebUI/UI/single.png new file mode 100755 index 000000000..0a55f5aaa Binary files /dev/null and b/Source/WebUI/UI/single.png differ diff --git a/Source/WebUI/UI/split.png b/Source/WebUI/UI/split.png new file mode 100755 index 000000000..ea9b10de4 Binary files /dev/null and b/Source/WebUI/UI/split.png differ diff --git a/Source/WebUI/UI/style.css b/Source/WebUI/UI/style.css new file mode 100755 index 000000000..8bfff0504 --- /dev/null +++ b/Source/WebUI/UI/style.css @@ -0,0 +1,292 @@ + +html, body +{ + width: 100%; + height: 100%; + padding: 0px; + margin: 0px; + background-color: black; + color: white; + + -webkit-user-select: none; + -webkit-user-drag: none; + + -moz-user-select: none; + -moz-user-drag: none; + + font-family: Arial, sans-serif; +} + + +table +{ + table-layout:fixed; + border-collapse: collapse; + width: 100%; + height: 100%; +} + +tr +{ + padding: 0px; + margin: 0px; +} + +td +{ + padding: 0px; + margin: 0px; + overflow: hidden; + white-space: nowrap; +} + +a +{ + cursor:hand; +} + + +/* + * + * Controls + * + */ + + +td#controlframe +{ + width: 190px; + padding-left:20px; +} + +div#controls +{ + height: 20px; + width: 150px; + margin: 0px; + padding: 15px 0px 0px 5px; + vertical-align: middle; + display: span; +} + + +a.button +{ + display: block; + float : left; + overflow: hidden; + + height: 19px; + width: 30px; + + padding: 0px; + margin: 0px; + + -webkit-user-select: none; + -webkit-user-drag: none; + + -moz-user-select: none; + -moz-user-drag: none; +} + +a.selected +{ + display: block; + float : left; + overflow: hidden; + + height: 19px; + width: 30px; + + padding: 0px; + margin: 0px; + + -webkit-user-select: none; + -webkit-user-drag: none; + + -moz-user-select: none; + -moz-user-drag: none; +} + +a.button:active +{ +} + + +a.button img +{ +} + +.button:active img, +.selected img +{ + position: relative; + top: -19px; + + -webkit-user-select: none; + -webkit-user-drag: none; + + -moz-user-select: none; + -moz-user-drag: none; +} + + + +td#iteration +{ + width: 100px; + padding-top: 15px; + vertical-align: middle; + font-size: 16px; + font-family: Arial, sans-serif; + text-align: left; + color: #AAAAAA; +} + +td#title +{ + padding-right: 40px; + padding-top: 20px; + font-size: 36px; + font-family: sans-serif; + text-align: right; + color: #AAAAAA; + height: 41; +} + +td#footer +{ + padding-bottom: 7px; + padding-left:20px; + padding-right: 20px; + font-size: 12px; + font-family: Arial, sans-serif; + color: #888888; + text-align: center; + height:25px; +} + +div#viewcontrol +{ + float: right; + text-align: right; + width: 120; +} + + +div#viewdots +{ + font-size: 16px; + clear: both; + display: inline; +} + + +div#toggle +{ + float: left; + text-align: left; + width: 120; +} + + +/* + * + * Group List Pane + * + */ + +div#grouppane +{ + padding: 0px; + margin:0px; + height:100%; + background-color: #303030; + border: 1px solid #666666; + -webkit-border-radius: 5px; +} + +ul +{ + padding-left: 16px; + padding-top: 2px; + padding-bottom: 6px; +} + +ul#grouplist +{ + padding: 0px 0px 0px 0px; + margin: 16px 0px 0px 16px; + list-style-type: none; + padding-left:0; + color: #CCCCCC; +} + +ul.visible +{ + display: block; +} + + +ul.hidden +{ + display: none; +} + +li { + font-family: Arial; + font-size: 9pt; + line-height: 1.5em; + margin-left: 0; + cursor:hand; + list-style-type: none; +} + +span.group-bar, +span.group-bar-selected +{ + -webkit-border-radius: 10px; + padding: 2px 15px 1px 10px; +} + +span.group-bar:hover +{ + background-color: #111; +} + +span.group-bar-selected +{ + color: #333; + background-color: #DDD; +} + +td#pane +{ + width: 0px; + -webkit-transition: width 0.5s ease-in-out; + padding: 10px;margin: 0px; + padding-right: 0px; + padding-left:20px; +} + +td#viewbox +{ + padding: 10px; + padding-right:20px; + padding-left:20px; + margin: 0px; +} + +div#viewframe +{ + position: relative; + top: 0; + left:0; + overflow: hidden; + border: 1px solid #666666; + background-color: #303030; + padding: 4px; + margin:0px; + height:100%; + -webkit-border-radius: 5; +} diff --git a/Source/WebUI/UI/viewer.css b/Source/WebUI/UI/viewer.css new file mode 100755 index 000000000..64146a5f0 --- /dev/null +++ b/Source/WebUI/UI/viewer.css @@ -0,0 +1,22 @@ + +.object_background +{ + stroke: #1D1D1D; + fill: #1D1D1D; +} + +.object_title +{ + font-size: 11px; + font-family: sans-serif; + fill: #BABABA; +} + +.object_titlebar +{ + stroke: black; + fill: black; + stroke-opacity: 0.5; + fill-opacity: 0.5; +} + diff --git a/Source/WebUI/UI/viewer.js b/Source/WebUI/UI/viewer.js new file mode 100755 index 000000000..9b5df5c6b --- /dev/null +++ b/Source/WebUI/UI/viewer.js @@ -0,0 +1,375 @@ +var svgns = "http://www.w3.org/2000/svg"; +var xlinkns = "http://www.w3.org/1999/xlink"; +var xmlns = "http://www.w3.org/1999/xhtml"; + +var clip_id = 0; + +LUT_gray = [ + '#000000', '#040404', '#080808', '#0C0C0C', '#101010', '#141414', '#181818', '#1C1C1C', + '#202020', '#242424', '#282828', '#2C2C2C', '#303030', '#343434', '#383838', '#3C3C3C', + '#404040', '#444444', '#484848', '#4C4C4C', '#505050', '#545454', '#585858', '#5C5C5C', + '#606060', '#646464', '#686868', '#6C6C6C', '#707070', '#747474', '#787878', '#7C7C7C', + '#808080', '#848484', '#888888', '#8C8C8C', '#909090', '#949494', '#989898', '#9C9C9C', + '#A0A0A0', '#A4A4A4', '#A8A8A8', '#ACACAC', '#B0B0B0', '#B4B4B4', '#B8B8B8', '#BCBCBC', + '#C0C0C0', '#C4C4C4', '#C8C8C8', '#CCCCCC', '#D0D0D0', '#D4D4D4', '#D8D8D8', '#DCDCDC', + '#E0E0E0', '#E4E4E4', '#E8E8E8', '#ECECEC', '#F0F0F0', '#F4F4F4', '#F8F8F8', '#FCFCFC']; + +LUT_fire = [ + '#000000', '#00001F', '#00002E', '#00003D', '#00004E', '#010060', '#0D0071', '#190082', + '#250093', '#3100A5', '#3D00B2', '#4900C0', '#5500CE', '#6200DC', '#6E00DF', '#7A00E3', + '#8600DA', '#9200D2', '#9A00C3', '#A200B5', '#A700A6', '#AD0097', '#B20088', '#B8007A', + '#BD006B', '#C3005D', '#C9074E', '#CF0E40', '#D41831', '#D92323', '#DF2E14', '#E53905', + '#EA4402', '#F04F00', '#F65A00', '#FC6500', '#FD6D00', '#FF7500', '#FF7D00', '#FF8500', + '#FF8C00', '#FF9300', '#FF9A00', '#FFA100', '#FFA800', '#FFAF00', '#FFB600', '#FFBE00', + '#FFC500', '#FFCD00', '#FFD400', '#FFDB00', '#FFE200', '#FFEA00', '#FFF111', '#FFF823', + '#FFFB42', '#FFFF62', '#FFFF81', '#FFFFA0', '#FFFFBF', '#FFFFDF', '#FFFFEF', '#FFFFFF']; + +LUT_spectrum = [ + '#FF0000', '#FF0000', '#FF1800', '#FF3000', '#FF4800', '#FF6000', '#FF7800', '#FF9000', + '#FFA800', '#FFC000', '#FFD800', '#FFF000', '#F6FF00', '#DEFF00', '#C6FF00', '#AEFF00', + '#96FF00', '#7EFF00', '#66FF00', '#4EFF00', '#36FF00', '#1EFF00', '#06FF00', '#00FF12', + '#00FF2A', '#00FF42', '#00FF5A', '#00FF72', '#00FF8A', '#00FFA2', '#00FFBA', '#00FFD2', + '#00FFEA', '#00FCFF', '#00E4FF', '#00CCFF', '#00B4FF', '#009CFF', '#0084FF', '#006CFF', + '#0054FF', '#003CFF', '#0024FF', '#000CFF', '#0C00FF', '#2400FF', '#3C00FF', '#5400FF', + '#6C00FF', '#8400FF', '#9C00FF', '#B400FF', '#CC00FF', '#E400FF', '#FC00FF', '#FF00EA', + '#FF00D2', '#FF00BA', '#FF00A2', '#FF008A', '#FF0072', '#FF005A', '#FF0042', '#FF002A']; + + +function makeSelectionArray(s) +{ + if(s == undefined) + return [[0,0]]; + + if(String.prototype.isPrototypeOf(s)) + s = s.split(","); + + if(Array.prototype.isPrototypeOf(s)) + { + if(Array.prototype.isPrototypeOf(s[0])) + return s; + + var a = new Array(0); + for(var i in s) + a.push([s[i],0]); + return a; + } + + return makeSelectionArray(eval('['+s+']')); +} + + + +function makeLUTArray(c, d) +{ + if(c == undefined) + { + if(d == undefined) + return ['yellow']; + else + return d; + } + + if(c.indexOf("LUT_") == 0) + return eval(c); + + return c.split(","); +} + + + +function Graph(p, title) +{ + clip_id++; + this.clip = document.createElementNS(svgns,"clipPath"); + this.clip.setAttribute('id', 'clip'+clip_id); + document.documentElement.appendChild(this.clip); + + this.clipRect = document.createElementNS(svgns,"rect"); + this.clipRect.setAttribute('x', '0'); + this.clipRect.setAttribute('y', '0'); + this.clipRect.setAttribute('rx', '10'); + this.clipRect.setAttribute('ry', '10'); + this.clipRect.setAttribute('width', p.width); + this.clipRect.setAttribute('height', p.height); + this.clip.appendChild(this.clipRect); + + if(!p.title) + p.title = title; + + // Create outer group + + this.main = document.createElementNS(svgns,"g"); + this.main.setAttribute("clip-path", 'url(#clip'+clip_id+')'); + this.main.setAttribute("transform", "translate("+p.x+","+p.y+")"); + + // Add contents group + + this.group = document.createElementNS(svgns,"g"); + + if(p.opaque != undefined ? p.opaque=='yes' : p.behind) + { + this.background = this.AddRect(0, 0, p.width-1, p.height-1); + this.background.setAttribute("class", "object_background"); + // this.background.setAttribute("filter", "url(#filter)"); + } + + this.main.appendChild(this.group); + + // Add title bar + + this.titlebar = document.createElementNS(svgns,"g"); + + if(p.opaque != undefined ? p.opaque=='yes' : p.behind) + { + this.dragarea = document.createElementNS(svgns,"rect"); + this.dragarea.setAttribute('x', 0); + this.dragarea.setAttribute('y', 0); + this.dragarea.setAttribute('width', p.width-1); + this.dragarea.setAttribute('height', 20+1); + this.dragarea.setAttribute('class','object_titlebar'); + this.titlebar.appendChild(this.dragarea); + + this.title = document.createElementNS(svgns,"text"); + this.title.setAttribute('x', 10); + this.title.setAttribute('y', 14); + this.title.setAttribute('class', 'object_title'); + this.title.setAttribute('text-rendering','optimizeLegibility'); + var tn = document.createTextNode(p.title); + this.title.appendChild(tn); + this.titlebar.appendChild(this.title); + } + + this.main.appendChild(this.titlebar); + + document.documentElement.appendChild(this.main); +} + + +Graph.prototype.AddRect = function (x, y, width, height, f, s, radius) +{ + var r = document.createElementNS(svgns,"rect"); + r.setAttribute('x', x); + r.setAttribute('y', y); + r.setAttribute('width', width); + r.setAttribute('height', height); + if(f) r.setAttribute('fill', f); + if(s) r.setAttribute('stroke', s); + if(radius) r.setAttribute('rx', radius); + if(radius) r.setAttribute('ry', radius); + + this.group.appendChild(r); + + return r; +} + + +Graph.prototype.AddPolygon = function (points, f, s, w) +{ + var r = document.createElementNS(svgns,"polygon"); + r.setAttribute('points', points); + if(f) r.setAttribute('fill', f); + if(s) r.setAttribute('stroke', s); + if(w) r.setAttribute('stroke-width', w); + + this.group.appendChild(r); + + return r; +} + + +Graph.prototype.AddClippingRect= function (x, y, width, height) +{ + clip_id++; + + var g = document.createElementNS(svgns,"g"); + + g.setAttribute('clip-path', 'url(#clip'+clip_id+')'); + + var cp = document.createElementNS(svgns,"clipPath"); + cp.setAttribute('id', 'clip'+clip_id); + + g.appendChild(cp); + + cr = document.createElementNS(svgns,"rect"); + cr.setAttribute('x', y); + cr.setAttribute('y', y); + cr.setAttribute('width', width); + cr.setAttribute('height', height); + + cp.appendChild(cr); + + this.group.appendChild(g); + + return g; +} + +Graph.prototype.AddCircle = function (cx, cy, radius, f, s, sw) +{ + var r = document.createElementNS(svgns,"circle"); + r.setAttribute('cx', cx); + r.setAttribute('cy', cy); + r.setAttribute('r', radius); + + if(f) r.setAttribute('fill', f); + if(s) r.setAttribute('stroke', s); + if(sw) r.setAttribute('stroke-width', sw); + + this.group.appendChild(r); + + return r; +} + +Graph.prototype.AddLine = function (x1, y1, x2, y2, s, sw) +{ + var r = document.createElementNS(svgns,"line"); + r.setAttribute('x1', x1); + r.setAttribute('y1', y1); + r.setAttribute('x2', x2); + r.setAttribute('y2', y2); + + if(s) r.setAttribute('stroke', s); + if(sw) r.setAttribute('stroke-width', sw); + + this.group.appendChild(r); + + return r; +} + +Graph.prototype.AddImage = function (x, y, width, height, path) +{ + var r = document.createElementNS(svgns,"image"); + r.setAttribute('x', x); + r.setAttribute('y', y); + r.setAttribute('width', width); + r.setAttribute('height', height); + r.setAttribute('preserveAspectRatio', 'none'); + r.setAttributeNS(xlinkns, 'href', path); + + this.group.appendChild(r); + + return r; +} + + + +Graph.prototype.AddText = function (x, y, t, width, height, anchor, fontsize, color) +{ + var r = document.createElementNS(svgns,"text"); + r.setAttribute('x', x); + r.setAttribute('y', y); + r.setAttribute('font-size', (fontsize ? fontsize : "11px")); + r.setAttribute('font-family', 'sans-serif'); + r.setAttribute('fill', (color ? color: '#BABABA')); + + if(anchor) r.setAttribute('text-anchor', anchor); + r.setAttribute('text-rendering','optimizeLegibility'); + var tn = document.createTextNode(t); + r.appendChild(tn); + this.group.appendChild(r); + + return r; +} + + + +Graph.prototype.AddHTMLText = function (x, y, t, width, height, style) +{ + var r = document.createElementNS(svgns,"foreignObject"); + r.setAttribute('x', x); + r.setAttribute('y', y); + r.setAttribute('width', width); + r.setAttribute('height', height); + + var b = document.createElementNS(xmlns,"body"); + b.setAttribute('xmlns', 'http://www.w3.org/1999/xhtml'); + + var d = document.createElementNS(xmlns,"div"); + b.setAttribute('style', (style ? style: 'font-family: sans-serif; font-size: 11px; color: #BABABA')); + + var tn = document.createTextNode(t); + + d.appendChild(tn); + b.appendChild(d); + r.appendChild(b); + this.group.appendChild(r); + + return r; +} + + + +var uiobject = new Array(0); + + + +function ignore_data(obj) +{ +} + + +function get(url, callback) +{ + function getURL_alt(url, callback) + { + function callCallback() + { + if (ajaxRequest.readyState == 4) + { + if(ajaxRequest.status == 200) + if (ajaxCallback) ajaxCallback({content:ajaxRequest.responseText}); + else + alert("Returned status code " + ajaxRequest.status); + } + } + + var ajaxRequest = null; + var ajaxCallback = callback; + + ajaxRequest = new XMLHttpRequest(); + ajaxRequest.onreadystatechange = callCallback; + ajaxRequest.open("GET", url, true); + ajaxRequest.send(null); + } + + if(window.getURL) + getURL(url, callback); + else if(window.XMLHttpRequest) + getURL_alt(url, callback); + else + alert("Error: This web browser does not have getURL or XMLHttpRequest"); +} + + + +function update(data) +{ + try { + for(i in uiobject) + { + uiobject[i].Update(data); + } + } + catch(err) + { + // view is being loaded - ignore! + // if(console) console.log("Error: "+err.message); + // alert("Exception"); + + } + +} + + +function add(obj) +{ + uiobject.push(obj); + +} + + + +function usesData(module, source) +{ + get("/uses/"+module+'/'+source, ignore_data); +} + diff --git a/Source/WebUI/UI/viewer.svg b/Source/WebUI/UI/viewer.svg new file mode 100755 index 000000000..e847ef8ff --- /dev/null +++ b/Source/WebUI/UI/viewer.svg @@ -0,0 +1,55 @@ +\n"); + socket->Send("\n"); + return; + } + } + + Send404(); +} + + + +void +WebUI::Run() +{ + if(socket == NULL) + return; // ERROR + + // SYNCHRONIZATION + + if(xml) + { + const char * ip = xml->GetAttribute("masterip"); + if(ip) + { + Socket s; + char rr[100]; + int masterport = string_to_int(xml->GetAttribute("masterport"), 9000); + printf("Waiting for master: %s:%d\n", ip, masterport); + fflush(stdout); + if(!s.Get(ip, masterport, "*", rr, 100)) + { + printf("Master not running.\n"); + throw -1; // No master + } + } + } + + chdir(webui_dir); + k->timer->Restart(); + tick = 0; + +#ifdef USE_THREADED_WEBUI + { + httpThread = new Thread(); + httpThread->Create(WebUI::StartHTTPThread, this); + + while (!k->Terminate()) + { + if (!isRunning) + { + Timer::Sleep(10); // Wait 10ms to avoid wasting cycles if there are no requests + } + + if (isRunning) + { + chdir(k->ikc_dir); + k->Tick(); + tick++; + chdir(webui_dir); + + if (k->tick_length > 0) + { + float lag = k->timer->WaitUntil(float(tick*k->tick_length)); + if (lag > 0.1) k->Notify(msg_warning, "Lagging %.2f ms at tick = %ld\n", lag, k->tick); + } + } + } + + httpThread->Join(); + chdir(k->ikc_dir); + } +#else // Old Unthreaded WebUI + { + while (!k->Terminate()) + { + if (socket->GetRequest()) + { + if (equal_strings(socket->header.Get("Method"), "GET")) + HandleHTTPRequest(); + socket->Close(); + } + else if (!isRunning) + { + Timer::Sleep(10); // Wait 10ms to avoid wasting cycles if there are no requests + } + + if (isRunning) + { + chdir(k->ikc_dir); + k->Tick(); + tick++; + chdir(webui_dir); + + if (k->tick_length > 0) + { + float lag = k->timer->WaitUntil(float(tick*k->tick_length)); + if (lag > 0.1) k->Notify(msg_warning, "Lagging %.2f ms at tick = %ld\n", lag, k->tick); + } + } + + } + chdir(k->ikc_dir); + } +#endif +} + + + +void +WebUI::HandleRGBImageRequest(const char * module, const char * output) +{ + char m1[256], m2[256], m3[256]; + + if (sscanf(module, "%[^+]+%[^+]+%[^+]", m1, m2, m3) == 1) // use same module for all sources if only one name is given + { + copy_string(m2, m1, 255); + copy_string(m3, m1, 255); + } + + bool err = false; + char red[256], green[256], blue[256]; + int cc = sscanf(output, "%[^+]+%[^+]+%[^+]", red, green, blue); + + Module * mod1, * mod2, * mod3; + Module_IO * source1, * source2, * source3; + + err |= !k->GetSource(current_xml_root, mod1, source1, m1, red); // was xml ********* + err |= !k->GetSource(current_xml_root, mod2, source2, m2, green); + err |= !k->GetSource(current_xml_root, mod3, source3, m3, blue); + + if (cc != 3) err = true; // Error + + if(!err) + { + if (source1->sizex != source2->sizex) err = true; // ERROR + if (source1->sizey != source2->sizey) err = true; // ERROR + if (source1->sizex != source3->sizex) err = true; // ERROR + if (source1->sizey != source3->sizey) err = true; // ERROR + } + + if (!err) + SendColorJPEG(socket, source1->matrix[0], source2->matrix[0], source3->matrix[0], source1->sizex, source1->sizey); + else + socket->SendFile("404.jpg", webui_dir); +} + + + +void +WebUI::HandleHTTPRequest() +{ + if (debug_mode) + printf("HTTP Request: %s %s\n", socket->header.Get("Method"), socket->header.Get("URI")); + + // Copy URI and remove index + + char * uri = create_string(socket->header.Get("URI")); + if(char * x = strpbrk(uri, "?#")) *x = '\0'; + + if (!strcmp(uri, "/stop")) + { + ui_state = ui_state_stop; + SendAllJSONData(); + k->Notify(msg_terminate, "Sent by WebUI.\n"); + } + + else if (!strcmp(uri, "/step")) + { + ui_state = ui_state_pause; + chdir(k->ikc_dir); + + for(int i=0; iTick(); + + chdir(webui_dir); + SendAllJSONData(); + isRunning = false; + } + + else if (!strcmp(uri, "/runstep")) + { + ui_state = ui_state_run; + chdir(k->ikc_dir); + + for(int i=0; iTick(); + + chdir(webui_dir); + SendAllJSONData(); + isRunning = false; + } + + else if (!strcmp(uri, "/update")) + { + SendAllJSONData(); + } + + else if (!strcmp(uri, "/pause")) + { + ui_state = ui_state_pause; + SendAllJSONData(); + isRunning = false; + } + + else if (!strcmp(uri, "/realtime")) + { + ui_state = ui_state_realtime; + socket->Send("REALTIME\n"); + k->timer->Restart(); + tick = 0; + isRunning = true; + } + + else if (strstart(uri, "/setroot")) + { + if(current_xml_root_path) destroy_string(current_xml_root_path); + current_xml_root_path = create_string(&uri[8]); + char * p = create_string(uri); // TODO: write as separate function (XPath style?) + char * group_in_path; + XMLElement * group_xml = xml; + group_in_path = strsep(&p, "/"); + group_in_path = strsep(&p, "/"); + while((group_in_path = strsep(&p, "/"))) + { + group_xml = group_xml->GetElement("group"); + for (XMLElement * xml_module = group_xml->GetContentElement("group"); xml_module != NULL; xml_module = xml_module->GetNextElement("group")) + if(equal_strings(xml_module->GetAttribute("name"), group_in_path)) + { + group_xml = xml_module; + break; + } + } + current_xml_root = group_xml; + destroy_string(p); + } + + else if (strstart(uri, "/uses")) + { + char * module = new char [256]; + char * output = new char [256]; + int c = sscanf(uri, "/uses/%[^/]/%[^/]", module, output); + if (c == 2) + AddDataSource(module, output); + + Dictionary header; + header.Set("Content-Type", "text/plain"); + socket->SendHTTPHeader(&header); + socket->Send("OK\n"); + + delete module; + delete output; + } + + else if (strstart(uri, "/run/")) + { + char filepath[1024]; + printf("RUN\n"); + sscanf(uri, "/run/%s", filepath); + RunIKCFile(filepath); + // return; + } + + else if (strstart(uri, "/control/")) + { + char module_name[255]; + char name[255]; + int x, y; + float value; + int c = sscanf(uri, "/control/%[^/]/%[^/]/%d/%d/%f", module_name, name, &x, &y, &value); + if(c == 5) + { + Module * module = k->GetModule(module_name); + if(!module) + { + k->Notify(msg_warning, "Module \"%s\" does not exist.\n", module_name); + destroy_string(uri); // TODO: should use single exit point + return; + } + + for(Binding * b = module->bindings; b != NULL; b = b->next) + if(equal_strings(name, b->name)) + { + if(b->type == bind_float) + *((float *)(b->value)) = value; + else if(b->type == bind_int || b->type == bind_list) + *((int *)(b->value)) = (int)value; + else if(b->type == bind_float) + *((bool *)(b->value)) = (value > 0); + else if(b->type == bind_array) + ((float *)(b->value))[x] = value; // TODO: add range check!!! + else if(b->type == bind_matrix) + ((float **)(b->value))[y][x] = value; + } + } + + Dictionary header; + header.Set("Content-Type", "text/plain"); + header.Set("Cache-Control", "no-cache"); // make sure Opera reloads every time + header.Set("Cache-Control", "no-store"); + header.Set("Pragma", "no-cache"); + socket->SendHTTPHeader(&header); + socket->Send("OK\n"); + // return; + } + + else if (!strcmp(uri, "/getlog")) + { + if (k->logfile) + socket->SendFile("logfile", webui_dir); + else + socket->Send("ERROR - No logfile found\n"); + } + + else if (strend(uri, "/editor.svg")) + { + socket->SendFile("editor.svg", webui_dir); + } + + else if (!strcmp(uri, "/editor.js")) + { + socket->SendFile("editor.js", webui_dir); + } + + else if (!strcmp(uri, "/ikcfile.js")) + { + socket->Send("getXML('/xml.ikc', function(xml) {bg.read_modules(xml);});\n"); + } + + else if(strend(uri, "/modulegraph.svg")) + { + SendSyntheticModuleSVG(socket, k->xmlDoc->xml, uri); + } + + else if(strstart(uri, "/view") && strend(uri, ".svg")) // second test not necessary in the future + { + SendView(uri); + } + + else if (strstart(uri, "/module/")) + { + char module[256], output[256], type[256]; + int c = sscanf(uri, "/module/%[^/]/%[^/]/%[^/]", module, output, type); + if(!strcmp(type, "rgb.jpg")) + { + HandleRGBImageRequest(module, output); + destroy_string(uri); // TODO: should use single exit point + return; + } + + Module * m; + Module_IO * source; + + if(!k->GetSource(current_xml_root, m, source, module, output)) + { + k->Notify(msg_warning, "The output \"%s.%s\" does not exist, or\n", module, output); + k->Notify(msg_warning, "\"%s\" may be an unkown data type.\n", type); + destroy_string(uri); // TODO: should use single exit point + + return; + } + + if (c == 3 && !strcmp(type, "gray.jpg")) + { + if (!SendGrayJPEG(socket, source->matrix[0], source->sizex, source->sizey)) + socket->SendFile("no_image.jpg", webui_dir); + } + + else if (c == 3 && !strcmp(type, "green.jpg")) + { + if (!SendGreenJPEG(socket, source->matrix[0], source->sizex, source->sizey)) + socket->SendFile("404.jpg", webui_dir); + } + + else if (c == 3 && !strcmp(type, "spectrum.jpg")) + { + if (!SendSpectrumJPEG(socket, source->matrix[0], source->sizex, source->sizey)) + socket->SendFile("404.jpg", webui_dir); + } + + else if (c == 3 && !strcmp(type, "fire.jpg")) + { + if (!SendFireJPEG(socket, source->matrix[0], source->sizex, source->sizey)) + socket->SendFile("404.jpg", webui_dir); + } + + else if (c == 3 && !strcmp(type, "data.txt")) + { + int sx = m->GetOutputSizeX(output); + int sy = m->GetOutputSizeY(output); + if (!SendTextData(socket, m->GetOutputMatrix(output), sx, sy)) + k->Notify(msg_warning, "Could not send: data.txt\n"); + } + + else + { + k->Notify(msg_warning, "Unkown data type: %s\n", type); + } + } + + else if (!strcmp(uri, "/examples")) + { + SendExamples(); + } + + else if(strend(uri, "/inspector.html")) + { + SendInspector(); + } + + else if(strstart(uri, "/xml")) + { + SendXML(); + } + + else if(equal_strings(uri, "/")) + { + socket->SendFile("index.html", webui_dir); + } + + else if ( + strend(uri, ".xml") || + strend(uri, ".jpg") || + strend(uri, ".html") || + strend(uri, ".css") || + strend(uri, ".png") || + strend(uri, ".svg") || + strend(uri, ".js") || + strend(uri, ".gif") || + strend(uri, ".ico")) + { + if(!socket->SendFile(&uri[1], k->ikc_dir)) // Check IKC-directory first to allow files to be overriden + if(!socket->SendFile(&uri[1], webui_dir)) // Now look in WebUI directory + { + // Send 404 if not file found + + if (strend(uri, ".jpg")) + socket->SendFile("404.jpg", webui_dir); + else if (strend(uri, ".html")) + socket->SendFile("404.html", webui_dir); + } + } + + else if (strstart(uri,"/")) + { +/* + int v = 0; + if (!xml || xml->GetContentElement("view") == NULL) + { + socket->Send("\n\nIkaros Web View\n\n\n

Ikaros Web View

\n

No views were defined.

\n\n"); + destroy_string(uri); // TODO: should use single exit point + return; + } + + // Send index page + + socket->Send("\n\nIkaros Web View\n\n"); + socket->Send("\n"); + socket->Send("

Ikaros Web View

\n

The following views are available:

\n
    "); + for (XMLElement * xml_view = xml->GetContentElement("view"); xml_view != NULL; xml_view = xml_view->GetNextElement("view"), v++) + { + const char * n = xml_view->GetAttribute("name"); + if (n == NULL) + socket->Send("
  • View %d
  • \n", v, v); + else + socket->Send("
  • %s
  • \n", n, n); + } +*/ + socket->Send("ERROR\n"); + } + + destroy_string(uri); +} + + + +void +WebUI::HandleHTTPThread() +{ + while(!k->Terminate()) + { + if (socket->GetRequest(true)) + { + if (equal_strings(socket->header.Get("Method"), "GET")) + HandleHTTPRequest(); + socket->Close(); + } + } +} + + + +void * +WebUI::StartHTTPThread(void * webui) +{ + ((WebUI *)(webui))->HandleHTTPThread(); + return NULL; +} + + + +// This is an experimental POSIX only function which sends a HTML page with all ikc files in the Examples directory + +void +WebUI::SendExamplesDirectory(const char * directory, const char * path) +{ +#ifdef POSIX + struct dirent * dp; + DIR * dirp = opendir(path); + if(!dirp) + return; + + Dictionary header; + header.Set("Content-Type", "text/xhtml"); + socket->SendHTTPHeader(&header); + + socket->Send("
      \n"); + while ((dp = readdir(dirp)) != NULL) + if(strstr(dp->d_name,".ikc")) // should test only at end *** + socket->Send("
    • %s
    • \n", directory, dp->d_name, dp->d_name); + else if(!strstr(dp->d_name, ".") && !equal_strings(dp->d_name, "Media")) // assume if it is directory + { + socket->Send("
    • %s:
    • \n", dp->d_name); + char * p = create_formatted_string("%s/%s", path, dp->d_name); + char * d = create_formatted_string("%s/%s", directory, dp->d_name); + SendExamplesDirectory(d, p); + destroy_string(d); + destroy_string(p); + } + socket->Send("
    \n"); + + closedir(dirp); +#endif +} + + + +void +WebUI::SendExamples() +{ +#ifdef POSIX + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("Modules\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("

    Ikaros Web View

    \n

    The following examples are available in the Examples directory.
    Start an example by clicking on its title.

    \n"); + + char * directory = create_formatted_string("%sExamples/", k->ikaros_dir); + struct dirent * dp; + DIR * dirp = opendir(directory); + if(!dirp) + return; + + while ((dp = readdir(dirp)) != NULL) + if(strend(dp->d_name,".ikc")) + socket->Send("

    %s

    \n", dp->d_name, dp->d_name); + else if(!strstr(dp->d_name, ".") && !equal_strings(dp->d_name, "Media")) // assume it is a directory + { + socket->Send("\n"); + socket->Send("\n", dp->d_name); + socket->Send("\n"); + socket->Send("
    %s
    \n"); + char * d = create_formatted_string("%s/%s", directory, dp->d_name); + SendExamplesDirectory(dp->d_name, d); + destroy_string(d); + socket->Send("
    \n"); + } + + closedir(dirp); + destroy_string(directory); + socket->Send("\n\n"); + socket->Close(); +#endif +} + + + +// Send XML sends the XML tree + +void +WebUI::SendXML() +{ + FILE * f = fopen("temp.xml","w"); + if(!f) return; + if(k->xmlDoc) + k->xmlDoc->xml->Print(f, 0); + fclose(f); + + socket->SendFile("temp.xml"); + socket->Close(); +} + + + +void +WebUI::SendModule(Module * m) +{ + socket->Send("\n"); + + m->GetFullName(); + + socket->Send("\n"); + + socket->Send("\n"); + + // Parameters + + socket->Send("\n"); + + // Inputs + + if(m->input_list) + { + socket->Send("\n"); + } + + // Outputs + + if(m->output_list) + { + socket->Send("\n"); + } + + socket->Send("
    \n", m->GetName()); + const char * n = m->GetFullName(); + socket->Send("%s", n); + socket->Send("
    Class:%s\n", m->class_name, m->class_name); + + XMLElement * gg = m->xml->GetParentElement(); + if(gg) + { + XMLElement * x = gg->GetContentElement("description"); + if(x) + { + XMLCharacterData * c = (XMLCharacterData *)(x->content); + if(c) + { + char * description = c->data; + socket->Send("
    \n", description, m->class_name); + } + } + } + + socket->Send("
    Parameters:\n"); + socket->Send("\n"); + + socket->Send("\n", m->period); + socket->Send("\n", m->phase); + + XMLElement * g = m->xml->GetParentElement(); + if(g) + for (XMLElement * parameter = g->GetContentElement("parameter"); parameter != NULL; parameter = parameter->GetNextElement("parameter")) + { + const char * name = parameter->GetAttribute("name"); + const char * type = parameter->GetAttribute("type"); + const char * description = parameter->GetAttribute("description"); + + // TODO: Allow editing if bound + // **** + + socket->Send("\n"); + socket->Send("\n", description, name, description); + if(type) + { + if(equal_strings(type, "int")) + socket->Send("\n", m->GetIntValue(name)); + else if(equal_strings(type, "float")) + socket->Send("\n", m->GetFloatValue(name)); + else if(equal_strings(type, "bool")) + socket->Send("\n", (m->GetBoolValue(name) ? "yes" : "no")); + else if(equal_strings(type, "list")) + socket->Send("\n", m->GetValue(name)); + else if(equal_strings(type, "string")) + socket->Send("\n", m->GetValue(name)); + else + socket->Send("\n"); + + socket->Send("\n", type); + } + else + { + socket->Send("\n"); + socket->Send("\n", name, m->class_name); + } + + socket->Send("\n"); + } + socket->Send("
    period%dint
    phase%dint
    %s
    %d%f%s%s%s-%sERR
    \n"); + socket->Send("
    Inputs:\n"); + socket->Send("\n"); + for (Module_IO * i = m->input_list; i != NULL; i = i->next) + { + socket->Send("\n"); + if(!i->data) + { + socket->Send("\n", i->name); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + } + else + { + socket->Send("\n", i->name); + socket->Send("\n", i->sizex); + socket->Send("\n", i->sizey); + socket->Send("\n", (i->data == NULL ? NULL : i->data[0])); + socket->Send("\n"); + } + socket->Send("\n", i->name, i->sizex, i->sizey, (i->data == NULL ? NULL : i->data[0])); + } + socket->Send("
    %-10s nc %-10s%d%d%p 
    \n"); + socket->Send("
    Outputs:\n"); + socket->Send("\n"); + for (Module_IO * i = m->output_list; i != NULL; i = i->next) + { + socket->Send("\n"); + socket->Send("\n", i->name); + socket->Send("\n", i->sizex); + socket->Send("\n", i->sizey); + if(m->OutputConnected(i->name)) + socket->Send("\n", (i->data == NULL ? NULL : i->data[0])); + else + socket->Send("\n", (i->data == NULL ? NULL : i->data[0])); + socket->Send("\n", i->max_delay); + socket->Send("\n"); + } + socket->Send("
    %-10s%d%d%pnc, %p%d
    \n"); + socket->Send("

    \n"); +} + + + +void +WebUI::SendGroups(XMLElement * xml) +{ + for(XMLNode * e = xml->content; e != NULL; e = e->next) + if(e->IsElement()) + { + if(equal_strings(((XMLElement *)(e))->name, "group")) + SendGroups((XMLElement *)(e)); + else if(equal_strings( ((XMLElement *)(e))->name, "module") && ((XMLElement *)(e))->aux) + SendModule((Module *)((XMLElement *)(e)->aux)); + } +} + + + +void +WebUI::SendInspector() +{ + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("\n"); + socket->Send("Modules\n"); + socket->Send("\n"); + socket->Send(""); + socket->Send("\n"); + socket->Send("\n"); + + if(!k->modules) + { + socket->Send("

    No modules

    \n"); + } +/* + for (Module * m = k->modules; m != NULL; m = m->next) + { + SendModule(m); + } +*/ + SendGroups(current_xml_root); + + // Connections + + socket->Send("\n"); + + socket->Send("\n"); + + if(!k->connections) + { + socket->Send("\n"); + } + + for (Connection * c = k->connections; c != NULL; c = c->next) + { + if(!c->source_io->module->GetName() || !c->target_io->module->GetName()) + socket->Send("X"); + if (c->delay == 0) + socket->Send("\n", + c->source_io->module->GetName(), c->source_io->module->GetName(), c->source_io->name, 0, c->source_io->size-1, + c->target_io->module->GetName(), c->target_io->module->GetName(), c->target_io->name, 0, c->source_io->size-1, + c->delay); + else if (c->size > 1) + socket->Send("\n", + c->source_io->module->GetName(), c->source_io->module->GetName(), c->source_io->name, c->source_offset, c->source_offset+c->size-1, + c->target_io->module->GetName(), c->target_io->module->GetName(), c->target_io->name, c->target_offset, c->target_offset+c->size-1, + c->delay); + else + socket->Send("\n", + c->source_io->module->GetName(), c->source_io->module->GetName(), c->source_io->name, c->source_offset, + c->target_io->module->GetName(), c->target_io->module->GetName(), c->target_io->name, c->target_offset, + c->delay); + } + socket->Send("
    Connections
    No connections
    XXX
    %s.%s[%d..%d]==%s.%s[%d..%d]%d
    %s.%s[%d..%d]->%s.%s[%d..%d]%d
    %s.%s[%d]>%s.%s[%d]%d
    \n"); + socket->Send("\n"); + + socket->Close(); +} + + + +void +WebUI::RunIKCFile(char * filepath) +{ +#ifdef POSIX + + // Send reply + + socket->Send("HTTP/1.1 200 OK\n"); + socket->Send("Content-Type: text/html\n"); + socket->Send("\n"); + socket->Send("Restarting Ikaros...\n"); + socket->Close(); + + char * binpath = create_formatted_string("%sBin/IKAROS", k->ikaros_dir); + printf("%s: %s\n", binpath, filepath); + delete socket; + char * s = create_formatted_string("%sExamples/%s", k->ikaros_dir, filepath); + printf("%s\n", s); + + char p[256]; + snprintf(p, 255, "-w%d", port); + execl(binpath, binpath, p, s, NULL); +#endif +} + + + +void +WebUI::ReadXML(XMLDocument * xmlDoc) +{ + if (xmlDoc == NULL) + { + return; + } + + if (xmlDoc->xml == NULL) + { + k->Notify(msg_fatal_error, "WebUI: xmlDoc missing\n"); + return; + } + + xml = xmlDoc->xml->GetElement("group"); + current_xml_root = xml; + + if (xml == NULL) + { + xml = xmlDoc->xml->GetElement("network"); + if (xml != NULL) + xml = xml->GetElement("views"); + } + + // Catch exceptions here!!! + + if (xml == NULL) + { + k->Notify(msg_warning, "WebUI: No views found\n"); // add exception based error handling later + return; + } +} + +#endif diff --git a/Source/WebUI/WebUI.h b/Source/WebUI/WebUI.h new file mode 100755 index 000000000..7f873b32a --- /dev/null +++ b/Source/WebUI/WebUI.h @@ -0,0 +1,141 @@ +// +// WebUI.h Web UI code for the IKAROS project +// +// Copyright (C) 2005-2010 Christian Balkenius +// +// 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 2 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, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// See http://www.ikaros-project.org/ for more information. +// +// Created August 31, 2005 +// + +#ifndef WEBUI +#define WEBUI + +#include +#include + +#include "IKAROS.h" + +#ifdef USE_SOCKET + +#ifndef WEBUIPATH +#define WEBUIPATH "Source/WebUI/UI/" +#endif + +#define PORT 8000 + +class WebUI; + +/* + const int data_source_IO = 0; + const int data_source_float = 1; + const int data_source_array = 2; + const int data_source_matrix = 3; + */ + + +class DataSource +{ +public: + DataSource * next; + char * name; + int type; // 0 = Module_IO, 1 = float, 2 = array, 3 = matrix ... + void * data; + int size_x; + int size_y; + + DataSource(const char * s, int type, void * data_ptr, int sx, int sy, DataSource * n); + + ~DataSource(); +}; + + + +class ModuleData +{ +public: + ModuleData * next; + char * name; + Module * module; + DataSource * source; + + ModuleData(const char * module_name, Module * m, ModuleData * n); + ~ModuleData(); + + void AddSource(const char * s, Module_IO * io); + void AddSource(const char * s, int type, void * value_ptr, int sx, int sy); +}; + + + +const int ui_state_stop = 0; +const int ui_state_pause = 1; +const int ui_state_step = 2; +const int ui_state_run = 3; +const int ui_state_realtime = 4; + + + +class WebUI +{ +public: + Kernel * k; + char * webui_dir; + int port; + ServerSocket * socket; + XMLElement * xml; + XMLElement * current_xml_root; + char * current_xml_root_path; + bool debug_mode; + bool isRunning; + long tick; + int ui_state; + int iterations_per_runstep; + + ModuleData * view_data; + + WebUI(Kernel * kernel); + ~WebUI(); + + void AddDataSource(const char * module, const char * source); + void AddParameterSource(const char * module, const char * source); + void SendAllJSONData(); + void SendMinimalJSONData(); + void SendMenu(float x, float y, const char * name); + void Send404(); + void SendView(const char * view); + void SendExamplesDirectory(const char * directory, const char * path); + void SendExamples(); + void SendModule(Module * m); + void SendGroups(XMLElement * xml); + void SendInspector(); + void SendXML(); + void RunIKCFile(char * filepath); + void ReadXML(XMLDocument * xmlDoc); + void HandleRGBImageRequest(const char * module, const char * output); + void HandleHTTPRequest(); + void HandleHTTPThread(); + + Thread * httpThread; + static void * StartHTTPThread(void * webui); + + void Run(); +}; + +#endif +#endif +