Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/unrealcv/unrealcv into d…
Browse files Browse the repository at this point in the history
…evelop
  • Loading branch information
qiuwch committed Jul 8, 2017
2 parents 940b5aa + 39ce01e commit 91e3672
Show file tree
Hide file tree
Showing 7 changed files with 394 additions and 210 deletions.
24 changes: 17 additions & 7 deletions client/python/unrealcv/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ def ReceivePayload(cls, socket):

rfile.close()

return payload.decode('UTF-8')
return payload

@classmethod
def WrapAndSendPayload(cls, socket, payload):
Expand All @@ -107,7 +107,9 @@ def WrapAndSendPayload(cls, socket, payload):
wfile.write(struct.pack(fmt, socket_message.payload_size))
# print 'Sent ', socket_message.payload_size

wfile.write(payload.encode('UTF-8'))
if isinstance(payload, str):
payload = payload.encode('utf-8')
wfile.write(payload)
# print 'Sent ', payload
wfile.flush()
wfile.close() # Close file object, not close the socket
Expand All @@ -116,6 +118,7 @@ def WrapAndSendPayload(cls, socket, payload):
_L.error('Fail to send message %s', e)
return False


class BaseClient(object):
'''
BaseClient send message out and receiving message in a seperate thread.
Expand Down Expand Up @@ -171,7 +174,7 @@ def connect(self, timeout = 1):
self.socket = None

def isconnected(self):
return self.socket != None
return self.socket is not None

def disconnect(self):
if self.isconnected():
Expand All @@ -191,7 +194,7 @@ def __receiving(self):
Also check whether client is still connected
'''
_L.debug('BaseClient start receiving in %s', threading.current_thread().name)
while (1):
while True:
if self.isconnected():
# Only this thread is allowed to read from socket, otherwise need lock to avoid competing
message = SocketMessage.ReceivePayload(self.socket)
Expand All @@ -201,8 +204,8 @@ def __receiving(self):
self.socket = None
continue

if message.startswith('connected'):
_L.info('Got connection confirm: %s', repr(message))
if message.startswith(b'connected'):
_L.info('Got connection confirm: %s', repr(message.decode('utf-8')))
self.wait_connected.set()
# self.wait_connected.clear()
continue
Expand All @@ -224,6 +227,7 @@ def send(self, message):
_L.error('Fail to send message, client is not connected')
return False


class Client(object):
'''
Client can be used to send request to a game and get response
Expand All @@ -233,9 +237,15 @@ class Client(object):
def __raw_message_handler(self, raw_message):
# print 'Waiting for message id %d' % self.message_id
match = self.raw_message_regexp.match(raw_message)

if match:
[message_id, message_body] = (int(match.group(1)), match.group(2)) # TODO: handle multiline response
message_body = raw_message[len(match.group(1))+1:]
# Convert to utf-8 if it's not a byte array (as is the case for images)
try:
message_body = message_body.decode('utf-8')
except UnicodeDecodeError:
pass
# print 'Received message id %s' % message_id
if message_id == self.message_id:
self.response = message_body
Expand All @@ -252,7 +262,7 @@ def do_callback():
_L.error('No message handler to handle message %s', raw_message)

def __init__(self, endpoint, message_handler=None):
self.raw_message_regexp = re.compile('(\d{1,8}):(.*)')
self.raw_message_regexp = re.compile(b'(\d{1,8}):(.*)')
self.message_client = BaseClient(endpoint, self.__raw_message_handler)
self.message_handler = message_handler
self.message_id = 0
Expand Down
56 changes: 50 additions & 6 deletions docs/plugin/develop.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ UE4 has two types of game projects. Blueprint project and C++ project. We need a

In a C++ project, the plugin code will be compiled together with the game project.

The simplest way to start is using the `playground project`_. Playground project is a simple UE4 project to show basic features or UE4 and UnrealCV, it serves as a development base and test platform for UnrealCV team.
The simplest way to start is using the `playground project`_. Playground project is a simple UE4 project to show basic features or UE4 and UnrealCV. It serves as a development base and test platform for UnrealCV team.

.. _playground project: https://github.com/unrealcv/playground

Expand Down Expand Up @@ -64,9 +64,11 @@ Linux
Mac

.. note::
- Install Xcode.

- To generate Xcode Project, right click :file:`playground.uproject` and choose :code:`Service->Generate Xcode Project`.

Need help for writing this section
- Open the :file:`*.xcworkspace` file and build. The plugin code will be compiled together with the game project.


Useful resources for development include:
Expand All @@ -79,17 +81,59 @@ Useful resources for development include:
Add a new command
=================

UnrealCV provides a set of commands for accomplishing tasks and the list is growing. But it might not be sufficient for your task. If you need any functions that is missing, you can try to implement it yourself.
UnrealCV provides a set of commands for accomplishing tasks and the list is growing. But it might not be sufficient for your task. If you need any function that is missing, you can try to implement it yourself.

The benefit of implementing an UnrealCV command are:
The benefits of implementing an UnrealCV command are:

1. You can use the communication protocol provided by UnrealCV to exchange data between your program and UE4.
2. You can share your code with other researchers, so that it can be used by others.


.. note::

You are supposed to edit your code in `playground->Plugins->UnrealCV` instead of `UE4->Plugins->UnrealCV`.


First we go through a very simple example which prints a message. Assume that we want to add a commamd :code:`vget /object/helloworld` to print "Hello World!". We need to modify two files: :file:`ObjectHandler.h` and :file:`ObjectHandler.cpp`.

In :file:`ObjectHandler.h`, we need to add a member function:

.. code:: c
   FExecStatus HelloWorld(const TArray<FString>& Args);
In :file:`ObjectHandler.cpp`, we define this member function:

.. code:: c
   FExecStatus FObjectCommandHandler::HelloWorld(const TArray<FString>& Args)
{
FString Msg;
Msg += "Hello World!";
return FExecStatus::OK(Msg);
}
Then we need to bind the command with the function:

.. code:: c
void FObjectCommandHandler::RegisterCommands()
{
...
Cmd = FDispatcherDelegate::CreateRaw(this, &FObjectCommandHandler::HelloWorld);
Help = "Print Hello World";
CommandDispatcher->BindCommand(TEXT("vget /object/helloworld"), Cmd, Help);
...
}
After the modification, we can compile and use the new command.

Here we will walk you through how to implement a command :code:`vset /object/[id]/rotation` to enable you set the rotation of an object.

:code:`FExecStatus` return the exec result of this command. The result will be returned as a text string.

Available variables for a command are :code:`GetWorld()`, :code:`GetActor()`, , :code:`GetLevel()`.

A new functions will be implemented in a CommandHandler. CommandDispatcher will use CommandHandler.
A new function will be implemented in a CommandHandler. CommandDispatcher will use CommandHandler.
3 changes: 2 additions & 1 deletion docs/reference/contact.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,12 @@ Team Members

UnrealCV is developed and maintained by a group of students working on computer vision (sort alphabetically).

- `Fangwei Zhong`
- `Siyuan Qiao <http://www.cs.jhu.edu/~syqiao/>`_: Stochastic virtual scene generation
- `Tae Soo Kim`: Deep learning for transferable concepts between the real and the virtual environment
- `Weichao Qiu <http://weichaoqiu.com>`_: Constructing virtual worlds to train and diagnose computer vision algorithms
- `Yi Zhang`: Algorithm diagnosis with synthetic data
- `Fangwei Zhong`
- `Zihao Xiao`

.. _Github: http://github.com/unrealcv/unrealcv
.. _issue tracker: https://github.com/unrealcv/unrealcv/issues
Expand Down

0 comments on commit 91e3672

Please sign in to comment.