diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 00000000..dc8dcce9
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "src/hal/components/cros"]
+ path = src/hal/components/cros
+ url = git@github.com:jjrbfi/cros.git
diff --git a/.vscode/settings.json b/.vscode/settings.json
deleted file mode 100644
index 772e47ee..00000000
--- a/.vscode/settings.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "ros.distro": "noetic",
- "python.autoComplete.extraPaths": [
- "/opt/ros/noetic/lib/python3/dist-packages"
- ],
- "python.analysis.extraPaths": [
- "/opt/ros/noetic/lib/python3/dist-packages"
- ],
- "cmake.configureOnOpen": false
-}
\ No newline at end of file
diff --git a/Readme.md b/Readme.md
index 4842ad87..c1a6ac85 100644
--- a/Readme.md
+++ b/Readme.md
@@ -1,28 +1,48 @@
+
+
+
-Hal_core is a lightweight hal environment.
-The installed size is approx 6.8Mib
+
+
+ROS + LinuxCNC HAL
-A hal environment can be used as platform to run realtime applications like:
+Hal-core is a lightweight HAL environment from LinuxCNC.
+The installed size is approx 7Mib
- motion controllers
- robots
- cnc-machines
- parport, ethercat applications
- research and development
- scientific projects
+### A hal environment can be used as platform to run realtime applications like:
-Packages needed for the installation (at the bottom):
+ Motion controllers
+ Robots
+ CNC-machines
+ Parport, EtherCAT applications
+ Research and development
+ Scientific projects
-https://github.com/grotius-cnc/hal_core/tree/main/src#readme
+### Install hal-core:
-To install:
-
- Install hal-core:
- $ git clone https://github.com/grotius-cnc/hal_core.git /opt/hal-core
- $ /opt/hal-core/./make
+ $ git clone --recursive https://github.com/jjrbfi/hal-core.git /opt/hal-core
+ $ cd /op/hal-core/
+ $ sudo ./make
+ $ sudo chown -R $USER:$USER /opt/hal-core/
-To run:
+### Before run:
+1. Modify **config/hal.yaml** file with your Hardware configuration and then run **hal_config.py** to create our .xml
+2. Run ROScore and keep it in the background with: ```roscore &```
+
- $ /opt/hal-core/./runtest
+### To run:
-https://user-images.githubusercontent.com/44880102/129791198-ab705999-23ca-4004-a5f5-f0bd3357b47e.mp4
+ Setup HAL
+ $ ./runtest
+
+ Run ROS listener
+ $ halcmd -r
+
+
+### Requirements:
+```bash
+apt-get install -y build-essential
+apt-get install -y libudev-dev
+apt-get install -y libboost-all-dev
+apt-get install -y libreadline-dev
+```
diff --git a/img/logo.png b/img/logo.png
new file mode 100644
index 00000000..446b464e
Binary files /dev/null and b/img/logo.png differ
diff --git a/make b/make
index 9db7c1d0..762e444e 100755
--- a/make
+++ b/make
@@ -5,12 +5,30 @@ chmod +x /opt/hal-core/runtest
chmod +x /opt/hal-core/src/clean
chmod +x /opt/hal-core/src/make
chmod +x /opt/hal-core/src/configure
+chmod +x /opt/hal-core/scripts/halrun
+chmod +x /opt/hal-core/scripts/realtime
+
+# Compile cROS and copy shared library
+if [ -f /opt/hal-core/src/hal/components/cros/build/libcros.so ]; then
+ echo "Exist!"
+else
+ mkdir /opt/hal-core/src/hal/components/cros/build
+ cd /opt/hal-core/src/hal/components/cros/build && cmake ..
+ cd /opt/hal-core/src/hal/components/cros/build/ && make
+ ln -s /opt/hal-core/src/hal/components/cros/build/libcros.so /opt/hal-core/lib/
+ ln -s /opt/hal-core/src/hal/components/cros/include/ /opt/hal-core/src/cros
+fi
# Compile hal-core
cd /opt/hal-core/src/
./configure --disable-gtk --with-realtime=uspace
./make && sudo make setuid
+# Set user able to insert kernel modules
+chown 777 -R /opt/hal-core/bin/rtapi_app
+chown 777 -R /opt/hal-core/bin/module_helper
+chmod 777 /opt/hal-core/bin/rtapi_app
+chmod 777 /opt/hal-core/bin/module_helper
# Compile test component:
chmod +x /opt/hal-core/src/hal/components/test/make
diff --git a/runtest b/runtest
index e55f71e8..9cb525a1 100755
--- a/runtest
+++ b/runtest
@@ -1,10 +1,24 @@
#!/usr/bin/bash
+# Startup hal-core
cd /opt/hal-core/scripts/ && . ./rip-environment
-
cd /opt/hal-core/bin
+halcmd stop
+halcmd loadrt threads name1=base-thread fp1=0 period1=1000000
+#name2=servo-thread period2=1
+
+# Unix command to load the ethercat .xml config
+/opt/hal-core/rtlib/./lcec_conf /opt/hal-core/rtlib/ethercat-conf.xml &
+halcmd loadrt lcec
+#halcmd loadrt test
+
+halcmd addf lcec.read-all base-thread
+halcmd addf lcec.write-all base-thread
+
+halcmd start
+
halcmd show
# To clean the hal environment :
diff --git a/src/hal/components/cros b/src/hal/components/cros
new file mode 160000
index 00000000..d180cfff
--- /dev/null
+++ b/src/hal/components/cros
@@ -0,0 +1 @@
+Subproject commit d180cfff709ae56cb2d8befa486991a11a0e9321
diff --git a/src/hal/utils/halcmd_main.c b/src/hal/utils/halcmd_main.c
index 16a55b3e..ac3f3a29 100644
--- a/src/hal/utils/halcmd_main.c
+++ b/src/hal/utils/halcmd_main.c
@@ -59,6 +59,19 @@
#include
#include
+// cROS
+#include "cros.h"
+#include
+#include
+#include
+
+#define DIR_SEPARATOR_STR "/"
+#define ROS_MASTER_PORT 11311
+#define ROS_MASTER_ADDRESS "127.0.0.1"
+
+CrosNode *node; //! Pointer to object storing the ROS node. This object includes all the ROS node state variables
+static unsigned char exit_flag = 0; //! ROS node loop exit flag. When set to 1 the cRosNodeStart() function exits
+
static int get_input(FILE *srcfile, char *buf, size_t bufsize);
static void print_help_general(int showR);
static int release_HAL_mutex(void);
@@ -71,10 +84,128 @@ static char *prompt_continue = "halcmd+: ";
#define MAX_EXTEND_LINES 20
+
+/***********************************************************************
+* cROS FUNCTION DEFINITIONS *
+************************************************************************/
+
+// This callback will be invoked when the subscriber receives a message
+static CallbackResponse callback_sub(cRosMessage *message, void* data_context)
+{
+ int retval;
+ char *tokens[MAX_TOK+1];
+
+ cRosMessageField *data_field = cRosMessageGetField(message, "data");
+ if(data_field != NULL)
+ {
+ ROS_INFO(node, "I heard: [%s]\n", data_field->data.as_string);
+ halcmd_startup(1);
+ // remove comments, do var substitution, and tokenise
+ retval = halcmd_preprocess_line(data_field->data.as_string, tokens);
+ // Run the command
+ retval = halcmd_parse_cmd(tokens);
+ return 0; // 0=success
+ }
+}
+
+struct sigaction old_int_signal_handler, old_term_signal_handler; //! Structures codifying the original handlers of SIGINT and SIGTERM signals (e.g. used when pressing Ctrl-C for the second time);
+
+// This callback function will be called when the main process receives a SIGINT or
+// SIGTERM signal.
+// Function set_signal_handler() should be called to set this function as the handler of
+// these signals
+static void exit_deamon_handler(int sig)
+{
+ printf("Signal %i received: exiting safely.\n", sig);
+ sigaction(SIGINT, &old_int_signal_handler, NULL);
+ sigaction(SIGTERM, &old_term_signal_handler, NULL);
+ exit_flag = 1; // Indicate the exit of cRosNodeStart loop (safe exit)
+}
+
+// Sets the signal handler functions of SIGINT and SIGTERM: exit_deamon_handler
+static int set_signal_handler(void)
+ {
+ int ret;
+ struct sigaction act;
+
+ memset (&act, '\0', sizeof(act));
+
+ act.sa_handler = exit_deamon_handler;
+ // If the signal handler is invoked while a system call or library function call is blocked,
+ // then the we want the call to be automatically restarted after the signal handler returns
+ // instead of making the call fail with the error EINTR.
+ act.sa_flags=SA_RESTART;
+ if(sigaction(SIGINT, &act, &old_int_signal_handler) == 0 && sigaction(SIGTERM, &act, &old_term_signal_handler) == 0)
+ ret=0;
+ else
+ {
+ ret=errno;
+ printf("Error setting termination signal handler. errno=%d\n",ret);
+ }
+ return(ret);
+ }
+
+
/***********************************************************************
* LOCAL FUNCTION DEFINITIONS *
************************************************************************/
+int cros_main(){
+ //char path[4097]; // We need to tell our node where to find the .msg files that we'll be using
+ char *path="/opt/hal-core/src/hal/components/cros/samples/rosdb/";
+ const char *node_name;
+ int subidx; // Index (identifier) of the created subscriber
+ cRosErrCodePack err_cod;
+
+ node_name="/listener"; // Default node name if no command-line parameters are specified
+ //getcwd(path, sizeof(path));
+ //strncat(path, DIR_SEPARATOR_STR"rosdb", sizeof(path) - strlen(path) - 1);
+
+ printf("Using the following path for message definitions: %s\n", path);
+ // Create a new node and tell it to connect to roscore in the usual place
+ node = cRosNodeCreate(node_name, "127.0.0.1", ROS_MASTER_ADDRESS, ROS_MASTER_PORT, path);
+ if( node == NULL )
+ {
+ printf("cRosNodeCreate() failed; is this program already being run?");
+ return EXIT_FAILURE;
+ }
+
+ err_cod = cRosWaitPortOpen(ROS_MASTER_ADDRESS, ROS_MASTER_PORT, 0);
+ if(err_cod != CROS_SUCCESS_ERR_PACK)
+ {
+ cRosPrintErrCodePack(err_cod, "Port %s:%hu cannot be opened: ROS Master does not seems to be running", ROS_MASTER_ADDRESS, ROS_MASTER_PORT);
+ return EXIT_FAILURE;
+ }
+
+ // Create a subscriber to topic /chatter of type "std_msgs/String" and supply a callback for received messages (callback_sub)
+ err_cod = cRosApiRegisterSubscriber(node, "/chatter", "std_msgs/String", callback_sub, NULL, NULL, 0, &subidx);
+ if(err_cod != CROS_SUCCESS_ERR_PACK)
+ {
+ cRosPrintErrCodePack(err_cod, "cRosApiRegisterSubscriber() failed; did you run this program one directory above 'rosdb'?");
+ cRosNodeDestroy( node );
+ return EXIT_FAILURE;
+ }
+
+ ROS_INFO(node, "Node %s created with XMLRPC port: %i, TCPROS port: %i and RPCROS port: %i\n", node->name, node->xmlrpc_port, node->tcpros_port, node->rpcros_port);
+
+ // Function exit_deamon_handler() will be called when Ctrl-C is pressed or kill is executed
+ set_signal_handler();
+
+ // Run the main loop until exit_flag is 1
+ err_cod = cRosNodeStart( node, CROS_INFINITE_TIMEOUT, &exit_flag );
+ if(err_cod != CROS_SUCCESS_ERR_PACK)
+ cRosPrintErrCodePack(err_cod, "cRosNodeStart() returned an error code");
+
+ // Free memory and unregister
+ err_cod=cRosNodeDestroy( node );
+ if(err_cod != CROS_SUCCESS_ERR_PACK)
+ {
+ cRosPrintErrCodePack(err_cod, "cRosNodeDestroy() failed; Error unregistering from ROS master");
+ return EXIT_FAILURE;
+ }
+ return EXIT_SUCCESS;;
+}
+
int main(int argc, char **argv)
{
int c, fd;
@@ -97,7 +228,7 @@ int main(int argc, char **argv)
keep_going = 0;
/* start parsing the command line, options first */
while(1) {
- c = getopt(argc, argv, "+RCfi:kqQsvVhe");
+ c = getopt(argc, argv, "+RCfri:kqQsvVhe");
if(c == -1) break;
switch(c) {
case 'R':
@@ -147,6 +278,9 @@ int main(int argc, char **argv)
case 'f':
filemode = 1;
break;
+ case 'r':
+ cros_main();
+ break;
case 'C':
cl = getenv("COMP_LINE");
cw = getenv("COMP_POINT");
@@ -276,7 +410,6 @@ int main(int argc, char **argv)
if (!extend_ct) { elineptr = (char*)raw_buf; }
extend_ct = 0;
if (prompt == prompt_continue) { prompt = prompt_interactive; }
-
/* remove comments, do var substitution, and tokenise */
retval = halcmd_preprocess_line(elineptr, tokens);
if(echo_mode) {
@@ -390,6 +523,7 @@ static void print_help_general(int showR)
printf(" -e echo the commands from stdin to stderr\n");
printf(" -f [filename] Read commands from 'filename', not command\n");
printf(" line. If no filename, read from stdin.\n");
+ printf(" -r Start ROS listener (roscore have to be running)\n");
#ifndef NO_INI
printf(" -i filename Open .ini file 'filename', allow commands\n");
printf(" to get their values from ini file.\n");
@@ -445,6 +579,7 @@ static int get_input(FILE *srcfile, char *buf, size_t bufsize) {
}
#endif
+
void halcmd_output(const char *format, ...) {
va_list ap;
va_start(ap, format);
diff --git a/src/make b/src/make
index 83087734..64db8c94 100755
--- a/src/make
+++ b/src/make
@@ -35,7 +35,7 @@ gcc -c -I. -Irtapi -Ihal -Os -fwrapv -g -Wall -DULAPI -std=gnu99 -fgnu89-inline
-MP -MD -MF "objects/hal/utils/halcmd_commands.d" -MT "objects/hal/utils/halcmd_commands.o" \
hal/utils/halcmd_commands.c -o objects/hal/utils/halcmd_commands.o
# Compiling hal/utils/halcmd_main.c
-gcc -c -I. -Irtapi -Ihal -Os -fwrapv -g -Wall -DULAPI -std=gnu99 -fgnu89-inline -Werror=implicit-function-declaration -g -O2 \
+gcc -c -I. -Icros -Irtapi -Ihal -Os -fwrapv -g -Wall -DULAPI -std=gnu99 -fgnu89-inline -Werror=implicit-function-declaration -g -O2 \
-MP -MD -MF "objects/hal/utils/halcmd_main.d" -MT "objects/hal/utils/halcmd_main.o" \
hal/utils/halcmd_main.c -o objects/hal/utils/halcmd_main.o
# Compiling hal/utils/halcmd_completion.c
@@ -54,7 +54,7 @@ gcc -c -I. -Irtapi -Ihal -Os -fwrapv -g -Wall -DULAPI -std=gnu99 -fgnu89-inline
# Creating shared library libhalcore.so.0
gcc -L/opt/hal-core/lib -Wl,-rpath,/opt/hal-core/lib -Wl,-soname,libhalcore.so.0 -shared -o ../lib/libhalcore.so.0 objects/hal/hal_lib.o objects/rtapi/uspace_ulapi.o -pthread -lrt
# Linking halcmd
-gcc -L/opt/hal-core/lib -Wl,-rpath,/opt/hal-core/lib -o ../bin/halcmd objects/hal/utils/halcmd.o objects/hal/utils/halcmd_commands.o objects/hal/utils/halcmd_main.o objects/hal/utils/halcmd_completion.o ../lib/libhalcore.so.0 -lreadline
+gcc -L/opt/hal-core/lib -Wl,-rpath,/opt/hal-core/lib -o ../bin/halcmd objects/hal/utils/halcmd.o objects/hal/utils/halcmd_commands.o objects/hal/utils/halcmd_main.o objects/hal/utils/halcmd_completion.o ../lib/libcros.so ../lib/libhalcore.so.0 -lreadline
ln -sf libhalcore.so.0 ../lib/libhalcore.so
# Compiling module_helper/module_helper.c