diff --git a/Tools/sitl_multiple_run.sh b/Tools/sitl_multiple_run.sh
index a15ab1d3ec..826931f3f1 100755
--- a/Tools/sitl_multiple_run.sh
+++ b/Tools/sitl_multiple_run.sh
@@ -43,7 +43,7 @@ while [ $n -le $sitl_num ]; do
pushd "$working_dir" &>/dev/null
echo "starting instance $n in $(pwd)"
- sudo -b -u $user ../bin/px4 -d "$src_path" rcS >out.log 2>err.log
+ sudo -b -u $user ../bin/px4 -i $n -d "$src_path" -s rcS >out.log 2>err.log
popd &>/dev/null
n=$(($n + 1))
diff --git a/cmake/posix/px4-alias.sh_in b/cmake/posix/px4-alias.sh_in
index e0c361feb3..bd79461192 100644
--- a/cmake/posix/px4-alias.sh_in
+++ b/cmake/posix/px4-alias.sh_in
@@ -18,4 +18,9 @@ set() {
# Don't stop on errors.
#set -e
+# Arguments passed to this script:
+# $1: optional instance id
+px4_instance=0
+[[ -n "$1" ]] && px4_instance=$1
+
${alias_string}
diff --git a/launch/single_vehicle_spawn.launch b/launch/single_vehicle_spawn.launch
index 9c2c3fe7b0..c2f8bc5e39 100644
--- a/launch/single_vehicle_spawn.launch
+++ b/launch/single_vehicle_spawn.launch
@@ -23,7 +23,7 @@
-
+
diff --git a/platforms/posix/cmake/px4_impl_os.cmake b/platforms/posix/cmake/px4_impl_os.cmake
index 217d1662a5..3c6faa944d 100644
--- a/platforms/posix/cmake/px4_impl_os.cmake
+++ b/platforms/posix/cmake/px4_impl_os.cmake
@@ -123,7 +123,7 @@ function(px4_posix_generate_alias)
endforeach()
if (MAIN)
set(alias_string
- "${alias_string}alias ${MAIN}='${PREFIX}${MAIN}'\n"
+ "${alias_string}alias ${MAIN}='${PREFIX}${MAIN} --instance $px4_instance'\n"
)
endif()
endforeach()
diff --git a/platforms/posix/src/main.cpp b/platforms/posix/src/main.cpp
index e2c391ed54..f305009c90 100644
--- a/platforms/posix/src/main.cpp
+++ b/platforms/posix/src/main.cpp
@@ -99,10 +99,11 @@ static void register_sig_handler();
static void set_cpu_scaling();
static int create_symlinks_if_needed(std::string &data_path);
static int create_dirs();
-static int run_startup_bash_script(const std::string &commands_file, const std::string &absolute_binary_path);
+static int run_startup_bash_script(const std::string &commands_file, const std::string &absolute_binary_path,
+ int instance);
static std::string get_absolute_binary_path(const std::string &argv0);
static void wait_to_exit();
-static bool is_already_running();
+static bool is_already_running(int instance);
static void print_usage();
static bool dir_exists(const std::string &path);
static bool file_exists(const std::string &name);
@@ -141,9 +142,23 @@ int main(int argc, char **argv)
absolute_binary_path = get_absolute_binary_path(full_binary_name);
}
+
if (is_client) {
+ int instance = 0;
+
+ if (argc >= 3 && strcmp(argv[1], "--instance") == 0) {
+ instance = strtoul(argv[2], nullptr, 10);
+ /* update argv so that "--instance " is not visible anymore */
+ argc -= 2;
+
+ for (int i = 1; i < argc; ++i) {
+ argv[i] = argv[i + 2];
+ }
+ }
+
+ PX4_DEBUG("instance: %i", instance);
- if (!is_already_running()) {
+ if (!is_already_running(instance)) {
PX4_ERR("PX4 daemon not running yet");
return -1;
}
@@ -151,28 +166,24 @@ int main(int argc, char **argv)
/* Remove the path and prefix. */
argv[0] += path_length + strlen(prefix);
- px4_daemon::Client client;
+ px4_daemon::Client client(instance);
client.generate_uuid();
client.register_sig_handler();
return client.process_args(argc, (const char **)argv);
} else {
- if (is_already_running()) {
- PX4_ERR("PX4 daemon already running");
- return -1;
- }
-
/* Server/daemon apps need to parse the command line arguments. */
std::string data_path = "";
std::string commands_file = "etc/init.d/rcS";
std::string test_data_path = "";
+ int instance = 0;
int myoptind = 1;
int ch;
const char *myoptarg = nullptr;
- while ((ch = px4_getopt(argc, argv, "hdt:s:", &myoptind, &myoptarg)) != EOF) {
+ while ((ch = px4_getopt(argc, argv, "hdt:s:i:", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'h':
print_usage();
@@ -190,6 +201,10 @@ int main(int argc, char **argv)
commands_file = myoptarg;
break;
+ case 'i':
+ instance = strtoul(myoptarg, nullptr, 10);
+ break;
+
default:
PX4_ERR("unrecognized flag");
print_usage();
@@ -197,10 +212,19 @@ int main(int argc, char **argv)
}
}
+ PX4_DEBUG("instance: %i", instance);
+
if (myoptind < argc) {
data_path = argv[myoptind];
}
+ if (is_already_running(instance)) {
+ // allow running multiple instances, but the server is only started for the first
+ PX4_INFO("PX4 daemon already running for instance %i", instance);
+ return -1;
+ }
+
+
int ret = create_symlinks_if_needed(data_path);
if (ret != PX4_OK) {
@@ -223,7 +247,7 @@ int main(int argc, char **argv)
register_sig_handler();
set_cpu_scaling();
- px4_daemon::Server server;
+ px4_daemon::Server server(instance);
server.start();
ret = create_dirs();
@@ -237,7 +261,7 @@ int main(int argc, char **argv)
px4::init_once();
px4::init(argc, argv, "px4");
- ret = run_startup_bash_script(commands_file, absolute_binary_path);
+ ret = run_startup_bash_script(commands_file, absolute_binary_path, instance);
// We now block here until we need to exit.
if (pxh_off) {
@@ -432,11 +456,12 @@ std::string get_absolute_binary_path(const std::string &argv0)
return pwd() + "/" + base;
}
-int run_startup_bash_script(const std::string &commands_file, const std::string &absolute_binary_path)
+int run_startup_bash_script(const std::string &commands_file, const std::string &absolute_binary_path,
+ int instance)
{
std::string bash_command("bash ");
- bash_command += commands_file;
+ bash_command += commands_file + ' ' + std::to_string(instance);
// Update the PATH variable to include the absolute_binary_path
// (required for the px4-alias.sh script and px4-* commands).
@@ -506,24 +531,26 @@ void print_usage()
{
printf("Usage for Server/daemon process: \n");
printf("\n");
- printf(" px4 [-h|-d] [-s ] [-d ] []\n");
+ printf(" px4 [-h|-d] [-s ] [-t ] [] [-i ]\n");
printf("\n");
- printf(" bash start script to be used as startup (default=etc/init.d/rcS)\n");
+ printf(" -s bash start script to be used as startup (default=etc/init.d/rcS)\n");
printf(" directory where startup files and mixers are located,\n");
printf(" (if not given, CWD is used)\n");
- printf(" -h help/usage information\n");
- printf(" -d daemon mode, don't start pxh shell\n");
+ printf(" -i px4 instance id to run multiple instances [0...N], default=0\n");
+ printf(" -h help/usage information\n");
+ printf(" -d daemon mode, don't start pxh shell\n");
printf("\n");
printf("Usage for client: \n");
printf("\n");
- printf(" px4-MODULE command using symlink.\n");
+ printf(" px4-MODULE [--instance ] command using symlink.\n");
printf(" e.g.: px4-commander status\n");
}
-bool is_already_running()
+bool is_already_running(int instance)
{
+ const std::string file_lock_path = std::string(LOCK_FILE_PATH) + '-' + std::to_string(instance);
struct flock fl;
- int fd = open(LOCK_FILE_PATH, O_RDWR | O_CREAT, 0666);
+ int fd = open(file_lock_path.c_str(), O_RDWR | O_CREAT, 0666);
if (fd < 0) {
return false;
diff --git a/platforms/posix/src/px4_daemon/client.cpp b/platforms/posix/src/px4_daemon/client.cpp
index bd064fe34e..bbb3def133 100644
--- a/platforms/posix/src/px4_daemon/client.cpp
+++ b/platforms/posix/src/px4_daemon/client.cpp
@@ -59,9 +59,10 @@ namespace client
static Client *_instance;
}
-Client::Client() :
+Client::Client(int instance_id) :
_uuid(0),
- _client_send_pipe_fd(-1)
+ _client_send_pipe_fd(-1),
+ _instance_id(instance_id)
{
client::_instance = this;
}
@@ -166,7 +167,7 @@ Client::_send_cmds(const int argc, const char **argv)
// The size is +1 because we want to include the null termination.
packet.header.payload_length = cmd_buf.size() + 1;
- _client_send_pipe_fd = open(CLIENT_SEND_PIPE_PATH, O_WRONLY);
+ _client_send_pipe_fd = open(get_client_send_pipe_path(_instance_id).c_str(), O_WRONLY);
if (_client_send_pipe_fd < 0) {
PX4_ERR("pipe open fail");
diff --git a/platforms/posix/src/px4_daemon/client.h b/platforms/posix/src/px4_daemon/client.h
index b0a606cfcb..2e454c4cc2 100644
--- a/platforms/posix/src/px4_daemon/client.h
+++ b/platforms/posix/src/px4_daemon/client.h
@@ -56,7 +56,7 @@ namespace px4_daemon
class Client
{
public:
- Client();
+ Client(int instance_id = 0);
~Client();
/**
@@ -97,6 +97,7 @@ private:
uint64_t _uuid;
int _client_send_pipe_fd;
char _recv_pipe_path[RECV_PIPE_PATH_LEN];
+ int _instance_id; ///< instance ID for running multiple instances of the px4 server
};
} // namespace px4_daemon
diff --git a/platforms/posix/src/px4_daemon/pipe_protocol.cpp b/platforms/posix/src/px4_daemon/pipe_protocol.cpp
index 0cdf49c94b..bbdc0e92a2 100644
--- a/platforms/posix/src/px4_daemon/pipe_protocol.cpp
+++ b/platforms/posix/src/px4_daemon/pipe_protocol.cpp
@@ -43,6 +43,10 @@
#include "pipe_protocol.h"
+static const char CLIENT_SEND_PIPE_PATH[] = "/tmp/px4_client_send_pipe-";
+static const char CLIENT_RECV_PIPE_PATH[] = "/tmp/px4_client_recv_pipe";
+
+
namespace px4_daemon
{
@@ -59,9 +63,13 @@ unsigned get_client_recv_packet_length(const client_recv_packet_s *packet)
int get_client_recv_pipe_path(const uint64_t uuid, char *path, const size_t path_len)
{
- return snprintf(path, path_len, "%s_%016" PRIx64, CLIENT_RECV_PIPE_PATH, uuid);
+ return snprintf(path, path_len, "%s-%016" PRIx64, CLIENT_RECV_PIPE_PATH, uuid);
}
+std::string get_client_send_pipe_path(int instance_id)
+{
+ return std::string(CLIENT_SEND_PIPE_PATH) + std::to_string(instance_id);
+}
} // namespace px4_daemon
diff --git a/platforms/posix/src/px4_daemon/pipe_protocol.h b/platforms/posix/src/px4_daemon/pipe_protocol.h
index b0bcd0ba37..abc2b9b87a 100644
--- a/platforms/posix/src/px4_daemon/pipe_protocol.h
+++ b/platforms/posix/src/px4_daemon/pipe_protocol.h
@@ -39,14 +39,11 @@
#pragma once
#include
+#include
namespace px4_daemon
{
-
-static const char CLIENT_SEND_PIPE_PATH[] = "/tmp/px4_client_send_pipe";
-static const char CLIENT_RECV_PIPE_PATH[] = "/tmp/px4_client_recv_pipe";
-
static const unsigned RECV_PIPE_PATH_LEN = 64;
struct client_send_packet_s {
@@ -93,6 +90,7 @@ struct client_recv_packet_s {
unsigned get_client_send_packet_length(const client_send_packet_s *packet);
unsigned get_client_recv_packet_length(const client_recv_packet_s *packet);
int get_client_recv_pipe_path(const uint64_t uuid, char *path, const size_t path_len);
+std::string get_client_send_pipe_path(int instance_id);
} // namespace px4_daemon
diff --git a/platforms/posix/src/px4_daemon/server.cpp b/platforms/posix/src/px4_daemon/server.cpp
index cb6e2f1908..f8c544940e 100644
--- a/platforms/posix/src/px4_daemon/server.cpp
+++ b/platforms/posix/src/px4_daemon/server.cpp
@@ -57,7 +57,8 @@ namespace px4_daemon
Server *Server::_instance = nullptr;
-Server::Server()
+Server::Server(int instance_id)
+ : _instance_id(instance_id)
{
_instance = this;
}
@@ -109,12 +110,14 @@ Server::_server_main(void *arg)
return;
}
+ std::string client_send_pipe_path = get_client_send_pipe_path(_instance_id);
+
// Delete pipe in case it exists already.
- unlink(CLIENT_SEND_PIPE_PATH);
+ unlink(client_send_pipe_path.c_str());
// Create new pipe to listen to clients.
- mkfifo(CLIENT_SEND_PIPE_PATH, 0666);
- int client_send_pipe_fd = open(CLIENT_SEND_PIPE_PATH, O_RDONLY);
+ mkfifo(client_send_pipe_path.c_str(), 0666);
+ int client_send_pipe_fd = open(client_send_pipe_path.c_str(), O_RDONLY);
while (true) {
@@ -129,7 +132,7 @@ Server::_server_main(void *arg)
// 0 means the pipe has been closed by all clients
// and we need to re-open it.
close(client_send_pipe_fd);
- client_send_pipe_fd = open(CLIENT_SEND_PIPE_PATH, O_RDONLY);
+ client_send_pipe_fd = open(client_send_pipe_path.c_str(), O_RDONLY);
}
}
diff --git a/platforms/posix/src/px4_daemon/server.h b/platforms/posix/src/px4_daemon/server.h
index 44bcf0918a..7ef8edd89f 100644
--- a/platforms/posix/src/px4_daemon/server.h
+++ b/platforms/posix/src/px4_daemon/server.h
@@ -64,7 +64,7 @@ namespace px4_daemon
class Server
{
public:
- Server();
+ Server(int instance_id = 0);
~Server();
/**
@@ -118,6 +118,8 @@ private:
pthread_key_t _key;
+ int _instance_id; ///< instance ID for running multiple instances of the px4 server
+
static void _pthread_key_destructor(void *arg);
static Server *_instance;