1 #ifdef BT_ENABLE_GRPC
2 #include "PhysicsClientGRPC.h"
3 #include "SharedMemory/grpc/proto/pybullet.grpc.pb.h"
4 #include <grpc++/grpc++.h>
5 using grpc::Channel;
6 #include <stdio.h>
7 #include <string.h>
8 #include "../Utils/b3Clock.h"
9 #include "PhysicsClient.h"
10 //#include "LinearMath/btVector3.h"
11 #include "SharedMemoryCommands.h"
12 #include <string>
13 #include "Bullet3Common/b3Logging.h"
14 #include "Bullet3Common/b3AlignedObjectArray.h"
15 #include "SharedMemory/grpc/ConvertGRPCBullet.h"
16
17 using pybullet_grpc::grpc::PyBulletAPI;
18
b3DeserializeInt2(const unsigned char * input)19 static unsigned int b3DeserializeInt2(const unsigned char* input)
20 {
21 unsigned int tmp = (input[3] << 24) + (input[2] << 16) + (input[1] << 8) + input[0];
22 return tmp;
23 }
24
25 bool gVerboseNetworkMessagesClient3 = false;
26
27 struct GRPCNetworkedInternalData
28 {
29 std::shared_ptr<grpc::Channel> m_grpcChannel;
30 std::unique_ptr<PyBulletAPI::Stub> m_stub;
31
32 bool m_isConnected;
33
34 SharedMemoryCommand m_clientCmd;
35 bool m_hasCommand;
36
37 SharedMemoryStatus m_lastStatus;
38 b3AlignedObjectArray<char> m_stream;
39
40 std::string m_hostName;
41 int m_port;
42
43 b3AlignedObjectArray<unsigned char> m_tempBuffer;
44 double m_timeOutInSeconds;
45
GRPCNetworkedInternalDataGRPCNetworkedInternalData46 GRPCNetworkedInternalData()
47 : m_isConnected(false),
48 m_hasCommand(false),
49 m_timeOutInSeconds(60)
50 {
51 }
52
disconnectGRPCNetworkedInternalData53 void disconnect()
54 {
55 if (m_isConnected)
56 {
57 m_stub = 0;
58 m_grpcChannel = 0;
59 m_isConnected = false;
60 }
61 }
connectGRPCGRPCNetworkedInternalData62 bool connectGRPC()
63 {
64 if (m_isConnected)
65 return true;
66 std::string hostport = m_hostName;
67 if (m_port >= 0)
68 {
69 hostport += ':' + std::to_string(m_port);
70 }
71 m_grpcChannel = grpc::CreateChannel(
72 hostport, grpc::InsecureChannelCredentials());
73
74 m_stub = PyBulletAPI::NewStub(m_grpcChannel);
75
76 // Set timeout for API
77 std::chrono::system_clock::time_point deadline =
78 std::chrono::system_clock::now() + std::chrono::seconds((long long)m_timeOutInSeconds);
79 grpc::ClientContext context;
80 context.set_deadline(deadline);
81 ::pybullet_grpc::PyBulletCommand request;
82 pybullet_grpc::CheckVersionCommand* cmd1 = request.mutable_checkversioncommand();
83 cmd1->set_clientversion(SHARED_MEMORY_MAGIC_NUMBER);
84 ::pybullet_grpc::PyBulletStatus response;
85 // The actual RPC.
86 grpc::Status status = m_stub->SubmitCommand(&context, request, &response);
87 if (response.has_checkversionstatus())
88 {
89 if (response.checkversionstatus().serverversion() == SHARED_MEMORY_MAGIC_NUMBER)
90 {
91 m_isConnected = true;
92 }
93 else
94 {
95 printf("Error: Client version (%d) is different from server version (%d)", SHARED_MEMORY_MAGIC_NUMBER, response.checkversionstatus().serverversion());
96 }
97 }
98 else
99 {
100 printf("Error: cannot connect to GRPC server\n");
101 }
102
103 return m_isConnected;
104 }
105
checkDataGRPCNetworkedInternalData106 bool checkData()
107 {
108 bool hasStatus = false;
109 return hasStatus;
110 }
111 };
112
GRPCNetworkedPhysicsProcessor(const char * hostName,int port)113 GRPCNetworkedPhysicsProcessor::GRPCNetworkedPhysicsProcessor(const char* hostName, int port)
114 {
115 m_data = new GRPCNetworkedInternalData;
116 if (hostName)
117 {
118 m_data->m_hostName = hostName;
119 }
120 m_data->m_port = port;
121 }
122
~GRPCNetworkedPhysicsProcessor()123 GRPCNetworkedPhysicsProcessor::~GRPCNetworkedPhysicsProcessor()
124 {
125 disconnect();
126 delete m_data;
127 }
128
processCommand(const struct SharedMemoryCommand & clientCmd,struct SharedMemoryStatus & serverStatusOut,char * bufferServerToClient,int bufferSizeInBytes)129 bool GRPCNetworkedPhysicsProcessor::processCommand(const struct SharedMemoryCommand& clientCmd, struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
130 {
131 if (gVerboseNetworkMessagesClient3)
132 {
133 printf("GRPCNetworkedPhysicsProcessor::processCommand\n");
134 }
135
136 ::pybullet_grpc::PyBulletCommand grpcCommand;
137 pybullet_grpc::PyBulletCommand* grpcCmdPtr = convertBulletToGRPCCommand(clientCmd, grpcCommand);
138
139 if (grpcCmdPtr)
140 {
141 grpc::ClientContext context;
142 std::chrono::system_clock::time_point deadline =
143 std::chrono::system_clock::now() + std::chrono::seconds((long long)m_data->m_timeOutInSeconds);
144 context.set_deadline(deadline);
145 ::pybullet_grpc::PyBulletStatus status;
146 // The actual RPC.
147 grpc::Status grpcStatus = m_data->m_stub->SubmitCommand(&context, grpcCommand, &status);
148
149 //convert grpc status to Bullet status
150 bool convertedOk = convertGRPCToStatus(status, serverStatusOut, bufferServerToClient, bufferSizeInBytes);
151 if (!convertedOk)
152 {
153 disconnect();
154 }
155 return convertedOk;
156 }
157
158 return false;
159 }
160
receiveStatus(struct SharedMemoryStatus & serverStatusOut,char * bufferServerToClient,int bufferSizeInBytes)161 bool GRPCNetworkedPhysicsProcessor::receiveStatus(struct SharedMemoryStatus& serverStatusOut, char* bufferServerToClient, int bufferSizeInBytes)
162 {
163 bool hasStatus = m_data->checkData();
164
165 if (hasStatus)
166 {
167 if (gVerboseNetworkMessagesClient3)
168 {
169 printf("GRPCNetworkedPhysicsProcessor::receiveStatus\n");
170 }
171
172 serverStatusOut = m_data->m_lastStatus;
173 int numStreamBytes = m_data->m_stream.size();
174
175 if (numStreamBytes < bufferSizeInBytes)
176 {
177 for (int i = 0; i < numStreamBytes; i++)
178 {
179 bufferServerToClient[i] = m_data->m_stream[i];
180 }
181 }
182 else
183 {
184 printf("Error: steam buffer overflow\n");
185 }
186 }
187
188 return hasStatus;
189 }
190
renderScene(int renderFlags)191 void GRPCNetworkedPhysicsProcessor::renderScene(int renderFlags)
192 {
193 }
194
physicsDebugDraw(int debugDrawFlags)195 void GRPCNetworkedPhysicsProcessor::physicsDebugDraw(int debugDrawFlags)
196 {
197 }
198
setGuiHelper(struct GUIHelperInterface * guiHelper)199 void GRPCNetworkedPhysicsProcessor::setGuiHelper(struct GUIHelperInterface* guiHelper)
200 {
201 }
202
isConnected() const203 bool GRPCNetworkedPhysicsProcessor::isConnected() const
204 {
205 return m_data->m_isConnected;
206 }
207
connect()208 bool GRPCNetworkedPhysicsProcessor::connect()
209 {
210 bool isConnected = m_data->connectGRPC();
211 return isConnected;
212 }
213
disconnect()214 void GRPCNetworkedPhysicsProcessor::disconnect()
215 {
216 m_data->disconnect();
217 }
218
setTimeOut(double timeOutInSeconds)219 void GRPCNetworkedPhysicsProcessor::setTimeOut(double timeOutInSeconds)
220 {
221 m_data->m_timeOutInSeconds = timeOutInSeconds;
222 }
223
224 #endif //BT_ENABLE_GRPC
225