How do I simulate swarm movement of drones with ns-3? - ns-3

First of all, I'm still an absolute beginner in ns-3. I am trying to simulate swarm movement of drones using ns-3. I've gotten some source codes/tutorial from youtube which is partly what I want. So far, the codes are simulating FANET(Flying Ad Hoc Network) together with a 3D Gauss Markov Mobility model. I'm thinking that maybe I can add to these codes to also simulate swarm movement together.
Problem is I don't know where to begin and also have not been able to find much resources online. Could someone maybe give some ideas as to what I should do or maybe provide relevant resources? I will attach the codes that I have right now.
Reference: https://www.nsnam.com/2020/11/flying-adhoc-network-simulation-fanet.html
#include "ns3/point-to-point-module.h"
#include "ns3/ipv4-global-routing-helper.h"
#include <fstream>
#include <string>
#include "ns3/core-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/config-store-module.h"
#include "ns3/wifi-module.h"
#include "ns3/aodv-helper.h"
#include "ns3/internet-module.h"
#include "ns3/netanim-module.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("Mob");
int main (int argc, char *argv[])
{
CommandLine cmd;
cmd.Parse (argc, argv);
NodeContainer c;
c.Create (20); //20 wireless nodes
WifiHelper wifi;
wifi.SetStandard (WIFI_PHY_STANDARD_80211b);
//80211a, 80211b, 80211n, 2.4g and 5G, 80211ac, 80211ax is also supported.80211p (VANETs, WAVE)
WifiMacHelper mac;
mac.SetType ("ns3::AdhocWifiMac");
//AdhocWifiMac, StaWifiMac, ApWifiMac
wifi.SetRemoteStationManager ("ns3::ConstantRateWifiManager",
"DataMode", StringValue ("OfdmRate54Mbps"));
YansWifiPhyHelper wifiPhy = YansWifiPhyHelper::Default ();
YansWifiChannelHelper wifiChannel = YansWifiChannelHelper::Default ();
wifiChannel.SetPropagationDelay ("ns3::ConstantSpeedPropagationDelayModel");
wifiChannel.AddPropagationLoss ("ns3::FriisPropagationLossModel");
wifiPhy.SetChannel (wifiChannel.Create ());
NetDeviceContainer cDevices = wifi.Install (wifiPhy, mac, c);
//
NS_LOG_INFO ("Enabling AODV routing on all backbone nodes");
AodvHelper aodv;
//AODV protocol is being using FANETs.
InternetStackHelper internet;
internet.SetRoutingHelper (aodv); // has effect on the next Install ()
internet.Install (c);
//
// Assign IPv4 addresses to the device drivers (actually to the associated
// IPv4 interfaces) we just created.
//
Ipv4AddressHelper ipAddrs;
ipAddrs.SetBase ("192.168.0.0", "255.255.255.0");
Ipv4InterfaceContainer cInterfaces;
cInterfaces=ipAddrs.Assign (cDevices);
//Mobility Model -3D
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::GaussMarkovMobilityModel",
"Bounds", BoxValue (Box (0, 100, 0, 100, 0, 100)),
"TimeStep", TimeValue (Seconds (0.5)),
"Alpha", DoubleValue (0.85),
"MeanVelocity", StringValue ("ns3::UniformRandomVariable[Min=800|Max=1200]"),
"MeanDirection", StringValue ("ns3::UniformRandomVariable[Min=0|Max=6.283185307]"),
"MeanPitch", StringValue ("ns3::UniformRandomVariable[Min=0.05|Max=0.05]"),
"NormalVelocity", StringValue ("ns3::NormalRandomVariable[Mean=0.0|Variance=0.0|Bound=0.0]"),
"NormalDirection", StringValue ("ns3::NormalRandomVariable[Mean=0.0|Variance=0.2|Bound=0.4]"),
"NormalPitch", StringValue ("ns3::NormalRandomVariable[Mean=0.0|Variance=0.02|Bound=0.04]"));
mobility.SetPositionAllocator ("ns3::RandomBoxPositionAllocator",
"X", StringValue ("ns3::UniformRandomVariable[Min=0|Max=100]"),
"Y", StringValue ("ns3::UniformRandomVariable[Min=0|Max=100]"),
"Z", StringValue ("ns3::UniformRandomVariable[Min=0|Max=100]"));
mobility.Install (c);
UdpEchoServerHelper echoServer (9);
ApplicationContainer serverApps = echoServer.Install (c.Get(0));
serverApps.Start (Seconds (1.0));
serverApps.Stop (Seconds (10.0));
UdpEchoClientHelper echoClient (cInterfaces.GetAddress(0), 9);
echoClient.SetAttribute ("MaxPackets", UintegerValue (1));
echoClient.SetAttribute ("Interval", TimeValue (Seconds (1.0)));
echoClient.SetAttribute ("PacketSize", UintegerValue (1024));
ApplicationContainer clientApps = echoClient.Install (c.Get(1));
clientApps.Start (Seconds (2.0));
clientApps.Stop (Seconds (10.0));
wifiPhy.EnablePcapAll ("Fanet3D"); //Packet Capture.
//Network Animation using NetAnim.
AnimationInterface anim("Fanet3D.xml");
//Ascii Trace Metrics can be processed using Tracemetrics Software.
AsciiTraceHelper ascii;
wifiPhy.EnableAsciiAll(ascii.CreateFileStream("Fanet3D.tr"));
Simulator::Stop (Seconds (10.0));
Simulator::Run ();
Simulator::Destroy ();
return 0;
}

Related

How to make downward connection in Contiki-NG with UDP

I'm trying to make a simple mesh connection using 6LoWPAN with Contiki.
For simplicity I'm making this in Cooja, so the hardware is not a constrain in this problem i think.
My objective is to have one root (UDP Server) and many motes (UDP Client). With the examples provided by Contiki, I'm able to do start the communication with the Motes and talk to the Server, but is it possible to do it the other way around?
I want the Root to start send the message to any client, and if it's neccesary, to hop the message via another clients in the network.
Do you have any idea if this is possible to do? Or any track for achieve this?
Update: What I've tried so far:
What i've tried so far, in the server device, create two process, one for initiating the root, and the other one for sendig the packet periodically:
#include "contiki.h"
#include <stdlib.h>
#include "net/routing/routing.h"
#include "random.h"
#include "net/netstack.h"
#include "net/ipv6/simple-udp.h"
#include "sys/log.h"
#define LOG_MODULE "App"
#define LOG_LEVEL LOG_LEVEL_DBG
#define UDP_CLIENT_PORT 8765
#define UDP_SERVER_PORT 5678
#define SEND_INTERVAL (5 * CLOCK_SECOND)
static struct simple_udp_connection udp_conn;
static struct etimer periodic_timer;
PROCESS(udp_server_process, "UDP server");
PROCESS(send_msg_process, "UDP server");
AUTOSTART_PROCESSES(&udp_server_process, &send_msg_process);
static void
udp_rx_callback(struct simple_udp_connection *c,
const uip_ipaddr_t *sender_addr,
uint16_t sender_port,
const uip_ipaddr_t *receiver_addr,
uint16_t receiver_port,
const uint8_t *data,
uint16_t datalen)
{
LOG_INFO("Received response '%.*s' from ", datalen, (char *) data);
LOG_INFO_6ADDR(sender_addr);
LOG_INFO_("\n");
}
PROCESS_THREAD(udp_server_process, ev, data)
{
PROCESS_BEGIN();
/* Initialize DAG root */
NETSTACK_ROUTING.root_start();
/* Initialize UDP connection */
simple_udp_register(&udp_conn, UDP_SERVER_PORT, NULL,
UDP_CLIENT_PORT, udp_rx_callback);
PROCESS_END();
}
PROCESS_THREAD(send_msg_process, ev, data)
{
static unsigned count;
static char str[32];
uip_ipaddr_t dest_ipaddr;
LOG_INFO("%u", count);
PROCESS_BEGIN();
while(1) {
etimer_set(&periodic_timer, CLOCK_SECOND);
PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&periodic_timer));
uip_ip6addr(&dest_ipaddr,0xfe80,0,0,0,0x207,0x7,0x7,0x7);
LOG_INFO("Sending request %u to ", count);
LOG_INFO_6ADDR(&dest_ipaddr);
LOG_INFO_("\n");
snprintf(str, sizeof(str), "hello %d", count);
simple_udp_sendto(&udp_conn, str, strlen(str), &dest_ipaddr);
count++;
}
PROCESS_END();
}
In the cliend side, the code is based simply on listening to the UDP socket, and make a response in the case that it receives a packet.
#include "contiki.h"
#include "net/routing/routing.h"
#include "random.h"
#include "net/netstack.h"
#include "net/ipv6/simple-udp.h"
#include "sys/log.h"
#define LOG_MODULE "App"
#define LOG_LEVEL LOG_LEVEL_DBG
#define WITH_SERVER_REPLY 1
#define UDP_CLIENT_PORT 8765
#define UDP_SERVER_PORT 5678
#define SEND_INTERVAL (5 * CLOCK_SECOND)
static struct simple_udp_connection udp_conn;
/*---------------------------------------------------------------------------*/
PROCESS(udp_client_process, "UDP client");
AUTOSTART_PROCESSES(&udp_client_process);
/*---------------------------------------------------------------------------*/
static void
udp_rx_callback(struct simple_udp_connection *c,
const uip_ipaddr_t *sender_addr,
uint16_t sender_port,
const uip_ipaddr_t *receiver_addr,
uint16_t receiver_port,
const uint8_t *data,
uint16_t datalen)
{
LOG_INFO("Received request '%.*s' from ", datalen, (char *) data);
LOG_INFO_6ADDR(sender_addr);
LOG_INFO("Sending response.\n");
simple_udp_sendto(&udp_conn, data, datalen, sender_addr);
LOG_INFO_("\n");
}
PROCESS_THREAD(udp_client_process, ev, data)
{
PROCESS_BEGIN();
simple_udp_register(&udp_conn, UDP_CLIENT_PORT, NULL,
UDP_SERVER_PORT, udp_rx_callback);
PROCESS_END();
}
As you can see, the code for the server sends periodically a packet to the ipv6 direction: 0xfe80:0:0:0:0x207:0x7:0x7:0x7, which is the ip that will be assigned to a mote in cooja when it is the number 7 in the simulation.
The results I've obtained is that, when the root (A) and the client (B) are in direct connection, they talk to each other perfectly, but when I separate them and try to make the connection from the root (A) to the client (B) via another client (C), the message won't get from A to B.
Yes, it is possible. The RPL routing protocol allows to send packets in both directions from and to the root. Simply use the node's IP address as the destination.
One issue is that a node typically has two IPv6 addresses:
Addresses starting with 0xfe80 are link local.
Addresses starting with the network prefix - defined in the OS config as UIP_DS6_DEFAULT_PREFIX, equal to 0xfd00 by default. This address is only present after the node has joined the RPL network.
Packets to link-local addresses must be single-hop, they are not forwarded by nodes. In order to utilize the multi-hop mesh forwarding properly, use the other address as the destination.

How to set node position in NetAnim? I always get Use SetConstantPosition if it is stationary error

I am new to ns-3. I am trying to understand from the very basic. I created a network simulation containing two switches, then I want to visualize it using NetAnim.
Followings are my code
/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation;
*
* 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 "ns3/core-module.h"
#include "ns3/point-to-point-module.h"
#include "ns3/network-module.h"
#include "ns3/applications-module.h"
#include "ns3/mobility-module.h"
#include "ns3/csma-module.h"
#include "ns3/internet-module.h"
#include "ns3/yans-wifi-helper.h"
#include "ns3/ssid.h"
#include "ns3/netanim-module.h"
#include "stdio.h"
using namespace ns3;
NS_LOG_COMPONENT_DEFINE ("HMTMRSim");
int
main (int argc, char *argv[])
{
std::cout << "create switches" << std::endl;
NodeContainer switches;
switches.Create(2); // create two switches
AnimationInterface anim("myanim.xml");
std::cout << "set position for switches" << std::endl;
anim.SetConstantPosition(switches.Get(0), 48.0, 70.0, 0);
anim.SetConstantPosition(switches.Get(1), 48.0, 90.0, 0);
anim.UpdateNodeDescription(0, "Main");
anim.UpdateNodeDescription(1, "Rack0");
anim.UpdateNodeSize(0, 10, 10);
anim.UpdateNodeColor(0, 0, 0, 255);
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
When I run it, it works without problem, but I get this warning
Waf: Leaving directory `/Users/arwankhoiruddin/Downloads/ns-allinone-3.30.1/ns-3.30.1/build'
Build commands will be stored in build/compile_commands.json
'build' finished successfully (18.508s)
create switches
AnimationInterface WARNING:Node:0 Does not have a mobility model. Use SetConstantPosition if it is stationary
AnimationInterface WARNING:Node:1 Does not have a mobility model. Use SetConstantPosition if it is stationary
AnimationInterface WARNING:Node:0 Does not have a mobility model. Use SetConstantPosition if it is stationary
AnimationInterface WARNING:Node:
When I open in NetAnim (shown in the picture below), it seems to ignore the position that I defined in my code. As you see in the following properties, the first node (node 0) has position of (x,y) = (81.00, 83.00).
I am aware that I can change the position by changing the value in properties, but later using ns-3, I want to create quite a complex network, so it will be difficult to set them manually.
In internet, I found this suggestion, i.e. adding mobility to replace the SetConstantPosition. However, the result in NetAnim is still similar.
MobilityHelper mobility;
Ptr<ListPositionAllocator> positionAlloc = CreateObject<ListPositionAllocator>();
positionAlloc->Add(Vector(0.0, 0.0, 0.0));
positionAlloc->Add(Vector(5.0, 0.0, 0.0));
mobility.SetPositionAllocator(positionAlloc);
mobility.SetMobilityModel("ns3::ConstantPositionMobilityModel");
mobility.Install(switches);
Please let me know how to set the position from my code and get rid of the warning.
Thank you for your kind helps
I posted the same question in NS3 Google Group. Few days later, I got a great answer from Liu XinXin (many thanks for the help - her StackOverflow account is xxliu95). Here's the code that she posted
int
main (int argc, char *argv[])
{
std::cout << "create switches" << std::endl;
NodeContainer switches;
switches.Create(2); // create two switches
MobilityHelper mobility;
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");
mobility.Install (switches);
AnimationInterface anim("myanim.xml");
std::cout << "set position for switches" << std::endl;
Ptr<ConstantPositionMobilityModel> s1 = switches.Get (0)->GetObject<ConstantPositionMobilityModel> ();
Ptr<ConstantPositionMobilityModel> s2 = switches.Get (1)->GetObject<ConstantPositionMobilityModel> ();
s1->SetPosition (Vector ( 48.0, 70.0, 0 ));
s2->SetPosition (Vector ( 48.0, 90.0, 0 ));
anim.UpdateNodeDescription(0, "Main");
anim.UpdateNodeDescription(1, "Rack0");
Simulator::Run ();
Simulator::Destroy ();
return 0;
}
This is what I got in NetAnim

Using AABB_tree with multiple surface meshes

I'm trying to use CGAL's AABB_tree with multiple Surface_mesh and fail an odd assertion which makes me think it's trying to use the first surface mesh's vertices with the second mesh's indices or something similarly weird.
Before I file a bug, I'd like to validate that I'm not misunderstanding something.
Here's a minimally modified example. I'm using cube.off from: https://github.com/libigl/libigl/blob/master/tutorial/shared/cube.off and the Tetrahedron from CGAL's examples, but it seems to reproduce every time the second surface mesh I add has less vertices than the first mesh no matter what it is.
The assertion I'm failing is /usr/local/include/CGAL/Surface_mesh/Properties.h:178 - CGAL_assertion( idx < data.size() );
Using:
CGAL_VERSION 4.12
CGAL_VERSION_NR 1041201000
CGAL_SVN_REVISION 99999
CGAL_GIT_HASH f7c3c8212b56c0d6dae63787efc99093f4383415
#include <iostream>
#include <fstream>
#include <CGAL/Simple_cartesian.h>
#include <CGAL/AABB_tree.h>
#include <CGAL/AABB_traits.h>
#include <CGAL/Surface_mesh.h>
#include <CGAL/AABB_face_graph_triangle_primitive.h>
typedef CGAL::Simple_cartesian<double> K;
typedef K::Point_3 Point;
typedef K::Ray_3 Ray;
typedef CGAL::Surface_mesh<Point> Mesh;
typedef CGAL::AABB_face_graph_triangle_primitive<Mesh> Primitive;
typedef CGAL::AABB_traits<K, Primitive> Traits;
typedef CGAL::AABB_tree<Traits> Tree;
typedef boost::optional<Tree::Intersection_and_primitive_id<Ray>::Type> Ray_intersection;
int main(int argc, char* argv[])
{
const char* filename1 = "cube.off";
const char* filename2 = "tetrahedron.off";
std::ifstream input1(filename1);
Mesh mesh1;
input1 >> mesh1;
std::ifstream input2(filename2);
Mesh mesh2;
input2 >> mesh2;
Tree tree;
tree.insert(faces(mesh1).first, faces(mesh1).second, mesh1);
tree.insert(faces(mesh2).first, faces(mesh2).second, mesh2);
tree.build(); // CGAL_assertion( idx < data.size() ) fails
return 0;
}
I repost my comment as an answer:
From my comment: Actually you can use this primitive but you need to set the template tag OneFaceGraphPerTree to CGAL::Tag_false.
See here

how to perform ssdp communicationbetween upnp devices

i am trying to implement the upnp level communication between the devices .. but facing problem in getting the response message .and more over on sending the ssdp:discovery multicast not able to recieve the messages from the devices ... please guide me through i am completely newto this topic
pre-requisite done by me :
1.able to send the M-Search ..and notify message on the network .. and have confirmed via wireshark
2.gone through the upnp architecture related pdf
response got in wireshark :
when ever i am sending the message i am getting the icmp error message that destination is not reachable ..
< client side code > is the first one and second one is the for time being i am just sending up the data on local host
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define SRV_IP "127.0.0.1"
/* diep(), #includes and #defines like in the server */
#define BUFLEN 512
#define NPACK 10
#define PORT 1900
void diep(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &si_other.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
for (i=0; i<NPACK; i++) {
printf("Sending packet %d\n", i);
sprintf(buf, "\n");
if (sendto(s, buf, BUFLEN, 0, &si_other, slen)==-1)
diep("sendto()");
}
close(s);
return 0;
}
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFLEN 512
#define NPACK 10
#define PORT 1900
void diep(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, &si_me, sizeof(si_me))==-1)
diep("bind");
for (i=0; i<NPACK; i++) {
if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1)
diep("recvfrom()");
printf("Received packet from %s:%d\nData: %s\n\n",
inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
}
close(s);
return 0;
}
The individual lines in you M-SEARCH need to have "\r\n" at the end of each line, not just a "\n". Your system may just be sending "\n" across the wire. Check the bytes you're sending for a 13 followed by a 10. That's "\r\n".

Setting the vector length in SystemC with a received parameter

Im making a xor gate in SystemC, from the binding of four NAND gates. I want the module to receive a vector of N bits, where N is passed as parameter. I should be able to perform & and not bitwise operations (for the NAND gate).
The best solution may be using sc_bv_base type, but I don't know how to initialize it in the constructor.
How can I create a bit vector using a custom length?
A way to parameterise the module is to create a new C++ template for the module.
In this example, the width of the input vector can be set at the level of the instantiation of this module
#ifndef MY_XOR_H_
#define MY_XOR_H_
#include <systemc.h>
template<int depth>
struct my_xor: sc_module {
sc_in<bool > clk;
sc_in<sc_uint<depth> > din;
sc_out<bool > dout;
void p1() {
dout.write(xor_reduce(din.read()));
}
SC_CTOR(my_xor) {
SC_METHOD(p1);
sensitive << clk.pos();
}
};
#endif /* MY_XOR_H_ */
Note that the struct my_xor: sc_module is used i.s.o. the SC_MODULE macro. (See page 40 , 5.2.5 SC_MODULE of the IEEE Std 1666-2011).
You can test this with the following testbench:
//------------------------------------------------------------------
// Simple Testbench for xor file
//------------------------------------------------------------------
#include <systemc.h>
#include "my_xor.h"
int sc_main(int argc, char* argv[]) {
const int WIDTH = 8;
sc_signal<sc_uint<WIDTH> > din;
sc_signal<bool> dout;
sc_clock clk("clk", 10, SC_NS, 0.5); // Create a clock signal
my_xor<WIDTH> DUT("my_xor"); // Instantiate Device Under Test
DUT.din(din); // Connect ports
DUT.dout(dout);
DUT.clk(clk);
sc_trace_file *fp; // Create VCD file
fp = sc_create_vcd_trace_file("wave"); // open(fp), create wave.vcd file
fp->set_time_unit(100, SC_PS); // set tracing resolution to ns
sc_trace(fp, clk, "clk"); // Add signals to trace file
sc_trace(fp, din, "din");
sc_trace(fp, dout, "dout");
sc_start(31, SC_NS); // Run simulation
din = 0x00;
sc_start(31, SC_NS); // Run simulation
din = 0x01;
sc_start(31, SC_NS); // Run simulation
din = 0xFF;
sc_start(31, SC_NS); // Run simulation
sc_close_vcd_trace_file(fp); // close(fp)
return 0;
}
Note that I'm using a struct and not a class. A class is also possible.
class my_xor: public sc_module{
public:
The XOR in this code is just the xor_reduce. You can find more about in the IEEE Std 1666-2011 at page 197 (7.2.8 Reduction operators). But I assume this is not the solution you wanted to have.