I would like to generate a 3D scenario for a traffic simulation.
The main idea would be having SUMO running a simulation and then getting the direction, speed and coordinates (X,Y) from each vehicle, so that I would create 3D models for this cars.
For this purpose, I was thinking about using some kind of TCP/IP communication between Unity and SUMO. Since this is possible while communicating SUMO with a network simulator such as OMNeT++, I was wondering if this would also be possible. I don't need to control the simulation in SUMO from Unity, just retrieve data regarding the vehicles in the network.
Unfortunately, I have no remarkable experience with Unity, so I cannot provide any code trying to achieve this...
EDIT:
As requested, I included some code. However, I only have code in Java.
String configFile = "test/resources/sumo_maps/Test2/Test2.sumo.cfg";
SumoTraciConnection trial = new SumoTraciConnection(configFile,-1);
trial.runServer();
Collection<Vehicle> vehicles = trial.getVehicleRepository().getAll().values();
for(Vehicle car : vehicles){
bw.write(time + " // The vehicle with ID: " + car.getID()+ " is driving "
+ "with a speed of "+ car.getSpeed() + " and is in coordinates x: " +car.getPosition().getX()+
" and y: " + car.getPosition().getY());
bw.newLine();
}
Now, let's proceed to get a bit into the class SumoTraciConnection and its methods. This class is part of the mentioned (in the comments) library Traci4j.
It can be found in GitHub in case you need more info: https://github.com/egueli/TraCI4J/blob/master/src/java/it/polito/appeal/traci/SumoTraciConnection.java
The constructor:
public SumoTraciConnection(String configFile, int randomSeed) {
this.randomSeed = randomSeed;
this.configFile = configFile;
}
Now the runServer() method (I put the one with a boolean argument because if no parameter is given then it is automatically called with a false) Basically, this boolean is used to determine wheter the GUI version of SUMO or the console version will be ran:
public void runServer(boolean withGui) throws IOException, InterruptedException {
retrieveFromURLs(); //Checks if the configFile given has an "http://" at the beggining, in order to download the file
int port = findAvailablePort(); //creates a Socket and finds a port with ServerSocket.getLocalPort()
runSUMO(port, withGui); //It is used to run SUMO with different options, such as the configFile for the simulation, the remote port... sumoProcess is set here as: sumoProcess = Runtime.getRuntime().exec(argsArray);, where argsArray contains the different options mentioned
tryConnect(InetAddress.getLocalHost(), port, sumoProcess); // tryConnect basicaly calls this method tryConnectOnce, which connects as a client to the sumo process mentioned before, and does some checks that everything is correct.
postConnect(); //I will explain this function after
}
postConnect() initialices the DataInput and DataOutput streams and creates the repositories. I show now the relevant parts of the code:
dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
vehicles = new HashMap<String, Vehicle>();
edgeRepo = new Repository.Edges(dis, dos, newIDListQuery(Constants.CMD_GET_EDGE_VARIABLE));
addStepAdvanceListener(edgeRepo);
laneRepo = new Repository.Lanes(dis, dos, edgeRepo, newIDListQuery(Constants.CMD_GET_LANE_VARIABLE));
vehicleListQuery = newIDListQuery(Constants.CMD_GET_VEHICLE_VARIABLE);
addStepAdvanceListener(new StepAdvanceListener() {
public void nextStep(double step) {
vehicleListQuery.setObsolete();
}
});
vehicleListBefore = new HashSet<String>(vehicleListQuery.get());
vehicleRepo = new Repository.Vehicles(dis, dos, edgeRepo, laneRepo, vehicles, vehicleListQuery);
addStepAdvanceListener(vehicleRepo);
Where one StepAdvanceListener is just the following(I cannot explain exactly what is this for but I understand that is something that allow us to realize the new simulationstep has been done, so we have to update the repositories):
//Interface for an object that can be notified when the simulation advances by one step.
public interface StepAdvanceListener {
/**
* Callback for step advancement.
* #param step the new simulation time, in seconds
*/
void nextStep(double step);
}
Up to here, it would be the part related to the connection with SUMO. In the next edit (I need some rest right now..) I'll put the parts related with the Repositories and the Data retrieval
Thanks in advance!
Related
I have been playing around with SharpDX.XAudio2 for a few days now, and while things have been largely positive (the odd software quirk here and there) the following problem has me completely stuck:
I am working in C# .NET using VS2015.
I am trying to play multiple sounds simultaneously.
To do this, I have made:
- Test.cs: Contains main method
- cSoundEngine.cs: Holds XAudio2, MasteringVoice, and sound management methods.
- VoiceChannel.cs: Holds a SourceVoice, and in future any sfx/ related data.
cSoundEngine:
List<VoiceChannel> sourceVoices;
XAudio2 engine;
MasteringVoice master;
public cSoundEngine()
{
engine = new XAudio2();
master = new MasteringVoice(engine);
sourceVoices = new List<VoiceChannel>();
}
public VoiceChannel AddAndPlaySFX(string filepath, double vol, float pan)
{
/**
* Set up and start SourceVoice
*/
NativeFileStream fileStream = new NativeFileStream(filepath, NativeFileMode.Open, NativeFileAccess.Read);
SoundStream soundStream = new SoundStream(fileStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source);
sourceVoices.Add(voice);
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
return voice;
}
Test.cs:
cSoundEngine engine = new cSoundEngine();
total = 6;
for (int i = 0; i < total; i++)
{
string filepath = System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory()).Parent.FullName + #"\Assets\Planet.wav";
VoiceChannel sfx = engine.AddAndPlaySFX(filepath, 0.1, 0);
}
Console.Read(); //Input anything to end play.
There is currently nothing worth showing in VoiceChannel.cs - it holds 'SourceVoice source' which is the one parameter sent in the constructor!
Everything is fine and well running with up to 5 sounds (total = 5). All you hear is the blissful drone of Planet.wav. Any higher than 5 however causes the console to freeze for ~5 seconds, then close (likely a c++ error which debugger can't handle). Sadly no error message for us to look at or anything.
From testing:
- Will not crash as long as you do not have more than 5 running sourcevoices.
- Changing sample rate does not seem to help.
- Setting inputChannels for master object to a different number makes no difference.
- MasteringVoice seems to say the max number of inputvoices is 64.
- Making each sfx play from a different wav file makes no difference.
- Setting the volume for sourcevoices and/or master makes no difference.
From the XAudio2 API Documentation I found this quote: 'XAudio2 removes the 6-channel limit on multichannel sounds, and supports multichannel audio on any multichannel-capable audio card. The card does not need to be hardware-accelerated.'. This is the closest I have come to finding something that mentions this problem.
I am not well experienced with programming sfx and a lot of this is very new to me, so feel free to call me an idiot where appropriate but please try and explain things in layman terms.
Please, if you have any ideas or answers they would be greatly appreciated!
-Josh
As Chuck has suggested, I have created a databank which holds the .wav data, and I just reference the single data store with each buffer. This has improved the sound limit up to 20 - however this has not fixed the problem as a whole, likely because I have not implemented this properly.
Implementation:
class SoundDataBank
{
/**
* Holds a single byte array for each sound
*/
Dictionary<eSFX, Byte[]> bank;
string curdir => Directory.GetParent(Directory.GetCurrentDirectory()).Parent.FullName;
public SoundDataBank()
{
bank = new Dictionary<eSFX, byte[]>();
bank.Add(eSFX.planet, NativeFile.ReadAllBytes(curdir + #"\Assets\Planet.wav"));
bank.Add(eSFX.base1, NativeFile.ReadAllBytes(curdir + #"\Assets\Base.wav"));
}
public Byte[] GetSoundData(eSFX sfx)
{
byte[] output = bank[sfx];
return output;
}
}
In SoundEngine we create a SoundBank object (initialised in SoundEngine constructor):
SoundDataBank soundBank;
public VoiceChannel AddAndPlaySFXFromStore(eSFX sfx, double vol)
{
/**
* sourcevoice will be automatically added to MasteringVoice and engine in the constructor.
*/
byte[] buffer = soundBank.GetSoundData(sfx);
MemoryStream memoryStream = new MemoryStream(buffer);
SoundStream soundStream = new SoundStream(memoryStream);
SourceVoice source = new SourceVoice(engine, soundStream.Format);
AudioBuffer audioBuffer = new AudioBuffer()
{
Stream = soundStream.ToDataStream(),
AudioBytes = (int)soundStream.Length,
Flags = SharpDX.XAudio2.BufferFlags.EndOfStream
};
//Make voice wrapper
VoiceChannel voice = new VoiceChannel(source, engine, MakeOutputMatrix());
//Volume
source.SetVolume((float)vol);
//Play sound
source.SubmitSourceBuffer(audioBuffer, soundStream.DecodedPacketsInfo);
source.Start();
sourceVoices.Add(voice);
return voice;
}
Following this implementation now lets me play up to 20 sound effects - but NOT because we are playing from the soundbank. Infact, even running the old method for sound effects now gets up to 20 sfx instances.
This has improved up to 20 because we have done NativeFile.ReadAllBytes(curdir + #"\Assets\Base.wav") in the constructor for the SoundBank.
I suspect NativeFile is holding a store of loaded file data, so you regardless of whether you run the original SoundEngine.AddAndPlaySFX() or SoundEngine.AddAndPlaySFXFromStore(), they are both running from memory?
Either way, this has quadrupled the limit from before, so this has been incredibly useful - but requires further work.
I'm trying to use libgit2sharp to push to my repo on bitbucket. I'm trying to do this:
repo.Network.Push(repo.Branches[branchName], pushOptions);
Everything seems fine, no exceptions are thrown and I get no errors in the callback, but when I check on bitbucket none of my commits are there. Other methods seem to work fine (ie I can create a new branch on bitbucket and then use libgit2sharp to fetch and see that I now have that branch locally). Is there anything that I might be missing here?
edit:
Tried to just make a small sample program to see if I can get this working no go. I don't know if my code will help but here it is:
class Program
{
static void Main(string[] args)
{
PushOptions options = new PushOptions();
Credentials creds = new Credentials();
creds.Username = "username";
creds.Password = "password";
options.Credentials = creds;
options.OnPackBuilderProgress = Program.packBuilderProgressHandler;
options.OnPushTransferProgress = Program.pushTransferProgressHandler;
options.OnPushStatusError = Program.pushStatusErrorHandler;
Repository repo = new Repository("E:/Ohad/Work/libgitTest");
repo.Network.Push(repo.Branches["origin/master"], options);
Console.WriteLine("Press enter to close...");
Console.ReadLine();
}
public static bool packBuilderProgressHandler(PackBuilderStage stage, int current, int total)
{
Console.Out.WriteLine("packBuilder => " + current + " / " + total);
return true;
}
public static bool pushTransferProgressHandler(int current, int total, long bytes)
{
Console.Out.WriteLine("pushTransfer => " + current + " / " + total + " , " + bytes);
return true;
}
public static void pushStatusErrorHandler(PushStatusError error)
{
Console.Out.WriteLine("error => " + error.Message);
}
}
Just make a new repo on bitbucket and add the above code (changing the stuff thats hard coded) and it should be reproducible. I just made a random change, added and commited it and then used the program to try to push to bitbucket. The output that I am getting from the above is:
pushTransfer => 0 / 0 , 12
pushTransfer => 0 / 0 , 32
Press enter to close...
The 0/0 looks suspicious to me but I don't know what I'm doing wrong =/. Thanks for any help!!
edit 2:
I just added this:
repo.Branches.Update(repo.Head, delegate(BranchUpdater updater)
{
updater.Remote = "origin";
updater.UpstreamBranch= repo.Head.CanonicalName;
})
to before when I push and it fixed the issue. Not sure exactly why but I'll take it =).
I think that you're willing to push your local master branch rather than the remote tracking one.
repo.Network.Push(repo.Branches["master"], options);
Update:
*The branch 'master' ("refs/heads/master") that you are trying to push does not track an upstream branch. *
Provided you have no "origin" remote, the following should work.
Remote remote = localRepo.Network.Remotes.Add("origin", url);
repo.Branches.Update(repo.Head, -> (A)
b => b.Remote = remote.Name, -> (B)
b => b.UpstreamBranch = repo.Head.CanonicalName); -> (C)
The code above should be read as "The branch pointed at by the HEAD (A) on this local repository will be, by default, configured to track a branch bearing the same name (C) in the distant repository identified by this remote (B)."
I want to build console application with similar interface like htop's one (fixed console design). Here is a link to htop console design: http://upload.wikimedia.org/wikipedia/commons/b/b1/Htop.png. I wanted to ask how can I build application like this as I only know C#'s Console.Write() method. I am writing simple program that is starting up applications via Process.Start() and then I am monitoring for example their RAM usage via Process.WorkingSet64 and outputing it via simple Console.WriteLine() each line to console. But how could I design C# console application like htop so it has fixed design that will be for example refreshing every 1 second. By fixed designed I mean that I it will be fixed position on the console where I will print out process names, ram usage, application name, etc. Here is my code of the program:
class Program
{
static void Main(string[] args)
{
string[] myApps = { "notepad.exe", "calc.exe", "explorer.exe" };
Thread w;
ParameterizedThreadStart ts = new ParameterizedThreadStart(StartMyApp);
foreach (var myApp in myApps)
{
w = new Thread(ts);
w.Start(myApp);
Thread.Sleep(1000);
}
}
public static void StartMyApp(object myAppPath)
{
ProcessStartInfo myInfoProcess = new ProcessStartInfo();
myInfoProcess.FileName = myAppPath.ToString();
myInfoProcess.WindowStyle = ProcessWindowStyle.Minimized;
Process myProcess = Process.Start(myInfoProcess);
do
{
if (!myProcess.HasExited)
{
myProcess.Refresh(); // Refresh the current process property values.
Console.WriteLine(myProcess.ProcessName+" RAM: " + (myProcess.WorkingSet64 / 1024 / 1024).ToString() + "\n");
Thread.Sleep(1000);
}
}
while (!myProcess.WaitForExit(1000));
}
}
EDIT: Thanks for pointing to Console.SetCursorPosition #Jim Mischel. I want to use that in my application but now I have another problem. How could I pass to my StartMyApp method, the index number from myApps array so I could do something like:
Console.WriteLine((Array.IndexOf(myApps, myAppPath) + " " + myProcess.ProcessName+" RAM: "+ (myProcess.WorkingSet64 / 1024 / 1024).ToString() + "\n");
That is inside my StartMyApp method. Any method I use I end up getting The name 'myApps' does not exist in the current context. This is very important for me so I could design my application later using Console.SetCursorPosition but I need that index number. So my output would be for example:
0 notepad RAM: 4
1 calc RAM: 4
2 explorer RAM: 12
You want to call Console.SetCursorPosition to set the position where the next write will occur. The linked MSDN topic has a basic example that will get you started.
You'll also be interested in the BackgroundColor, ForegroundColor, and possibly other properties. See the Console class documentation for details.
I have a C# Web Service which records data from an IP camera. This service works fine when I record data during a specified amount of time, for example 10 seconds. But my objective is to achieve data recording for an unspecified amount of time and let the user press to stop recording. So I modified my code creating a new Web Service (stopRecording) to change the value of a global variable that acts as a mutex. Obviously this is wrong because I test it but I don´t know how to proceed. Can anybody help me? I would really appreciate it.
Down here I leave the relevant code.
[WebMethod]
public string startRecording(string ipAddress)
{
// Connection preset for H.264 (HTTP API 3.0)
string Url = "axrtsp:://" + ipAddress + "/axis-media/media.amp?videocodec=h264";
string UserName = "username";
string Password = "pass";
string Path = "C:/directory/subdirectory/";
string Filename = "myRecordedFile.bin";
string FilePath = Path + Filename;
// Open binary output file to write parsed video frames into
using (FileStream outFileStream = new FileStream(FilePath, FileMode.Create))
using (outFile = new BinaryWriter(outFileStream))
{
try
{
// Register for events like OnVideoSample, OnAudioSample, OnTriggerData and OnError
...
// Set connection and media properties
...
// Get absolute time from Axis device
...
// Connect to the device
int cookieID;
int numberOfStreams;
object buffer;
parser.Connect(out cookieID, out numberOfStreams, out buffer);
// Write media type information to out file (buffer is an array of bytes)
byte[] mediaTypeBuffer = (byte[])buffer;
outFile.Write(mediaTypeBuffer.Length);
outFile.Write(mediaTypeBuffer, 0, mediaTypeBuffer.Length);
// Start the media stream and registered event handlers will be called
parser.Start();
Debug.WriteLine("Will start recording...");
do {
Debug.WriteLine("recording..."); //want to record during an unspecified time
} while (record); //my mutex variable that doesn´t make the thing even when I call the stopRecording Web Service. The program remains overlooping
System.Diagnostics.Debug.Write("Finish recording... never reached!!!!! ");
// Stop the stream
parser.Stop();
// Unregister event handlers
...
}
catch (COMException e)
{
Console.WriteLine("Exception for {0}, {1}", parser.MediaURL, e.Message);
}
// Inform the GC that COM object no longer will be used
Marshal.FinalReleaseComObject(parser);
parser = null;
Console.WriteLine("Stream stopped");
}
return "Recording from camera " + Url;
}
[WebMethod]
public string stopRecording()
{
System.Diagnostics.Debug.Write("I want to stop recording...");
record = false;
return "Stop";
}
Your record variable is not a Mutex object, but a simple flag... Which is besides the point.
Trouble here is that you code in startRecording() never gives the hand back to the parent class and might be holding the processing thread forever.
If I might suggest, why not create a thread to do your recording ? You have a number of possibilities here ( new Thread(), Action.BeginInvoke(), .. )
This way, you give a chance to your stopRecording to be received and set this record flag to false and leave the recording thread.
I am wondering how to write a "good" gameserver. I had a few ideas but I never made a server and I don't want to end up in writing brainfuck code.
I know how to handle TCP-Connections and so on but my problem is how do I communicate between server and client.
As example: I write a game like TicTacTow. Now a user clicked on a cell and I want to tell that server. The server should validate whether the user can click on that cell and tell that the client. If the server tells yes; you can click that the client displays this as a "X".
Now my problem: How exactly do I tell the server that I want to click that field. I came across another question here and they ended up in using the command-pattern. But if I understood it right, I would have to create a Command that implements an Interface. I serialize an instance of that command and send it to the server. The server executes the command. But I have to main problems with that:
If the command sets a cell of the tictacto to an X. How do I tell the Server that he has to pass the GameBoard which I need to set the cell to an X to my Invoke-Method of the interface ICommand.
Isn't that extremely unsecure? I mean I could write a command that deletes all my files or stops the server and send it to the server. I don't believe that the Command-Pattern is that nice idea.
So I am searching for something better. I just want to have an easy and extensible architecture for my client and the server. Is there any good pattern?
Oh and another question: Would you use a serializer or would you encode the data yourself?
What gave you the idea to use serialization of objects directly? That would be a very bad thing for a game server as it's slow, can be prone to break (especially if you have a complicated object graph to serialize) and generally is hackish. The solution is to design and implement your own game communication protocol from scratch - fortunately it's easy.
Serialization is largely done in boring business applications and data tiers, where the objective is to easily transfer data, often between heterogeneous systems, which is why XML-based serialization is often used. These requirements do not apply to games.
Note that serializing an object only serializes the data members, it does not serialize methods. So your fears about malicious code being sent down the line are ill-founded.
Anyway, The first rule of server design is to never trust the client - which means the game server needs to maintain a copy of the current game-state in memory and apply the game's rules to each game-move message sent from a client.
From a bird's eye perspective, here is how I'd design your tic-tac-toe system:
Protocol
Because changes to the game state are event-driven and it's turn-based, a protocol based on verbs and arguments works best. I would have the following verbs, on the assumption this is strictly a 2-player game (using 2 clients and a server)
Client-to-Server
JOIN
READY
MOVE (x, y)
QUIT
Server-to-Client
JOINED
ISREADY
MOVED (player, x, y)
DENIED (reason)
LEFTGAME (player)
The client-to-server verbs should be self-explanatory. You'll notice the server-to-client verbs are proxied versions of the original client-to-server messages, with the exception that MOVED contains the ID of the player who moved, and also contains DENIED to inform clients their move was rejected. The LEFTGAME verb is used to signal that the other player has quit.
Server
This is an incomplete psuedo-code implementation of a hypothetical Tic-tac-toe server. The code I have written is concerned only with the network layer of the application, all of the actual logic surrounding tic-tac-toe game rules and moves is contained within the TicTacToeBoard class and is not described here, however it should be trivial to implement.
The server logic happens in a single thread, the logic for demultiplexing incoming messages can be done in a single thread very easily if you use the modern Task/async IO APIs in .NET, otherwise using one-thread-per-remote-connection can be quick and easy way to handle it too (2-player games don't need to worry about scaling - but this won't scale well to hundreds of players, just saying). (The code for handling those remote connections is not detailed here, it is hidden behind the abstract WaitForAndGetConnection, GetLastIncomingMessage, and SendMessage methods).
// Ready-room state
connection1 = WaitForAndGetConnection();
connection2 = WaitForAndGetConnection();
SendMessage( connection1, "JOINED" ); // inform player 1 that another player joined
p1Ready = false, p2Ready = false;
while(message = GetLastIncomingMessage() && !p1Ready && !p2Ready) {
if( message.From == connection1 && message.Verb == "READY" ) p1Ready = true;
if( message.From == connection2 && message.Verb == "READY" ) p2Ready = true;
}
SendMessage( connection1, "ISREADY" ); // inform the players the game has started
SendMessage( connection2, "ISREADY" ); // inform the players the game has started
// Game playing state
TicTacToeBoard board = new TicTacToeBoard(); // this class represents the game state and game rules
p1Move = true; // indicates whose turn it is to move
while(message = GetLastIncomingMessage()) {
if( message.Verb == "MOVE" ) {
if( p1Move && message.From == connection1 ) {
if( board.Player1Move( message.X, message.Y ) ) {
SendMessage( connection1, "MOVED (1, " + message.X + "," + message.Y + " )");
SendMessage( connection2, "MOVED (1, " + message.X + "," + message.Y + " )");
p1Move = false;
} else {
SendMessage( message.From, "DENIED \"Disallowed move.\".");
}
} else if( !p1Move && message.From == connection2 ) {
if( board.Player2Move( message.X, message.Y ) ) {
SendMessage( connection1, "MOVED (2, " + message.X + "," + message.Y + " )");
SendMessage( connection2, "MOVED (2, " + message.X + "," + message.Y + " )");
p1Move = true;
} else {
SendMessage( message.From, "DENIED \"Disallowed move.\".");
}
} else {
SendMessage( message.From, "DENIED \"It isn't your turn to move\".");
}
if( board.IsEnded ) {
// handle game-over...
}
} else if( message.Verb == ... // handle all of the other verbs, like QUIT
}
}